diff options
Diffstat (limited to 'drivers/i2c')
30 files changed, 1358 insertions, 448 deletions
| diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index c33dcfb87993..5e5990a83da5 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -1,21 +1,12 @@ -/* ------------------------------------------------------------------------- - * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters - * ------------------------------------------------------------------------- +// SPDX-License-Identifier: GPL-2.0+ +/* + * i2c-algo-bit.c: i2c driver algorithms for bit-shift adapters + *   *   Copyright (C) 1995-2000 Simon G. Vogl - -    This program is free software; you can redistribute it and/or modify -    it under the terms of the GNU General Public License as published by -    the Free Software Foundation; either version 2 of the License, or -    (at your option) any later version. - -    This program is distributed in the hope that it will be useful, -    but WITHOUT ANY WARRANTY; without even the implied warranty of -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -    GNU General Public License for more details. - * ------------------------------------------------------------------------- */ - -/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki -   <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> */ + * + * With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki + * <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> + */  #include <linux/kernel.h>  #include <linux/module.h> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index f2c681971201..f8979abb9a19 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -131,6 +131,7 @@ config I2C_I801  	    Cannon Lake (PCH)  	    Cedar Fork (PCH)  	    Ice Lake (PCH) +	    Comet Lake (PCH)  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 8dc9161ced38..6c8b38fd6e64 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -117,6 +117,7 @@  enum aspeed_i2c_master_state {  	ASPEED_I2C_MASTER_INACTIVE, +	ASPEED_I2C_MASTER_PENDING,  	ASPEED_I2C_MASTER_START,  	ASPEED_I2C_MASTER_TX_FIRST,  	ASPEED_I2C_MASTER_TX, @@ -126,12 +127,13 @@ enum aspeed_i2c_master_state {  };  enum aspeed_i2c_slave_state { -	ASPEED_I2C_SLAVE_STOP, +	ASPEED_I2C_SLAVE_INACTIVE,  	ASPEED_I2C_SLAVE_START,  	ASPEED_I2C_SLAVE_READ_REQUESTED,  	ASPEED_I2C_SLAVE_READ_PROCESSED,  	ASPEED_I2C_SLAVE_WRITE_REQUESTED,  	ASPEED_I2C_SLAVE_WRITE_RECEIVED, +	ASPEED_I2C_SLAVE_STOP,  };  struct aspeed_i2c_bus { @@ -156,6 +158,8 @@ struct aspeed_i2c_bus {  	int				cmd_err;  	/* Protected only by i2c_lock_bus */  	int				master_xfer_result; +	/* Multi-master */ +	bool				multi_master;  #if IS_ENABLED(CONFIG_I2C_SLAVE)  	struct i2c_client		*slave;  	enum aspeed_i2c_slave_state	slave_state; @@ -251,7 +255,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  	}  	/* Slave is not currently active, irq was for someone else. */ -	if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) +	if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)  		return irq_handled;  	dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n", @@ -277,16 +281,15 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  		irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;  		bus->slave_state = ASPEED_I2C_SLAVE_STOP;  	} -	if (irq_status & ASPEED_I2CD_INTR_TX_NAK) { +	if (irq_status & ASPEED_I2CD_INTR_TX_NAK && +	    bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {  		irq_handled |= ASPEED_I2CD_INTR_TX_NAK;  		bus->slave_state = ASPEED_I2C_SLAVE_STOP;  	} -	if (irq_status & ASPEED_I2CD_INTR_TX_ACK) -		irq_handled |= ASPEED_I2CD_INTR_TX_ACK;  	switch (bus->slave_state) {  	case ASPEED_I2C_SLAVE_READ_REQUESTED: -		if (irq_status & ASPEED_I2CD_INTR_TX_ACK) +		if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_ACK))  			dev_err(bus->dev, "Unexpected ACK on read request.\n");  		bus->slave_state = ASPEED_I2C_SLAVE_READ_PROCESSED;  		i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value); @@ -294,9 +297,12 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  		writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG);  		break;  	case ASPEED_I2C_SLAVE_READ_PROCESSED: -		if (!(irq_status & ASPEED_I2CD_INTR_TX_ACK)) +		if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {  			dev_err(bus->dev,  				"Expected ACK after processed read.\n"); +			break; +		} +		irq_handled |= ASPEED_I2CD_INTR_TX_ACK;  		i2c_slave_event(slave, I2C_SLAVE_READ_PROCESSED, &value);  		writel(value, bus->base + ASPEED_I2C_BYTE_BUF_REG);  		writel(ASPEED_I2CD_S_TX_CMD, bus->base + ASPEED_I2C_CMD_REG); @@ -310,10 +316,15 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  		break;  	case ASPEED_I2C_SLAVE_STOP:  		i2c_slave_event(slave, I2C_SLAVE_STOP, &value); +		bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; +		break; +	case ASPEED_I2C_SLAVE_START: +		/* Slave was just started. Waiting for the next event. */;  		break;  	default: -		dev_err(bus->dev, "unhandled slave_state: %d\n", +		dev_err(bus->dev, "unknown slave_state: %d\n",  			bus->slave_state); +		bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;  		break;  	} @@ -329,6 +340,17 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)  	u8 slave_addr = i2c_8bit_addr_from_msg(msg);  	bus->master_state = ASPEED_I2C_MASTER_START; + +#if IS_ENABLED(CONFIG_I2C_SLAVE) +	/* +	 * If it's requested in the middle of a slave session, set the master +	 * state to 'pending' then H/W will continue handling this master +	 * command when the bus comes back to the idle state. +	 */ +	if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) +		bus->master_state = ASPEED_I2C_MASTER_PENDING; +#endif /* CONFIG_I2C_SLAVE */ +  	bus->buf_index = 0;  	if (msg->flags & I2C_M_RD) { @@ -384,10 +406,6 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  		bus->master_state = ASPEED_I2C_MASTER_INACTIVE;  		irq_handled |= ASPEED_I2CD_INTR_BUS_RECOVER_DONE;  		goto out_complete; -	} else { -		/* Master is not currently active, irq was for someone else. */ -		if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE) -			goto out_no_complete;  	}  	/* @@ -399,11 +417,32 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  	if (ret) {  		dev_dbg(bus->dev, "received error interrupt: 0x%08x\n",  			irq_status); -		bus->cmd_err = ret; -		bus->master_state = ASPEED_I2C_MASTER_INACTIVE;  		irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS); -		goto out_complete; +		if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) { +			bus->cmd_err = ret; +			bus->master_state = ASPEED_I2C_MASTER_INACTIVE; +			goto out_complete; +		} +	} + +#if IS_ENABLED(CONFIG_I2C_SLAVE) +	/* +	 * A pending master command will be started by H/W when the bus comes +	 * back to idle state after completing a slave operation so change the +	 * master state from 'pending' to 'start' at here if slave is inactive. +	 */ +	if (bus->master_state == ASPEED_I2C_MASTER_PENDING) { +		if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) +			goto out_no_complete; + +		bus->master_state = ASPEED_I2C_MASTER_START;  	} +#endif /* CONFIG_I2C_SLAVE */ + +	/* Master is not currently active, irq was for someone else. */ +	if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE || +	    bus->master_state == ASPEED_I2C_MASTER_PENDING) +		goto out_no_complete;  	/* We are in an invalid state; reset bus to a known state. */  	if (!bus->msgs) { @@ -423,6 +462,20 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)  	 * then update the state and handle the new state below.  	 */  	if (bus->master_state == ASPEED_I2C_MASTER_START) { +#if IS_ENABLED(CONFIG_I2C_SLAVE) +		/* +		 * If a peer master starts a xfer immediately after it queues a +		 * master command, change its state to 'pending' then H/W will +		 * continue the queued master xfer just after completing the +		 * slave mode session. +		 */ +		if (unlikely(irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH)) { +			bus->master_state = ASPEED_I2C_MASTER_PENDING; +			dev_dbg(bus->dev, +				"master goes pending due to a slave start\n"); +			goto out_no_complete; +		} +#endif /* CONFIG_I2C_SLAVE */  		if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {  			if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_NAK))) {  				bus->cmd_err = -ENXIO; @@ -566,7 +619,8 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)  	 * interrupt bits. Each case needs to be handled using corresponding  	 * handlers depending on the current state.  	 */ -	if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) { +	if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE && +	    bus->master_state != ASPEED_I2C_MASTER_PENDING) {  		irq_handled = aspeed_i2c_master_irq(bus, irq_remaining);  		irq_remaining &= ~irq_handled;  		if (irq_remaining) @@ -601,15 +655,16 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,  {  	struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap);  	unsigned long time_left, flags; -	int ret = 0;  	spin_lock_irqsave(&bus->lock, flags);  	bus->cmd_err = 0; -	/* If bus is busy, attempt recovery. We assume a single master -	 * environment. -	 */ -	if (readl(bus->base + ASPEED_I2C_CMD_REG) & ASPEED_I2CD_BUS_BUSY_STS) { +	/* If bus is busy in a single master environment, attempt recovery. */ +	if (!bus->multi_master && +	    (readl(bus->base + ASPEED_I2C_CMD_REG) & +	     ASPEED_I2CD_BUS_BUSY_STS)) { +		int ret; +  		spin_unlock_irqrestore(&bus->lock, flags);  		ret = aspeed_i2c_recover_bus(bus);  		if (ret) @@ -629,10 +684,20 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,  	time_left = wait_for_completion_timeout(&bus->cmd_complete,  						bus->adap.timeout); -	if (time_left == 0) +	if (time_left == 0) { +		/* +		 * If timed out and bus is still busy in a multi master +		 * environment, attempt recovery at here. +		 */ +		if (bus->multi_master && +		    (readl(bus->base + ASPEED_I2C_CMD_REG) & +		     ASPEED_I2CD_BUS_BUSY_STS)) +			aspeed_i2c_recover_bus(bus); +  		return -ETIMEDOUT; -	else -		return bus->master_xfer_result; +	} + +	return bus->master_xfer_result;  }  static u32 aspeed_i2c_functionality(struct i2c_adapter *adap) @@ -672,7 +737,7 @@ static int aspeed_i2c_reg_slave(struct i2c_client *client)  	__aspeed_i2c_reg_slave(bus, client->addr);  	bus->slave = client; -	bus->slave_state = ASPEED_I2C_SLAVE_STOP; +	bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;  	spin_unlock_irqrestore(&bus->lock, flags);  	return 0; @@ -827,7 +892,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,  	if (ret < 0)  		return ret; -	if (!of_property_read_bool(pdev->dev.of_node, "multi-master")) +	if (of_property_read_bool(pdev->dev.of_node, "multi-master")) +		bus->multi_master = true; +	else  		fun_ctrl_reg |= ASPEED_I2CD_MULTI_MASTER_DIS;  	/* Enable Master Mode */ @@ -930,7 +997,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)  	init_completion(&bus->cmd_complete);  	bus->adap.owner = THIS_MODULE;  	bus->adap.retries = 0; -	bus->adap.timeout = 5 * HZ;  	bus->adap.algo = &aspeed_i2c_algo;  	bus->adap.dev.parent = &pdev->dev;  	bus->adap.dev.of_node = pdev->dev.of_node; diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 826d32049996..f4d862234980 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -170,7 +170,6 @@ struct brcmstb_i2c_dev {  	struct bsc_regs *bsc_regmap;  	struct i2c_adapter adapter;  	struct completion done; -	bool is_suspended;  	u32 clk_freq_hz;  	int data_regsz;  }; @@ -467,9 +466,6 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,  	int xfersz = brcmstb_i2c_get_xfersz(dev);  	u32 cond, cond_per_msg; -	if (dev->is_suspended) -		return -EBUSY; -  	/* Loop through all messages */  	for (i = 0; i < num; i++) {  		pmsg = &msgs[i]; @@ -689,10 +685,7 @@ static int brcmstb_i2c_suspend(struct device *dev)  {  	struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); -	i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); -	i2c_dev->is_suspended = true; -	i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); - +	i2c_mark_adapter_suspended(&i2c_dev->adapter);  	return 0;  } @@ -700,10 +693,8 @@ static int brcmstb_i2c_resume(struct device *dev)  {  	struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); -	i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);  	brcmstb_i2c_set_bsc_reg_defaults(i2c_dev); -	i2c_dev->is_suspended = false; -	i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); +	i2c_mark_adapter_resumed(&i2c_dev->adapter);  	return 0;  } diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index b4f91e48948a..72df563477b1 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -18,16 +18,14 @@  #include <linux/io.h>  #include <linux/i2c.h> -#include <linux/gpio.h>  #include <linux/slab.h>  #include <linux/delay.h>  #include <linux/errno.h>  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/platform_device.h> -#include <linux/platform_data/i2c-cbus-gpio.h>  /*   * Bit counts are derived from Nokia implementation. These should be checked @@ -39,9 +37,9 @@  struct cbus_host {  	spinlock_t	lock;		/* host lock */  	struct device	*dev; -	int		clk_gpio; -	int		dat_gpio; -	int		sel_gpio; +	struct gpio_desc *clk; +	struct gpio_desc *dat; +	struct gpio_desc *sel;  };  /** @@ -51,9 +49,9 @@ struct cbus_host {   */  static void cbus_send_bit(struct cbus_host *host, unsigned bit)  { -	gpio_set_value(host->dat_gpio, bit ? 1 : 0); -	gpio_set_value(host->clk_gpio, 1); -	gpio_set_value(host->clk_gpio, 0); +	gpiod_set_value(host->dat, bit ? 1 : 0); +	gpiod_set_value(host->clk, 1); +	gpiod_set_value(host->clk, 0);  }  /** @@ -78,9 +76,9 @@ static int cbus_receive_bit(struct cbus_host *host)  {  	int ret; -	gpio_set_value(host->clk_gpio, 1); -	ret = gpio_get_value(host->dat_gpio); -	gpio_set_value(host->clk_gpio, 0); +	gpiod_set_value(host->clk, 1); +	ret = gpiod_get_value(host->dat); +	gpiod_set_value(host->clk, 0);  	return ret;  } @@ -123,10 +121,10 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,  	spin_lock_irqsave(&host->lock, flags);  	/* Reset state and start of transfer, SEL stays down during transfer */ -	gpio_set_value(host->sel_gpio, 0); +	gpiod_set_value(host->sel, 0);  	/* Set the DAT pin to output */ -	gpio_direction_output(host->dat_gpio, 1); +	gpiod_direction_output(host->dat, 1);  	/* Send the device address */  	cbus_send_data(host, dev, CBUS_ADDR_BITS); @@ -141,12 +139,12 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,  		cbus_send_data(host, data, 16);  		ret = 0;  	} else { -		ret = gpio_direction_input(host->dat_gpio); +		ret = gpiod_direction_input(host->dat);  		if (ret) {  			dev_dbg(host->dev, "failed setting direction\n");  			goto out;  		} -		gpio_set_value(host->clk_gpio, 1); +		gpiod_set_value(host->clk, 1);  		ret = cbus_receive_word(host);  		if (ret < 0) { @@ -156,9 +154,9 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,  	}  	/* Indicate end of transfer, SEL goes up until next transfer */ -	gpio_set_value(host->sel_gpio, 1); -	gpio_set_value(host->clk_gpio, 1); -	gpio_set_value(host->clk_gpio, 0); +	gpiod_set_value(host->sel, 1); +	gpiod_set_value(host->clk, 1); +	gpiod_set_value(host->clk, 0);  out:  	spin_unlock_irqrestore(&host->lock, flags); @@ -214,7 +212,6 @@ static int cbus_i2c_probe(struct platform_device *pdev)  {  	struct i2c_adapter *adapter;  	struct cbus_host *chost; -	int ret;  	adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),  			       GFP_KERNEL); @@ -225,22 +222,20 @@ static int cbus_i2c_probe(struct platform_device *pdev)  	if (!chost)  		return -ENOMEM; -	if (pdev->dev.of_node) { -		struct device_node *dnode = pdev->dev.of_node; -		if (of_gpio_count(dnode) != 3) -			return -ENODEV; -		chost->clk_gpio = of_get_gpio(dnode, 0); -		chost->dat_gpio = of_get_gpio(dnode, 1); -		chost->sel_gpio = of_get_gpio(dnode, 2); -	} else if (dev_get_platdata(&pdev->dev)) { -		struct i2c_cbus_platform_data *pdata = -			dev_get_platdata(&pdev->dev); -		chost->clk_gpio = pdata->clk_gpio; -		chost->dat_gpio = pdata->dat_gpio; -		chost->sel_gpio = pdata->sel_gpio; -	} else { +	if (gpiod_count(&pdev->dev, NULL) != 3)  		return -ENODEV; -	} +	chost->clk = devm_gpiod_get_index(&pdev->dev, NULL, 0, GPIOD_OUT_LOW); +	if (IS_ERR(chost->clk)) +		return PTR_ERR(chost->clk); +	chost->dat = devm_gpiod_get_index(&pdev->dev, NULL, 1, GPIOD_IN); +	if (IS_ERR(chost->dat)) +		return PTR_ERR(chost->dat); +	chost->sel = devm_gpiod_get_index(&pdev->dev, NULL, 2, GPIOD_OUT_HIGH); +	if (IS_ERR(chost->sel)) +		return PTR_ERR(chost->sel); +	gpiod_set_consumer_name(chost->clk, "CBUS clk"); +	gpiod_set_consumer_name(chost->dat, "CBUS dat"); +	gpiod_set_consumer_name(chost->sel, "CBUS sel");  	adapter->owner		= THIS_MODULE;  	adapter->class		= I2C_CLASS_HWMON; @@ -254,21 +249,6 @@ static int cbus_i2c_probe(struct platform_device *pdev)  	spin_lock_init(&chost->lock);  	chost->dev = &pdev->dev; -	ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio, -				    GPIOF_OUT_INIT_LOW, "CBUS clk"); -	if (ret) -		return ret; - -	ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN, -				    "CBUS data"); -	if (ret) -		return ret; - -	ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio, -				    GPIOF_OUT_INIT_HIGH, "CBUS sel"); -	if (ret) -		return ret; -  	i2c_set_adapdata(adapter, chost);  	platform_set_drvdata(pdev, adapter); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index b4a0b2b99a78..6b4ef1d38fb2 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -215,6 +215,7 @@   * @disable_int: function to disable all interrupts   * @init: function to initialize the I2C hardware   * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE + * @suspended: set to true if the controller is suspended   *   * HCNT and LCNT parameters can be used if the platform knows more accurate   * values than the one computed based only on the input clock frequency. @@ -270,6 +271,7 @@ struct dw_i2c_dev {  	int			(*set_sda_hold_time)(struct dw_i2c_dev *dev);  	int			mode;  	struct i2c_bus_recovery_info rinfo; +	bool			suspended;  };  #define ACCESS_SWAP		0x00000001 diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 8d1bc44d2530..bb8e3f149979 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -426,6 +426,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  	pm_runtime_get_sync(dev->dev); +	if (dev->suspended) { +		dev_err(dev->dev, "Error %s call while suspended\n", __func__); +		ret = -ESHUTDOWN; +		goto done_nolock; +	} +  	reinit_completion(&dev->cmd_complete);  	dev->msgs = msgs;  	dev->msgs_num = num; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index d50f80487214..76810deb2de6 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -176,6 +176,7 @@ static int i2c_dw_pci_suspend(struct device *dev)  	struct pci_dev *pdev = to_pci_dev(dev);  	struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev); +	i_dev->suspended = true;  	i_dev->disable(i_dev);  	return 0; @@ -185,8 +186,12 @@ static int i2c_dw_pci_resume(struct device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	struct dw_i2c_dev *i_dev = pci_get_drvdata(pdev); +	int ret; -	return i_dev->init(i_dev); +	ret = i_dev->init(i_dev); +	i_dev->suspended = false; + +	return ret;  }  #endif diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 9eaac3be1f63..416f89b8f881 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -86,7 +86,6 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)  	struct i2c_timings *t = &dev->timings;  	u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0; -	dev->adapter.nr = -1;  	dev->tx_fifo_depth = 32;  	dev->rx_fifo_depth = 32; @@ -219,7 +218,7 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)  	dev->mode = DW_IC_SLAVE;  } -static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id) +static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev)  {  	u32 param, tx_fifo_depth, rx_fifo_depth; @@ -233,7 +232,6 @@ static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)  	if (!dev->tx_fifo_depth) {  		dev->tx_fifo_depth = tx_fifo_depth;  		dev->rx_fifo_depth = rx_fifo_depth; -		dev->adapter.nr = id;  	} else if (tx_fifo_depth >= 2) {  		dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,  				tx_fifo_depth); @@ -358,13 +356,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  				div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);  	} -	dw_i2c_set_fifo_size(dev, pdev->id); +	dw_i2c_set_fifo_size(dev);  	adap = &dev->adapter;  	adap->owner = THIS_MODULE;  	adap->class = I2C_CLASS_DEPRECATED;  	ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));  	adap->dev.of_node = pdev->dev.of_node; +	adap->nr = -1;  	dev_pm_set_driver_flags(&pdev->dev,  				DPM_FLAG_SMART_PREPARE | @@ -454,6 +453,8 @@ static int dw_i2c_plat_suspend(struct device *dev)  {  	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); +	i_dev->suspended = true; +  	if (i_dev->shared_with_punit)  		return 0; @@ -471,6 +472,7 @@ static int dw_i2c_plat_resume(struct device *dev)  		i2c_dw_prepare_clk(i_dev, true);  	i_dev->init(i_dev); +	i_dev->suspended = false;  	return 0;  } diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 835d54ac2971..231675b10376 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -177,7 +177,6 @@ static wait_queue_head_t pch_event;  static DEFINE_MUTEX(pch_mutex);  /* Definition for ML7213 by LAPIS Semiconductor */ -#define PCI_VENDOR_ID_ROHM		0x10DB  #define PCI_DEVICE_ID_ML7213_I2C	0x802D  #define PCI_DEVICE_ID_ML7223_I2C	0x8010  #define PCI_DEVICE_ID_ML7831_I2C	0x8817 diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index c1ce2299a76e..41de4ee409b6 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -183,7 +183,6 @@ enum i2c_type_exynos {  struct exynos5_i2c {  	struct i2c_adapter	adap; -	unsigned int		suspended:1;  	struct i2c_msg		*msg;  	struct completion	msg_complete; @@ -715,11 +714,6 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,  	struct exynos5_i2c *i2c = adap->algo_data;  	int i, ret; -	if (i2c->suspended) { -		dev_err(i2c->dev, "HS-I2C is not initialized.\n"); -		return -EIO; -	} -  	ret = clk_enable(i2c->clk);  	if (ret)  		return ret; @@ -847,8 +841,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev)  {  	struct exynos5_i2c *i2c = dev_get_drvdata(dev); -	i2c->suspended = 1; - +	i2c_mark_adapter_suspended(&i2c->adap);  	clk_unprepare(i2c->clk);  	return 0; @@ -871,7 +864,7 @@ static int exynos5_i2c_resume_noirq(struct device *dev)  	exynos5_i2c_init(i2c);  	clk_disable(i2c->clk); -	i2c->suspended = 0; +	i2c_mark_adapter_resumed(&i2c->adap);  	return 0;  } diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index c008d209f0b8..bba5c4627de3 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -7,17 +7,19 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   */ +#include <linux/completion.h>  #include <linux/debugfs.h>  #include <linux/delay.h> -#include <linux/i2c.h> +#include <linux/gpio/consumer.h>  #include <linux/i2c-algo-bit.h> -#include <linux/platform_data/i2c-gpio.h> +#include <linux/i2c.h>  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/gpio/consumer.h>  #include <linux/of.h> +#include <linux/platform_data/i2c-gpio.h> +#include <linux/platform_device.h> +#include <linux/slab.h>  struct i2c_gpio_private_data {  	struct gpio_desc *sda; @@ -27,6 +29,9 @@ struct i2c_gpio_private_data {  	struct i2c_gpio_platform_data pdata;  #ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR  	struct dentry *debug_dir; +	/* these must be protected by bus lock */ +	struct completion scl_irq_completion; +	u64 scl_irq_data;  #endif  }; @@ -162,6 +167,96 @@ static int fops_incomplete_write_byte_set(void *data, u64 addr)  }  DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_write_byte, NULL, fops_incomplete_write_byte_set, "%llu\n"); +static int i2c_gpio_fi_act_on_scl_irq(struct i2c_gpio_private_data *priv, +				       irqreturn_t handler(int, void*)) +{ +	int ret, irq = gpiod_to_irq(priv->scl); + +	if (irq < 0) +		return irq; + +	i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); + +	ret = gpiod_direction_input(priv->scl); +	if (ret) +		goto unlock; + +	reinit_completion(&priv->scl_irq_completion); + +	ret = request_irq(irq, handler, IRQF_TRIGGER_FALLING, +			  "i2c_gpio_fault_injector_scl_irq", priv); +	if (ret) +		goto output; + +	wait_for_completion_interruptible(&priv->scl_irq_completion); + +	free_irq(irq, priv); + output: +	ret = gpiod_direction_output(priv->scl, 1) ?: ret; + unlock: +	i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); + +	return ret; +} + +static irqreturn_t lose_arbitration_irq(int irq, void *dev_id) +{ +	struct i2c_gpio_private_data *priv = dev_id; + +	setsda(&priv->bit_data, 0); +	udelay(priv->scl_irq_data); +	setsda(&priv->bit_data, 1); + +	complete(&priv->scl_irq_completion); + +	return IRQ_HANDLED; +} + +static int fops_lose_arbitration_set(void *data, u64 duration) +{ +	struct i2c_gpio_private_data *priv = data; + +	if (duration > 100 * 1000) +		return -EINVAL; + +	priv->scl_irq_data = duration; +	/* +	 * Interrupt on falling SCL. This ensures that the master under test has +	 * really started the transfer. Interrupt on falling SDA did only +	 * exercise 'bus busy' detection on some HW but not 'arbitration lost'. +	 * Note that the interrupt latency may cause the first bits to be +	 * transmitted correctly. +	 */ +	return i2c_gpio_fi_act_on_scl_irq(priv, lose_arbitration_irq); +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_lose_arbitration, NULL, fops_lose_arbitration_set, "%llu\n"); + +static irqreturn_t inject_panic_irq(int irq, void *dev_id) +{ +	struct i2c_gpio_private_data *priv = dev_id; + +	udelay(priv->scl_irq_data); +	panic("I2C fault injector induced panic"); + +	return IRQ_HANDLED; +} + +static int fops_inject_panic_set(void *data, u64 duration) +{ +	struct i2c_gpio_private_data *priv = data; + +	if (duration > 100 * 1000) +		return -EINVAL; + +	priv->scl_irq_data = duration; +	/* +	 * Interrupt on falling SCL. This ensures that the master under test has +	 * really started the transfer. +	 */ +	return i2c_gpio_fi_act_on_scl_irq(priv, inject_panic_irq); +} +DEFINE_DEBUGFS_ATTRIBUTE(fops_inject_panic, NULL, fops_inject_panic_set, "%llu\n"); +  static void i2c_gpio_fault_injector_init(struct platform_device *pdev)  {  	struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev); @@ -181,12 +276,20 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)  	if (!priv->debug_dir)  		return; -	debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl); -	debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda); +	init_completion(&priv->scl_irq_completion); +  	debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir,  				   priv, &fops_incomplete_addr_phase);  	debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir,  				   priv, &fops_incomplete_write_byte); +	if (priv->bit_data.getscl) { +		debugfs_create_file_unsafe("inject_panic", 0200, priv->debug_dir, +					   priv, &fops_inject_panic); +		debugfs_create_file_unsafe("lose_arbitration", 0200, priv->debug_dir, +					   priv, &fops_lose_arbitration); +	} +	debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl); +	debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);  }  static void i2c_gpio_fault_injector_exit(struct platform_device *pdev) @@ -286,11 +389,11 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	/*  	 * First get the GPIO pins; if it fails, we'll defer the probe. -	 * If the SDA line is marked from platform data or device tree as -	 * "open drain" it means something outside of our control is making -	 * this line being handled as open drain, and we should just handle -	 * it as any other output. Else we enforce open drain as this is -	 * required for an I2C bus. +	 * If the SCL/SDA lines are marked "open drain" by platform data or +	 * device tree then this means that something outside of our control is +	 * marking these lines to be handled as open drain, and we should just +	 * handle them as we handle any other output. Else we enforce open +	 * drain as this is required for an I2C bus.  	 */  	if (pdata->sda_is_open_drain)  		gflags = GPIOD_OUT_HIGH; @@ -300,13 +403,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	if (IS_ERR(priv->sda))  		return PTR_ERR(priv->sda); -	/* -	 * If the SCL line is marked from platform data or device tree as -	 * "open drain" it means something outside of our control is making -	 * this line being handled as open drain, and we should just handle -	 * it as any other output. Else we enforce open drain as this is -	 * required for an I2C bus. -	 */  	if (pdata->scl_is_open_drain)  		gflags = GPIOD_OUT_HIGH;  	else diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c91e145ef5a5..679c6c41f64b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -71,6 +71,7 @@   * Cannon Lake-LP (PCH)		0x9da3	32	hard	yes	yes	yes   * Cedar Fork (PCH)		0x18df	32	hard	yes	yes	yes   * Ice Lake-LP (PCH)		0x34a3	32	hard	yes	yes	yes + * Comet Lake (PCH)		0x02a3	32	hard	yes	yes	yes   *   * Features supported by this driver:   * Software PEC				no @@ -240,6 +241,7 @@  #define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS	0xa223  #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS	0xa2a3  #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS		0xa323 +#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS		0x02a3  struct i801_mux_config {  	char *gpio_chip; @@ -1038,6 +1040,7 @@ static const struct pci_device_id i801_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) },  	{ 0, }  }; @@ -1534,6 +1537,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  	case PCI_DEVICE_ID_INTEL_DNV_SMBUS:  	case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:  	case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: +	case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS:  		priv->features |= FEATURE_I2C_BLOCK_READ;  		priv->features |= FEATURE_IRQ;  		priv->features |= FEATURE_SMBUS_PEC; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index fa9ad53845d9..42fed40198a0 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,  }  /* Functions for DMA support */ -static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, -						dma_addr_t phy_addr) +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, +			       dma_addr_t phy_addr)  {  	struct imx_i2c_dma *dma;  	struct dma_slave_config dma_sconfig; @@ -283,11 +283,13 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,  	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);  	if (!dma) -		return; +		return -ENOMEM; -	dma->chan_tx = dma_request_slave_channel(dev, "tx"); -	if (!dma->chan_tx) { -		dev_dbg(dev, "can't request DMA tx channel\n"); +	dma->chan_tx = dma_request_chan(dev, "tx"); +	if (IS_ERR(dma->chan_tx)) { +		ret = PTR_ERR(dma->chan_tx); +		if (ret != -ENODEV && ret != -EPROBE_DEFER) +			dev_err(dev, "can't request DMA tx channel (%d)\n", ret);  		goto fail_al;  	} @@ -298,13 +300,15 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,  	dma_sconfig.direction = DMA_MEM_TO_DEV;  	ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig);  	if (ret < 0) { -		dev_dbg(dev, "can't configure tx channel\n"); +		dev_err(dev, "can't configure tx channel (%d)\n", ret);  		goto fail_tx;  	} -	dma->chan_rx = dma_request_slave_channel(dev, "rx"); -	if (!dma->chan_rx) { -		dev_dbg(dev, "can't request DMA rx channel\n"); +	dma->chan_rx = dma_request_chan(dev, "rx"); +	if (IS_ERR(dma->chan_rx)) { +		ret = PTR_ERR(dma->chan_rx); +		if (ret != -ENODEV && ret != -EPROBE_DEFER) +			dev_err(dev, "can't request DMA rx channel (%d)\n", ret);  		goto fail_tx;  	} @@ -315,7 +319,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,  	dma_sconfig.direction = DMA_DEV_TO_MEM;  	ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig);  	if (ret < 0) { -		dev_dbg(dev, "can't configure rx channel\n"); +		dev_err(dev, "can't configure rx channel (%d)\n", ret);  		goto fail_rx;  	} @@ -324,7 +328,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,  	dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",  		dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx)); -	return; +	return 0;  fail_rx:  	dma_release_channel(dma->chan_rx); @@ -332,7 +336,8 @@ fail_tx:  	dma_release_channel(dma->chan_tx);  fail_al:  	devm_kfree(dev, dma); -	dev_info(dev, "can't use DMA, using PIO instead.\n"); +	/* return successfully if there is no dma support */ +	return ret == -ENODEV ? 0 : ret;  }  static void i2c_imx_dma_callback(void *arg) @@ -1160,11 +1165,13 @@ static int i2c_imx_probe(struct platform_device *pdev)  	dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);  	dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",  		i2c_imx->adapter.name); -	dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");  	/* Init DMA config if supported */ -	i2c_imx_dma_request(i2c_imx, phy_addr); +	ret = i2c_imx_dma_request(i2c_imx, phy_addr); +	if (ret < 0) +		goto clk_notifier_unregister; +	dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");  	return 0;   /* Return OK */  clk_notifier_unregister: diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 85cbe4b55578..a34cb3848280 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -471,6 +471,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)  	new_adapter->owner = THIS_MODULE;  	new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;  	new_adapter->dev.parent = &pdev->dev; +	new_adapter->dev.of_node = pdev->dev.of_node;  	new_adapter->nr = pdev->id;  	/* @@ -508,12 +509,19 @@ out:  	return ret;  } +static const struct of_device_id i2c_iop3xx_match[] = { +	{ .compatible = "intel,iop3xx-i2c", }, +	{ .compatible = "intel,ixp4xx-i2c", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, i2c_iop3xx_match);  static struct platform_driver iop3xx_i2c_driver = {  	.probe		= iop3xx_i2c_probe,  	.remove		= iop3xx_i2c_remove,  	.driver		= {  		.name	= "IOP3xx-I2C", +		.of_match_table = i2c_iop3xx_match,  	},  }; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index a74ef76705e0..684d651612b3 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -456,7 +456,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  	control_reg = readw(i2c->base + OFFSET_CONTROL) &  			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); -	if ((i2c->speed_hz > 400000) || (left_num >= 1)) +	if ((i2c->speed_hz > MAX_FS_MODE_SPEED) || (left_num >= 1))  		control_reg |= I2C_CONTROL_RS;  	if (i2c->op == I2C_MASTER_WRRD) @@ -465,7 +465,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  	writew(control_reg, i2c->base + OFFSET_CONTROL);  	/* set start condition */ -	if (i2c->speed_hz <= 100000) +	if (i2c->speed_hz <= I2C_DEFAULT_SPEED)  		writew(I2C_ST_START_CON, i2c->base + OFFSET_EXT_CONF);  	else  		writew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF); @@ -503,7 +503,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  		writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);  		writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON); -		dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 0); +		dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);  		if (!dma_rd_buf)  			return -ENOMEM; @@ -526,7 +526,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  		writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);  		writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON); -		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0); +		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);  		if (!dma_wr_buf)  			return -ENOMEM; @@ -549,7 +549,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  		writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);  		writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON); -		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0); +		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);  		if (!dma_wr_buf)  			return -ENOMEM; @@ -561,7 +561,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  			return -ENOMEM;  		} -		dma_rd_buf = i2c_get_dma_safe_msg_buf((msgs + 1), 0); +		dma_rd_buf = i2c_get_dma_safe_msg_buf((msgs + 1), 1);  		if (!dma_rd_buf) {  			dma_unmap_single(i2c->dev, wpaddr,  					 msgs->len, DMA_TO_DEVICE); @@ -642,8 +642,6 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,  		return -ETIMEDOUT;  	} -	completion_done(&i2c->msg_complete); -  	if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) {  		dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr);  		mtk_i2c_init_hw(i2c); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 87f9caacba85..4e1a077fb688 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * i2c-ocores.c: I2C bus driver for OpenCores I2C controller   * (https://opencores.org/project/i2c/overview) @@ -6,13 +7,10 @@   *   * Support for the GRLIB port of the controller by   * Andreas Larsson <andreas@gaisler.com> - * - * This file is licensed under the terms of the GNU General Public License - * version 2.  This program is licensed "as is" without any warranty of any - * kind, whether express or implied.   */  #include <linux/clk.h> +#include <linux/delay.h>  #include <linux/err.h>  #include <linux/kernel.h>  #include <linux/module.h> @@ -25,17 +23,28 @@  #include <linux/slab.h>  #include <linux/io.h>  #include <linux/log2.h> +#include <linux/spinlock.h> +#include <linux/jiffies.h> + +#define OCORES_FLAG_POLL BIT(0) +/* + * 'process_lock' exists because ocores_process() and ocores_process_timeout() + * can't run in parallel. + */  struct ocores_i2c {  	void __iomem *base; +	int iobase;  	u32 reg_shift;  	u32 reg_io_width; +	unsigned long flags;  	wait_queue_head_t wait;  	struct i2c_adapter adap;  	struct i2c_msg *msg;  	int pos;  	int nmsgs;  	int state; /* see STATE_ */ +	spinlock_t process_lock;  	struct clk *clk;  	int ip_clock_khz;  	int bus_clock_khz; @@ -127,6 +136,16 @@ static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg)  	return ioread32be(i2c->base + (reg << i2c->reg_shift));  } +static void oc_setreg_io_8(struct ocores_i2c *i2c, int reg, u8 value) +{ +	outb(value, i2c->iobase + reg); +} + +static inline u8 oc_getreg_io_8(struct ocores_i2c *i2c, int reg) +{ +	return inb(i2c->iobase + reg); +} +  static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)  {  	i2c->setreg(i2c, reg, value); @@ -137,23 +156,29 @@ static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)  	return i2c->getreg(i2c, reg);  } -static void ocores_process(struct ocores_i2c *i2c) +static void ocores_process(struct ocores_i2c *i2c, u8 stat)  {  	struct i2c_msg *msg = i2c->msg; -	u8 stat = oc_getreg(i2c, OCI2C_STATUS); +	unsigned long flags; + +	/* +	 * If we spin here is because we are in timeout, so we are going +	 * to be in STATE_ERROR. See ocores_process_timeout() +	 */ +	spin_lock_irqsave(&i2c->process_lock, flags);  	if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {  		/* stop has been sent */  		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);  		wake_up(&i2c->wait); -		return; +		goto out;  	}  	/* error? */  	if (stat & OCI2C_STAT_ARBLOST) {  		i2c->state = STATE_ERROR;  		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); -		return; +		goto out;  	}  	if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { @@ -163,10 +188,11 @@ static void ocores_process(struct ocores_i2c *i2c)  		if (stat & OCI2C_STAT_NACK) {  			i2c->state = STATE_ERROR;  			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); -			return; +			goto out;  		} -	} else +	} else {  		msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); +	}  	/* end of msg? */  	if (i2c->pos == msg->len) { @@ -183,15 +209,15 @@ static void ocores_process(struct ocores_i2c *i2c)  				i2c->state = STATE_START;  				oc_setreg(i2c, OCI2C_DATA, addr); -				oc_setreg(i2c, OCI2C_CMD,  OCI2C_CMD_START); -				return; -			} else -				i2c->state = (msg->flags & I2C_M_RD) -					? STATE_READ : STATE_WRITE; +				oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); +				goto out; +			} +			i2c->state = (msg->flags & I2C_M_RD) +				? STATE_READ : STATE_WRITE;  		} else {  			i2c->state = STATE_DONE;  			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); -			return; +			goto out;  		}  	} @@ -202,20 +228,148 @@ static void ocores_process(struct ocores_i2c *i2c)  		oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);  		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);  	} + +out: +	spin_unlock_irqrestore(&i2c->process_lock, flags);  }  static irqreturn_t ocores_isr(int irq, void *dev_id)  {  	struct ocores_i2c *i2c = dev_id; +	u8 stat = oc_getreg(i2c, OCI2C_STATUS); + +	if (!(stat & OCI2C_STAT_IF)) +		return IRQ_NONE; -	ocores_process(i2c); +	ocores_process(i2c, stat);  	return IRQ_HANDLED;  } -static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +/** + * Process timeout event + * @i2c: ocores I2C device instance + */ +static void ocores_process_timeout(struct ocores_i2c *i2c)  { -	struct ocores_i2c *i2c = i2c_get_adapdata(adap); +	unsigned long flags; + +	spin_lock_irqsave(&i2c->process_lock, flags); +	i2c->state = STATE_ERROR; +	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); +	spin_unlock_irqrestore(&i2c->process_lock, flags); +} + +/** + * Wait until something change in a given register + * @i2c: ocores I2C device instance + * @reg: register to query + * @mask: bitmask to apply on register value + * @val: expected result + * @timeout: timeout in jiffies + * + * Timeout is necessary to avoid to stay here forever when the chip + * does not answer correctly. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_wait(struct ocores_i2c *i2c, +		       int reg, u8 mask, u8 val, +		       const unsigned long timeout) +{ +	unsigned long j; + +	j = jiffies + timeout; +	while (1) { +		u8 status = oc_getreg(i2c, reg); + +		if ((status & mask) == val) +			break; + +		if (time_after(jiffies, j)) +			return -ETIMEDOUT; +	} +	return 0; +} + +/** + * Wait until is possible to process some data + * @i2c: ocores I2C device instance + * + * Used when the device is in polling mode (interrupts disabled). + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +static int ocores_poll_wait(struct ocores_i2c *i2c) +{ +	u8 mask; +	int err; + +	if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) { +		/* transfer is over */ +		mask = OCI2C_STAT_BUSY; +	} else { +		/* on going transfer */ +		mask = OCI2C_STAT_TIP; +		/* +		 * We wait for the data to be transferred (8bit), +		 * then we start polling on the ACK/NACK bit +		 */ +		udelay((8 * 1000) / i2c->bus_clock_khz); +	} + +	/* +	 * once we are here we expect to get the expected result immediately +	 * so if after 1ms we timeout then something is broken. +	 */ +	err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(1)); +	if (err) +		dev_warn(i2c->adap.dev.parent, +			 "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n", +			 __func__, mask); +	return err; +} + +/** + * It handles an IRQ-less transfer + * @i2c: ocores I2C device instance + * + * Even if IRQ are disabled, the I2C OpenCore IP behavior is exactly the same + * (only that IRQ are not produced). This means that we can re-use entirely + * ocores_isr(), we just add our polling code around it. + * + * It can run in atomic context + */ +static void ocores_process_polling(struct ocores_i2c *i2c) +{ +	while (1) { +		irqreturn_t ret; +		int err; + +		err = ocores_poll_wait(i2c); +		if (err) { +			i2c->state = STATE_ERROR; +			break; /* timeout */ +		} + +		ret = ocores_isr(-1, i2c); +		if (ret == IRQ_NONE) +			break; /* all messages have been transferred */ +	} +} + +static int ocores_xfer_core(struct ocores_i2c *i2c, +			    struct i2c_msg *msgs, int num, +			    bool polling) +{ +	int ret; +	u8 ctrl; + +	ctrl = oc_getreg(i2c, OCI2C_CONTROL); +	if (polling) +		oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~OCI2C_CTRL_IEN); +	else +		oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN);  	i2c->msg = msgs;  	i2c->pos = 0; @@ -225,11 +379,35 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg));  	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); -	if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || -			       (i2c->state == STATE_DONE), HZ)) -		return (i2c->state == STATE_DONE) ? num : -EIO; -	else -		return -ETIMEDOUT; +	if (polling) { +		ocores_process_polling(i2c); +	} else { +		ret = wait_event_timeout(i2c->wait, +					 (i2c->state == STATE_ERROR) || +					 (i2c->state == STATE_DONE), HZ); +		if (ret == 0) { +			ocores_process_timeout(i2c); +			return -ETIMEDOUT; +		} +	} + +	return (i2c->state == STATE_DONE) ? num : -EIO; +} + +static int ocores_xfer_polling(struct i2c_adapter *adap, +			       struct i2c_msg *msgs, int num) +{ +	return ocores_xfer_core(i2c_get_adapdata(adap), msgs, num, true); +} + +static int ocores_xfer(struct i2c_adapter *adap, +		       struct i2c_msg *msgs, int num) +{ +	struct ocores_i2c *i2c = i2c_get_adapdata(adap); + +	if (i2c->flags & OCORES_FLAG_POLL) +		return ocores_xfer_polling(adap, msgs, num); +	return ocores_xfer_core(i2c, msgs, num, false);  }  static int ocores_init(struct device *dev, struct ocores_i2c *i2c) @@ -239,7 +417,8 @@ static int ocores_init(struct device *dev, struct ocores_i2c *i2c)  	u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);  	/* make sure the device is disabled */ -	oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); +	ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); +	oc_setreg(i2c, OCI2C_CONTROL, ctrl);  	prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1;  	prescale = clamp(prescale, 0, 0xffff); @@ -257,7 +436,7 @@ static int ocores_init(struct device *dev, struct ocores_i2c *i2c)  	/* Init the device */  	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); -	oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); +	oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN);  	return 0;  } @@ -294,13 +473,16 @@ static const struct of_device_id ocores_i2c_match[] = {  MODULE_DEVICE_TABLE(of, ocores_i2c_match);  #ifdef CONFIG_OF -/* Read and write functions for the GRLIB port of the controller. Registers are +/* + * Read and write functions for the GRLIB port of the controller. Registers are   * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one - * register. The subsequent registers has their offset decreased accordingly. */ + * register. The subsequent registers have their offsets decreased accordingly. + */  static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)  {  	u32 rd;  	int rreg = reg; +  	if (reg != OCI2C_PRELOW)  		rreg--;  	rd = ioread32be(i2c->base + (rreg << i2c->reg_shift)); @@ -314,6 +496,7 @@ static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)  {  	u32 curr, wr;  	int rreg = reg; +  	if (reg != OCI2C_PRELOW)  		rreg--;  	if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) { @@ -402,7 +585,7 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,  	return 0;  }  #else -#define ocores_i2c_of_probe(pdev,i2c) -ENODEV +#define ocores_i2c_of_probe(pdev, i2c) -ENODEV  #endif  static int ocores_i2c_probe(struct platform_device *pdev) @@ -414,25 +597,41 @@ static int ocores_i2c_probe(struct platform_device *pdev)  	int ret;  	int i; -	irq = platform_get_irq(pdev, 0); -	if (irq < 0) -		return irq; -  	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);  	if (!i2c)  		return -ENOMEM; +	spin_lock_init(&i2c->process_lock); +  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	i2c->base = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(i2c->base)) -		return PTR_ERR(i2c->base); +	if (res) { +		i2c->base = devm_ioremap_resource(&pdev->dev, res); +		if (IS_ERR(i2c->base)) +			return PTR_ERR(i2c->base); +	} else { +		res = platform_get_resource(pdev, IORESOURCE_IO, 0); +		if (!res) +			return -EINVAL; +		i2c->iobase = res->start; +		if (!devm_request_region(&pdev->dev, res->start, +					 resource_size(res), +					 pdev->name)) { +			dev_err(&pdev->dev, "Can't get I/O resource.\n"); +			return -EBUSY; +		} +		i2c->setreg = oc_setreg_io_8; +		i2c->getreg = oc_getreg_io_8; +	}  	pdata = dev_get_platdata(&pdev->dev);  	if (pdata) {  		i2c->reg_shift = pdata->reg_shift;  		i2c->reg_io_width = pdata->reg_io_width;  		i2c->ip_clock_khz = pdata->clock_khz; -		i2c->bus_clock_khz = 100; +		if (pdata->bus_khz) +			i2c->bus_clock_khz = pdata->bus_khz; +		else +			i2c->bus_clock_khz = 100;  	} else {  		ret = ocores_i2c_of_probe(pdev, i2c);  		if (ret) @@ -470,18 +669,29 @@ static int ocores_i2c_probe(struct platform_device *pdev)  		}  	} +	init_waitqueue_head(&i2c->wait); + +	irq = platform_get_irq(pdev, 0); +	if (irq == -ENXIO) { +		i2c->flags |= OCORES_FLAG_POLL; +	} else { +		if (irq < 0) +			return irq; +	} + +	if (!(i2c->flags & OCORES_FLAG_POLL)) { +		ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, +				       pdev->name, i2c); +		if (ret) { +			dev_err(&pdev->dev, "Cannot claim IRQ\n"); +			goto err_clk; +		} +	} +  	ret = ocores_init(&pdev->dev, i2c);  	if (ret)  		goto err_clk; -	init_waitqueue_head(&i2c->wait); -	ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0, -			       pdev->name, i2c); -	if (ret) { -		dev_err(&pdev->dev, "Cannot claim IRQ\n"); -		goto err_clk; -	} -  	/* hook up driver to tree */  	platform_set_drvdata(pdev, i2c);  	i2c->adap = ocores_adapter; @@ -510,10 +720,11 @@ err_clk:  static int ocores_i2c_remove(struct platform_device *pdev)  {  	struct ocores_i2c *i2c = platform_get_drvdata(pdev); +	u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);  	/* disable i2c logic */ -	oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL) -		  & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); +	ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); +	oc_setreg(i2c, OCI2C_CONTROL, ctrl);  	/* remove adapter & data */  	i2c_del_adapter(&i2c->adap); @@ -531,7 +742,8 @@ static int ocores_i2c_suspend(struct device *dev)  	u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);  	/* make sure the device is disabled */ -	oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); +	ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN); +	oc_setreg(i2c, OCI2C_CONTROL, ctrl);  	if (!IS_ERR(i2c->clk))  		clk_disable_unprepare(i2c->clk); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 254e6219e538..a7578f6da979 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -2,8 +2,8 @@  /*   * Driver for the Renesas R-Car I2C unit   * - * Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com> - * Copyright (C) 2011-2015 Renesas Electronics Corporation + * Copyright (C) 2014-19 Wolfram Sang <wsa@sang-engineering.com> + * Copyright (C) 2011-2019 Renesas Electronics Corporation   *   * Copyright (C) 2012-14 Renesas Solutions Corp.   * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> @@ -39,8 +39,8 @@  #define ICSAR	0x1C	/* slave address */  #define ICMAR	0x20	/* master address */  #define ICRXTX	0x24	/* data port */ -#define ICDMAER	0x3c	/* DMA enable */ -#define ICFBSCR	0x38	/* first bit setup cycle */ +#define ICFBSCR	0x38	/* first bit setup cycle (Gen3) */ +#define ICDMAER	0x3c	/* DMA enable (Gen3) */  /* ICSCR */  #define SDBS	(1 << 3)	/* slave data buffer select */ @@ -83,7 +83,6 @@  #define TMDMAE	(1 << 0)	/* DMA Master Transmitted Enable */  /* ICFBSCR */ -#define TCYC06	0x04		/*  6*Tcyc delay 1st bit between SDA and SCL */  #define TCYC17	0x0f		/* 17*Tcyc delay 1st bit between SDA and SCL */ @@ -212,6 +211,10 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)  	rcar_i2c_write(priv, ICMSR, 0);  	/* start clock */  	rcar_i2c_write(priv, ICCCR, priv->icccr); + +	if (priv->devtype == I2C_RCAR_GEN3) +		rcar_i2c_write(priv, ICFBSCR, TCYC17); +  }  static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) @@ -355,20 +358,11 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)  	rcar_i2c_prepare_msg(priv);  } -/* - *		interrupt functions - */  static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)  {  	struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE  		? priv->dma_rx : priv->dma_tx; -	/* Disable DMA Master Received/Transmitted */ -	rcar_i2c_write(priv, ICDMAER, 0); - -	/* Reset default delay */ -	rcar_i2c_write(priv, ICFBSCR, TCYC06); -  	dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),  			 sg_dma_len(&priv->sg), priv->dma_direction); @@ -378,6 +372,9 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)  		priv->flags |= ID_P_NO_RXDMA;  	priv->dma_direction = DMA_NONE; + +	/* Disable DMA Master Received/Transmitted, must be last! */ +	rcar_i2c_write(priv, ICDMAER, 0);  }  static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv) @@ -464,9 +461,6 @@ static void rcar_i2c_dma(struct rcar_i2c_priv *priv)  		return;  	} -	/* Set delay for DMA operations */ -	rcar_i2c_write(priv, ICFBSCR, TCYC17); -  	/* Enable DMA Master Received/Transmitted */  	if (read)  		rcar_i2c_write(priv, ICDMAER, RMDMAE); @@ -617,6 +611,15 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)  	return true;  } +/* + * This driver has a lock-free design because there are IP cores (at least + * R-Car Gen2) which have an inherent race condition in their hardware design. + * There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after + * the interrupt was generated, otherwise an unwanted repeated message gets + * generated. It turned out that taking a spinlock at the beginning of the ISR + * was already causing repeated messages. Thus, this driver was converted to + * the now lockless behaviour. Please keep this in mind when hacking the driver. + */  static irqreturn_t rcar_i2c_irq(int irq, void *ptr)  {  	struct rcar_i2c_priv *priv = ptr; @@ -1017,10 +1020,37 @@ static int rcar_i2c_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_PM_SLEEP +static int rcar_i2c_suspend(struct device *dev) +{ +	struct rcar_i2c_priv *priv = dev_get_drvdata(dev); + +	i2c_mark_adapter_suspended(&priv->adap); +	return 0; +} + +static int rcar_i2c_resume(struct device *dev) +{ +	struct rcar_i2c_priv *priv = dev_get_drvdata(dev); + +	i2c_mark_adapter_resumed(&priv->adap); +	return 0; +} + +static const struct dev_pm_ops rcar_i2c_pm_ops = { +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rcar_i2c_suspend, rcar_i2c_resume) +}; + +#define DEV_PM_OPS (&rcar_i2c_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ +  static struct platform_driver rcar_i2c_driver = {  	.driver	= {  		.name	= "i2c-rcar",  		.of_match_table = rcar_i2c_dt_ids, +		.pm	= DEV_PM_OPS,  	},  	.probe		= rcar_i2c_probe,  	.remove		= rcar_i2c_remove, diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 2f2e28d60ef5..53bc021f4a5a 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -104,7 +104,6 @@ enum s3c24xx_i2c_state {  struct s3c24xx_i2c {  	wait_queue_head_t	wait;  	kernel_ulong_t		quirks; -	unsigned int		suspended:1;  	struct i2c_msg		*msg;  	unsigned int		msg_num; @@ -703,9 +702,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,  	unsigned long timeout;  	int ret; -	if (i2c->suspended) -		return -EIO; -  	ret = s3c24xx_i2c_set_master(i2c);  	if (ret != 0) {  		dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); @@ -1246,7 +1242,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev)  {  	struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); -	i2c->suspended = 1; +	i2c_mark_adapter_suspended(&i2c->adap);  	if (!IS_ERR(i2c->sysreg))  		regmap_read(i2c->sysreg, EXYNOS5_SYS_I2C_CFG, &i2c->sys_i2c_cfg); @@ -1267,7 +1263,7 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev)  		return ret;  	s3c24xx_i2c_init(i2c);  	clk_disable(i2c->clk); -	i2c->suspended = 0; +	i2c_mark_adapter_resumed(&i2c->adap);  	return 0;  } diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index a64f2ff3cb49..8777af4c695e 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -2,8 +2,7 @@  /*   * SuperH Mobile I2C Controller   * - * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com> - * + * Copyright (C) 2014-19 Wolfram Sang <wsa@sang-engineering.com>   * Copyright (C) 2008 Magnus Damm   *   * Portions of the code based on out-of-tree driver i2c-sh7343.c @@ -303,13 +302,12 @@ static int sh_mobile_i2c_v2_init(struct sh_mobile_i2c_data *pd)  	return sh_mobile_i2c_check_timing(pd);  } -static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, -			    enum sh_mobile_i2c_op op, unsigned char data) +static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op op)  {  	unsigned char ret = 0;  	unsigned long flags; -	dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data); +	dev_dbg(pd->dev, "op %d\n", op);  	spin_lock_irqsave(&pd->lock, flags); @@ -317,12 +315,12 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,  	case OP_START: /* issue start and trigger DTE interrupt */  		iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY);  		break; -	case OP_TX_FIRST: /* disable DTE interrupt and write data */ +	case OP_TX_FIRST: /* disable DTE interrupt and write client address */  		iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); -		iic_wr(pd, ICDR, data); +		iic_wr(pd, ICDR, i2c_8bit_addr_from_msg(pd->msg));  		break;  	case OP_TX: /* write data */ -		iic_wr(pd, ICDR, data); +		iic_wr(pd, ICDR, pd->msg->buf[pd->pos]);  		break;  	case OP_TX_STOP: /* issue a stop (or rep_start) */  		iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS @@ -353,34 +351,17 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,  	return ret;  } -static bool sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd) -{ -	return pd->pos == -1; -} - -static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, -				   unsigned char *buf) -{ -	switch (pd->pos) { -	case -1: -		*buf = i2c_8bit_addr_from_msg(pd->msg); -		break; -	default: -		*buf = pd->msg->buf[pd->pos]; -	} -} -  static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd)  { -	unsigned char data; -  	if (pd->pos == pd->msg->len) { -		i2c_op(pd, OP_TX_STOP, 0); +		i2c_op(pd, OP_TX_STOP);  		return 1;  	} -	sh_mobile_i2c_get_data(pd, &data); -	i2c_op(pd, sh_mobile_i2c_is_first_byte(pd) ? OP_TX_FIRST : OP_TX, data); +	if (pd->pos == -1) +		i2c_op(pd, OP_TX_FIRST); +	else +		i2c_op(pd, OP_TX);  	pd->pos++;  	return 0; @@ -391,45 +372,32 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd)  	unsigned char data;  	int real_pos; -	do { -		if (pd->pos <= -1) { -			sh_mobile_i2c_get_data(pd, &data); - -			if (sh_mobile_i2c_is_first_byte(pd)) -				i2c_op(pd, OP_TX_FIRST, data); -			else -				i2c_op(pd, OP_TX, data); -			break; -		} - -		if (pd->pos == 0) { -			i2c_op(pd, OP_TX_TO_RX, 0); -			break; -		} - -		real_pos = pd->pos - 2; - -		if (pd->pos == pd->msg->len) { -			if (pd->stop_after_dma) { -				/* Simulate PIO end condition after DMA transfer */ -				i2c_op(pd, OP_RX_STOP, 0); -				pd->pos++; -				break; -			} - -			if (real_pos < 0) { -				i2c_op(pd, OP_RX_STOP, 0); -				break; -			} -			data = i2c_op(pd, OP_RX_STOP_DATA, 0); -		} else if (real_pos >= 0) { -			data = i2c_op(pd, OP_RX, 0); +	/* switch from TX (address) to RX (data) adds two interrupts */ +	real_pos = pd->pos - 2; + +	if (pd->pos == -1) { +		i2c_op(pd, OP_TX_FIRST); +	} else if (pd->pos == 0) { +		i2c_op(pd, OP_TX_TO_RX); +	} else if (pd->pos == pd->msg->len) { +		if (pd->stop_after_dma) { +			/* Simulate PIO end condition after DMA transfer */ +			i2c_op(pd, OP_RX_STOP); +			pd->pos++; +			goto done;  		} -		if (real_pos >= 0) -			pd->msg->buf[real_pos] = data; -	} while (0); +		if (real_pos < 0) +			i2c_op(pd, OP_RX_STOP); +		else +			data = i2c_op(pd, OP_RX_STOP_DATA); +	} else if (real_pos >= 0) { +		data = i2c_op(pd, OP_RX); +	} +	if (real_pos >= 0) +		pd->msg->buf[real_pos] = data; + done:  	pd->pos++;  	return pd->pos == (pd->msg->len + 2);  } @@ -698,7 +666,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,  		start_ch(pd, msg, do_start);  		if (do_start) -			i2c_op(pd, OP_START, 0); +			i2c_op(pd, OP_START);  		/* The interrupt handler takes care of the rest... */  		timeout = wait_event_timeout(pd->wait, @@ -749,8 +717,7 @@ static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {  };  /* - * r8a7740 chip has lasting errata on I2C I/O pad reset. - * this is work-around for it. + * r8a7740 has an errata regarding I2C I/O pad reset needing this workaround.   */  static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd)  { @@ -802,15 +769,15 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = {  	{ .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },  	{ .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config },  	{ .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config }, -	{ .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config }, -	{ .compatible = "renesas,iic-r8a77990", .data = &fast_clock_dt_config }, +	{ .compatible = "renesas,iic-r8a7791", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,iic-r8a7792", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,iic-r8a7793", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,iic-r8a7794", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,iic-r8a7795", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,iic-r8a77990", .data = &v2_freq_calc_dt_config },  	{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config }, +	{ .compatible = "renesas,rcar-gen2-iic", .data = &v2_freq_calc_dt_config }, +	{ .compatible = "renesas,rcar-gen3-iic", .data = &v2_freq_calc_dt_config },  	{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config },  	{},  }; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 1e6805b5cef2..a57aa4fe51a4 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -478,7 +478,7 @@ static int sis630_setup(struct pci_dev *sis630_dev)  	if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,  			    sis630_driver.name)) {  		dev_err(&sis630_dev->dev, -			"I/O Region 0x%04hx-0x%04hx for SMBus already in use.\n", +			"I/O Region 0x%04x-0x%04x for SMBus already in use.\n",  			smbus_base + SMB_STS,  			smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);  		retval = -EBUSY; @@ -528,7 +528,7 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)  	sis630_adapter.dev.parent = &dev->dev;  	snprintf(sis630_adapter.name, sizeof(sis630_adapter.name), -		 "SMBus SIS630 adapter at %04hx", smbus_base + SMB_STS); +		 "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);  	return i2c_add_adapter(&sis630_adapter);  } diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index a94e724f51dc..961123529678 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -86,7 +86,6 @@ struct sprd_i2c {  	u32 count;  	int irq;  	int err; -	bool is_suspended;  };  static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count) @@ -284,9 +283,6 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,  	struct sprd_i2c *i2c_dev = i2c_adap->algo_data;  	int im, ret; -	if (i2c_dev->is_suspended) -		return -EBUSY; -  	ret = pm_runtime_get_sync(i2c_dev->dev);  	if (ret < 0)  		return ret; @@ -586,40 +582,34 @@ static int sprd_i2c_remove(struct platform_device *pdev)  	return 0;  } -static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev) +static int __maybe_unused sprd_i2c_suspend_noirq(struct device *dev)  { -	struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); - -	i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); -	i2c_dev->is_suspended = true; -	i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); +	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); -	return pm_runtime_force_suspend(pdev); +	i2c_mark_adapter_suspended(&i2c_dev->adap); +	return pm_runtime_force_suspend(dev);  } -static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev) +static int __maybe_unused sprd_i2c_resume_noirq(struct device *dev)  { -	struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); - -	i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); -	i2c_dev->is_suspended = false; -	i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); +	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); -	return pm_runtime_force_resume(pdev); +	i2c_mark_adapter_resumed(&i2c_dev->adap); +	return pm_runtime_force_resume(dev);  } -static int __maybe_unused sprd_i2c_runtime_suspend(struct device *pdev) +static int __maybe_unused sprd_i2c_runtime_suspend(struct device *dev)  { -	struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); +	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);  	clk_disable_unprepare(i2c_dev->clk);  	return 0;  } -static int __maybe_unused sprd_i2c_runtime_resume(struct device *pdev) +static int __maybe_unused sprd_i2c_runtime_resume(struct device *dev)  { -	struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); +	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);  	int ret;  	ret = clk_prepare_enable(i2c_dev->clk); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 13e1213561d4..4284fc991cfd 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -432,7 +432,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,  		 STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0);  	dnf_delay = setup->dnf * i2cclk; -	sdadel_min = setup->fall_time - i2c_specs[setup->speed].hddat_min - +	sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -  		af_delay_min - (setup->dnf + 3) * i2cclk;  	sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time - diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 2184b7c3580e..d18b0941b71a 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -144,8 +144,6 @@ struct synquacer_i2c {  	u32			timeout_ms;  	enum i2c_state		state;  	struct i2c_adapter	adapter; - -	bool			is_suspended;  };  static inline int is_lastmsg(struct synquacer_i2c *i2c) @@ -316,9 +314,6 @@ static int synquacer_i2c_doxfer(struct synquacer_i2c *i2c,  	unsigned long timeout;  	int ret; -	if (i2c->is_suspended) -		return -EBUSY; -  	synquacer_i2c_hw_init(i2c);  	bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);  	if (bsr & SYNQUACER_I2C_BSR_BB) { diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c77adbbea0c7..ebaa78d17d6e 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -6,26 +6,24 @@   * Author: Colin Cross <ccross@android.com>   */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h>  #include <linux/clk.h> +#include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h>  #include <linux/err.h>  #include <linux/i2c.h> -#include <linux/io.h> +#include <linux/init.h>  #include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/of_device.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/kernel.h>  #include <linux/module.h> -#include <linux/reset.h> +#include <linux/of_device.h>  #include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h>  #include <linux/pm_runtime.h> -#include <linux/iopoll.h> - -#include <asm/unaligned.h> +#include <linux/reset.h> -#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000))  #define BYTES_PER_FIFO_WORD 4  #define I2C_CNFG				0x000 @@ -45,8 +43,8 @@  #define I2C_FIFO_CONTROL			0x05c  #define I2C_FIFO_CONTROL_TX_FLUSH		BIT(1)  #define I2C_FIFO_CONTROL_RX_FLUSH		BIT(0) -#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT		5 -#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT		2 +#define I2C_FIFO_CONTROL_TX_TRIG(x)		(((x) - 1) << 5) +#define I2C_FIFO_CONTROL_RX_TRIG(x)		(((x) - 1) << 2)  #define I2C_FIFO_STATUS				0x060  #define I2C_FIFO_STATUS_TX_MASK			0xF0  #define I2C_FIFO_STATUS_TX_SHIFT		4 @@ -54,6 +52,7 @@  #define I2C_FIFO_STATUS_RX_SHIFT		0  #define I2C_INT_MASK				0x064  #define I2C_INT_STATUS				0x068 +#define I2C_INT_BUS_CLR_DONE			BIT(11)  #define I2C_INT_PACKET_XFER_COMPLETE		BIT(7)  #define I2C_INT_ALL_PACKETS_XFER_COMPLETE	BIT(6)  #define I2C_INT_TX_FIFO_OVERFLOW		BIT(5) @@ -96,6 +95,15 @@  #define I2C_HEADER_MASTER_ADDR_SHIFT		12  #define I2C_HEADER_SLAVE_ADDR_SHIFT		1 +#define I2C_BUS_CLEAR_CNFG			0x084 +#define I2C_BC_SCLK_THRESHOLD			9 +#define I2C_BC_SCLK_THRESHOLD_SHIFT		16 +#define I2C_BC_STOP_COND			BIT(2) +#define I2C_BC_TERMINATE			BIT(1) +#define I2C_BC_ENABLE				BIT(0) +#define I2C_BUS_CLEAR_STATUS			0x088 +#define I2C_BC_STATUS				BIT(0) +  #define I2C_CONFIG_LOAD				0x08C  #define I2C_MSTR_CONFIG_LOAD			BIT(0)  #define I2C_SLV_CONFIG_LOAD			BIT(1) @@ -118,6 +126,25 @@  #define I2C_MST_FIFO_STATUS_TX_MASK		0xff0000  #define I2C_MST_FIFO_STATUS_TX_SHIFT		16 +#define I2C_INTERFACE_TIMING_0			0x94 +#define I2C_THIGH_SHIFT				8 +#define I2C_INTERFACE_TIMING_1			0x98 + +#define I2C_STANDARD_MODE			100000 +#define I2C_FAST_MODE				400000 +#define I2C_FAST_PLUS_MODE			1000000 +#define I2C_HS_MODE				3500000 + +/* Packet header size in bytes */ +#define I2C_PACKET_HEADER_SIZE			12 + +/* + * Upto I2C_PIO_MODE_MAX_LEN bytes, controller will use PIO mode, + * above this, controller will use DMA to fill FIFO. + * MAX PIO len is 20 bytes excluding packet header. + */ +#define I2C_PIO_MODE_MAX_LEN			32 +  /*   * msg_end_type: The bus control which need to be send at end of transfer.   * @MSG_END_STOP: Send stop pulse at end of transfer. @@ -142,7 +169,10 @@ enum msg_end_type {   * @has_config_load_reg: Has the config load register to load the new   *		configuration.   * @clk_divisor_hs_mode: Clock divisor in HS mode. - * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is + * @clk_divisor_std_mode: Clock divisor in standard mode. It is + *		applicable if there is no fast clock source i.e. single clock + *		source. + * @clk_divisor_fast_mode: Clock divisor in fast mode. It is   *		applicable if there is no fast clock source i.e. single clock   *		source.   * @clk_divisor_fast_plus_mode: Clock divisor in fast mode plus. It is @@ -157,6 +187,21 @@ enum msg_end_type {   *		be transferred in one go.   * @quirks: i2c adapter quirks for limiting write/read transfer size and not   *		allowing 0 length transfers. + * @supports_bus_clear: Bus Clear support to recover from bus hang during + *		SDA stuck low from device for some unknown reasons. + * @has_apb_dma: Support of APBDMA on corresponding Tegra chip. + * @tlow_std_mode: Low period of the clock in standard mode. + * @thigh_std_mode: High period of the clock in standard mode. + * @tlow_fast_fastplus_mode: Low period of the clock in fast/fast-plus modes. + * @thigh_fast_fastplus_mode: High period of the clock in fast/fast-plus modes. + * @setup_hold_time_std_mode: Setup and hold time for start and stop conditions + *		in standard mode. + * @setup_hold_time_fast_fast_plus_mode: Setup and hold time for start and stop + *		conditions in fast/fast-plus modes. + * @setup_hold_time_hs_mode: Setup and hold time for start and stop conditions + *		in HS mode. + * @has_interface_timing_reg: Has interface timing register to program the tuned + *		timing settings.   */  struct tegra_i2c_hw_feature {  	bool has_continue_xfer_support; @@ -164,12 +209,23 @@ struct tegra_i2c_hw_feature {  	bool has_single_clk_source;  	bool has_config_load_reg;  	int clk_divisor_hs_mode; -	int clk_divisor_std_fast_mode; +	int clk_divisor_std_mode; +	int clk_divisor_fast_mode;  	u16 clk_divisor_fast_plus_mode;  	bool has_multi_master_mode;  	bool has_slcg_override_reg;  	bool has_mst_fifo;  	const struct i2c_adapter_quirks *quirks; +	bool supports_bus_clear; +	bool has_apb_dma; +	u8 tlow_std_mode; +	u8 thigh_std_mode; +	u8 tlow_fast_fastplus_mode; +	u8 thigh_fast_fastplus_mode; +	u32 setup_hold_time_std_mode; +	u32 setup_hold_time_fast_fast_plus_mode; +	u32 setup_hold_time_hs_mode; +	bool has_interface_timing_reg;  };  /** @@ -181,6 +237,7 @@ struct tegra_i2c_hw_feature {   * @fast_clk: clock reference for fast clock of I2C controller   * @rst: reset control for the I2C controller   * @base: ioremapped registers cookie + * @base_phys: physical base address of the I2C controller   * @cont_id: I2C controller ID, used for packet header   * @irq: IRQ number of transfer complete interrupt   * @irq_disabled: used to track whether or not the interrupt is enabled @@ -194,6 +251,13 @@ struct tegra_i2c_hw_feature {   * @clk_divisor_non_hs_mode: clock divider for non-high-speed modes   * @is_multimaster_mode: track if I2C controller is in multi-master mode   * @xfer_lock: lock to serialize transfer submission and processing + * @tx_dma_chan: DMA transmit channel + * @rx_dma_chan: DMA receive channel + * @dma_phys: handle to DMA resources + * @dma_buf: pointer to allocated DMA buffer + * @dma_buf_size: DMA buffer size + * @is_curr_dma_xfer: indicates active DMA transfer + * @dma_complete: DMA completion notifier   */  struct tegra_i2c_dev {  	struct device *dev; @@ -203,6 +267,7 @@ struct tegra_i2c_dev {  	struct clk *fast_clk;  	struct reset_control *rst;  	void __iomem *base; +	phys_addr_t base_phys;  	int cont_id;  	int irq;  	bool irq_disabled; @@ -216,6 +281,13 @@ struct tegra_i2c_dev {  	u16 clk_divisor_non_hs_mode;  	bool is_multimaster_mode;  	spinlock_t xfer_lock; +	struct dma_chan *tx_dma_chan; +	struct dma_chan *rx_dma_chan; +	dma_addr_t dma_phys; +	u32 *dma_buf; +	unsigned int dma_buf_size; +	bool is_curr_dma_xfer; +	struct completion dma_complete;  };  static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, @@ -284,6 +356,111 @@ static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)  	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);  } +static void tegra_i2c_dma_complete(void *args) +{ +	struct tegra_i2c_dev *i2c_dev = args; + +	complete(&i2c_dev->dma_complete); +} + +static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len) +{ +	struct dma_async_tx_descriptor *dma_desc; +	enum dma_transfer_direction dir; +	struct dma_chan *chan; + +	dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len); +	reinit_completion(&i2c_dev->dma_complete); +	dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; +	chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan; +	dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys, +					       len, dir, DMA_PREP_INTERRUPT | +					       DMA_CTRL_ACK); +	if (!dma_desc) { +		dev_err(i2c_dev->dev, "failed to get DMA descriptor\n"); +		return -EINVAL; +	} + +	dma_desc->callback = tegra_i2c_dma_complete; +	dma_desc->callback_param = i2c_dev; +	dmaengine_submit(dma_desc); +	dma_async_issue_pending(chan); +	return 0; +} + +static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev) +{ +	if (i2c_dev->dma_buf) { +		dma_free_coherent(i2c_dev->dev, i2c_dev->dma_buf_size, +				  i2c_dev->dma_buf, i2c_dev->dma_phys); +		i2c_dev->dma_buf = NULL; +	} + +	if (i2c_dev->tx_dma_chan) { +		dma_release_channel(i2c_dev->tx_dma_chan); +		i2c_dev->tx_dma_chan = NULL; +	} + +	if (i2c_dev->rx_dma_chan) { +		dma_release_channel(i2c_dev->rx_dma_chan); +		i2c_dev->rx_dma_chan = NULL; +	} +} + +static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) +{ +	struct dma_chan *chan; +	u32 *dma_buf; +	dma_addr_t dma_phys; +	int err; + +	if (!i2c_dev->hw->has_apb_dma) +		return 0; + +	if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) { +		dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n"); +		return 0; +	} + +	chan = dma_request_slave_channel_reason(i2c_dev->dev, "rx"); +	if (IS_ERR(chan)) { +		err = PTR_ERR(chan); +		goto err_out; +	} + +	i2c_dev->rx_dma_chan = chan; + +	chan = dma_request_slave_channel_reason(i2c_dev->dev, "tx"); +	if (IS_ERR(chan)) { +		err = PTR_ERR(chan); +		goto err_out; +	} + +	i2c_dev->tx_dma_chan = chan; + +	dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size, +				     &dma_phys, GFP_KERNEL | __GFP_NOWARN); +	if (!dma_buf) { +		dev_err(i2c_dev->dev, "failed to allocate the DMA buffer\n"); +		err = -ENOMEM; +		goto err_out; +	} + +	i2c_dev->dma_buf = dma_buf; +	i2c_dev->dma_phys = dma_phys; +	return 0; + +err_out: +	tegra_i2c_release_dma(i2c_dev); +	if (err != -EPROBE_DEFER) { +		dev_err(i2c_dev->dev, "cannot use DMA: %d\n", err); +		dev_err(i2c_dev->dev, "falling back to PIO\n"); +		return 0; +	} + +	return err; +} +  static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)  {  	unsigned long timeout = jiffies + HZ; @@ -518,11 +695,13 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)  	return 0;  } -static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) +static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)  {  	u32 val;  	int err; -	u32 clk_divisor; +	u32 clk_divisor, clk_multiplier; +	u32 tsu_thd = 0; +	u8 tlow, thigh;  	err = pm_runtime_get_sync(i2c_dev->dev);  	if (err < 0) { @@ -552,6 +731,41 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  					I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT;  	i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR); +	if (i2c_dev->bus_clk_rate > I2C_STANDARD_MODE && +	    i2c_dev->bus_clk_rate <= I2C_FAST_PLUS_MODE) { +		tlow = i2c_dev->hw->tlow_fast_fastplus_mode; +		thigh = i2c_dev->hw->thigh_fast_fastplus_mode; +		tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode; +	} else { +		tlow = i2c_dev->hw->tlow_std_mode; +		thigh = i2c_dev->hw->thigh_std_mode; +		tsu_thd = i2c_dev->hw->setup_hold_time_std_mode; +	} + +	if (i2c_dev->hw->has_interface_timing_reg) { +		val = (thigh << I2C_THIGH_SHIFT) | tlow; +		i2c_writel(i2c_dev, val, I2C_INTERFACE_TIMING_0); +	} + +	/* +	 * configure setup and hold times only when tsu_thd is non-zero. +	 * otherwise, preserve the chip default values +	 */ +	if (i2c_dev->hw->has_interface_timing_reg && tsu_thd) +		i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1); + +	if (!clk_reinit) { +		clk_multiplier = (tlow + thigh + 2); +		clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1); +		err = clk_set_rate(i2c_dev->div_clk, +				   i2c_dev->bus_clk_rate * clk_multiplier); +		if (err) { +			dev_err(i2c_dev->dev, +				"failed changing clock rate: %d\n", err); +			goto err; +		} +	} +  	if (!i2c_dev->is_dvc) {  		u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); @@ -561,16 +775,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  		i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);  	} -	if (i2c_dev->hw->has_mst_fifo) { -		val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) | -		      I2C_MST_FIFO_CONTROL_RX_TRIG(1); -		i2c_writel(i2c_dev, val, I2C_MST_FIFO_CONTROL); -	} else { -		val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT | -			0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT; -		i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); -	} -  	err = tegra_i2c_flush_fifos(i2c_dev);  	if (err)  		goto err; @@ -643,25 +847,44 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)  		goto err;  	} -	if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { -		if (i2c_dev->msg_buf_remaining) -			tegra_i2c_empty_rx_fifo(i2c_dev); -		else -			BUG(); -	} +	/* +	 * I2C transfer is terminated during the bus clear so skip +	 * processing the other interrupts. +	 */ +	if (i2c_dev->hw->supports_bus_clear && (status & I2C_INT_BUS_CLR_DONE)) +		goto err; -	if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { -		if (i2c_dev->msg_buf_remaining) -			tegra_i2c_fill_tx_fifo(i2c_dev); -		else -			tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); +	if (!i2c_dev->is_curr_dma_xfer) { +		if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { +			if (i2c_dev->msg_buf_remaining) +				tegra_i2c_empty_rx_fifo(i2c_dev); +			else +				BUG(); +		} + +		if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { +			if (i2c_dev->msg_buf_remaining) +				tegra_i2c_fill_tx_fifo(i2c_dev); +			else +				tegra_i2c_mask_irq(i2c_dev, +						   I2C_INT_TX_FIFO_DATA_REQ); +		}  	}  	i2c_writel(i2c_dev, status, I2C_INT_STATUS);  	if (i2c_dev->is_dvc)  		dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); +	/* +	 * During message read XFER_COMPLETE interrupt is triggered prior to +	 * DMA completion and during message write XFER_COMPLETE interrupt is +	 * triggered after DMA completion. +	 * PACKETS_XFER_COMPLETE indicates completion of all bytes of transfer. +	 * so forcing msg_buf_remaining to 0 in DMA mode. +	 */  	if (status & I2C_INT_PACKET_XFER_COMPLETE) { +		if (i2c_dev->is_curr_dma_xfer) +			i2c_dev->msg_buf_remaining = 0;  		BUG_ON(i2c_dev->msg_buf_remaining);  		complete(&i2c_dev->msg_complete);  	} @@ -671,16 +894,135 @@ err:  	tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST |  		I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ |  		I2C_INT_RX_FIFO_DATA_REQ); +	if (i2c_dev->hw->supports_bus_clear) +		tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);  	i2c_writel(i2c_dev, status, I2C_INT_STATUS);  	if (i2c_dev->is_dvc)  		dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); +	if (i2c_dev->is_curr_dma_xfer) { +		if (i2c_dev->msg_read) +			dmaengine_terminate_async(i2c_dev->rx_dma_chan); +		else +			dmaengine_terminate_async(i2c_dev->tx_dma_chan); + +		complete(&i2c_dev->dma_complete); +	} +  	complete(&i2c_dev->msg_complete);  done:  	spin_unlock(&i2c_dev->xfer_lock);  	return IRQ_HANDLED;  } +static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev, +				       size_t len) +{ +	u32 val, reg; +	u8 dma_burst; +	struct dma_slave_config slv_config = {0}; +	struct dma_chan *chan; +	int ret; +	unsigned long reg_offset; + +	if (i2c_dev->hw->has_mst_fifo) +		reg = I2C_MST_FIFO_CONTROL; +	else +		reg = I2C_FIFO_CONTROL; + +	if (i2c_dev->is_curr_dma_xfer) { +		if (len & 0xF) +			dma_burst = 1; +		else if (len & 0x10) +			dma_burst = 4; +		else +			dma_burst = 8; + +		if (i2c_dev->msg_read) { +			chan = i2c_dev->rx_dma_chan; +			reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO); +			slv_config.src_addr = i2c_dev->base_phys + reg_offset; +			slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +			slv_config.src_maxburst = dma_burst; + +			if (i2c_dev->hw->has_mst_fifo) +				val = I2C_MST_FIFO_CONTROL_RX_TRIG(dma_burst); +			else +				val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst); +		} else { +			chan = i2c_dev->tx_dma_chan; +			reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO); +			slv_config.dst_addr = i2c_dev->base_phys + reg_offset; +			slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +			slv_config.dst_maxburst = dma_burst; + +			if (i2c_dev->hw->has_mst_fifo) +				val = I2C_MST_FIFO_CONTROL_TX_TRIG(dma_burst); +			else +				val = I2C_FIFO_CONTROL_TX_TRIG(dma_burst); +		} + +		slv_config.device_fc = true; +		ret = dmaengine_slave_config(chan, &slv_config); +		if (ret < 0) { +			dev_err(i2c_dev->dev, "DMA slave config failed: %d\n", +				ret); +			dev_err(i2c_dev->dev, "falling back to PIO\n"); +			tegra_i2c_release_dma(i2c_dev); +			i2c_dev->is_curr_dma_xfer = false; +		} else { +			goto out; +		} +	} + +	if (i2c_dev->hw->has_mst_fifo) +		val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) | +		      I2C_MST_FIFO_CONTROL_RX_TRIG(1); +	else +		val = I2C_FIFO_CONTROL_TX_TRIG(8) | +		      I2C_FIFO_CONTROL_RX_TRIG(1); +out: +	i2c_writel(i2c_dev, val, reg); +} + +static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap) +{ +	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); +	int err; +	unsigned long time_left; +	u32 reg; + +	reinit_completion(&i2c_dev->msg_complete); +	reg = (I2C_BC_SCLK_THRESHOLD << I2C_BC_SCLK_THRESHOLD_SHIFT) | +	      I2C_BC_STOP_COND | I2C_BC_TERMINATE; +	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG); +	if (i2c_dev->hw->has_config_load_reg) { +		err = tegra_i2c_wait_for_config_load(i2c_dev); +		if (err) +			return err; +	} + +	reg |= I2C_BC_ENABLE; +	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG); +	tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE); + +	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, +						msecs_to_jiffies(50)); +	if (time_left == 0) { +		dev_err(i2c_dev->dev, "timed out for bus clear\n"); +		return -ETIMEDOUT; +	} + +	reg = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS); +	if (!(reg & I2C_BC_STATUS)) { +		dev_err(i2c_dev->dev, +			"un-recovered arbitration lost\n"); +		return -EIO; +	} + +	return -EAGAIN; +} +  static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  	struct i2c_msg *msg, enum msg_end_type end_state)  { @@ -688,6 +1030,11 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  	u32 int_mask;  	unsigned long time_left;  	unsigned long flags; +	size_t xfer_size; +	u32 *buffer = NULL; +	int err = 0; +	bool dma; +	u16 xfer_time = 100;  	tegra_i2c_flush_fifos(i2c_dev); @@ -697,19 +1044,63 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  	i2c_dev->msg_read = (msg->flags & I2C_M_RD);  	reinit_completion(&i2c_dev->msg_complete); +	if (i2c_dev->msg_read) +		xfer_size = msg->len; +	else +		xfer_size = msg->len + I2C_PACKET_HEADER_SIZE; + +	xfer_size = ALIGN(xfer_size, BYTES_PER_FIFO_WORD); +	i2c_dev->is_curr_dma_xfer = (xfer_size > I2C_PIO_MODE_MAX_LEN) && +				    i2c_dev->dma_buf; +	tegra_i2c_config_fifo_trig(i2c_dev, xfer_size); +	dma = i2c_dev->is_curr_dma_xfer; +	/* +	 * Transfer time in mSec = Total bits / transfer rate +	 * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits +	 */ +	xfer_time += DIV_ROUND_CLOSEST(((xfer_size * 9) + 2) * MSEC_PER_SEC, +					i2c_dev->bus_clk_rate);  	spin_lock_irqsave(&i2c_dev->xfer_lock, flags);  	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;  	tegra_i2c_unmask_irq(i2c_dev, int_mask); +	if (dma) { +		if (i2c_dev->msg_read) { +			dma_sync_single_for_device(i2c_dev->dev, +						   i2c_dev->dma_phys, +						   xfer_size, +						   DMA_FROM_DEVICE); +			err = tegra_i2c_dma_submit(i2c_dev, xfer_size); +			if (err < 0) { +				dev_err(i2c_dev->dev, +					"starting RX DMA failed, err %d\n", +					err); +				goto unlock; +			} + +		} else { +			dma_sync_single_for_cpu(i2c_dev->dev, +						i2c_dev->dma_phys, +						xfer_size, +						DMA_TO_DEVICE); +			buffer = i2c_dev->dma_buf; +		} +	}  	packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |  			PACKET_HEADER0_PROTOCOL_I2C |  			(i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) |  			(1 << PACKET_HEADER0_PACKET_ID_SHIFT); -	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); +	if (dma && !i2c_dev->msg_read) +		*buffer++ = packet_header; +	else +		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);  	packet_header = msg->len - 1; -	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); +	if (dma && !i2c_dev->msg_read) +		*buffer++ = packet_header; +	else +		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);  	packet_header = I2C_HEADER_IE_ENABLE;  	if (end_state == MSG_END_CONTINUE) @@ -726,31 +1117,85 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  		packet_header |= I2C_HEADER_CONT_ON_NAK;  	if (msg->flags & I2C_M_RD)  		packet_header |= I2C_HEADER_READ; -	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); - -	if (!(msg->flags & I2C_M_RD)) -		tegra_i2c_fill_tx_fifo(i2c_dev); +	if (dma && !i2c_dev->msg_read) +		*buffer++ = packet_header; +	else +		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); + +	if (!i2c_dev->msg_read) { +		if (dma) { +			memcpy(buffer, msg->buf, msg->len); +			dma_sync_single_for_device(i2c_dev->dev, +						   i2c_dev->dma_phys, +						   xfer_size, +						   DMA_TO_DEVICE); +			err = tegra_i2c_dma_submit(i2c_dev, xfer_size); +			if (err < 0) { +				dev_err(i2c_dev->dev, +					"starting TX DMA failed, err %d\n", +					err); +				goto unlock; +			} +		} else { +			tegra_i2c_fill_tx_fifo(i2c_dev); +		} +	}  	if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)  		int_mask |= I2C_INT_PACKET_XFER_COMPLETE; -	if (msg->flags & I2C_M_RD) -		int_mask |= I2C_INT_RX_FIFO_DATA_REQ; -	else if (i2c_dev->msg_buf_remaining) -		int_mask |= I2C_INT_TX_FIFO_DATA_REQ; +	if (!dma) { +		if (msg->flags & I2C_M_RD) +			int_mask |= I2C_INT_RX_FIFO_DATA_REQ; +		else if (i2c_dev->msg_buf_remaining) +			int_mask |= I2C_INT_TX_FIFO_DATA_REQ; +	}  	tegra_i2c_unmask_irq(i2c_dev, int_mask); -	spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags);  	dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",  		i2c_readl(i2c_dev, I2C_INT_MASK)); +unlock: +	spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags); + +	if (dma) { +		if (err) +			return err; + +		time_left = wait_for_completion_timeout( +						&i2c_dev->dma_complete, +						msecs_to_jiffies(xfer_time)); +		if (time_left == 0) { +			dev_err(i2c_dev->dev, "DMA transfer timeout\n"); +			dmaengine_terminate_sync(i2c_dev->msg_read ? +						 i2c_dev->rx_dma_chan : +						 i2c_dev->tx_dma_chan); +			tegra_i2c_init(i2c_dev, true); +			return -ETIMEDOUT; +		} + +		if (i2c_dev->msg_read && i2c_dev->msg_err == I2C_ERR_NONE) { +			dma_sync_single_for_cpu(i2c_dev->dev, +						i2c_dev->dma_phys, +						xfer_size, +						DMA_FROM_DEVICE); +			memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, +			       msg->len); +		} + +		if (i2c_dev->msg_err != I2C_ERR_NONE) +			dmaengine_synchronize(i2c_dev->msg_read ? +					      i2c_dev->rx_dma_chan : +					      i2c_dev->tx_dma_chan); +	} +  	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, -						TEGRA_I2C_TIMEOUT); +						msecs_to_jiffies(xfer_time));  	tegra_i2c_mask_irq(i2c_dev, int_mask);  	if (time_left == 0) {  		dev_err(i2c_dev->dev, "i2c transfer timed out\n"); -		tegra_i2c_init(i2c_dev); +		tegra_i2c_init(i2c_dev, true);  		return -ETIMEDOUT;  	} @@ -758,10 +1203,18 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  		time_left, completion_done(&i2c_dev->msg_complete),  		i2c_dev->msg_err); +	i2c_dev->is_curr_dma_xfer = false;  	if (likely(i2c_dev->msg_err == I2C_ERR_NONE))  		return 0; -	tegra_i2c_init(i2c_dev); +	tegra_i2c_init(i2c_dev, true); +	/* start recovery upon arbitration loss in single master mode */ +	if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) { +		if (!i2c_dev->is_multimaster_mode) +			return i2c_recover_bus(&i2c_dev->adapter); +		return -EAGAIN; +	} +  	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {  		if (msg->flags & I2C_M_IGNORE_NAK)  			return 0; @@ -836,12 +1289,17 @@ static const struct i2c_algorithm tegra_i2c_algo = {  /* payload size is only 12 bit */  static const struct i2c_adapter_quirks tegra_i2c_quirks = {  	.flags = I2C_AQ_NO_ZERO_LEN, -	.max_read_len = 4096, -	.max_write_len = 4096, +	.max_read_len = SZ_4K, +	.max_write_len = SZ_4K - I2C_PACKET_HEADER_SIZE,  };  static const struct i2c_adapter_quirks tegra194_i2c_quirks = {  	.flags = I2C_AQ_NO_ZERO_LEN, +	.max_write_len = SZ_64K - I2C_PACKET_HEADER_SIZE, +}; + +static struct i2c_bus_recovery_info tegra_i2c_recovery_info = { +	.recover_bus = tegra_i2c_issue_bus_clear,  };  static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { @@ -849,13 +1307,24 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {  	.has_per_pkt_xfer_complete_irq = false,  	.has_single_clk_source = false,  	.clk_divisor_hs_mode = 3, -	.clk_divisor_std_fast_mode = 0, +	.clk_divisor_std_mode = 0, +	.clk_divisor_fast_mode = 0,  	.clk_divisor_fast_plus_mode = 0,  	.has_config_load_reg = false,  	.has_multi_master_mode = false,  	.has_slcg_override_reg = false,  	.has_mst_fifo = false,  	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = false, +	.has_apb_dma = true, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x2, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0x0, +	.setup_hold_time_fast_fast_plus_mode = 0x0, +	.setup_hold_time_hs_mode = 0x0, +	.has_interface_timing_reg = false,  };  static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { @@ -863,13 +1332,24 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {  	.has_per_pkt_xfer_complete_irq = false,  	.has_single_clk_source = false,  	.clk_divisor_hs_mode = 3, -	.clk_divisor_std_fast_mode = 0, +	.clk_divisor_std_mode = 0, +	.clk_divisor_fast_mode = 0,  	.clk_divisor_fast_plus_mode = 0,  	.has_config_load_reg = false,  	.has_multi_master_mode = false,  	.has_slcg_override_reg = false,  	.has_mst_fifo = false,  	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = false, +	.has_apb_dma = true, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x2, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0x0, +	.setup_hold_time_fast_fast_plus_mode = 0x0, +	.setup_hold_time_hs_mode = 0x0, +	.has_interface_timing_reg = false,  };  static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { @@ -877,13 +1357,24 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {  	.has_per_pkt_xfer_complete_irq = true,  	.has_single_clk_source = true,  	.clk_divisor_hs_mode = 1, -	.clk_divisor_std_fast_mode = 0x19, +	.clk_divisor_std_mode = 0x19, +	.clk_divisor_fast_mode = 0x19,  	.clk_divisor_fast_plus_mode = 0x10,  	.has_config_load_reg = false,  	.has_multi_master_mode = false,  	.has_slcg_override_reg = false,  	.has_mst_fifo = false,  	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = true, +	.has_apb_dma = true, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x2, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0x0, +	.setup_hold_time_fast_fast_plus_mode = 0x0, +	.setup_hold_time_hs_mode = 0x0, +	.has_interface_timing_reg = false,  };  static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { @@ -891,13 +1382,24 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {  	.has_per_pkt_xfer_complete_irq = true,  	.has_single_clk_source = true,  	.clk_divisor_hs_mode = 1, -	.clk_divisor_std_fast_mode = 0x19, +	.clk_divisor_std_mode = 0x19, +	.clk_divisor_fast_mode = 0x19,  	.clk_divisor_fast_plus_mode = 0x10,  	.has_config_load_reg = true,  	.has_multi_master_mode = false,  	.has_slcg_override_reg = true,  	.has_mst_fifo = false,  	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = true, +	.has_apb_dma = true, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x2, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0x0, +	.setup_hold_time_fast_fast_plus_mode = 0x0, +	.setup_hold_time_hs_mode = 0x0, +	.has_interface_timing_reg = true,  };  static const struct tegra_i2c_hw_feature tegra210_i2c_hw = { @@ -905,32 +1407,80 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {  	.has_per_pkt_xfer_complete_irq = true,  	.has_single_clk_source = true,  	.clk_divisor_hs_mode = 1, -	.clk_divisor_std_fast_mode = 0x19, +	.clk_divisor_std_mode = 0x19, +	.clk_divisor_fast_mode = 0x19,  	.clk_divisor_fast_plus_mode = 0x10,  	.has_config_load_reg = true, -	.has_multi_master_mode = true, +	.has_multi_master_mode = false,  	.has_slcg_override_reg = true,  	.has_mst_fifo = false,  	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = true, +	.has_apb_dma = true, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x2, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0, +	.setup_hold_time_fast_fast_plus_mode = 0, +	.setup_hold_time_hs_mode = 0, +	.has_interface_timing_reg = true,  }; -static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { +static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {  	.has_continue_xfer_support = true,  	.has_per_pkt_xfer_complete_irq = true,  	.has_single_clk_source = true,  	.clk_divisor_hs_mode = 1, -	.clk_divisor_std_fast_mode = 0x19, +	.clk_divisor_std_mode = 0x16, +	.clk_divisor_fast_mode = 0x19,  	.clk_divisor_fast_plus_mode = 0x10,  	.has_config_load_reg = true, +	.has_multi_master_mode = false, +	.has_slcg_override_reg = true, +	.has_mst_fifo = false, +	.quirks = &tegra_i2c_quirks, +	.supports_bus_clear = true, +	.has_apb_dma = false, +	.tlow_std_mode = 0x4, +	.thigh_std_mode = 0x3, +	.tlow_fast_fastplus_mode = 0x4, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0, +	.setup_hold_time_fast_fast_plus_mode = 0, +	.setup_hold_time_hs_mode = 0, +	.has_interface_timing_reg = true, +}; + +static const struct tegra_i2c_hw_feature tegra194_i2c_hw = { +	.has_continue_xfer_support = true, +	.has_per_pkt_xfer_complete_irq = true, +	.has_single_clk_source = true, +	.clk_divisor_hs_mode = 1, +	.clk_divisor_std_mode = 0x4f, +	.clk_divisor_fast_mode = 0x3c, +	.clk_divisor_fast_plus_mode = 0x16, +	.has_config_load_reg = true,  	.has_multi_master_mode = true,  	.has_slcg_override_reg = true,  	.has_mst_fifo = true,  	.quirks = &tegra194_i2c_quirks, +	.supports_bus_clear = true, +	.has_apb_dma = false, +	.tlow_std_mode = 0x8, +	.thigh_std_mode = 0x7, +	.tlow_fast_fastplus_mode = 0x2, +	.thigh_fast_fastplus_mode = 0x2, +	.setup_hold_time_std_mode = 0x08080808, +	.setup_hold_time_fast_fast_plus_mode = 0x02020202, +	.setup_hold_time_hs_mode = 0x090909, +	.has_interface_timing_reg = true,  };  /* Match table for of_platform binding */  static const struct of_device_id tegra_i2c_of_match[] = {  	{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, }, +	{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },  	{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },  	{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },  	{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, }, @@ -948,11 +1498,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)  	struct clk *div_clk;  	struct clk *fast_clk;  	void __iomem *base; +	phys_addr_t base_phys;  	int irq;  	int ret = 0; -	int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	base_phys = res->start;  	base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(base))  		return PTR_ERR(base); @@ -975,8 +1526,11 @@ static int tegra_i2c_probe(struct platform_device *pdev)  		return -ENOMEM;  	i2c_dev->base = base; +	i2c_dev->base_phys = base_phys;  	i2c_dev->div_clk = div_clk;  	i2c_dev->adapter.algo = &tegra_i2c_algo; +	i2c_dev->adapter.retries = 1; +	i2c_dev->adapter.timeout = 6 * HZ;  	i2c_dev->irq = irq;  	i2c_dev->cont_id = pdev->id;  	i2c_dev->dev = &pdev->dev; @@ -993,7 +1547,10 @@ static int tegra_i2c_probe(struct platform_device *pdev)  	i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,  						  "nvidia,tegra20-i2c-dvc");  	i2c_dev->adapter.quirks = i2c_dev->hw->quirks; +	i2c_dev->dma_buf_size = i2c_dev->adapter.quirks->max_write_len + +				I2C_PACKET_HEADER_SIZE;  	init_completion(&i2c_dev->msg_complete); +	init_completion(&i2c_dev->dma_complete);  	spin_lock_init(&i2c_dev->xfer_lock);  	if (!i2c_dev->hw->has_single_clk_source) { @@ -1015,20 +1572,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)  		}  	} -	i2c_dev->clk_divisor_non_hs_mode = -			i2c_dev->hw->clk_divisor_std_fast_mode; -	if (i2c_dev->hw->clk_divisor_fast_plus_mode && -		(i2c_dev->bus_clk_rate == 1000000)) +	if (i2c_dev->bus_clk_rate > I2C_FAST_MODE && +	    i2c_dev->bus_clk_rate <= I2C_FAST_PLUS_MODE)  		i2c_dev->clk_divisor_non_hs_mode = -			i2c_dev->hw->clk_divisor_fast_plus_mode; - -	clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1); -	ret = clk_set_rate(i2c_dev->div_clk, -			   i2c_dev->bus_clk_rate * clk_multiplier); -	if (ret) { -		dev_err(i2c_dev->dev, "Clock rate change failed %d\n", ret); -		goto unprepare_fast_clk; -	} +				i2c_dev->hw->clk_divisor_fast_plus_mode; +	else if (i2c_dev->bus_clk_rate > I2C_STANDARD_MODE && +		 i2c_dev->bus_clk_rate <= I2C_FAST_MODE) +		i2c_dev->clk_divisor_non_hs_mode = +				i2c_dev->hw->clk_divisor_fast_mode; +	else +		i2c_dev->clk_divisor_non_hs_mode = +				i2c_dev->hw->clk_divisor_std_mode;  	ret = clk_prepare(i2c_dev->div_clk);  	if (ret < 0) { @@ -1054,17 +1608,24 @@ static int tegra_i2c_probe(struct platform_device *pdev)  		}  	} -	ret = tegra_i2c_init(i2c_dev); +	if (i2c_dev->hw->supports_bus_clear) +		i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info; + +	ret = tegra_i2c_init_dma(i2c_dev); +	if (ret < 0) +		goto disable_div_clk; + +	ret = tegra_i2c_init(i2c_dev, false);  	if (ret) {  		dev_err(&pdev->dev, "Failed to initialize i2c controller\n"); -		goto disable_div_clk; +		goto release_dma;  	}  	ret = devm_request_irq(&pdev->dev, i2c_dev->irq,  			tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);  	if (ret) {  		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); -		goto disable_div_clk; +		goto release_dma;  	}  	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); @@ -1078,10 +1639,13 @@ static int tegra_i2c_probe(struct platform_device *pdev)  	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);  	if (ret) -		goto disable_div_clk; +		goto release_dma;  	return 0; +release_dma: +	tegra_i2c_release_dma(i2c_dev); +  disable_div_clk:  	if (i2c_dev->is_multimaster_mode)  		clk_disable(i2c_dev->div_clk); @@ -1118,6 +1682,7 @@ static int tegra_i2c_remove(struct platform_device *pdev)  	if (!i2c_dev->hw->has_single_clk_source)  		clk_unprepare(i2c_dev->fast_clk); +	tegra_i2c_release_dma(i2c_dev);  	return 0;  } @@ -1141,18 +1706,7 @@ static struct platform_driver tegra_i2c_driver = {  	},  }; -static int __init tegra_i2c_init_driver(void) -{ -	return platform_driver_register(&tegra_i2c_driver); -} - -static void __exit tegra_i2c_exit_driver(void) -{ -	platform_driver_unregister(&tegra_i2c_driver); -} - -subsys_initcall(tegra_i2c_init_driver); -module_exit(tegra_i2c_exit_driver); +module_platform_driver(tegra_i2c_driver);  MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver");  MODULE_AUTHOR("Colin Cross"); diff --git a/drivers/i2c/busses/i2c-zx2967.c b/drivers/i2c/busses/i2c-zx2967.c index b8f9e020d80e..7b98d97da3c6 100644 --- a/drivers/i2c/busses/i2c-zx2967.c +++ b/drivers/i2c/busses/i2c-zx2967.c @@ -66,7 +66,6 @@ struct zx2967_i2c {  	int			msg_rd;  	u8			*cur_trans;  	u8			access_cnt; -	bool			is_suspended;  	int			error;  }; @@ -313,9 +312,6 @@ static int zx2967_i2c_xfer(struct i2c_adapter *adap,  	int ret;  	int i; -	if (i2c->is_suspended) -		return -EBUSY; -  	zx2967_set_addr(i2c, msgs->addr);  	for (i = 0; i < num; i++) { @@ -470,7 +466,7 @@ static int __maybe_unused zx2967_i2c_suspend(struct device *dev)  {  	struct zx2967_i2c *i2c = dev_get_drvdata(dev); -	i2c->is_suspended = true; +	i2c_mark_adapter_suspended(&i2c->adap);  	clk_disable_unprepare(i2c->clk);  	return 0; @@ -480,8 +476,8 @@ static int __maybe_unused zx2967_i2c_resume(struct device *dev)  {  	struct zx2967_i2c *i2c = dev_get_drvdata(dev); -	i2c->is_suspended = false;  	clk_prepare_enable(i2c->clk); +	i2c_mark_adapter_resumed(&i2c->adap);  	return 0;  } diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 28460f6a60cc..38af18645133 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -430,7 +430,7 @@ static int i2c_device_remove(struct device *dev)  	dev_pm_clear_wake_irq(&client->dev);  	device_init_wakeup(&client->dev, false); -	client->irq = 0; +	client->irq = client->init_irq;  	return status;  } @@ -741,10 +741,11 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  	client->flags = info->flags;  	client->addr = info->addr; -	client->irq = info->irq; -	if (!client->irq) -		client->irq = i2c_dev_irq_from_resources(info->resources, +	client->init_irq = info->irq; +	if (!client->init_irq) +		client->init_irq = i2c_dev_irq_from_resources(info->resources,  							 info->num_resources); +	client->irq = client->init_irq;  	strlcpy(client->name, info->type, sizeof(client->name)); @@ -1232,6 +1233,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	if (!adap->lock_ops)  		adap->lock_ops = &i2c_adapter_lock_ops; +	adap->locked_flags = 0;  	rt_mutex_init(&adap->bus_lock);  	rt_mutex_init(&adap->mux_lock);  	mutex_init(&adap->userspace_clients_lock); @@ -1865,6 +1867,8 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	if (WARN_ON(!msgs || num < 1))  		return -EINVAL; +	if (WARN_ON(test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags))) +		return -ESHUTDOWN;  	if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))  		return -EOPNOTSUPP; @@ -2254,7 +2258,8 @@ EXPORT_SYMBOL(i2c_put_adapter);  /**   * i2c_get_dma_safe_msg_buf() - get a DMA safe buffer for the given i2c_msg   * @msg: the message to be checked - * @threshold: the minimum number of bytes for which using DMA makes sense + * @threshold: the minimum number of bytes for which using DMA makes sense. + *	       Should at least be 1.   *   * Return: NULL if a DMA safe buffer was not obtained. Use msg->buf with PIO.   *	   Or a valid pointer to be used with DMA. After use, release it by @@ -2264,7 +2269,11 @@ EXPORT_SYMBOL(i2c_put_adapter);   */  u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold)  { -	if (msg->len < threshold) +	/* also skip 0-length msgs for bogus thresholds of 0 */ +	if (!threshold) +		pr_debug("DMA buffer for addr=0x%02x with length 0 is bogus\n", +			 msg->addr); +	if (msg->len < threshold || msg->len == 0)  		return NULL;  	if (msg->flags & I2C_M_DMA_SAFE) diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 6cb7ad608bcd..0f01cdba9d2c 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -121,6 +121,17 @@ static int of_dev_node_match(struct device *dev, void *data)  	return dev->of_node == data;  } +static int of_dev_or_parent_node_match(struct device *dev, void *data) +{ +	if (dev->of_node == data) +		return 1; + +	if (dev->parent) +		return dev->parent->of_node == data; + +	return 0; +} +  /* must call put_device() when done with returned i2c_client device */  struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)  { @@ -145,7 +156,8 @@ struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)  	struct device *dev;  	struct i2c_adapter *adapter; -	dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); +	dev = bus_find_device(&i2c_bus_type, NULL, node, +			      of_dev_or_parent_node_match);  	if (!dev)  		return NULL; diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index 9cd66cabb84f..132119112596 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -585,7 +585,7 @@ s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,  trace:  	/* If enabled, the reply tracepoint is conditional on read_write. */  	trace_smbus_reply(adapter, addr, flags, read_write, -			  command, protocol, data); +			  command, protocol, data, res);  	trace_smbus_result(adapter, addr, flags, read_write,  			   command, protocol, res); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index ccd76c71af09..3f7b9af11137 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -52,7 +52,7 @@ struct i2c_dev {  	struct cdev cdev;  }; -#define I2C_MINORS	MINORMASK +#define I2C_MINORS	(MINORMASK + 1)  static LIST_HEAD(i2c_dev_list);  static DEFINE_SPINLOCK(i2c_dev_list_lock); | 
