diff options
Diffstat (limited to 'drivers/i2c')
24 files changed, 464 insertions, 903 deletions
| diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index c6b854a9e476..42da31c1ab70 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -617,7 +617,7 @@ config I2C_EXYNOS5  	help  	  High-speed I2C controller on Samsung Exynos5 and newer Samsung SoCs:  	  Exynos5250, Exynos5260, Exynos5410, Exynos542x, Exynos5800, -	  Exynos5433 and Exynos7. +	  Exynos5433, Exynos7, Exynos850 and ExynosAutoV9.  	  Choose Y here only if you build for such Samsung SoC.  config I2C_GPIO @@ -1153,22 +1153,12 @@ config I2C_XILINX  	  This driver can also be built as a module.  If so, the module  	  will be called xilinx_i2c. -config I2C_XLR -	tristate "Netlogic XLR I2C support" -	depends on CPU_XLR || COMPILE_TEST -	help -	  This driver enables support for the on-chip I2C interface of -	  the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs. - -	  This driver can also be built as a module.  If so, the module -	  will be called i2c-xlr. -  config I2C_XLP9XX -	tristate "XLP9XX I2C support" -	depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST +	tristate "Cavium ThunderX2 I2C support" +	depends on ARCH_THUNDER2 || COMPILE_TEST  	help  	  This driver enables support for the on-chip I2C interface of -	  the Broadcom XLP9xx/XLP5xx MIPS and Vulcan ARM64 processors. +	  the Cavium ThunderX2 processors. (Originally on Netlogic XLP SoCs.)  	  This driver can also be built as a module.  If so, the module will  	  be called i2c-xlp9xx. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index d85899fef8c7..1d00dce77098 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -119,7 +119,6 @@ obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o  i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o  obj-$(CONFIG_I2C_THUNDERX)	+= i2c-thunderx.o  obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o -obj-$(CONFIG_I2C_XLR)		+= i2c-xlr.o  obj-$(CONFIG_I2C_XLP9XX)	+= i2c-xlp9xx.o  obj-$(CONFIG_I2C_RCAR)		+= i2c-rcar.o diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 67e8b97c0c95..771e53d3d197 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -16,8 +16,6 @@  #include <linux/interrupt.h>  #include <linux/io.h>  #include <linux/irq.h> -#include <linux/irqchip/chained_irq.h> -#include <linux/irqdomain.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/of_address.h> diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index 37443edbf754..dfc534065595 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -402,7 +402,7 @@ static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {  static int bcm2835_i2c_probe(struct platform_device *pdev)  {  	struct bcm2835_i2c_dev *i2c_dev; -	struct resource *mem, *irq; +	struct resource *mem;  	int ret;  	struct i2c_adapter *adap;  	struct clk *mclk; @@ -452,12 +452,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)  		return ret;  	} -	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -	if (!irq) { -		dev_err(&pdev->dev, "No IRQ resource\n"); -		return -ENODEV; -	} -	i2c_dev->irq = irq->start; +	i2c_dev->irq = platform_get_irq(pdev, 0); +	if (i2c_dev->irq < 0) +		return i2c_dev->irq;  	ret = request_irq(i2c_dev->irq, bcm2835_i2c_isr, IRQF_SHARED,  			  dev_name(&pdev->dev), i2c_dev); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 60a2e750cee9..4b26cba40139 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -191,23 +191,26 @@ struct reset_control;   * @cmd_complete: tx completion indicator   * @clk: input reference clock   * @pclk: clock required to access the registers + * @rst: optional reset for the controller   * @slave: represent an I2C slave device + * @get_clk_rate_khz: callback to retrieve IP specific bus speed   * @cmd_err: run time hadware error code   * @msgs: points to an array of messages currently being transferred   * @msgs_num: the number of elements in msgs - * @msg_write_idx: the element index of the current tx message in the msgs - *	array + * @msg_write_idx: the element index of the current tx message in the msgs array   * @tx_buf_len: the length of the current tx buffer   * @tx_buf: the current tx buffer - * @msg_read_idx: the element index of the current rx message in the msgs - *	array + * @msg_read_idx: the element index of the current rx message in the msgs array   * @rx_buf_len: the length of the current rx buffer   * @rx_buf: the current rx buffer   * @msg_err: error status of the current transfer   * @status: i2c master status, one of STATUS_*   * @abort_source: copy of the TX_ABRT_SOURCE register   * @irq: interrupt number for the i2c master + * @flags: platform specific flags like type of IO accessors or model   * @adapter: i2c subsystem adapter node + * @functionality: I2C_FUNC_* ORed bits to reflect what controller does support + * @master_cfg: configuration for the master device   * @slave_cfg: configuration for the slave device   * @tx_fifo_depth: depth of the hardware tx fifo   * @rx_fifo_depth: depth of the hardware rx fifo @@ -228,7 +231,9 @@ struct reset_control;   * @disable: function to disable the controller   * @disable_int: function to disable all interrupts   * @init: function to initialize the I2C hardware + * @set_sda_hold_time: callback to retrieve IP specific SDA hold timing   * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE + * @rinfo: I²C GPIO recovery information   * @suspended: set to true if the controller is suspended   *   * HCNT and LCNT parameters can be used if the platform knows more accurate diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 9b08bb5df38d..9177463c2cbb 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -701,7 +701,8 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)  		regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy);  	if (stat & DW_IC_INTR_ACTIVITY)  		regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy); -	if (stat & DW_IC_INTR_STOP_DET) +	if ((stat & DW_IC_INTR_STOP_DET) && +	    ((dev->rx_outstanding == 0) || (stat & DW_IC_INTR_RX_FULL)))  		regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy);  	if (stat & DW_IC_INTR_START_DET)  		regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy); @@ -723,6 +724,7 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)  	if (stat & DW_IC_INTR_TX_ABRT) {  		dev->cmd_err |= DW_IC_ERR_TX_ABRT;  		dev->status = STATUS_IDLE; +		dev->rx_outstanding = 0;  		/*  		 * Anytime TX_ABRT is set, the contents of the tx/rx @@ -745,7 +747,8 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)  	 */  tx_aborted: -	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) +	if (((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) && +	     (dev->rx_outstanding == 0))  		complete(&dev->cmd_complete);  	else if (unlikely(dev->flags & ACCESS_INTR_MASK)) {  		/* Workaround to trigger pending interrupt */ diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 0f409a4c2da0..ef4250f8852b 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -38,11 +38,18 @@ enum dw_pci_ctl_id_t {  	navi_amd,  }; +/* + * This is a legacy structure to describe the hardware counters + * to configure signal timings on the bus. For Device Tree platforms + * one should use the respective properties and for ACPI there is + * a set of ACPI methods that provide these counters. No new + * platform should use this structure. + */  struct dw_scl_sda_cfg { -	u32 ss_hcnt; -	u32 fs_hcnt; -	u32 ss_lcnt; -	u32 fs_lcnt; +	u16 ss_hcnt; +	u16 fs_hcnt; +	u16 ss_lcnt; +	u16 fs_lcnt;  	u32 sda_hold;  }; @@ -206,8 +213,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {  	},  }; -#ifdef CONFIG_PM -static int i2c_dw_pci_suspend(struct device *dev) +static int __maybe_unused i2c_dw_pci_suspend(struct device *dev)  {  	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); @@ -217,7 +223,7 @@ static int i2c_dw_pci_suspend(struct device *dev)  	return 0;  } -static int i2c_dw_pci_resume(struct device *dev) +static int __maybe_unused i2c_dw_pci_resume(struct device *dev)  {  	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);  	int ret; @@ -227,7 +233,6 @@ static int i2c_dw_pci_resume(struct device *dev)  	return ret;  } -#endif  static UNIVERSAL_DEV_PM_OPS(i2c_dw_pm_ops, i2c_dw_pci_suspend,  			    i2c_dw_pci_resume, NULL); @@ -241,28 +246,24 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,  	struct dw_pci_controller *controller;  	struct dw_scl_sda_cfg *cfg; -	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { -		dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__, -			id->driver_data); -		return -EINVAL; -	} +	if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) +		return dev_err_probe(&pdev->dev, -EINVAL, +				     "Invalid driver data %ld\n", +				     id->driver_data);  	controller = &dw_pci_controllers[id->driver_data];  	r = pcim_enable_device(pdev); -	if (r) { -		dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n", -			r); -		return r; -	} +	if (r) +		return dev_err_probe(&pdev->dev, r, +				     "Failed to enable I2C PCI device\n");  	pci_set_master(pdev);  	r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); -	if (r) { -		dev_err(&pdev->dev, "I/O memory remapping failed\n"); -		return r; -	} +	if (r) +		return dev_err_probe(&pdev->dev, r, +				     "I/O memory remapping failed\n");  	dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);  	if (!dev) @@ -352,9 +353,6 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev)  	pci_free_irq_vectors(pdev);  } -/* work with hotplug and coldplug */ -MODULE_ALIAS("i2c_designware-pci"); -  static const struct pci_device_id i2_designware_pci_ids[] = {  	/* Medfield */  	{ PCI_VDEVICE(INTEL, 0x0817), medfield }, @@ -411,9 +409,10 @@ static struct pci_driver dw_i2c_driver = {  		.pm     = &i2c_dw_pm_ops,  	},  }; -  module_pci_driver(dw_i2c_driver); +/* Work with hotplug and coldplug */ +MODULE_ALIAS("i2c_designware-pci");  MODULE_AUTHOR("Baruch Siach <[email protected]>");  MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");  MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 21113665ddea..2bd81abc86f6 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -293,6 +293,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  					DPM_FLAG_MAY_SKIP_RESUME);  	} +	device_enable_async_suspend(&pdev->dev); +  	/* The code below assumes runtime PM to be disabled. */  	WARN_ON(pm_runtime_enabled(&pdev->dev)); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 97d4f3ac0abd..b812d1090c0f 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -169,6 +169,7 @@  enum i2c_type_exynos {  	I2C_TYPE_EXYNOS5,  	I2C_TYPE_EXYNOS7, +	I2C_TYPE_EXYNOSAUTOV9,  };  struct exynos5_i2c { @@ -181,7 +182,8 @@ struct exynos5_i2c {  	unsigned int		irq;  	void __iomem		*regs; -	struct clk		*clk; +	struct clk		*clk;		/* operating clock */ +	struct clk		*pclk;		/* bus clock */  	struct device		*dev;  	int			state; @@ -230,6 +232,11 @@ static const struct exynos_hsi2c_variant exynos7_hsi2c_data = {  	.hw		= I2C_TYPE_EXYNOS7,  }; +static const struct exynos_hsi2c_variant exynosautov9_hsi2c_data = { +	.fifo_depth	= 64, +	.hw		= I2C_TYPE_EXYNOSAUTOV9, +}; +  static const struct of_device_id exynos5_i2c_match[] = {  	{  		.compatible = "samsung,exynos5-hsi2c", @@ -243,6 +250,9 @@ static const struct of_device_id exynos5_i2c_match[] = {  	}, {  		.compatible = "samsung,exynos7-hsi2c",  		.data = &exynos7_hsi2c_data +	}, { +		.compatible = "samsung,exynosautov9-hsi2c", +		.data = &exynosautov9_hsi2c_data  	}, {},  };  MODULE_DEVICE_TABLE(of, exynos5_i2c_match); @@ -282,6 +292,31 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)  	int div, clk_cycle, temp;  	/* +	 * In case of HSI2C controllers in ExynosAutoV9: +	 * +	 * FSCL = IPCLK / ((CLK_DIV + 1) * 16) +	 * T_SCL_LOW = IPCLK * (CLK_DIV + 1) * (N + M) +	 *   [N : number of 0's in the TSCL_H_HS] +	 *   [M : number of 0's in the TSCL_L_HS] +	 * T_SCL_HIGH = IPCLK * (CLK_DIV + 1) * (N + M) +	 *   [N : number of 1's in the TSCL_H_HS] +	 *   [M : number of 1's in the TSCL_L_HS] +	 * +	 * Result of (N + M) is always 8. +	 * In general case, we don't need to control timing_s1 and timing_s2. +	 */ +	if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) { +		div = ((clkin / (16 * i2c->op_clock)) - 1); +		i2c_timing_s3 = div << 16; +		if (hs_timings) +			writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3); +		else +			writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3); + +		return 0; +	} + +	/*  	 * In case of HSI2C controller in Exynos5 series  	 * FPCLK / FI2C =  	 * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE @@ -422,7 +457,10 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)  	writel(int_status, i2c->regs + HSI2C_INT_STATUS);  	/* handle interrupt related to the transfer status */ -	if (i2c->variant->hw == I2C_TYPE_EXYNOS7) { +	switch (i2c->variant->hw) { +	case I2C_TYPE_EXYNOSAUTOV9: +		fallthrough; +	case I2C_TYPE_EXYNOS7:  		if (int_status & HSI2C_INT_TRANS_DONE) {  			i2c->trans_done = 1;  			i2c->state = 0; @@ -443,7 +481,12 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)  			i2c->state = -ETIMEDOUT;  			goto stop;  		} -	} else if (int_status & HSI2C_INT_I2C) { + +		break; +	case I2C_TYPE_EXYNOS5: +		if (!(int_status & HSI2C_INT_I2C)) +			break; +  		trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);  		if (trans_status & HSI2C_NO_DEV_ACK) {  			dev_dbg(i2c->dev, "No ACK from device\n"); @@ -465,6 +508,8 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)  			i2c->trans_done = 1;  			i2c->state = 0;  		} + +		break;  	}  	if ((i2c->msg->flags & I2C_M_RD) && (int_status & @@ -569,13 +614,13 @@ static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)  {  	unsigned long timeout; -	if (i2c->variant->hw != I2C_TYPE_EXYNOS7) +	if (i2c->variant->hw == I2C_TYPE_EXYNOS5)  		return;  	/* -	 * HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction -	 * indicates that bus is stuck (SDA is low). In such case bus recovery -	 * can be performed. +	 * HSI2C_MASTER_ST_LOSE state (in Exynos7 and ExynosAutoV9 variants) +	 * before transaction indicates that bus is stuck (SDA is low). +	 * In such case bus recovery can be performed.  	 */  	timeout = jiffies + msecs_to_jiffies(100);  	for (;;) { @@ -611,10 +656,10 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)  	unsigned long flags;  	unsigned short trig_lvl; -	if (i2c->variant->hw == I2C_TYPE_EXYNOS7) -		int_en |= HSI2C_INT_I2C_TRANS; -	else +	if (i2c->variant->hw == I2C_TYPE_EXYNOS5)  		int_en |= HSI2C_INT_I2C; +	else +		int_en |= HSI2C_INT_I2C_TRANS;  	i2c_ctl = readl(i2c->regs + HSI2C_CTL);  	i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON); @@ -713,10 +758,14 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,  	struct exynos5_i2c *i2c = adap->algo_data;  	int i, ret; -	ret = clk_enable(i2c->clk); +	ret = clk_enable(i2c->pclk);  	if (ret)  		return ret; +	ret = clk_enable(i2c->clk); +	if (ret) +		goto err_pclk; +  	for (i = 0; i < num; ++i) {  		ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);  		if (ret) @@ -724,6 +773,8 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,  	}  	clk_disable(i2c->clk); +err_pclk: +	clk_disable(i2c->pclk);  	return ret ?: num;  } @@ -763,10 +814,20 @@ static int exynos5_i2c_probe(struct platform_device *pdev)  		return -ENOENT;  	} -	ret = clk_prepare_enable(i2c->clk); +	i2c->pclk = devm_clk_get_optional(&pdev->dev, "hsi2c_pclk"); +	if (IS_ERR(i2c->pclk)) { +		return dev_err_probe(&pdev->dev, PTR_ERR(i2c->pclk), +				     "cannot get pclk"); +	} + +	ret = clk_prepare_enable(i2c->pclk);  	if (ret)  		return ret; +	ret = clk_prepare_enable(i2c->clk); +	if (ret) +		goto err_pclk; +  	i2c->regs = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(i2c->regs)) {  		ret = PTR_ERR(i2c->regs); @@ -809,11 +870,15 @@ static int exynos5_i2c_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, i2c);  	clk_disable(i2c->clk); +	clk_disable(i2c->pclk);  	return 0;   err_clk:  	clk_disable_unprepare(i2c->clk); + + err_pclk: +	clk_disable_unprepare(i2c->pclk);  	return ret;  } @@ -824,6 +889,7 @@ static int exynos5_i2c_remove(struct platform_device *pdev)  	i2c_del_adapter(&i2c->adap);  	clk_unprepare(i2c->clk); +	clk_unprepare(i2c->pclk);  	return 0;  } @@ -835,6 +901,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev)  	i2c_mark_adapter_suspended(&i2c->adap);  	clk_unprepare(i2c->clk); +	clk_unprepare(i2c->pclk);  	return 0;  } @@ -844,21 +911,30 @@ static int exynos5_i2c_resume_noirq(struct device *dev)  	struct exynos5_i2c *i2c = dev_get_drvdata(dev);  	int ret = 0; -	ret = clk_prepare_enable(i2c->clk); +	ret = clk_prepare_enable(i2c->pclk);  	if (ret)  		return ret; +	ret = clk_prepare_enable(i2c->clk); +	if (ret) +		goto err_pclk; +  	ret = exynos5_hsi2c_clock_setup(i2c); -	if (ret) { -		clk_disable_unprepare(i2c->clk); -		return ret; -	} +	if (ret) +		goto err_clk;  	exynos5_i2c_init(i2c);  	clk_disable(i2c->clk); +	clk_disable(i2c->pclk);  	i2c_mark_adapter_resumed(&i2c->adap);  	return 0; + +err_clk: +	clk_disable_unprepare(i2c->clk); +err_pclk: +	clk_disable_unprepare(i2c->pclk); +	return ret;  }  #endif diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 41446f9cc52d..7428cc6af5cc 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -328,22 +328,14 @@ static int i801_check_pre(struct i801_priv *priv)  	status = inb_p(SMBHSTSTS(priv));  	if (status & SMBHSTSTS_HOST_BUSY) { -		dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n"); +		pci_err(priv->pci_dev, "SMBus is busy, can't use it!\n");  		return -EBUSY;  	}  	status &= STATUS_FLAGS;  	if (status) { -		dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n", -			status); +		pci_dbg(priv->pci_dev, "Clearing status flags (%02x)\n", status);  		outb_p(status, SMBHSTSTS(priv)); -		status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; -		if (status) { -			dev_err(&priv->pci_dev->dev, -				"Failed clearing status flags (%02x)\n", -				status); -			return -EBUSY; -		}  	}  	/* @@ -356,27 +348,14 @@ static int i801_check_pre(struct i801_priv *priv)  	if (priv->features & FEATURE_SMBUS_PEC) {  		status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;  		if (status) { -			dev_dbg(&priv->pci_dev->dev, -				"Clearing aux status flags (%02x)\n", status); +			pci_dbg(priv->pci_dev, "Clearing aux status flags (%02x)\n", status);  			outb_p(status, SMBAUXSTS(priv)); -			status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; -			if (status) { -				dev_err(&priv->pci_dev->dev, -					"Failed clearing aux status flags (%02x)\n", -					status); -				return -EBUSY; -			}  		}  	}  	return 0;  } -/* - * Convert the status register to an error code, and clear it. - * Note that status only contains the bits we want to clear, not the - * actual register value. - */  static int i801_check_post(struct i801_priv *priv, int status)  {  	int result = 0; @@ -401,7 +380,6 @@ static int i801_check_post(struct i801_priv *priv, int status)  		    !(status & SMBHSTSTS_FAILED))  			dev_err(&priv->pci_dev->dev,  				"Failed terminating the transaction\n"); -		outb_p(STATUS_FLAGS, SMBHSTSTS(priv));  		return -ETIMEDOUT;  	} @@ -440,9 +418,6 @@ static int i801_check_post(struct i801_priv *priv, int status)  		dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");  	} -	/* Clear status flags except BYTE_DONE, to be cleared by caller */ -	outb_p(status, SMBHSTSTS(priv)); -  	return result;  } @@ -523,9 +498,11 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,  		return -EOPNOTSUPP;  	} +	/* Set block buffer mode */ +	outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); +  	inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ -	/* Use 32-byte buffer to process this transaction */  	if (read_write == I2C_SMBUS_WRITE) {  		len = data->block[0];  		outb_p(len, SMBHSTDAT0(priv)); @@ -760,14 +737,6 @@ exit:  	return i801_check_post(priv, status);  } -static int i801_set_block_buffer_mode(struct i801_priv *priv) -{ -	outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); -	if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) -		return -EIO; -	return 0; -} -  /* Block transaction function */  static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,  				  char read_write, int command) @@ -775,6 +744,11 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *  	int result = 0;  	unsigned char hostc; +	if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA) +		data->block[0] = I2C_SMBUS_BLOCK_MAX; +	else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) +		return -EPROTO; +  	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {  		if (read_write == I2C_SMBUS_WRITE) {  			/* set I2C_EN bit in configuration register */ @@ -788,22 +762,11 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *  		}  	} -	if (read_write == I2C_SMBUS_WRITE -	 || command == I2C_SMBUS_I2C_BLOCK_DATA) { -		if (data->block[0] < 1) -			data->block[0] = 1; -		if (data->block[0] > I2C_SMBUS_BLOCK_MAX) -			data->block[0] = I2C_SMBUS_BLOCK_MAX; -	} else { -		data->block[0] = 32;	/* max for SMBus block reads */ -	} -  	/* Experience has shown that the block buffer can only be used for  	   SMBus (not I2C) block transactions, even though the datasheet  	   doesn't mention this limitation. */ -	if ((priv->features & FEATURE_BLOCK_BUFFER) -	 && command != I2C_SMBUS_I2C_BLOCK_DATA -	 && i801_set_block_buffer_mode(priv) == 0) +	if ((priv->features & FEATURE_BLOCK_BUFFER) && +	    command != I2C_SMBUS_I2C_BLOCK_DATA)  		result = i801_block_transaction_by_block(priv, data,  							 read_write,  							 command); @@ -951,8 +914,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,  	}  out: -	/* Unlock the SMBus device for use by BIOS/ACPI */ -	outb_p(SMBHSTSTS_INUSE_STS, SMBHSTSTS(priv)); +	/* +	 * Unlock the SMBus device for use by BIOS/ACPI, +	 * and clear status flags if not done already. +	 */ +	outb_p(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));  	pm_runtime_mark_last_busy(&priv->pci_dev->dev);  	pm_runtime_put_autosuspend(&priv->pci_dev->dev); @@ -1009,66 +975,72 @@ static const struct i2c_algorithm smbus_algorithm = {  	.functionality	= i801_func,  }; +#define FEATURES_ICH5	(FEATURE_BLOCK_PROC | FEATURE_I2C_BLOCK_READ	| \ +			 FEATURE_IRQ | FEATURE_SMBUS_PEC		| \ +			 FEATURE_BLOCK_BUFFER | FEATURE_HOST_NOTIFY) +#define FEATURES_ICH4	(FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER | \ +			 FEATURE_HOST_NOTIFY) +  static const struct pci_device_id i801_ids[] = { -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) }, -	{ 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_ICELAKE_N_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS) }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS) }, +	{ PCI_DEVICE_DATA(INTEL, 82801AA_3,		0)				 }, +	{ PCI_DEVICE_DATA(INTEL, 82801AB_3,		0)				 }, +	{ PCI_DEVICE_DATA(INTEL, 82801BA_2,		0)				 }, +	{ PCI_DEVICE_DATA(INTEL, 82801CA_3,		FEATURE_HOST_NOTIFY)		 }, +	{ PCI_DEVICE_DATA(INTEL, 82801DB_3,		FEATURES_ICH4)			 }, +	{ PCI_DEVICE_DATA(INTEL, 82801EB_3,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ESB_4,			FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH6_16,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH7_17,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ESB2_17,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH8_5,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH9_6,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, EP80579_1,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH10_4,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, ICH10_5,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2,	FEATURES_ICH5 | FEATURE_IDF)	 }, +	{ PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS,	FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, CDF_SMBUS,		FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, DNV_SMBUS,		FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, EBG_SMBUS,		FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS,		FEATURES_ICH5)			 }, +	{ PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_SPT) }, +	{ PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) }, +	{ PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS,	FEATURES_ICH5 | FEATURE_TCO_CNL) },  	{ 0, }  }; @@ -1493,15 +1465,14 @@ static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)  }  #endif -static const struct itco_wdt_platform_data spt_tco_platform_data = { -	.name = "Intel PCH", -	.version = 4, -}; -  static struct platform_device *  i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,  		 struct resource *tco_res)  { +	static const struct itco_wdt_platform_data pldata = { +		.name = "Intel PCH", +		.version = 4, +	};  	struct resource *res;  	unsigned int devfn;  	u64 base64_addr; @@ -1544,22 +1515,20 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,  	res->flags = IORESOURCE_MEM;  	return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, -					tco_res, 2, &spt_tco_platform_data, -					sizeof(spt_tco_platform_data)); +					tco_res, 2, &pldata, sizeof(pldata));  } -static const struct itco_wdt_platform_data cnl_tco_platform_data = { -	.name = "Intel PCH", -	.version = 6, -}; -  static struct platform_device *  i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev,  		 struct resource *tco_res)  { -	return platform_device_register_resndata(&pci_dev->dev, -			"iTCO_wdt", -1, tco_res, 1, &cnl_tco_platform_data, -			sizeof(cnl_tco_platform_data)); +	static const struct itco_wdt_platform_data pldata = { +		.name = "Intel PCH", +		.version = 6, +	}; + +	return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, +						 tco_res, 1, &pldata, sizeof(pldata));  }  static void i801_add_tco(struct i801_priv *priv) @@ -1697,72 +1666,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  	mutex_init(&priv->acpi_lock);  	priv->pci_dev = dev; -	switch (dev->device) { -	case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS: -	case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS: -	case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS: -	case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS: -	case PCI_DEVICE_ID_INTEL_DNV_SMBUS: -	case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: -	case PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS: -		priv->features |= FEATURE_BLOCK_PROC; -		priv->features |= FEATURE_I2C_BLOCK_READ; -		priv->features |= FEATURE_IRQ; -		priv->features |= FEATURE_SMBUS_PEC; -		priv->features |= FEATURE_BLOCK_BUFFER; -		priv->features |= FEATURE_TCO_SPT; -		priv->features |= FEATURE_HOST_NOTIFY; -		break; - -	case PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS: -	case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS: -	case PCI_DEVICE_ID_INTEL_CDF_SMBUS: -	case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: -	case PCI_DEVICE_ID_INTEL_ICELAKE_N_SMBUS: -	case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: -	case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS: -	case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: -	case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS: -	case PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS: -	case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS: -	case PCI_DEVICE_ID_INTEL_EBG_SMBUS: -	case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS: -	case PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS: -	case PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS: -		priv->features |= FEATURE_BLOCK_PROC; -		priv->features |= FEATURE_I2C_BLOCK_READ; -		priv->features |= FEATURE_IRQ; -		priv->features |= FEATURE_SMBUS_PEC; -		priv->features |= FEATURE_BLOCK_BUFFER; -		priv->features |= FEATURE_TCO_CNL; -		priv->features |= FEATURE_HOST_NOTIFY; -		break; - -	case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0: -	case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1: -	case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2: -	case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0: -	case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1: -	case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2: -		priv->features |= FEATURE_IDF; -		fallthrough; -	default: -		priv->features |= FEATURE_BLOCK_PROC; -		priv->features |= FEATURE_I2C_BLOCK_READ; -		priv->features |= FEATURE_IRQ; -		fallthrough; -	case PCI_DEVICE_ID_INTEL_82801DB_3: -		priv->features |= FEATURE_SMBUS_PEC; -		priv->features |= FEATURE_BLOCK_BUFFER; -		fallthrough; -	case PCI_DEVICE_ID_INTEL_82801CA_3: -		priv->features |= FEATURE_HOST_NOTIFY; -		fallthrough; -	case PCI_DEVICE_ID_INTEL_82801BA_2: -	case PCI_DEVICE_ID_INTEL_82801AB_3: -	case PCI_DEVICE_ID_INTEL_82801AA_3: -		break; -	} +	priv->features = id->driver_data;  	/* Disable features on user request */  	for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 3576b63a6c03..27f969b3dc07 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -37,6 +37,8 @@  #include <linux/io.h>  #include <linux/iopoll.h>  #include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/hrtimer.h>  #include <linux/module.h>  #include <linux/of.h>  #include <linux/of_device.h> @@ -51,6 +53,8 @@  /* This will be the driver name the kernel reports */  #define DRIVER_NAME "imx-i2c" +#define I2C_IMX_CHECK_DELAY 30000 /* Time to check for bus idle, in NS */ +  /*   * Enable DMA if transfer byte size is bigger than this threshold.   * As the hardware request, it must bigger than 4 bytes.\ @@ -210,6 +214,10 @@ struct imx_i2c_struct {  	struct imx_i2c_dma	*dma;  	struct i2c_client	*slave;  	enum i2c_slave_event last_slave_event; + +	/* For checking slave events. */ +	spinlock_t     slave_lock; +	struct hrtimer slave_timer;  };  static const struct imx_i2c_hwdata imx1_i2c_hwdata = { @@ -680,7 +688,7 @@ static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,  static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)  { -	u8 val; +	u8 val = 0;  	while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) {  		switch (i2c_imx->last_slave_event) { @@ -701,10 +709,11 @@ static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)  	}  } -static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, -				     unsigned int status, unsigned int ctl) +/* Returns true if the timer should be restarted, false if not. */ +static irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx, +					unsigned int status, unsigned int ctl)  { -	u8 value; +	u8 value = 0;  	if (status & I2SR_IAL) { /* Arbitration lost */  		i2c_imx_clear_irq(i2c_imx, I2SR_IAL); @@ -712,6 +721,16 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,  			return IRQ_HANDLED;  	} +	if (!(status & I2SR_IBB)) { +		/* No master on the bus, that could mean a stop condition. */ +		i2c_imx_slave_finish_op(i2c_imx); +		return IRQ_HANDLED; +	} + +	if (!(status & I2SR_ICF)) +		/* Data transfer still in progress, ignore this. */ +		goto out; +  	if (status & I2SR_IAAS) { /* Addressed as a slave */  		i2c_imx_slave_finish_op(i2c_imx);  		if (status & I2SR_SRW) { /* Master wants to read from us*/ @@ -737,16 +756,9 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,  			imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);  		}  	} else if (!(ctl & I2CR_MTX)) { /* Receive mode */ -		if (status & I2SR_IBB) { /* No STOP signal detected */ -			value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); -			i2c_imx_slave_event(i2c_imx, -					    I2C_SLAVE_WRITE_RECEIVED, &value); -		} else { /* STOP signal is detected */ -			dev_dbg(&i2c_imx->adapter.dev, -				"STOP signal detected"); -			i2c_imx_slave_event(i2c_imx, -					    I2C_SLAVE_STOP, &value); -		} +		value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); +		i2c_imx_slave_event(i2c_imx, +				    I2C_SLAVE_WRITE_RECEIVED, &value);  	} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */  		ctl |= I2CR_MTX;  		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); @@ -755,15 +767,43 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,  				    I2C_SLAVE_READ_PROCESSED, &value);  		imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); -	} else { /* Transmit mode received NAK */ +	} else { /* Transmit mode received NAK, operation is done */  		ctl &= ~I2CR_MTX;  		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);  		imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); +		i2c_imx_slave_finish_op(i2c_imx); +		return IRQ_HANDLED;  	} +out: +	/* +	 * No need to check the return value here.  If it returns 0 or +	 * 1, then everything is fine.  If it returns -1, then the +	 * timer is running in the handler.  This will still work, +	 * though it may be redone (or already have been done) by the +	 * timer function. +	 */ +	hrtimer_try_to_cancel(&i2c_imx->slave_timer); +	hrtimer_forward_now(&i2c_imx->slave_timer, I2C_IMX_CHECK_DELAY); +	hrtimer_restart(&i2c_imx->slave_timer);  	return IRQ_HANDLED;  } +static enum hrtimer_restart i2c_imx_slave_timeout(struct hrtimer *t) +{ +	struct imx_i2c_struct *i2c_imx = container_of(t, struct imx_i2c_struct, +						      slave_timer); +	unsigned int ctl, status; +	unsigned long flags; + +	spin_lock_irqsave(&i2c_imx->slave_lock, flags); +	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); +	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +	i2c_imx_slave_handle(i2c_imx, status, ctl); +	spin_unlock_irqrestore(&i2c_imx->slave_lock, flags); +	return HRTIMER_NORESTART; +} +  static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx)  {  	int temp; @@ -843,7 +883,9 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)  {  	struct imx_i2c_struct *i2c_imx = dev_id;  	unsigned int ctl, status; +	unsigned long flags; +	spin_lock_irqsave(&i2c_imx->slave_lock, flags);  	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);  	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); @@ -851,14 +893,20 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)  		i2c_imx_clear_irq(i2c_imx, I2SR_IIF);  		if (i2c_imx->slave) {  			if (!(ctl & I2CR_MSTA)) { -				return i2c_imx_slave_isr(i2c_imx, status, ctl); -			} else if (i2c_imx->last_slave_event != -				   I2C_SLAVE_STOP) { -				i2c_imx_slave_finish_op(i2c_imx); +				irqreturn_t ret; + +				ret = i2c_imx_slave_handle(i2c_imx, +							   status, ctl); +				spin_unlock_irqrestore(&i2c_imx->slave_lock, +						       flags); +				return ret;  			} +			i2c_imx_slave_finish_op(i2c_imx);  		} +		spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);  		return i2c_imx_master_isr(i2c_imx, status);  	} +	spin_unlock_irqrestore(&i2c_imx->slave_lock, flags);  	return IRQ_NONE;  } @@ -1378,6 +1426,10 @@ static int i2c_imx_probe(struct platform_device *pdev)  	if (!i2c_imx)  		return -ENOMEM; +	spin_lock_init(&i2c_imx->slave_lock); +	hrtimer_init(&i2c_imx->slave_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); +	i2c_imx->slave_timer.function = i2c_imx_slave_timeout; +  	match = device_get_match_data(&pdev->dev);  	if (match)  		i2c_imx->hwdata = match; @@ -1491,6 +1543,8 @@ static int i2c_imx_remove(struct platform_device *pdev)  	if (ret < 0)  		return ret; +	hrtimer_cancel(&i2c_imx->slave_timer); +  	/* remove adapter */  	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");  	i2c_del_adapter(&i2c_imx->adapter); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index db26cc36e13f..6c698c10d3cd 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -119,23 +119,30 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x)  /* Sometimes 9th clock pulse isn't generated, and slave doesn't release   * the bus, because it wants to send ACK.   * Following sequence of enabling/disabling and sending start/stop generates - * the 9 pulses, so it's all OK. + * the 9 pulses, each with a START then ending with STOP, so it's all OK.   */  static void mpc_i2c_fixup(struct mpc_i2c *i2c)  {  	int k; -	u32 delay_val = 1000000 / i2c->real_clk + 1; - -	if (delay_val < 2) -		delay_val = 2; +	unsigned long flags;  	for (k = 9; k; k--) {  		writeccr(i2c, 0); -		writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); +		writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */ +		writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */ +		readb(i2c->base + MPC_I2C_DR); /* init xfer */ +		udelay(15); /* let it hit the bus */ +		local_irq_save(flags); /* should not be delayed further */ +		writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */  		readb(i2c->base + MPC_I2C_DR); -		writeccr(i2c, CCR_MEN); -		udelay(delay_val << 1); +		if (k != 1) +			udelay(5); +		local_irq_restore(flags);  	} +	writeccr(i2c, CCR_MEN); /* Initiate STOP */ +	readb(i2c->base + MPC_I2C_DR); +	udelay(15); /* Let STOP propagate */ +	writeccr(i2c, 0);  }  static int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index fc13511f4562..f71c730f9838 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -367,11 +367,15 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)  	rcar_i2c_prepare_msg(priv);  } -static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv) +static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv, bool terminate)  {  	struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE  		? priv->dma_rx : priv->dma_tx; +	/* only allowed from thread context! */ +	if (terminate) +		dmaengine_terminate_sync(chan); +  	dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),  			 sg_dma_len(&priv->sg), priv->dma_direction); @@ -386,25 +390,13 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)  	rcar_i2c_write(priv, ICDMAER, 0);  } -static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv) -{ -	if (priv->dma_direction == DMA_NONE) -		return; -	else if (priv->dma_direction == DMA_FROM_DEVICE) -		dmaengine_terminate_all(priv->dma_rx); -	else if (priv->dma_direction == DMA_TO_DEVICE) -		dmaengine_terminate_all(priv->dma_tx); - -	rcar_i2c_dma_unmap(priv); -} -  static void rcar_i2c_dma_callback(void *data)  {  	struct rcar_i2c_priv *priv = data;  	priv->pos += sg_dma_len(&priv->sg); -	rcar_i2c_dma_unmap(priv); +	rcar_i2c_cleanup_dma(priv, false);  }  static bool rcar_i2c_dma(struct rcar_i2c_priv *priv) @@ -456,7 +448,7 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv)  					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);  	if (!txdesc) {  		dev_dbg(dev, "dma prep slave sg failed, using PIO\n"); -		rcar_i2c_cleanup_dma(priv); +		rcar_i2c_cleanup_dma(priv, false);  		return false;  	} @@ -466,7 +458,7 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv)  	cookie = dmaengine_submit(txdesc);  	if (dma_submit_error(cookie)) {  		dev_dbg(dev, "submitting dma failed, using PIO\n"); -		rcar_i2c_cleanup_dma(priv); +		rcar_i2c_cleanup_dma(priv, false);  		return false;  	} @@ -846,7 +838,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,  	/* cleanup DMA if it couldn't complete properly due to an error */  	if (priv->dma_direction != DMA_NONE) -		rcar_i2c_cleanup_dma(priv); +		rcar_i2c_cleanup_dma(priv, true);  	if (!time_left) {  		rcar_i2c_init(priv); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 78b84445ee6a..8dfd27dc6149 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -433,12 +433,12 @@ static int riic_i2c_probe(struct platform_device *pdev)  	}  	for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { -		res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num); -		if (!res) -			return -ENODEV; +		ret = platform_get_irq(pdev, riic_irqs[i].res_num); +		if (ret < 0) +			return ret; -		ret = devm_request_irq(&pdev->dev, res->start, riic_irqs[i].isr, -					0, riic_irqs[i].name, riic); +		ret = devm_request_irq(&pdev->dev, ret, riic_irqs[i].isr, +				       0, riic_irqs[i].name, riic);  		if (ret) {  			dev_err(&pdev->dev, "failed to request irq %s\n", riic_irqs[i].name);  			return ret; diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 02ddb237f69a..989040a73626 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1338,8 +1338,15 @@ static int rk3x_i2c_probe(struct platform_device *pdev)  		goto err_pclk;  	} +	ret = clk_enable(i2c->clk); +	if (ret < 0) { +		dev_err(&pdev->dev, "Can't enable bus clk: %d\n", ret); +		goto err_clk_notifier; +	} +  	clk_rate = clk_get_rate(i2c->clk);  	rk3x_i2c_adapt_div(i2c, clk_rate); +	clk_disable(i2c->clk);  	ret = i2c_add_adapter(&i2c->adap);  	if (ret < 0) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index db8fa4186814..72f024a0c363 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -442,34 +442,26 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static void sh_mobile_i2c_dma_unmap(struct sh_mobile_i2c_data *pd) +static void sh_mobile_i2c_cleanup_dma(struct sh_mobile_i2c_data *pd, bool terminate)  {  	struct dma_chan *chan = pd->dma_direction == DMA_FROM_DEVICE  				? pd->dma_rx : pd->dma_tx; +	/* only allowed from thread context! */ +	if (terminate) +		dmaengine_terminate_sync(chan); +  	dma_unmap_single(chan->device->dev, sg_dma_address(&pd->sg),  			 pd->msg->len, pd->dma_direction);  	pd->dma_direction = DMA_NONE;  } -static void sh_mobile_i2c_cleanup_dma(struct sh_mobile_i2c_data *pd) -{ -	if (pd->dma_direction == DMA_NONE) -		return; -	else if (pd->dma_direction == DMA_FROM_DEVICE) -		dmaengine_terminate_sync(pd->dma_rx); -	else if (pd->dma_direction == DMA_TO_DEVICE) -		dmaengine_terminate_sync(pd->dma_tx); - -	sh_mobile_i2c_dma_unmap(pd); -} -  static void sh_mobile_i2c_dma_callback(void *data)  {  	struct sh_mobile_i2c_data *pd = data; -	sh_mobile_i2c_dma_unmap(pd); +	sh_mobile_i2c_cleanup_dma(pd, false);  	pd->pos = pd->msg->len;  	pd->stop_after_dma = true; @@ -549,7 +541,7 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)  					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);  	if (!txdesc) {  		dev_dbg(pd->dev, "dma prep slave sg failed, using PIO\n"); -		sh_mobile_i2c_cleanup_dma(pd); +		sh_mobile_i2c_cleanup_dma(pd, false);  		return;  	} @@ -559,7 +551,7 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)  	cookie = dmaengine_submit(txdesc);  	if (dma_submit_error(cookie)) {  		dev_dbg(pd->dev, "submitting dma failed, using PIO\n"); -		sh_mobile_i2c_cleanup_dma(pd); +		sh_mobile_i2c_cleanup_dma(pd, false);  		return;  	} @@ -698,7 +690,7 @@ static int sh_mobile_xfer(struct sh_mobile_i2c_data *pd,  		if (!time_left) {  			dev_err(pd->dev, "Transfer request timed out\n");  			if (pd->dma_direction != DMA_NONE) -				sh_mobile_i2c_cleanup_dma(pd); +				sh_mobile_i2c_cleanup_dma(pd, true);  			err = -ETIMEDOUT;  			break; @@ -838,20 +830,38 @@ static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd)  static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, struct sh_mobile_i2c_data *pd)  { -	struct resource *res; -	resource_size_t n; +	struct device_node *np = dev_of_node(&dev->dev);  	int k = 0, ret; -	while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { -		for (n = res->start; n <= res->end; n++) { -			ret = devm_request_irq(&dev->dev, n, sh_mobile_i2c_isr, -					  0, dev_name(&dev->dev), pd); +	if (np) { +		int irq; + +		while ((irq = platform_get_irq_optional(dev, k)) != -ENXIO) { +			if (irq < 0) +				return irq; +			ret = devm_request_irq(&dev->dev, irq, sh_mobile_i2c_isr, +					       0, dev_name(&dev->dev), pd);  			if (ret) { -				dev_err(&dev->dev, "cannot request IRQ %pa\n", &n); +				dev_err(&dev->dev, "cannot request IRQ %d\n", irq);  				return ret;  			} +			k++; +		} +	} else { +		struct resource *res; +		resource_size_t n; + +		while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { +			for (n = res->start; n <= res->end; n++) { +				ret = devm_request_irq(&dev->dev, n, sh_mobile_i2c_isr, +						       0, dev_name(&dev->dev), pd); +				if (ret) { +					dev_err(&dev->dev, "cannot request IRQ %pa\n", &n); +					return ret; +				} +			} +			k++;  		} -		k++;  	}  	return k > 0 ? 0 : -ENOENT; diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 66145d2b9b55..6d4aa64b195d 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -828,18 +828,14 @@ static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)  	writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);  } -static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap) +static void stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)  {  	struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); -	dev_info(i2c_dev->dev, "Trying to recover bus\n"); -  	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,  			     STM32F7_I2C_CR1_PE);  	stm32f7_i2c_hw_config(i2c_dev); - -	return 0;  }  static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev) @@ -854,13 +850,7 @@ static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)  	if (!ret)  		return 0; -	dev_info(i2c_dev->dev, "bus busy\n"); - -	ret = stm32f7_i2c_release_bus(&i2c_dev->adap); -	if (ret) { -		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret); -		return ret; -	} +	stm32f7_i2c_release_bus(&i2c_dev->adap);  	return -EBUSY;  } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index b3184c422826..03cea102ab76 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -6,6 +6,7 @@   * Author: Colin Cross <[email protected]>   */ +#include <linux/acpi.h>  #include <linux/bitfield.h>  #include <linux/clk.h>  #include <linux/delay.h> @@ -245,7 +246,7 @@ struct tegra_i2c_hw_feature {   * @msg_buf: pointer to current message data   * @msg_buf_remaining: size of unsent data in the message buffer   * @msg_read: indicates that the transfer is a read access - * @bus_clk_rate: current I2C bus clock rate + * @timings: i2c timings information like bus frequency   * @multimaster_mode: indicates that I2C controller is in multi-master mode   * @tx_dma_chan: DMA transmit channel   * @rx_dma_chan: DMA receive channel @@ -272,7 +273,7 @@ struct tegra_i2c_dev {  	unsigned int nclocks;  	struct clk *div_clk; -	u32 bus_clk_rate; +	struct i2c_timings timings;  	struct completion msg_complete;  	size_t msg_buf_remaining; @@ -608,6 +609,8 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)  static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  {  	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; +	acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); +	struct i2c_timings *t = &i2c_dev->timings;  	int err;  	/* @@ -618,7 +621,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  	 * emit a noisy warning on error, which won't stay unnoticed and  	 * won't hose machine entirely.  	 */ -	err = reset_control_reset(i2c_dev->rst); +	if (handle) +		err = acpi_evaluate_object(handle, "_RST", NULL, NULL); +	else +		err = reset_control_reset(i2c_dev->rst); +  	WARN_ON_ONCE(err);  	if (i2c_dev->is_dvc) @@ -636,14 +643,14 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  	if (i2c_dev->is_vi)  		tegra_i2c_vi_init(i2c_dev); -	switch (i2c_dev->bus_clk_rate) { +	switch (t->bus_freq_hz) {  	case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:  	default:  		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; -		if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ) +		if (t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ)  			non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode;  		else  			non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode; @@ -679,7 +686,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)  	clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1);  	err = clk_set_rate(i2c_dev->div_clk, -			   i2c_dev->bus_clk_rate * clk_multiplier); +			   t->bus_freq_hz * clk_multiplier);  	if (err) {  		dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err);  		return err; @@ -718,7 +725,7 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)  	 * before disabling the controller so that the STOP condition has  	 * been delivered properly.  	 */ -	udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate)); +	udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->timings.bus_freq_hz));  	cnfg = i2c_readl(i2c_dev, I2C_CNFG);  	if (cnfg & I2C_CNFG_PACKET_MODE_EN) @@ -1248,7 +1255,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,  	 * 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); +				       i2c_dev->timings.bus_freq_hz);  	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;  	tegra_i2c_unmask_irq(i2c_dev, int_mask); @@ -1625,14 +1632,10 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)  {  	struct device_node *np = i2c_dev->dev->of_node;  	bool multi_mode; -	int err; -	err = of_property_read_u32(np, "clock-frequency", -				   &i2c_dev->bus_clk_rate); -	if (err) -		i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; +	i2c_parse_fw_timings(i2c_dev->dev, &i2c_dev->timings, true); -	multi_mode = of_property_read_bool(np, "multi-master"); +	multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");  	i2c_dev->multimaster_mode = multi_mode;  	if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc")) @@ -1642,10 +1645,26 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)  		i2c_dev->is_vi = true;  } +static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev) +{ +	if (ACPI_HANDLE(i2c_dev->dev)) +		return 0; + +	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); +	if (IS_ERR(i2c_dev->rst)) +		return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), +				      "failed to get reset control\n"); + +	return 0; +} +  static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)  {  	int err; +	if (ACPI_HANDLE(i2c_dev->dev)) +		return 0; +  	i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk";  	if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw) @@ -1720,7 +1739,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)  	init_completion(&i2c_dev->msg_complete);  	init_completion(&i2c_dev->dma_complete); -	i2c_dev->hw = of_device_get_match_data(&pdev->dev); +	i2c_dev->hw = device_get_match_data(&pdev->dev);  	i2c_dev->cont_id = pdev->id;  	i2c_dev->dev = &pdev->dev; @@ -1746,15 +1765,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)  	if (err)  		return err; -	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); -	if (IS_ERR(i2c_dev->rst)) { -		dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), -			      "failed to get reset control\n"); -		return PTR_ERR(i2c_dev->rst); -	} -  	tegra_i2c_parse_dt(i2c_dev); +	err = tegra_i2c_init_reset(i2c_dev); +	if (err) +		return err; +  	err = tegra_i2c_init_clocks(i2c_dev);  	if (err)  		return err; @@ -1923,12 +1939,21 @@ static const struct dev_pm_ops tegra_i2c_pm = {  			   NULL)  }; +static const struct acpi_device_id tegra_i2c_acpi_match[] = { +	{.id = "NVDA0101", .driver_data = (kernel_ulong_t)&tegra210_i2c_hw}, +	{.id = "NVDA0201", .driver_data = (kernel_ulong_t)&tegra186_i2c_hw}, +	{.id = "NVDA0301", .driver_data = (kernel_ulong_t)&tegra194_i2c_hw}, +	{ } +}; +MODULE_DEVICE_TABLE(acpi, tegra_i2c_acpi_match); +  static struct platform_driver tegra_i2c_driver = {  	.probe = tegra_i2c_probe,  	.remove = tegra_i2c_remove,  	.driver = {  		.name = "tegra-i2c",  		.of_match_table = tegra_i2c_of_match, +		.acpi_match_table = tegra_i2c_acpi_match,  		.pm = &tegra_i2c_pm,  	},  }; diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c index 41eb0dcc3204..4b9536f50800 100644 --- a/drivers/i2c/busses/i2c-virtio.c +++ b/drivers/i2c/busses/i2c-virtio.c @@ -165,7 +165,7 @@ err_free:  static void virtio_i2c_del_vqs(struct virtio_device *vdev)  { -	vdev->config->reset(vdev); +	virtio_reset_device(vdev);  	vdev->config->del_vqs(vdev);  } diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 6d24dc385522..4e3b11c0f732 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -572,12 +572,6 @@ static int xlp9xx_i2c_remove(struct platform_device *pdev)  	return 0;  } -static const struct of_device_id xlp9xx_i2c_of_match[] = { -	{ .compatible = "netlogic,xlp980-i2c", }, -	{ /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, xlp9xx_i2c_of_match); -  #ifdef CONFIG_ACPI  static const struct acpi_device_id xlp9xx_i2c_acpi_ids[] = {  	{"BRCM9007", 0}, @@ -592,7 +586,6 @@ static struct platform_driver xlp9xx_i2c_driver = {  	.remove = xlp9xx_i2c_remove,  	.driver = {  		.name = "xlp9xx-i2c", -		.of_match_table = xlp9xx_i2c_of_match,  		.acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids),  	},  }; diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c deleted file mode 100644 index 9ce20652d494..000000000000 --- a/drivers/i2c/busses/i2c-xlr.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright 2011, Netlogic Microsystems Inc. - * Copyright 2004, Matt Porter <[email protected]> - * - * 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/err.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/of_device.h> -#include <linux/clk.h> -#include <linux/interrupt.h> -#include <linux/wait.h> - -/* XLR I2C REGISTERS */ -#define XLR_I2C_CFG		0x00 -#define XLR_I2C_CLKDIV		0x01 -#define XLR_I2C_DEVADDR		0x02 -#define XLR_I2C_ADDR		0x03 -#define XLR_I2C_DATAOUT		0x04 -#define XLR_I2C_DATAIN		0x05 -#define XLR_I2C_STATUS		0x06 -#define XLR_I2C_STARTXFR	0x07 -#define XLR_I2C_BYTECNT		0x08 -#define XLR_I2C_HDSTATIM	0x09 - -/* Sigma Designs additional registers */ -#define XLR_I2C_INT_EN		0x09 -#define XLR_I2C_INT_STAT	0x0a - -/* XLR I2C REGISTERS FLAGS */ -#define XLR_I2C_BUS_BUSY	0x01 -#define XLR_I2C_SDOEMPTY	0x02 -#define XLR_I2C_RXRDY		0x04 -#define XLR_I2C_ACK_ERR		0x08 -#define XLR_I2C_ARB_STARTERR	0x30 - -/* Register Values */ -#define XLR_I2C_CFG_ADDR	0xF8 -#define XLR_I2C_CFG_NOADDR	0xFA -#define XLR_I2C_STARTXFR_ND	0x02    /* No Data */ -#define XLR_I2C_STARTXFR_RD	0x01    /* Read */ -#define XLR_I2C_STARTXFR_WR	0x00    /* Write */ - -#define XLR_I2C_TIMEOUT		10	/* timeout per byte in msec */ - -/* - * On XLR/XLS, we need to use __raw_ IO to read the I2C registers - * because they are in the big-endian MMIO area on the SoC. - * - * The readl/writel implementation on XLR/XLS byteswaps, because - * those are for its little-endian PCI space (see arch/mips/Kconfig). - */ -static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val) -{ -	__raw_writel(val, base + reg); -} - -static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg) -{ -	return __raw_readl(base + reg); -} - -#define XLR_I2C_FLAG_IRQ	1 - -struct xlr_i2c_config { -	u32 flags;		/* optional feature support */ -	u32 status_busy;	/* value of STATUS[0] when busy */ -	u32 cfg_extra;		/* extra CFG bits to set */ -}; - -struct xlr_i2c_private { -	struct i2c_adapter adap; -	u32 __iomem *iobase; -	int irq; -	int pos; -	struct i2c_msg *msg; -	const struct xlr_i2c_config *cfg; -	wait_queue_head_t wait; -	struct clk *clk; -}; - -static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status) -{ -	return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy; -} - -static int xlr_i2c_idle(struct xlr_i2c_private *priv) -{ -	return !xlr_i2c_busy(priv, xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS)); -} - -static int xlr_i2c_wait(struct xlr_i2c_private *priv, unsigned long timeout) -{ -	int status; -	int t; - -	t = wait_event_timeout(priv->wait, xlr_i2c_idle(priv), -				msecs_to_jiffies(timeout)); -	if (!t) -		return -ETIMEDOUT; - -	status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); - -	return status & XLR_I2C_ACK_ERR ? -EIO : 0; -} - -static void xlr_i2c_tx_irq(struct xlr_i2c_private *priv, u32 status) -{ -	struct i2c_msg *msg = priv->msg; - -	if (status & XLR_I2C_SDOEMPTY) -		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, -				msg->buf[priv->pos++]); -} - -static void xlr_i2c_rx_irq(struct xlr_i2c_private *priv, u32 status) -{ -	struct i2c_msg *msg = priv->msg; - -	if (status & XLR_I2C_RXRDY) -		msg->buf[priv->pos++] = -			xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN); -} - -static irqreturn_t xlr_i2c_irq(int irq, void *dev_id) -{ -	struct xlr_i2c_private *priv = dev_id; -	struct i2c_msg *msg = priv->msg; -	u32 int_stat, status; - -	int_stat = xlr_i2c_rdreg(priv->iobase, XLR_I2C_INT_STAT); -	if (!int_stat) -		return IRQ_NONE; - -	xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, int_stat); - -	if (!msg) -		return IRQ_HANDLED; - -	status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); - -	if (priv->pos < msg->len) { -		if (msg->flags & I2C_M_RD) -			xlr_i2c_rx_irq(priv, status); -		else -			xlr_i2c_tx_irq(priv, status); -	} - -	if (!xlr_i2c_busy(priv, status)) -		wake_up(&priv->wait); - -	return IRQ_HANDLED; -} - -static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len, -	u8 *buf, u16 addr) -{ -	struct i2c_adapter *adap = &priv->adap; -	unsigned long timeout, stoptime, checktime; -	u32 i2c_status; -	int pos, timedout; -	u8 offset; -	u32 xfer; - -	offset = buf[0]; -	xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset); -	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); -	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, -			XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra); - -	timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); -	stoptime = jiffies + timeout; -	timedout = 0; - -	if (len == 1) { -		xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1); -		xfer = XLR_I2C_STARTXFR_ND; -		pos = 1; -	} else { -		xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 2); -		xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[1]); -		xfer = XLR_I2C_STARTXFR_WR; -		pos = 2; -	} - -	priv->pos = pos; - -retry: -	/* retry can only happen on the first byte */ -	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, xfer); - -	if (priv->irq > 0) -		return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len); - -	while (!timedout) { -		checktime = jiffies; -		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); - -		if ((i2c_status & XLR_I2C_SDOEMPTY) && pos < len) { -			xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos++]); - -			/* reset timeout on successful xmit */ -			stoptime = jiffies + timeout; -		} -		timedout = time_after(checktime, stoptime); - -		if (i2c_status & XLR_I2C_ARB_STARTERR) { -			if (timedout) -				break; -			goto retry; -		} - -		if (i2c_status & XLR_I2C_ACK_ERR) -			return -EIO; - -		if (!xlr_i2c_busy(priv, i2c_status) && pos >= len) -			return 0; -	} -	dev_err(&adap->dev, "I2C transmit timeout\n"); -	return -ETIMEDOUT; -} - -static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr) -{ -	struct i2c_adapter *adap = &priv->adap; -	u32 i2c_status; -	unsigned long timeout, stoptime, checktime; -	int nbytes, timedout; - -	xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, -			XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra); -	xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1); -	xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); - -	priv->pos = 0; - -	timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); -	stoptime = jiffies + timeout; -	timedout = 0; -	nbytes = 0; -retry: -	xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD); - -	if (priv->irq > 0) -		return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len); - -	while (!timedout) { -		checktime = jiffies; -		i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); -		if (i2c_status & XLR_I2C_RXRDY) { -			if (nbytes >= len) -				return -EIO;	/* should not happen */ - -			buf[nbytes++] = -				xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN); - -			/* reset timeout on successful read */ -			stoptime = jiffies + timeout; -		} - -		timedout = time_after(checktime, stoptime); -		if (i2c_status & XLR_I2C_ARB_STARTERR) { -			if (timedout) -				break; -			goto retry; -		} - -		if (i2c_status & XLR_I2C_ACK_ERR) -			return -EIO; - -		if (!xlr_i2c_busy(priv, i2c_status)) -			return 0; -	} - -	dev_err(&adap->dev, "I2C receive timeout\n"); -	return -ETIMEDOUT; -} - -static int xlr_i2c_xfer(struct i2c_adapter *adap, -	struct i2c_msg *msgs, int num) -{ -	struct i2c_msg *msg; -	int i; -	int ret = 0; -	struct xlr_i2c_private *priv = i2c_get_adapdata(adap); - -	ret = clk_enable(priv->clk); -	if (ret) -		return ret; - -	if (priv->irq) -		xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0xf); - - -	for (i = 0; ret == 0 && i < num; i++) { -		msg = &msgs[i]; -		priv->msg = msg; -		if (msg->flags & I2C_M_RD) -			ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0], -					msg->addr); -		else -			ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0], -					msg->addr); -	} - -	if (priv->irq) -		xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0); - -	clk_disable(priv->clk); -	priv->msg = NULL; - -	return (ret != 0) ? ret : num; -} - -static u32 xlr_func(struct i2c_adapter *adap) -{ -	/* Emulate SMBUS over I2C */ -	return (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_I2C; -} - -static const struct i2c_algorithm xlr_i2c_algo = { -	.master_xfer	= xlr_i2c_xfer, -	.functionality	= xlr_func, -}; - -static const struct i2c_adapter_quirks xlr_i2c_quirks = { -	.flags = I2C_AQ_NO_ZERO_LEN, -}; - -static const struct xlr_i2c_config xlr_i2c_config_default = { -	.status_busy	= XLR_I2C_BUS_BUSY, -	.cfg_extra	= 0, -}; - -static const struct xlr_i2c_config xlr_i2c_config_tangox = { -	.flags		= XLR_I2C_FLAG_IRQ, -	.status_busy	= 0, -	.cfg_extra	= 1 << 8, -}; - -static const struct of_device_id xlr_i2c_dt_ids[] = { -	{ -		.compatible	= "sigma,smp8642-i2c", -		.data		= &xlr_i2c_config_tangox, -	}, -	{ } -}; -MODULE_DEVICE_TABLE(of, xlr_i2c_dt_ids); - -static int xlr_i2c_probe(struct platform_device *pdev) -{ -	const struct of_device_id *match; -	struct xlr_i2c_private  *priv; -	struct clk *clk; -	unsigned long clk_rate; -	unsigned long clk_div; -	u32 busfreq; -	int irq; -	int ret; - -	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -	if (!priv) -		return -ENOMEM; - -	match = of_match_device(xlr_i2c_dt_ids, &pdev->dev); -	if (match) -		priv->cfg = match->data; -	else -		priv->cfg = &xlr_i2c_config_default; - -	priv->iobase = devm_platform_ioremap_resource(pdev, 0); -	if (IS_ERR(priv->iobase)) -		return PTR_ERR(priv->iobase); - -	irq = platform_get_irq(pdev, 0); - -	if (irq > 0 && (priv->cfg->flags & XLR_I2C_FLAG_IRQ)) { -		priv->irq = irq; - -		xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0); -		xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, 0xf); - -		ret = devm_request_irq(&pdev->dev, priv->irq, xlr_i2c_irq, -					IRQF_SHARED, dev_name(&pdev->dev), -					priv); -		if (ret) -			return ret; - -		init_waitqueue_head(&priv->wait); -	} - -	if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", -				 &busfreq)) -		busfreq = I2C_MAX_STANDARD_MODE_FREQ; - -	clk = devm_clk_get(&pdev->dev, NULL); -	if (!IS_ERR(clk)) { -		ret = clk_prepare_enable(clk); -		if (ret) -			return ret; - -		clk_rate = clk_get_rate(clk); -		clk_div = DIV_ROUND_UP(clk_rate, 2 * busfreq); -		xlr_i2c_wreg(priv->iobase, XLR_I2C_CLKDIV, clk_div); - -		clk_disable(clk); -		priv->clk = clk; -	} - -	priv->adap.dev.parent = &pdev->dev; -	priv->adap.dev.of_node	= pdev->dev.of_node; -	priv->adap.owner	= THIS_MODULE; -	priv->adap.algo_data	= priv; -	priv->adap.algo		= &xlr_i2c_algo; -	priv->adap.quirks	= &xlr_i2c_quirks; -	priv->adap.nr		= pdev->id; -	priv->adap.class	= I2C_CLASS_HWMON; -	snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c"); - -	i2c_set_adapdata(&priv->adap, priv); -	ret = i2c_add_numbered_adapter(&priv->adap); -	if (ret < 0) -		goto err_unprepare_clk; - -	platform_set_drvdata(pdev, priv); -	dev_info(&priv->adap.dev, "Added I2C Bus.\n"); -	return 0; - -err_unprepare_clk: -	clk_unprepare(clk); -	return ret; -} - -static int xlr_i2c_remove(struct platform_device *pdev) -{ -	struct xlr_i2c_private *priv; - -	priv = platform_get_drvdata(pdev); -	i2c_del_adapter(&priv->adap); -	clk_unprepare(priv->clk); - -	return 0; -} - -static struct platform_driver xlr_i2c_driver = { -	.probe  = xlr_i2c_probe, -	.remove = xlr_i2c_remove, -	.driver = { -		.name   = "xlr-i2cbus", -		.of_match_table	= xlr_i2c_dt_ids, -	}, -}; - -module_platform_driver(xlr_i2c_driver); - -MODULE_AUTHOR("Ganesan Ramalingam <[email protected]>"); -MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:xlr-i2cbus"); diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 92c1cc07ed46..85ed4c1d4924 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,  	struct list_head resource_list;  	int ret; -	if (acpi_bus_get_status(adev) || !adev->status.present) +	if (acpi_bus_get_status(adev))  		return -EINVAL; +	if (!acpi_dev_ready_for_enumeration(adev)) +		return -ENODEV; +  	if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)  		return -ENODEV; @@ -254,6 +257,13 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter,  				     struct acpi_device *adev,  				     struct i2c_board_info *info)  { +	/* +	 * Skip registration on boards where the ACPI tables are +	 * known to contain bogus I2C devices. +	 */ +	if (acpi_quirk_skip_i2c_client_enumeration(adev)) +		return; +  	adev->power.flags.ignore_parent = true;  	acpi_device_set_enumerated(adev); @@ -473,8 +483,8 @@ struct notifier_block i2c_acpi_notifier = {  };  /** - * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource - * @dev:     Device owning the ACPI resources to get the client from + * i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource + * @fwnode:  fwnode with the ACPI resources to get the client from   * @index:   Index of ACPI resource to get   * @info:    describes the I2C device; note this is modified (addr gets set)   * Context: can sleep @@ -490,15 +500,20 @@ struct notifier_block i2c_acpi_notifier = {   * Returns a pointer to the new i2c-client, or error pointer in case of failure.   * Specifically, -EPROBE_DEFER is returned if the adapter is not found.   */ -struct i2c_client *i2c_acpi_new_device(struct device *dev, int index, -				       struct i2c_board_info *info) +struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode, +						 int index, +						 struct i2c_board_info *info)  { -	struct acpi_device *adev = ACPI_COMPANION(dev);  	struct i2c_acpi_lookup lookup;  	struct i2c_adapter *adapter; +	struct acpi_device *adev;  	LIST_HEAD(resource_list);  	int ret; +	adev = to_acpi_device_node(fwnode); +	if (!adev) +		return ERR_PTR(-ENODEV); +  	memset(&lookup, 0, sizeof(lookup));  	lookup.info = info;  	lookup.device_handle = acpi_device_handle(adev); @@ -520,7 +535,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,  	return i2c_new_client_device(adapter, info);  } -EXPORT_SYMBOL_GPL(i2c_acpi_new_device); +EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode);  bool i2c_acpi_waive_d0_probe(struct device *dev)  { diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 73253e667de1..2c59dd748a49 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -953,6 +953,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf  	client->dev.of_node = of_node_get(info->of_node);  	client->dev.fwnode = info->fwnode; +	device_enable_async_suspend(&client->dev);  	i2c_dev_set_name(adap, client, info);  	if (info->swnode) { @@ -1482,6 +1483,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	if (res)  		goto out_reg; +	device_enable_async_suspend(&adap->dev);  	pm_runtime_no_callbacks(&adap->dev);  	pm_suspend_ignore_children(&adap->dev, true);  	pm_runtime_enable(&adap->dev); diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index bac415a52b78..73a23e117ebe 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -7,6 +7,7 @@  #include <linux/i2c.h>  #include <linux/i2c-mux.h> +#include <linux/overflow.h>  #include <linux/platform_data/i2c-mux-gpio.h>  #include <linux/platform_device.h>  #include <linux/module.h> @@ -49,49 +50,11 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)  	return 0;  } -#ifdef CONFIG_ACPI - -static int i2c_mux_gpio_get_acpi_adr(struct device *dev, -				     struct fwnode_handle *fwdev, -				     unsigned int *adr) - -{ -	unsigned long long adr64; -	acpi_status status; - -	status = acpi_evaluate_integer(ACPI_HANDLE_FWNODE(fwdev), -				       METHOD_NAME__ADR, -				       NULL, &adr64); - -	if (!ACPI_SUCCESS(status)) { -		dev_err(dev, "Cannot get address\n"); -		return -EINVAL; -	} - -	*adr = adr64; -	if (*adr != adr64) { -		dev_err(dev, "Address out of range\n"); -		return -ERANGE; -	} - -	return 0; -} - -#else - -static int i2c_mux_gpio_get_acpi_adr(struct device *dev, -				     struct fwnode_handle *fwdev, -				     unsigned int *adr) -{ -	return -EINVAL; -} - -#endif -  static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,  				 struct platform_device *pdev)  {  	struct device *dev = &pdev->dev; +	struct fwnode_handle *fwnode = dev_fwnode(dev);  	struct device_node *np = dev->of_node;  	struct device_node *adapter_np;  	struct i2c_adapter *adapter = NULL; @@ -99,7 +62,7 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,  	unsigned *values;  	int rc, i = 0; -	if (is_of_node(dev->fwnode)) { +	if (is_of_node(fwnode)) {  		if (!np)  			return -ENODEV; @@ -111,7 +74,7 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,  		adapter = of_find_i2c_adapter_by_node(adapter_np);  		of_node_put(adapter_np); -	} else if (is_acpi_node(dev->fwnode)) { +	} else if (is_acpi_node(fwnode)) {  		/*  		 * In ACPI land the mux should be a direct child of the i2c  		 * bus it muxes. @@ -141,16 +104,16 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,  			fwnode_property_read_u32(child, "reg", values + i);  		} else if (is_acpi_node(child)) { -			rc = i2c_mux_gpio_get_acpi_adr(dev, child, values + i); +			rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i);  			if (rc) -				return rc; +				return dev_err_probe(dev, rc, "Cannot get address\n");  		}  		i++;  	}  	mux->data.values = values; -	if (fwnode_property_read_u32(dev->fwnode, "idle-state", &mux->data.idle)) +	if (device_property_read_u32(dev, "idle-state", &mux->data.idle))  		mux->data.idle = I2C_MUX_GPIO_NO_IDLE;  	return 0; @@ -190,7 +153,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)  		return -EPROBE_DEFER;  	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, -			     ngpios * sizeof(*mux->gpios), 0, +			     array_size(ngpios, sizeof(*mux->gpios)), 0,  			     i2c_mux_gpio_select, NULL);  	if (!muxc) {  		ret = -ENOMEM; |