diff options
| author | Mark Brown <broonie@kernel.org> | 2020-12-28 17:20:00 +0300 | 
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2020-12-28 17:20:00 +0300 | 
| commit | 2ae6f64ce1ce304b502461fdfe0b96c8171ae2cc (patch) | |
| tree | 88e987c447daf2c29e2d4c15e58d1029b0cc78c2 /drivers/i2c | |
| parent | 3b66e4a8e58a85af3212c7117d7a29c9ef6679a2 (diff) | |
| parent | 5c8fe583cce542aa0b84adc939ce85293de36e5e (diff) | |
| download | linux-2ae6f64ce1ce304b502461fdfe0b96c8171ae2cc.tar.xz | |
Merge tag 'v5.11-rc1' into regulator-5.11
Linux 5.11-rc1
Diffstat (limited to 'drivers/i2c')
23 files changed, 627 insertions, 435 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a4f473ef4e5c..d4d60ad0eda0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -675,6 +675,7 @@ config I2C_IMG  config I2C_IMX  	tristate "IMX I2C interface"  	depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE +	select I2C_SLAVE  	help  	  Say Y here if you want to use the IIC bus controller on  	  the Freescale i.MX/MXC, Layerscape or ColdFire processors. @@ -733,7 +734,8 @@ config I2C_LPC2K  config I2C_MLXBF          tristate "Mellanox BlueField I2C controller" -        depends on ARM64 +        depends on MELLANOX_PLATFORM && ARM64 +	select I2C_SLAVE          help            Enabling this option will add I2C SMBus support for Mellanox BlueField            system. diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index 66864f9cf7ac..1cceb6866689 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -26,7 +26,6 @@  #include <linux/of_device.h>  #include <linux/pinctrl/consumer.h>  #include <linux/platform_device.h> -#include <linux/platform_data/dma-atmel.h>  #include <linux/pm_runtime.h>  #include "i2c-at91.h" diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index eae673ae786c..942e9c3973bb 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -18,7 +18,6 @@  #include <linux/dma-mapping.h>  #include <linux/dmaengine.h>  #include <linux/i2c.h> -#include <linux/platform_data/dma-atmel.h>  #include <linux/platform_device.h>  #define AT91_I2C_TIMEOUT	msecs_to_jiffies(100)	/* transfer timeout */ @@ -123,7 +122,6 @@ struct at91_twi_pdata {  	bool has_adv_dig_filtr;  	bool has_ana_filtr;  	bool has_clear_cmd; -	struct at_dma_slave dma_slave;  };  struct at91_twi_dma { diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index eb5ef4d0f463..85307cfa7109 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -25,25 +25,25 @@  					I2C_FUNC_SMBUS_BLOCK_DATA |	\  					I2C_FUNC_SMBUS_I2C_BLOCK) -#define DW_IC_CON_MASTER		0x1 -#define DW_IC_CON_SPEED_STD		0x2 -#define DW_IC_CON_SPEED_FAST		0x4 -#define DW_IC_CON_SPEED_HIGH		0x6 -#define DW_IC_CON_SPEED_MASK		0x6 -#define DW_IC_CON_10BITADDR_SLAVE		0x8 -#define DW_IC_CON_10BITADDR_MASTER	0x10 -#define DW_IC_CON_RESTART_EN		0x20 -#define DW_IC_CON_SLAVE_DISABLE		0x40 -#define DW_IC_CON_STOP_DET_IFADDRESSED		0x80 -#define DW_IC_CON_TX_EMPTY_CTRL		0x100 -#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL		0x200 +#define DW_IC_CON_MASTER			BIT(0) +#define DW_IC_CON_SPEED_STD			(1 << 1) +#define DW_IC_CON_SPEED_FAST			(2 << 1) +#define DW_IC_CON_SPEED_HIGH			(3 << 1) +#define DW_IC_CON_SPEED_MASK			GENMASK(2, 1) +#define DW_IC_CON_10BITADDR_SLAVE		BIT(3) +#define DW_IC_CON_10BITADDR_MASTER		BIT(4) +#define DW_IC_CON_RESTART_EN			BIT(5) +#define DW_IC_CON_SLAVE_DISABLE			BIT(6) +#define DW_IC_CON_STOP_DET_IFADDRESSED		BIT(7) +#define DW_IC_CON_TX_EMPTY_CTRL			BIT(8) +#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL		BIT(9)  /*   * Registers offset   */ -#define DW_IC_CON		0x0 -#define DW_IC_TAR		0x4 -#define DW_IC_SAR		0x8 +#define DW_IC_CON		0x00 +#define DW_IC_TAR		0x04 +#define DW_IC_SAR		0x08  #define DW_IC_DATA_CMD		0x10  #define DW_IC_SS_SCL_HCNT	0x14  #define DW_IC_SS_SCL_LCNT	0x18 @@ -81,19 +81,19 @@  #define DW_IC_COMP_TYPE		0xfc  #define DW_IC_COMP_TYPE_VALUE	0x44570140 -#define DW_IC_INTR_RX_UNDER	0x001 -#define DW_IC_INTR_RX_OVER	0x002 -#define DW_IC_INTR_RX_FULL	0x004 -#define DW_IC_INTR_TX_OVER	0x008 -#define DW_IC_INTR_TX_EMPTY	0x010 -#define DW_IC_INTR_RD_REQ	0x020 -#define DW_IC_INTR_TX_ABRT	0x040 -#define DW_IC_INTR_RX_DONE	0x080 -#define DW_IC_INTR_ACTIVITY	0x100 -#define DW_IC_INTR_STOP_DET	0x200 -#define DW_IC_INTR_START_DET	0x400 -#define DW_IC_INTR_GEN_CALL	0x800 -#define DW_IC_INTR_RESTART_DET	0x1000 +#define DW_IC_INTR_RX_UNDER	BIT(0) +#define DW_IC_INTR_RX_OVER	BIT(1) +#define DW_IC_INTR_RX_FULL	BIT(2) +#define DW_IC_INTR_TX_OVER	BIT(3) +#define DW_IC_INTR_TX_EMPTY	BIT(4) +#define DW_IC_INTR_RD_REQ	BIT(5) +#define DW_IC_INTR_TX_ABRT	BIT(6) +#define DW_IC_INTR_RX_DONE	BIT(7) +#define DW_IC_INTR_ACTIVITY	BIT(8) +#define DW_IC_INTR_STOP_DET	BIT(9) +#define DW_IC_INTR_START_DET	BIT(10) +#define DW_IC_INTR_GEN_CALL	BIT(11) +#define DW_IC_INTR_RESTART_DET	BIT(12)  #define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \  					 DW_IC_INTR_TX_ABRT | \ @@ -105,13 +105,13 @@  					 DW_IC_INTR_RX_UNDER | \  					 DW_IC_INTR_RD_REQ) -#define DW_IC_STATUS_ACTIVITY		0x1 +#define DW_IC_STATUS_ACTIVITY		BIT(0)  #define DW_IC_STATUS_TFE		BIT(2)  #define DW_IC_STATUS_MASTER_ACTIVITY	BIT(5)  #define DW_IC_STATUS_SLAVE_ACTIVITY	BIT(6)  #define DW_IC_SDA_HOLD_RX_SHIFT		16 -#define DW_IC_SDA_HOLD_RX_MASK		GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT) +#define DW_IC_SDA_HOLD_RX_MASK		GENMASK(23, 16)  #define DW_IC_ERR_TX_ABRT	0x1 @@ -154,20 +154,20 @@  #define ABRT_SLAVE_ARBLOST	14  #define ABRT_SLAVE_RD_INTX	15 -#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK) -#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK) -#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK) -#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK) -#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK) -#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ) -#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET) -#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT) -#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT) -#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS) -#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST) -#define DW_IC_RX_ABRT_SLAVE_RD_INTX	(1UL << ABRT_SLAVE_RD_INTX) -#define DW_IC_RX_ABRT_SLAVE_ARBLOST	(1UL << ABRT_SLAVE_ARBLOST) -#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO	(1UL << ABRT_SLAVE_FLUSH_TXFIFO) +#define DW_IC_TX_ABRT_7B_ADDR_NOACK		BIT(ABRT_7B_ADDR_NOACK) +#define DW_IC_TX_ABRT_10ADDR1_NOACK		BIT(ABRT_10ADDR1_NOACK) +#define DW_IC_TX_ABRT_10ADDR2_NOACK		BIT(ABRT_10ADDR2_NOACK) +#define DW_IC_TX_ABRT_TXDATA_NOACK		BIT(ABRT_TXDATA_NOACK) +#define DW_IC_TX_ABRT_GCALL_NOACK		BIT(ABRT_GCALL_NOACK) +#define DW_IC_TX_ABRT_GCALL_READ		BIT(ABRT_GCALL_READ) +#define DW_IC_TX_ABRT_SBYTE_ACKDET		BIT(ABRT_SBYTE_ACKDET) +#define DW_IC_TX_ABRT_SBYTE_NORSTRT		BIT(ABRT_SBYTE_NORSTRT) +#define DW_IC_TX_ABRT_10B_RD_NORSTRT		BIT(ABRT_10B_RD_NORSTRT) +#define DW_IC_TX_ABRT_MASTER_DIS		BIT(ABRT_MASTER_DIS) +#define DW_IC_TX_ARB_LOST			BIT(ARB_LOST) +#define DW_IC_RX_ABRT_SLAVE_RD_INTX		BIT(ABRT_SLAVE_RD_INTX) +#define DW_IC_RX_ABRT_SLAVE_ARBLOST		BIT(ABRT_SLAVE_ARBLOST) +#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO	BIT(ABRT_SLAVE_FLUSH_TXFIFO)  #define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \  					 DW_IC_TX_ABRT_10ADDR1_NOACK | \ @@ -288,12 +288,12 @@ struct dw_i2c_dev {  	bool			suspended;  }; -#define ACCESS_INTR_MASK	0x00000001 -#define ACCESS_NO_IRQ_SUSPEND	0x00000002 +#define ACCESS_INTR_MASK	BIT(0) +#define ACCESS_NO_IRQ_SUSPEND	BIT(1) -#define MODEL_MSCC_OCELOT	0x00000100 -#define MODEL_BAIKAL_BT1	0x00000200 -#define MODEL_MASK		0x00000f00 +#define MODEL_MSCC_OCELOT	BIT(8) +#define MODEL_BAIKAL_BT1	BIT(9) +#define MODEL_MASK		GENMASK(11, 8)  int i2c_dw_init_regmap(struct dw_i2c_dev *dev);  u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset); diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index 44974b53a626..0d15f4c1e9f7 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -159,7 +159,6 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)  	u32 raw_stat, stat, enabled, tmp;  	u8 val = 0, slave_activity; -	regmap_read(dev->map, DW_IC_INTR_STAT, &stat);  	regmap_read(dev->map, DW_IC_ENABLE, &enabled);  	regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat);  	regmap_read(dev->map, DW_IC_STATUS, &tmp); @@ -168,32 +167,30 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)  	if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)  		return 0; +	stat = i2c_dw_read_clear_intrbits_slave(dev);  	dev_dbg(dev->dev,  		"%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n",  		enabled, slave_activity, raw_stat, stat); -	if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET)) -		i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val); +	if (stat & DW_IC_INTR_RX_FULL) { +		if (dev->status != STATUS_WRITE_IN_PROGRESS) { +			dev->status = STATUS_WRITE_IN_PROGRESS; +			i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, +					&val); +		} + +		regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); +		val = tmp; +		if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, +				     &val)) +			dev_vdbg(dev->dev, "Byte %X acked!", val); +	}  	if (stat & DW_IC_INTR_RD_REQ) {  		if (slave_activity) { -			if (stat & DW_IC_INTR_RX_FULL) { -				regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); -				val = tmp; - -				if (!i2c_slave_event(dev->slave, -						     I2C_SLAVE_WRITE_RECEIVED, -						     &val)) { -					dev_vdbg(dev->dev, "Byte %X acked!", -						 val); -				} -				regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp); -				stat = i2c_dw_read_clear_intrbits_slave(dev); -			} else { -				regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp); -				regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &tmp); -				stat = i2c_dw_read_clear_intrbits_slave(dev); -			} +			regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp); + +			dev->status = STATUS_READ_IN_PROGRESS;  			if (!i2c_slave_event(dev->slave,  					     I2C_SLAVE_READ_REQUESTED,  					     &val)) @@ -205,21 +202,11 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)  		if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,  				     &val))  			regmap_read(dev->map, DW_IC_CLR_RX_DONE, &tmp); - -		i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); -		stat = i2c_dw_read_clear_intrbits_slave(dev); -		return 1;  	} -	if (stat & DW_IC_INTR_RX_FULL) { -		regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); -		val = tmp; -		if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED, -				     &val)) -			dev_vdbg(dev->dev, "Byte %X acked!", val); -	} else { +	if (stat & DW_IC_INTR_STOP_DET) { +		dev->status = STATUS_IDLE;  		i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val); -		stat = i2c_dw_read_clear_intrbits_slave(dev);  	}  	return 1; @@ -230,7 +217,6 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)  	struct dw_i2c_dev *dev = dev_id;  	int ret; -	i2c_dw_read_clear_intrbits_slave(dev);  	ret = i2c_dw_irq_handler_slave(dev);  	if (ret > 0)  		complete(&dev->cmd_complete); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 6ce3ec03b595..20a9881a0d6c 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -778,11 +778,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)  	init_completion(&i2c->msg_complete);  	i2c->irq = ret = platform_get_irq(pdev, 0); -	if (ret <= 0) { -		dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n"); -		ret = -EINVAL; +	if (ret < 0)  		goto err_clk; -	}  	ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq,  			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index c98529c76348..b444fbf1a262 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -17,6 +17,7 @@   *	Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt>   *   *	Copyright 2013 Freescale Semiconductor, Inc. + *	Copyright 2020 NXP   *   */ @@ -73,6 +74,11 @@  #define IMX_I2C_I2SR	0x03	/* i2c status */  #define IMX_I2C_I2DR	0x04	/* i2c transfer data */ +/* + * All of the layerscape series SoCs support IBIC register. + */ +#define IMX_I2C_IBIC	0x05    /* i2c bus interrupt config */ +  #define IMX_I2C_REGSHIFT	2  #define VF610_I2C_REGSHIFT	0 @@ -91,6 +97,7 @@  #define I2CR_MSTA	0x20  #define I2CR_IIEN	0x40  #define I2CR_IEN	0x80 +#define IBIC_BIIE	0x80 /* Bus idle interrupt enable */  /* register bits different operating codes definition:   * 1) I2SR: Interrupt flags clear operation differ between SoCs: @@ -201,6 +208,7 @@ struct imx_i2c_struct {  	struct pinctrl_state *pinctrl_pins_gpio;  	struct imx_i2c_dma	*dma; +	struct i2c_client	*slave;  };  static const struct imx_i2c_hwdata imx1_i2c_hwdata = { @@ -233,19 +241,6 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = {  }; -static const struct platform_device_id imx_i2c_devtype[] = { -	{ -		.name = "imx1-i2c", -		.driver_data = (kernel_ulong_t)&imx1_i2c_hwdata, -	}, { -		.name = "imx21-i2c", -		.driver_data = (kernel_ulong_t)&imx21_i2c_hwdata, -	}, { -		/* sentinel */ -	} -}; -MODULE_DEVICE_TABLE(platform, imx_i2c_devtype); -  static const struct of_device_id i2c_imx_dt_ids[] = {  	{ .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },  	{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, @@ -265,6 +260,11 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx)  	return i2c_imx->hwdata->devtype == IMX1_I2C;  } +static inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx) +{ +	return i2c_imx->hwdata->devtype == VF610_I2C; +} +  static inline void imx_i2c_write_reg(unsigned int val,  		struct imx_i2c_struct *i2c_imx, unsigned int reg)  { @@ -277,6 +277,27 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx,  	return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift));  } +static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) +{ +	unsigned int temp; + +	/* +	 * i2sr_clr_opcode is the value to clear all interrupts. Here we want to +	 * clear only <bits>, so we write ~i2sr_clr_opcode with just <bits> +	 * toggled. This is required because i.MX needs W0C and Vybrid uses W1C. +	 */ +	temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; +	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); +} + +/* Set up i2c controller register and i2c status register to default value. */ +static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx) +{ +	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, +			  i2c_imx, IMX_I2C_I2CR); +	i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL); +} +  /* Functions for DMA support */  static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx,  						dma_addr_t phy_addr) @@ -424,8 +445,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a  		/* check for arbitration lost */  		if (temp & I2SR_IAL) { -			temp &= ~I2SR_IAL; -			imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); +			i2c_imx_clear_irq(i2c_imx, I2SR_IAL);  			return -EAGAIN;  		} @@ -469,7 +489,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)  		 */  		readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);  		i2c_imx->i2csr = regval; -		imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); +		i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);  	} else {  		wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);  	} @@ -478,6 +498,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)  		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);  		return -ETIMEDOUT;  	} + +	/* check for arbitration lost */ +	if (i2c_imx->i2csr & I2SR_IAL) { +		dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__); +		i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + +		i2c_imx->i2csr = 0; +		return -EAGAIN; +	} +  	dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);  	i2c_imx->i2csr = 0;  	return 0; @@ -593,6 +623,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)  		/* Stop I2C transaction */  		dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);  		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +		if (!(temp & I2CR_MSTA)) +			i2c_imx->stopped = 1;  		temp &= ~(I2CR_MSTA | I2CR_MTX);  		if (i2c_imx->dma)  			temp &= ~I2CR_DMAEN; @@ -614,20 +646,165 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)  	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);  } +/* + * Enable bus idle interrupts + * Note: IBIC register will be cleared after disabled i2c module. + * All of layerscape series SoCs support IBIC register. + */ +static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx) +{ +	if (is_vf610_i2c(i2c_imx)) { +		unsigned int temp; + +		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_IBIC); +		temp |= IBIC_BIIE; +		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_IBIC); +	} +} + +static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, +				     unsigned int status, unsigned int ctl) +{ +	u8 value; + +	if (status & I2SR_IAL) { /* Arbitration lost */ +		i2c_imx_clear_irq(i2c_imx, I2SR_IAL); +		if (!(status & I2SR_IAAS)) +			return IRQ_HANDLED; +	} + +	if (status & I2SR_IAAS) { /* Addressed as a slave */ +		if (status & I2SR_SRW) { /* Master wants to read from us*/ +			dev_dbg(&i2c_imx->adapter.dev, "read requested"); +			i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value); + +			/* Slave transmit */ +			ctl |= I2CR_MTX; +			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + +			/* Send data */ +			imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); +		} else { /* Master wants to write to us */ +			dev_dbg(&i2c_imx->adapter.dev, "write requested"); +			i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_REQUESTED, &value); + +			/* Slave receive */ +			ctl &= ~I2CR_MTX; +			imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); +			/* Dummy read */ +			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_slave_event(i2c_imx->slave,	I2C_SLAVE_WRITE_RECEIVED, &value); +		} else { /* STOP signal is detected */ +			dev_dbg(&i2c_imx->adapter.dev, +				"STOP signal detected"); +			i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value); +		} +	} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */ +		ctl |= I2CR_MTX; +		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + +		i2c_slave_event(i2c_imx->slave,	I2C_SLAVE_READ_PROCESSED, &value); + +		imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); +	} else { /* Transmit mode received NAK */ +		ctl &= ~I2CR_MTX; +		imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); +		imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); +	} + +	return IRQ_HANDLED; +} + +static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx) +{ +	int temp; + +	/* Set slave addr. */ +	imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR); + +	i2c_imx_reset_regs(i2c_imx); + +	/* Enable module */ +	temp = i2c_imx->hwdata->i2cr_ien_opcode; +	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + +	/* Enable interrupt from i2c module */ +	temp |= I2CR_IIEN; +	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + +	i2c_imx_enable_bus_idle(i2c_imx); +} + +static int i2c_imx_reg_slave(struct i2c_client *client) +{ +	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter); +	int ret; + +	if (i2c_imx->slave) +		return -EBUSY; + +	i2c_imx->slave = client; + +	/* Resume */ +	ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); +	if (ret < 0) { +		dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller"); +		return ret; +	} + +	i2c_imx_slave_init(i2c_imx); + +	return 0; +} + +static int i2c_imx_unreg_slave(struct i2c_client *client) +{ +	struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter); +	int ret; + +	if (!i2c_imx->slave) +		return -EINVAL; + +	/* Reset slave address. */ +	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR); + +	i2c_imx_reset_regs(i2c_imx); + +	i2c_imx->slave = NULL; + +	/* Suspend */ +	ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent); +	if (ret < 0) +		dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller"); + +	return ret; +} + +static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status) +{ +	/* save status register */ +	i2c_imx->i2csr = status; +	wake_up(&i2c_imx->queue); + +	return IRQ_HANDLED; +} +  static irqreturn_t i2c_imx_isr(int irq, void *dev_id)  {  	struct imx_i2c_struct *i2c_imx = dev_id; -	unsigned int temp; - -	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); -	if (temp & I2SR_IIF) { -		/* save status register */ -		i2c_imx->i2csr = temp; -		temp &= ~I2SR_IIF; -		temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF); -		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); -		wake_up(&i2c_imx->queue); -		return IRQ_HANDLED; +	unsigned int ctl, status; + +	status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); +	ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +	if (status & I2SR_IIF) { +		i2c_imx_clear_irq(i2c_imx, I2SR_IIF); +		if (i2c_imx->slave && !(ctl & I2CR_MSTA)) +			return i2c_imx_slave_isr(i2c_imx, status, ctl); +		return i2c_imx_master_isr(i2c_imx, status);  	}  	return IRQ_NONE; @@ -758,9 +935,12 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,  		 */  		dev_dbg(dev, "<%s> clear MSTA\n", __func__);  		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +		if (!(temp & I2CR_MSTA)) +			i2c_imx->stopped = 1;  		temp &= ~(I2CR_MSTA | I2CR_MTX);  		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); -		i2c_imx_bus_busy(i2c_imx, 0, false); +		if (!i2c_imx->stopped) +			i2c_imx_bus_busy(i2c_imx, 0, false);  	} else {  		/*  		 * For i2c master receiver repeat restart operation like: @@ -885,9 +1065,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,  				dev_dbg(&i2c_imx->adapter.dev,  					"<%s> clear MSTA\n", __func__);  				temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); +				if (!(temp & I2CR_MSTA)) +					i2c_imx->stopped =  1;  				temp &= ~(I2CR_MSTA | I2CR_MTX);  				imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); -				i2c_imx_bus_busy(i2c_imx, 0, atomic); +				if (!i2c_imx->stopped) +					i2c_imx_bus_busy(i2c_imx, 0, atomic);  			} else {  				/*  				 * For i2c master receiver repeat restart operation like: @@ -999,6 +1182,10 @@ fail0:  	dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,  		(result < 0) ? "error" : "success msg",  			(result < 0) ? result : num); +	/* After data is transferred, switch to slave mode(as a receiver) */ +	if (i2c_imx->slave) +		i2c_imx_slave_init(i2c_imx); +  	return (result < 0) ? result : num;  } @@ -1112,6 +1299,8 @@ static const struct i2c_algorithm i2c_imx_algo = {  	.master_xfer = i2c_imx_xfer,  	.master_xfer_atomic = i2c_imx_xfer_atomic,  	.functionality = i2c_imx_func, +	.reg_slave	= i2c_imx_reg_slave, +	.unreg_slave	= i2c_imx_unreg_slave,  };  static int i2c_imx_probe(struct platform_device *pdev) @@ -1141,11 +1330,7 @@ static int i2c_imx_probe(struct platform_device *pdev)  		return -ENOMEM;  	match = device_get_match_data(&pdev->dev); -	if (match) -		i2c_imx->hwdata = match; -	else -		i2c_imx->hwdata = (struct imx_i2c_hwdata *) -				platform_get_device_id(pdev)->driver_data; +	i2c_imx->hwdata = match;  	/* Setup i2c_imx driver structure */  	strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); @@ -1205,10 +1390,7 @@ static int i2c_imx_probe(struct platform_device *pdev)  	clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);  	i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); -	/* Set up chip registers to defaults */ -	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, -			i2c_imx, IMX_I2C_I2CR); -	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); +	i2c_imx_reset_regs(i2c_imx);  	/* Init optional bus recovery function */  	ret = i2c_imx_init_recovery_info(i2c_imx, pdev); @@ -1316,7 +1498,6 @@ static struct platform_driver i2c_imx_driver = {  		.of_match_table = i2c_imx_dt_ids,  		.acpi_match_table = i2c_imx_acpi_ids,  	}, -	.id_table = imx_i2c_devtype,  };  static int __init i2c_adap_imx_init(void) diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index a35a27c320e7..a6187cbec2c9 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -53,7 +53,7 @@   *  Features supported by this driver:   *  Hardware PEC                     yes   *  Block buffer                     yes - *  Block process call transaction   no + *  Block process call transaction   yes   *  Slave mode                       no   */ @@ -332,7 +332,8 @@ static int ismt_process_desc(const struct ismt_desc *desc,  	if (desc->status & ISMT_DESC_SCS) {  		if (read_write == I2C_SMBUS_WRITE && -		    size != I2C_SMBUS_PROC_CALL) +		    size != I2C_SMBUS_PROC_CALL && +		    size != I2C_SMBUS_BLOCK_PROC_CALL)  			return 0;  		switch (size) { @@ -345,6 +346,7 @@ static int ismt_process_desc(const struct ismt_desc *desc,  			data->word = dma_buffer[0] | (dma_buffer[1] << 8);  			break;  		case I2C_SMBUS_BLOCK_DATA: +		case I2C_SMBUS_BLOCK_PROC_CALL:  			if (desc->rxbytes != dma_buffer[0] + 1)  				return -EMSGSIZE; @@ -518,6 +520,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,  		}  		break; +	case I2C_SMBUS_BLOCK_PROC_CALL: +		dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n"); +		dma_size = I2C_SMBUS_BLOCK_MAX; +		desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1); +		desc->wr_len_cmd = data->block[0] + 1; +		desc->rd_len = dma_size; +		desc->control |= ISMT_DESC_BLK; +		dma_direction = DMA_BIDIRECTIONAL; +		dma_buffer[0] = command; +		memcpy(&dma_buffer[1], &data->block[1], data->block[0]); +		break; +  	case I2C_SMBUS_I2C_BLOCK_DATA:  		/* Make sure the length is valid */  		if (data->block[0] < 1) @@ -624,6 +638,7 @@ static u32 ismt_func(struct i2c_adapter *adap)  	       I2C_FUNC_SMBUS_BYTE_DATA		|  	       I2C_FUNC_SMBUS_WORD_DATA		|  	       I2C_FUNC_SMBUS_PROC_CALL		| +	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL	|  	       I2C_FUNC_SMBUS_BLOCK_DATA	|  	       I2C_FUNC_SMBUS_I2C_BLOCK		|  	       I2C_FUNC_SMBUS_PEC; diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c index ee59e0da082d..2fb0532d8a16 100644 --- a/drivers/i2c/busses/i2c-mlxbf.c +++ b/drivers/i2c/busses/i2c-mlxbf.c @@ -62,10 +62,8 @@   * Master. Default value is set to 400MHz.   */  #define MLXBF_I2C_TYU_PLL_OUT_FREQ  (400 * 1000 * 1000) -/* Reference clock for Bluefield 1 - 156 MHz. */ -#define MLXBF_I2C_TYU_PLL_IN_FREQ   (156 * 1000 * 1000) -/* Reference clock for BlueField 2 - 200 MHz. */ -#define MLXBF_I2C_YU_PLL_IN_FREQ    (200 * 1000 * 1000) +/* Reference clock for Bluefield - 156 MHz. */ +#define MLXBF_I2C_PLL_IN_FREQ       (156 * 1000 * 1000)  /* Constant used to determine the PLL frequency. */  #define MLNXBF_I2C_COREPLL_CONST    16384 @@ -489,44 +487,6 @@ static struct mutex mlxbf_i2c_bus_lock;  #define MLXBF_I2C_FREQUENCY_1GHZ  1000000000 -static void mlxbf_i2c_write(void __iomem *io, int reg, u32 val) -{ -	writel(val, io + reg); -} - -static u32 mlxbf_i2c_read(void __iomem *io, int reg) -{ -	return readl(io + reg); -} - -/* - * This function is used to read data from Master GW Data Descriptor. - * Data bytes in the Master GW Data Descriptor are shifted left so the - * data starts at the MSB of the descriptor registers as set by the - * underlying hardware. TYU_READ_DATA enables byte swapping while - * reading data bytes, and MUST be called by the SMBus read routines - * to copy data from the 32 * 32-bit HW Data registers a.k.a Master GW - * Data Descriptor. - */ -static u32 mlxbf_i2c_read_data(void __iomem *io, int reg) -{ -	return (u32)be32_to_cpu(mlxbf_i2c_read(io, reg)); -} - -/* - * This function is used to write data to the Master GW Data Descriptor. - * Data copied to the Master GW Data Descriptor MUST be shifted left so - * the data starts at the MSB of the descriptor registers as required by - * the underlying hardware. TYU_WRITE_DATA enables byte swapping when - * writing data bytes, and MUST be called by the SMBus write routines to - * copy data to the 32 * 32-bit HW Data registers a.k.a Master GW Data - * Descriptor. - */ -static void mlxbf_i2c_write_data(void __iomem *io, int reg, u32 val) -{ -	mlxbf_i2c_write(io, reg, (u32)cpu_to_be32(val)); -} -  /*   * Function to poll a set of bits at a specific address; it checks whether   * the bits are equal to zero when eq_zero is set to 'true', and not equal @@ -541,7 +501,7 @@ static u32 mlxbf_smbus_poll(void __iomem *io, u32 addr, u32 mask,  	timeout = (timeout / MLXBF_I2C_POLL_FREQ_IN_USEC) + 1;  	do { -		bits = mlxbf_i2c_read(io, addr) & mask; +		bits = readl(io + addr) & mask;  		if (eq_zero ? bits == 0 : bits != 0)  			return eq_zero ? 1 : bits;  		udelay(MLXBF_I2C_POLL_FREQ_IN_USEC); @@ -609,16 +569,16 @@ static int mlxbf_i2c_smbus_check_status(struct mlxbf_i2c_priv *priv)  			 MLXBF_I2C_SMBUS_TIMEOUT);  	/* Read cause status bits. */ -	cause_status_bits = mlxbf_i2c_read(priv->mst_cause->io, -					   MLXBF_I2C_CAUSE_ARBITER); +	cause_status_bits = readl(priv->mst_cause->io + +					MLXBF_I2C_CAUSE_ARBITER);  	cause_status_bits &= MLXBF_I2C_CAUSE_MASTER_ARBITER_BITS_MASK;  	/*  	 * Parse both Cause and Master GW bits, then return transaction status.  	 */ -	master_status_bits = mlxbf_i2c_read(priv->smbus->io, -					    MLXBF_I2C_SMBUS_MASTER_STATUS); +	master_status_bits = readl(priv->smbus->io + +					MLXBF_I2C_SMBUS_MASTER_STATUS);  	master_status_bits &= MLXBF_I2C_SMBUS_MASTER_STATUS_MASK;  	if (mlxbf_i2c_smbus_transaction_success(master_status_bits, @@ -649,10 +609,17 @@ static void mlxbf_i2c_smbus_write_data(struct mlxbf_i2c_priv *priv,  	aligned_length = round_up(length, 4); -	/* Copy data bytes from 4-byte aligned source buffer. */ +	/* +	 * Copy data bytes from 4-byte aligned source buffer. +	 * Data copied to the Master GW Data Descriptor MUST be shifted +	 * left so the data starts at the MSB of the descriptor registers +	 * as required by the underlying hardware. Enable byte swapping +	 * when writing data bytes to the 32 * 32-bit HW Data registers +	 * a.k.a Master GW Data Descriptor. +	 */  	for (offset = 0; offset < aligned_length; offset += sizeof(u32)) {  		data32 = *((u32 *)(data + offset)); -		mlxbf_i2c_write_data(priv->smbus->io, addr + offset, data32); +		iowrite32be(data32, priv->smbus->io + addr + offset);  	}  } @@ -664,15 +631,23 @@ static void mlxbf_i2c_smbus_read_data(struct mlxbf_i2c_priv *priv,  	mask = sizeof(u32) - 1; +	/* +	 * Data bytes in the Master GW Data Descriptor are shifted left +	 * so the data starts at the MSB of the descriptor registers as +	 * set by the underlying hardware. Enable byte swapping while +	 * reading data bytes from the 32 * 32-bit HW Data registers +	 * a.k.a Master GW Data Descriptor. +	 */ +  	for (offset = 0; offset < (length & ~mask); offset += sizeof(u32)) { -		data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset); +		data32 = ioread32be(priv->smbus->io + addr + offset);  		*((u32 *)(data + offset)) = data32;  	}  	if (!(length & mask))  		return; -	data32 = mlxbf_i2c_read_data(priv->smbus->io, addr + offset); +	data32 = ioread32be(priv->smbus->io + addr + offset);  	for (byte = 0; byte < (length & mask); byte++) {  		data[offset + byte] = data32 & GENMASK(7, 0); @@ -698,16 +673,16 @@ static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,  	command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT);  	/* Clear status bits. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_STATUS, 0x0); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_STATUS);  	/* Set the cause data. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0); +	writel(~0x0, priv->smbus->io + MLXBF_I2C_CAUSE_OR_CLEAR);  	/* Zero PEC byte. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_PEC, 0x0); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_PEC);  	/* Zero byte count. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_RS_BYTES, 0x0); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_RS_BYTES);  	/* GW activation. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, command); +	writel(command, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW);  	/*  	 * Poll master status and check status bits. An ACK is sent when @@ -823,8 +798,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,  		 * needs to be 'manually' reset. This should be removed in  		 * next tag integration.  		 */ -		mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_FSM, -				MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK); +		writel(MLXBF_I2C_SMBUS_MASTER_FSM_PS_STATE_MASK, +			priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM);  	}  	return ret; @@ -1113,8 +1088,8 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv,  	timer |= mlxbf_i2c_set_timer(priv, timings->scl_low,  				     false, MLXBF_I2C_MASK_16,  				     MLXBF_I2C_SHIFT_16); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH, -			  timer); +	writel(timer, priv->smbus->io + +		MLXBF_I2C_SMBUS_TIMER_SCL_LOW_SCL_HIGH);  	timer = mlxbf_i2c_set_timer(priv, timings->sda_rise, false,  				    MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_0); @@ -1124,37 +1099,34 @@ static void mlxbf_i2c_set_timings(struct mlxbf_i2c_priv *priv,  				     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_16);  	timer |= mlxbf_i2c_set_timer(priv, timings->scl_fall, false,  				     MLXBF_I2C_MASK_8, MLXBF_I2C_SHIFT_24); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE, -			  timer); +	writel(timer, priv->smbus->io + +		MLXBF_I2C_SMBUS_TIMER_FALL_RISE_SPIKE);  	timer = mlxbf_i2c_set_timer(priv, timings->hold_start, true,  				    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);  	timer |= mlxbf_i2c_set_timer(priv, timings->hold_data, true,  				     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_THOLD, timer); +	writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_THOLD);  	timer = mlxbf_i2c_set_timer(priv, timings->setup_start, true,  				    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);  	timer |= mlxbf_i2c_set_timer(priv, timings->setup_stop, true,  				     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); -	mlxbf_i2c_write(priv->smbus->io, -			MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP, timer); +	writel(timer, priv->smbus->io + +		MLXBF_I2C_SMBUS_TIMER_TSETUP_START_STOP);  	timer = mlxbf_i2c_set_timer(priv, timings->setup_data, true,  				    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA, -			  timer); +	writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_TIMER_TSETUP_DATA);  	timer = mlxbf_i2c_set_timer(priv, timings->buf, false,  				    MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_0);  	timer |= mlxbf_i2c_set_timer(priv, timings->thigh_max, false,  				     MLXBF_I2C_MASK_16, MLXBF_I2C_SHIFT_16); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_THIGH_MAX_TBUF, -			timer); +	writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_THIGH_MAX_TBUF);  	timer = timings->timeout; -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT, -			timer); +	writel(timer, priv->smbus->io + MLXBF_I2C_SMBUS_SCL_LOW_TIMEOUT);  }  enum mlxbf_i2c_timings_config { @@ -1286,9 +1258,9 @@ static int mlxbf_i2c_get_gpio(struct platform_device *pdev,  		return -EFAULT;  	gpio_res->io = devm_ioremap(dev, params->start, size); -	if (IS_ERR(gpio_res->io)) { +	if (!gpio_res->io) {  		devm_release_mem_region(dev, params->start, size); -		return PTR_ERR(gpio_res->io); +		return -ENOMEM;  	}  	return 0; @@ -1351,9 +1323,9 @@ static int mlxbf_i2c_get_corepll(struct platform_device *pdev,  		return -EFAULT;  	corepll_res->io = devm_ioremap(dev, params->start, size); -	if (IS_ERR(corepll_res->io)) { +	if (!corepll_res->io) {  		devm_release_mem_region(dev, params->start, size); -		return PTR_ERR(corepll_res->io); +		return -ENOMEM;  	}  	return 0; @@ -1426,19 +1398,15 @@ static int mlxbf_i2c_init_master(struct platform_device *pdev,  	 * platform firmware; disabling the bus might compromise the system  	 * functionality.  	 */ -	config_reg = mlxbf_i2c_read(gpio_res->io, -				    MLXBF_I2C_GPIO_0_FUNC_EN_0); +	config_reg = readl(gpio_res->io + MLXBF_I2C_GPIO_0_FUNC_EN_0);  	config_reg = MLXBF_I2C_GPIO_SMBUS_GW_ASSERT_PINS(priv->bus,  							 config_reg); -	mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FUNC_EN_0, -			config_reg); +	writel(config_reg, gpio_res->io + MLXBF_I2C_GPIO_0_FUNC_EN_0); -	config_reg = mlxbf_i2c_read(gpio_res->io, -				    MLXBF_I2C_GPIO_0_FORCE_OE_EN); +	config_reg = readl(gpio_res->io + MLXBF_I2C_GPIO_0_FORCE_OE_EN);  	config_reg = MLXBF_I2C_GPIO_SMBUS_GW_RESET_PINS(priv->bus,  							config_reg); -	mlxbf_i2c_write(gpio_res->io, MLXBF_I2C_GPIO_0_FORCE_OE_EN, -			config_reg); +	writel(config_reg, gpio_res->io + MLXBF_I2C_GPIO_0_FORCE_OE_EN);  	mutex_unlock(gpio_res->lock); @@ -1452,10 +1420,9 @@ static u64 mlxbf_calculate_freq_from_tyu(struct mlxbf_i2c_resource *corepll_res)  	u32 corepll_val;  	u16 core_f; -	pad_frequency = MLXBF_I2C_TYU_PLL_IN_FREQ; +	pad_frequency = MLXBF_I2C_PLL_IN_FREQ; -	corepll_val = mlxbf_i2c_read(corepll_res->io, -				     MLXBF_I2C_CORE_PLL_REG1); +	corepll_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1);  	/* Get Core PLL configuration bits. */  	core_f = rol32(corepll_val, MLXBF_I2C_COREPLL_CORE_F_TYU_SHIFT) & @@ -1488,12 +1455,10 @@ static u64 mlxbf_calculate_freq_from_yu(struct mlxbf_i2c_resource *corepll_res)  	u8 core_od, core_r;  	u32 core_f; -	pad_frequency = MLXBF_I2C_YU_PLL_IN_FREQ; +	pad_frequency = MLXBF_I2C_PLL_IN_FREQ; -	corepll_reg1_val = mlxbf_i2c_read(corepll_res->io, -					  MLXBF_I2C_CORE_PLL_REG1); -	corepll_reg2_val = mlxbf_i2c_read(corepll_res->io, -					  MLXBF_I2C_CORE_PLL_REG2); +	corepll_reg1_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG1); +	corepll_reg2_val = readl(corepll_res->io + MLXBF_I2C_CORE_PLL_REG2);  	/* Get Core PLL configuration bits */  	core_f = rol32(corepll_reg1_val, MLXBF_I2C_COREPLL_CORE_F_YU_SHIFT) & @@ -1585,7 +1550,7 @@ static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)  	 * (7-bit address, 1 status bit (1 if enabled, 0 if not)).  	 */  	for (reg = 0; reg < reg_cnt; reg++) { -		slave_reg = mlxbf_i2c_read(priv->smbus->io, +		slave_reg = readl(priv->smbus->io +  				MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);  		/*  		 * Each register holds 4 slave addresses. So, we have to keep @@ -1643,8 +1608,8 @@ static int mlxbf_slave_enable(struct mlxbf_i2c_priv *priv, u8 addr)  	/* Enable the slave address and update the register. */  	slave_reg |= (1 << MLXBF_I2C_SMBUS_SLAVE_ADDR_EN_BIT) << (byte * 8); -	mlxbf_i2c_write(priv->smbus->io, -			MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg); +	writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + +		reg * 0x4);  	return 0;  } @@ -1668,7 +1633,7 @@ static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)  	 * (7-bit address, 1 status bit (1 if enabled, 0 if not)).  	 */  	for (reg = 0; reg < reg_cnt; reg++) { -		slave_reg = mlxbf_i2c_read(priv->smbus->io, +		slave_reg = readl(priv->smbus->io +  				MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4);  		/* Check whether the address slots are empty. */ @@ -1708,8 +1673,8 @@ static int mlxbf_slave_disable(struct mlxbf_i2c_priv *priv)  	/* Cleanup the slave address slot. */  	slave_reg &= ~(GENMASK(7, 0) << (slave_byte * 8)); -	mlxbf_i2c_write(priv->smbus->io, -			MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + reg * 0x4, slave_reg); +	writel(slave_reg, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_ADDR_CFG + +		reg * 0x4);  	return 0;  } @@ -1752,9 +1717,9 @@ static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,  			return -EFAULT;  		coalesce_res->io = ioremap(params->start, size); -		if (IS_ERR(coalesce_res->io)) { +		if (!coalesce_res->io) {  			release_mem_region(params->start, size); -			return PTR_ERR(coalesce_res->io); +			return -ENOMEM;  		}  		priv->coalesce = coalesce_res; @@ -1801,7 +1766,7 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev,  	int ret;  	/* Reset FSM. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_FSM, 0); +	writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_FSM);  	/*  	 * Enable slave cause interrupt bits. Drive @@ -1810,15 +1775,13 @@ static int mlxbf_i2c_init_slave(struct platform_device *pdev,  	 * masters issue a Read and Write, respectively. But, clear all  	 * interrupts first.  	 */ -	mlxbf_i2c_write(priv->slv_cause->io, -			  MLXBF_I2C_CAUSE_OR_CLEAR, ~0); +	writel(~0, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);  	int_reg = MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE;  	int_reg |= MLXBF_I2C_CAUSE_WRITE_SUCCESS; -	mlxbf_i2c_write(priv->slv_cause->io, -			  MLXBF_I2C_CAUSE_OR_EVTEN0, int_reg); +	writel(int_reg, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_EVTEN0);  	/* Finally, set the 'ready' bit to start handling transactions. */ -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1); +	writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);  	/* Initialize the cause coalesce resource. */  	ret = mlxbf_i2c_init_coalesce(pdev, priv); @@ -1844,23 +1807,21 @@ static bool mlxbf_i2c_has_coalesce(struct mlxbf_i2c_priv *priv, bool *read,  				MLXBF_I2C_CAUSE_YU_SLAVE_BIT :  				priv->bus + MLXBF_I2C_CAUSE_TYU_SLAVE_BIT; -	coalesce0_reg = mlxbf_i2c_read(priv->coalesce->io, -				       MLXBF_I2C_CAUSE_COALESCE_0); +	coalesce0_reg = readl(priv->coalesce->io + MLXBF_I2C_CAUSE_COALESCE_0);  	is_set = coalesce0_reg & (1 << slave_shift);  	if (!is_set)  		return false;  	/* Check the source of the interrupt, i.e. whether a Read or Write. */ -	cause_reg = mlxbf_i2c_read(priv->slv_cause->io, -				     MLXBF_I2C_CAUSE_ARBITER); +	cause_reg = readl(priv->slv_cause->io + MLXBF_I2C_CAUSE_ARBITER);  	if (cause_reg & MLXBF_I2C_CAUSE_READ_WAIT_FW_RESPONSE)  		*read = true;  	else if (cause_reg & MLXBF_I2C_CAUSE_WRITE_SUCCESS)  		*write = true;  	/* Clear cause bits. */ -	mlxbf_i2c_write(priv->slv_cause->io, MLXBF_I2C_CAUSE_OR_CLEAR, ~0x0); +	writel(~0x0, priv->slv_cause->io + MLXBF_I2C_CAUSE_OR_CLEAR);  	return true;  } @@ -1900,8 +1861,8 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)  	 * address, if supplied.  	 */  	if (recv_bytes > 0) { -		data32 = mlxbf_i2c_read_data(priv->smbus->io, -					     MLXBF_I2C_SLAVE_DATA_DESC_ADDR); +		data32 = ioread32be(priv->smbus->io + +					MLXBF_I2C_SLAVE_DATA_DESC_ADDR);  		/* Parse the received bytes. */  		switch (recv_bytes) { @@ -1966,7 +1927,7 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)  	control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT);  	control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_GW, control32); +	writel(control32, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_GW);  	/*  	 * Wait until the transfer is completed; the driver will wait @@ -1975,10 +1936,9 @@ static int mlxbf_smbus_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)  	mlxbf_smbus_slave_wait_for_idle(priv, MLXBF_I2C_SMBUS_TIMEOUT);  	/* Release the Slave GW. */ -	mlxbf_i2c_write(priv->smbus->io, -			MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); +	writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);  	return 0;  } @@ -2023,10 +1983,9 @@ static int mlxbf_smbus_irq_recv(struct mlxbf_i2c_priv *priv, u8 recv_bytes)  	i2c_slave_event(slave, I2C_SLAVE_STOP, &value);  	/* Release the Slave GW. */ -	mlxbf_i2c_write(priv->smbus->io, -			MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES, 0x0); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_PEC, 0x0); -	mlxbf_i2c_write(priv->smbus->io, MLXBF_I2C_SMBUS_SLAVE_READY, 0x1); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); +	writel(0x0, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_PEC); +	writel(0x1, priv->smbus->io + MLXBF_I2C_SMBUS_SLAVE_READY);  	return ret;  } @@ -2061,8 +2020,8 @@ static irqreturn_t mlxbf_smbus_irq(int irq, void *ptr)  	 * slave, if the higher 8 bits are sent then the slave expect N bytes  	 * from the master.  	 */ -	rw_bytes_reg = mlxbf_i2c_read(priv->smbus->io, -				      MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES); +	rw_bytes_reg = readl(priv->smbus->io + +				MLXBF_I2C_SMBUS_SLAVE_RS_MASTER_BYTES);  	recv_bytes = (rw_bytes_reg >> 8) & GENMASK(7, 0);  	/* @@ -2264,6 +2223,7 @@ static const struct of_device_id mlxbf_i2c_dt_ids[] = {  MODULE_DEVICE_TABLE(of, mlxbf_i2c_dt_ids); +#ifdef CONFIG_ACPI  static const struct acpi_device_id mlxbf_i2c_acpi_ids[] = {  	{ "MLNXBF03", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_1] },  	{ "MLNXBF23", (kernel_ulong_t)&mlxbf_i2c_chip[MLXBF_I2C_CHIP_TYPE_2] }, @@ -2305,6 +2265,12 @@ static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv)  	return ret;  } +#else +static int mlxbf_i2c_acpi_probe(struct device *dev, struct mlxbf_i2c_priv *priv) +{ +	return -ENOENT; +} +#endif /* CONFIG_ACPI */  static int mlxbf_i2c_of_probe(struct device *dev, struct mlxbf_i2c_priv *priv)  { @@ -2473,7 +2439,9 @@ static struct platform_driver mlxbf_i2c_driver = {  	.driver = {  		.name = "i2c-mlxbf",  		.of_match_table = mlxbf_i2c_dt_ids, +#ifdef CONFIG_ACPI  		.acpi_match_table = ACPI_PTR(mlxbf_i2c_acpi_ids), +#endif /* CONFIG_ACPI  */  	},  }; @@ -2502,5 +2470,5 @@ static void __exit mlxbf_i2c_exit(void)  module_exit(mlxbf_i2c_exit);  MODULE_DESCRIPTION("Mellanox BlueField I2C bus driver"); -MODULE_AUTHOR("Khalil Blaiech <kblaiech@mellanox.com>"); +MODULE_AUTHOR("Khalil Blaiech <kblaiech@nvidia.com>");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 0cbdfbe605b5..33de99b7bc20 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -475,6 +475,10 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)  {  	u16 control_reg; +	writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST); +	udelay(50); +	writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); +  	mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);  	/* Set ioconfig */ @@ -529,10 +533,6 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)  	mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);  	mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN); - -	writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST); -	udelay(50); -	writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);  }  static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index e0e45fc19b8f..5cfe70aedced 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -17,6 +17,7 @@  #include <linux/interrupt.h>  #include <linux/mv643xx_i2c.h>  #include <linux/platform_device.h> +#include <linux/pinctrl/consumer.h>  #include <linux/reset.h>  #include <linux/io.h>  #include <linux/of.h> @@ -147,6 +148,7 @@ struct mv64xxx_i2c_data {  	bool			irq_clear_inverted;  	/* Clk div is 2 to the power n, not 2 to the power n + 1 */  	bool			clk_n_base_0; +	struct i2c_bus_recovery_info	rinfo;  };  static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -325,7 +327,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)  			 drv_data->msg->flags);  		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;  		mv64xxx_i2c_hw_init(drv_data); -		drv_data->rc = -EIO; +		i2c_recover_bus(&drv_data->adapter); +		drv_data->rc = -EAGAIN;  	}  } @@ -561,6 +564,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)  				"time_left: %d\n", drv_data->block,  				(int)time_left);  			mv64xxx_i2c_hw_init(drv_data); +			i2c_recover_bus(&drv_data->adapter);  		}  	} else  		spin_unlock_irqrestore(&drv_data->lock, flags); @@ -870,6 +874,25 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,  }  #endif /* CONFIG_OF */ +static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data, +					  struct device *dev) +{ +	struct i2c_bus_recovery_info *rinfo = &drv_data->rinfo; + +	rinfo->pinctrl = devm_pinctrl_get(dev); +	if (IS_ERR(rinfo->pinctrl)) { +		if (PTR_ERR(rinfo->pinctrl) == -EPROBE_DEFER) +			return -EPROBE_DEFER; +		dev_info(dev, "can't get pinctrl, bus recovery not supported\n"); +		return PTR_ERR(rinfo->pinctrl); +	} else if (!rinfo->pinctrl) { +		return -ENODEV; +	} + +	drv_data->adapter.bus_recovery_info = rinfo; +	return 0; +} +  static int  mv64xxx_i2c_probe(struct platform_device *pd)  { @@ -926,6 +949,10 @@ mv64xxx_i2c_probe(struct platform_device *pd)  		goto exit_reset;  	} +	rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev); +	if (rc == -EPROBE_DEFER) +		goto exit_reset; +  	drv_data->adapter.dev.parent = &pd->dev;  	drv_data->adapter.algo = &mv64xxx_i2c_algo;  	drv_data->adapter.owner = THIS_MODULE; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index c4b08a924461..f97243f02231 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -781,28 +781,15 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)  	return 0;  } -static const struct platform_device_id mxs_i2c_devtype[] = { -	{ -		.name = "imx23-i2c", -		.driver_data = MXS_I2C_V1, -	}, { -		.name = "imx28-i2c", -		.driver_data = MXS_I2C_V2, -	}, { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype); -  static const struct of_device_id mxs_i2c_dt_ids[] = { -	{ .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], }, -	{ .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], }, +	{ .compatible = "fsl,imx23-i2c", .data = (void *)MXS_I2C_V1, }, +	{ .compatible = "fsl,imx28-i2c", .data = (void *)MXS_I2C_V2, },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids);  static int mxs_i2c_probe(struct platform_device *pdev)  { -	const struct of_device_id *of_id = -				of_match_device(mxs_i2c_dt_ids, &pdev->dev);  	struct device *dev = &pdev->dev;  	struct mxs_i2c_dev *i2c;  	struct i2c_adapter *adap; @@ -812,10 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)  	if (!i2c)  		return -ENOMEM; -	if (of_id) { -		const struct platform_device_id *device_id = of_id->data; -		i2c->dev_type = device_id->driver_data; -	} +	i2c->dev_type = (enum mxs_i2c_devtype)of_device_get_match_data(&pdev->dev);  	i2c->regs = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(i2c->regs)) diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index f9a69b109e5c..6b20601ffb13 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -353,15 +353,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev)  	pci_free_irq_vectors(pdev);  } -/* - * We need gpu_i2c_suspend() even if it is stub, for runtime pm to work - * correctly. Without it, lspci shows runtime pm status as "D0" for the card. - * Documentation/power/pci.rst also insists for driver to provide this. - */ -static __maybe_unused int gpu_i2c_suspend(struct device *dev) -{ -	return 0; -} +#define gpu_i2c_suspend NULL  static __maybe_unused int gpu_i2c_resume(struct device *dev)  { diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index f5fc75b65a19..273222e38056 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -83,7 +83,6 @@ struct ocores_i2c {  #define TYPE_OCORES		0  #define TYPE_GRLIB		1 -#define TYPE_SIFIVE_REV0	2  #define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */ @@ -476,11 +475,9 @@ static const struct of_device_id ocores_i2c_match[] = {  	},  	{  		.compatible = "sifive,fu540-c000-i2c", -		.data = (void *)TYPE_SIFIVE_REV0,  	},  	{  		.compatible = "sifive,i2c0", -		.data = (void *)TYPE_SIFIVE_REV0,  	},  	{},  }; @@ -606,7 +603,6 @@ static int ocores_i2c_probe(struct platform_device *pdev)  {  	struct ocores_i2c *i2c;  	struct ocores_i2c_platform_data *pdata; -	const struct of_device_id *match;  	struct resource *res;  	int irq;  	int ret; @@ -686,17 +682,20 @@ static int ocores_i2c_probe(struct platform_device *pdev)  	init_waitqueue_head(&i2c->wait); -	irq = platform_get_irq(pdev, 0); +	irq = platform_get_irq_optional(pdev, 0); +	/* +	 * Since the SoC does have an interrupt, its DT has an interrupt +	 * property - But this should be bypassed as the IRQ logic in this +	 * SoC is broken. +	 */ +	if (of_device_is_compatible(pdev->dev.of_node, +				    "sifive,fu540-c000-i2c")) { +		i2c->flags |= OCORES_FLAG_BROKEN_IRQ; +		irq = -ENXIO; +	} +  	if (irq == -ENXIO) {  		ocores_algorithm.master_xfer = ocores_xfer_polling; - -		/* -		 * Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for -		 * FU540-C000 SoC in polling mode. -		 */ -		match = of_match_node(ocores_i2c_match, pdev->dev.of_node); -		if (match && (long)match->data == TYPE_SIFIVE_REV0) -			i2c->flags |= OCORES_FLAG_BROKEN_IRQ;  	} else {  		if (irq < 0)  			return irq; diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 9918b2a0b909..98882fe4e965 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -14,6 +14,7 @@  #include <linux/i2c.h>  #include <linux/interrupt.h>  #include <linux/io.h> +#include <linux/iopoll.h>  #include <linux/module.h>  #include <linux/of_device.h> @@ -76,6 +77,7 @@  #define OWL_I2C_FIFOCTL_TFR	BIT(2)  /* I2Cc_FIFOSTAT Bit Mask */ +#define OWL_I2C_FIFOSTAT_CECB	BIT(0)  #define OWL_I2C_FIFOSTAT_RNB	BIT(1)  #define OWL_I2C_FIFOSTAT_RFE	BIT(2)  #define OWL_I2C_FIFOSTAT_TFF	BIT(5) @@ -83,7 +85,8 @@  #define OWL_I2C_FIFOSTAT_RFD	GENMASK(15, 8)  /* I2C bus timeout */ -#define OWL_I2C_TIMEOUT		msecs_to_jiffies(4 * 1000) +#define OWL_I2C_TIMEOUT_MS	(4 * 1000) +#define OWL_I2C_TIMEOUT		msecs_to_jiffies(OWL_I2C_TIMEOUT_MS)  #define OWL_I2C_MAX_RETRIES	50 @@ -161,14 +164,11 @@ static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)  	writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);  } -static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) +static void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev)  { -	struct owl_i2c_dev *i2c_dev = _dev;  	struct i2c_msg *msg = i2c_dev->msg;  	unsigned int stat, fifostat; -	spin_lock(&i2c_dev->lock); -  	i2c_dev->err = 0;  	/* Handle NACK from slave */ @@ -178,7 +178,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)  		/* Clear NACK error bit by writing "1" */  		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,  				   OWL_I2C_FIFOSTAT_RNB, true); -		goto stop; +		return;  	}  	/* Handle bus error */ @@ -188,7 +188,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)  		/* Clear BUS error bit by writing "1" */  		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,  				   OWL_I2C_STAT_BEB, true); -		goto stop; +		return;  	}  	/* Handle FIFO read */ @@ -206,8 +206,16 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)  			       i2c_dev->base + OWL_I2C_REG_TXDAT);  		}  	} +} + +static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) +{ +	struct owl_i2c_dev *i2c_dev = _dev; + +	spin_lock(&i2c_dev->lock); + +	owl_i2c_xfer_data(i2c_dev); -stop:  	/* Clear pending interrupts */  	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,  			   OWL_I2C_STAT_IRQP, true); @@ -240,8 +248,8 @@ static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)  	return 0;  } -static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, -			       int num) +static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs, +			       int num, bool atomic)  {  	struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);  	struct i2c_msg *msg; @@ -285,11 +293,12 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,  		goto err_exit;  	} -	reinit_completion(&i2c_dev->msg_complete); +	if (!atomic) +		reinit_completion(&i2c_dev->msg_complete); -	/* Enable I2C controller interrupt */ +	/* Enable/disable I2C controller interrupt */  	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, -			   OWL_I2C_CTL_IRQE, true); +			   OWL_I2C_CTL_IRQE, !atomic);  	/*  	 * Select: FIFO enable, Master mode, Stop enable, Data count enable, @@ -357,20 +366,33 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,  	spin_unlock_irqrestore(&i2c_dev->lock, flags); -	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, -						adap->timeout); +	if (atomic) { +		/* Wait for Command Execute Completed or NACK Error bits */ +		ret = readl_poll_timeout_atomic(i2c_dev->base + OWL_I2C_REG_FIFOSTAT, +						val, val & (OWL_I2C_FIFOSTAT_CECB | +							    OWL_I2C_FIFOSTAT_RNB), +						10, OWL_I2C_TIMEOUT_MS * 1000); +	} else { +		time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, +							adap->timeout); +		if (!time_left) +			ret = -ETIMEDOUT; +	}  	spin_lock_irqsave(&i2c_dev->lock, flags); -	if (time_left == 0) { + +	if (ret) {  		dev_err(&adap->dev, "Transaction timed out\n");  		/* Send stop condition and release the bus */  		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,  				   OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,  				   true); -		ret = -ETIMEDOUT;  		goto err_exit;  	} +	if (atomic) +		owl_i2c_xfer_data(i2c_dev); +  	ret = i2c_dev->err < 0 ? i2c_dev->err : num;  err_exit: @@ -384,9 +406,22 @@ unlocked_err_exit:  	return ret;  } +static int owl_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, +			int num) +{ +	return owl_i2c_xfer_common(adap, msgs, num, false); +} + +static int owl_i2c_xfer_atomic(struct i2c_adapter *adap, +			       struct i2c_msg *msgs, int num) +{ +	return owl_i2c_xfer_common(adap, msgs, num, true); +} +  static const struct i2c_algorithm owl_i2c_algorithm = { -	.master_xfer    = owl_i2c_master_xfer, -	.functionality  = owl_i2c_func, +	.master_xfer	     = owl_i2c_xfer, +	.master_xfer_atomic  = owl_i2c_xfer_atomic, +	.functionality	     = owl_i2c_func,  };  static const struct i2c_adapter_quirks owl_i2c_quirks = { @@ -473,6 +508,7 @@ disable_clk:  }  static const struct of_device_id owl_i2c_of_match[] = { +	{ .compatible = "actions,s500-i2c" },  	{ .compatible = "actions,s700-i2c" },  	{ .compatible = "actions,s900-i2c" },  	{ /* sentinel */ } @@ -484,6 +520,7 @@ static struct platform_driver owl_i2c_driver = {  	.driver		= {  		.name	= "owl-i2c",  		.of_match_table = of_match_ptr(owl_i2c_of_match), +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,  	},  };  module_platform_driver(owl_i2c_driver); diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 546426a470cc..86d4f75ef8d3 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -33,8 +33,6 @@ struct i2c_pca_pf_data {  	wait_queue_head_t		wait;  	struct i2c_adapter		adap;  	struct i2c_algo_pca_data	algo_data; -	unsigned long			io_base; -	unsigned long			io_size;  };  /* Read/Write functions for different register alignments */ @@ -156,8 +154,6 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)  	init_waitqueue_head(&i2c->wait); -	i2c->io_base = res->start; -	i2c->io_size = resource_size(res);  	i2c->irq = irq;  	i2c->adap.nr = pdev->id; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 35ca2c02c9b9..a636ea0eb50a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -264,9 +264,6 @@ struct pxa_i2c {  	u32			hs_mask;  	struct i2c_bus_recovery_info recovery; -	struct pinctrl		*pinctrl; -	struct pinctrl_state	*pinctrl_default; -	struct pinctrl_state	*pinctrl_recovery;  };  #define _IBMR(i2c)	((i2c)->reg_ibmr) @@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)  	 */  	gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);  	gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS); - -	WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));  }  static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)  {  	struct pxa_i2c *i2c = adap->algo_data; +	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;  	u32 isr;  	/* @@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)  		i2c_pxa_do_reset(i2c);  	} -	WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default)); +	WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));  	dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",  	        readl(_IBMR(i2c)), readl(_ISR(i2c))); @@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)  	if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))  		return 0; -	i2c->pinctrl = devm_pinctrl_get(dev); -	if (PTR_ERR(i2c->pinctrl) == -ENODEV) -		i2c->pinctrl = NULL; -	if (IS_ERR(i2c->pinctrl)) -		return PTR_ERR(i2c->pinctrl); - -	if (!i2c->pinctrl) -		return 0; - -	i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl, -						    PINCTRL_STATE_DEFAULT); -	i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery"); - -	if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) { -		dev_info(dev, "missing pinmux recovery information: %ld %ld\n", -			 PTR_ERR(i2c->pinctrl_default), -			 PTR_ERR(i2c->pinctrl_recovery)); -		return 0; -	} - -	/* -	 * Claiming GPIOs can influence the pinmux state, and may glitch the -	 * I2C bus. Do this carefully. -	 */ -	bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN); -	if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER)) -		return -EPROBE_DEFER; -	if (IS_ERR(bri->scl_gpiod)) { -		dev_info(dev, "missing scl gpio recovery information: %pe\n", -			 bri->scl_gpiod); -		return 0; -	} - -	/* -	 * We have SCL. Pull SCL low and wait a bit so that SDA glitches -	 * have no effect. -	 */ -	gpiod_direction_output(bri->scl_gpiod, 0); -	udelay(10); -	bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN); - -	/* Wait a bit in case of a SDA glitch, and then release SCL. */ -	udelay(10); -	gpiod_direction_output(bri->scl_gpiod, 1); - -	if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER)) -		return -EPROBE_DEFER; - -	if (IS_ERR(bri->sda_gpiod)) { -		dev_info(dev, "missing sda gpio recovery information: %pe\n", -			 bri->sda_gpiod); +	bri->pinctrl = devm_pinctrl_get(dev); +	if (PTR_ERR(bri->pinctrl) == -ENODEV) { +		bri->pinctrl = NULL;  		return 0;  	} +	if (IS_ERR(bri->pinctrl)) +		return PTR_ERR(bri->pinctrl);  	bri->prepare_recovery = i2c_pxa_prepare_recovery;  	bri->unprepare_recovery = i2c_pxa_unprepare_recovery; -	bri->recover_bus = i2c_generic_scl_recovery;  	i2c->adap.bus_recovery_info = bri; -	/* -	 * Claiming GPIOs can change the pinmux state, which confuses the -	 * pinctrl since pinctrl's idea of the current setting is unaffected -	 * by the pinmux change caused by claiming the GPIO. Work around that -	 * by switching pinctrl to the GPIO state here. We do it this way to -	 * avoid glitching the I2C bus. -	 */ -	pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery); - -	return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default); +	return 0;  }  static int i2c_pxa_probe(struct platform_device *dev) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index f13735beca58..1c259b5188de 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -194,9 +194,9 @@ static irqreturn_t cci_isr(int irq, void *dev)  	if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_ERROR)) {  		if (val & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR ||  			val & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR) -			cci->master[0].status = -ENXIO; +			cci->master[1].status = -ENXIO;  		else -			cci->master[0].status = -EIO; +			cci->master[1].status = -EIO;  		writel(CCI_HALT_REQ_I2C_M1_Q0Q1, cci->base + CCI_HALT_REQ);  		ret = IRQ_HANDLED; diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 8b4c35f47a70..046d241183c5 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -353,19 +353,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  {  	dma_addr_t rx_dma;  	unsigned long time_left; -	void *dma_buf = NULL; +	void *dma_buf;  	struct geni_se *se = &gi2c->se;  	size_t len = msg->len; -	if (!of_machine_is_compatible("lenovo,yoga-c630")) -		dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); - +	dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);  	if (dma_buf)  		geni_se_select_mode(se, GENI_SE_DMA);  	else  		geni_se_select_mode(se, GENI_SE_FIFO);  	writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN); +	geni_se_setup_m_cmd(se, I2C_READ, m_param);  	if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) {  		geni_se_select_mode(se, GENI_SE_FIFO); @@ -373,8 +372,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		dma_buf = NULL;  	} -	geni_se_setup_m_cmd(se, I2C_READ, m_param); -  	time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);  	if (!time_left)  		geni_i2c_abort_xfer(gi2c); @@ -395,19 +392,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  {  	dma_addr_t tx_dma;  	unsigned long time_left; -	void *dma_buf = NULL; +	void *dma_buf;  	struct geni_se *se = &gi2c->se;  	size_t len = msg->len; -	if (!of_machine_is_compatible("lenovo,yoga-c630")) -		dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); - +	dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);  	if (dma_buf)  		geni_se_select_mode(se, GENI_SE_DMA);  	else  		geni_se_select_mode(se, GENI_SE_FIFO);  	writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN); +	geni_se_setup_m_cmd(se, I2C_WRITE, m_param);  	if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) {  		geni_se_select_mode(se, GENI_SE_FIFO); @@ -415,8 +411,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		dma_buf = NULL;  	} -	geni_se_setup_m_cmd(se, I2C_WRITE, m_param); -  	if (!dma_buf) /* Get FIFO IRQ */  		writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index fbc04b60cfd1..5a47915869ae 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -801,7 +801,8 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)  	if (ret || qup->bus_err || qup->qup_err) {  		reinit_completion(&qup->xfer); -		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) { +		ret = qup_i2c_change_state(qup, QUP_RUN_STATE); +		if (ret) {  			dev_err(qup->dev, "change to run state timed out");  			goto desc_err;  		} diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index cab725559999..3ae6ca21a02c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -129,6 +129,7 @@ struct sh_mobile_i2c_data {  	int sr;  	bool send_stop;  	bool stop_after_dma; +	bool atomic_xfer;  	struct resource *res;  	struct dma_chan *dma_tx; @@ -330,13 +331,15 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op  		ret = iic_rd(pd, ICDR);  		break;  	case OP_RX_STOP: /* enable DTE interrupt, issue stop */ -		iic_wr(pd, ICIC, -		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); +		if (!pd->atomic_xfer) +			iic_wr(pd, ICIC, +			       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);  		iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);  		break;  	case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ -		iic_wr(pd, ICIC, -		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); +		if (!pd->atomic_xfer) +			iic_wr(pd, ICIC, +			       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);  		ret = iic_rd(pd, ICDR);  		iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);  		break; @@ -429,7 +432,8 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)  	if (wakeup) {  		pd->sr |= SW_DONE; -		wake_up(&pd->wait); +		if (!pd->atomic_xfer) +			wake_up(&pd->wait);  	}  	/* defeat write posting to avoid spurious WAIT interrupts */ @@ -581,6 +585,9 @@ static void start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,  	pd->pos = -1;  	pd->sr = 0; +	if (pd->atomic_xfer) +		return; +  	pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8);  	if (pd->dma_buf)  		sh_mobile_i2c_xfer_dma(pd); @@ -637,15 +644,13 @@ static int poll_busy(struct sh_mobile_i2c_data *pd)  	return i ? 0 : -ETIMEDOUT;  } -static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, -			      struct i2c_msg *msgs, -			      int num) +static int sh_mobile_xfer(struct sh_mobile_i2c_data *pd, +			 struct i2c_msg *msgs, int num)  { -	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);  	struct i2c_msg	*msg;  	int err = 0;  	int i; -	long timeout; +	long time_left;  	/* Wake up device and enable clock */  	pm_runtime_get_sync(pd->dev); @@ -662,15 +667,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,  		if (do_start)  			i2c_op(pd, OP_START); -		/* The interrupt handler takes care of the rest... */ -		timeout = wait_event_timeout(pd->wait, -				       pd->sr & (ICSR_TACK | SW_DONE), -				       adapter->timeout); - -		/* 'stop_after_dma' tells if DMA transfer was complete */ -		i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma); +		if (pd->atomic_xfer) { +			unsigned long j = jiffies + pd->adap.timeout; + +			time_left = time_before_eq(jiffies, j); +			while (time_left && +			       !(pd->sr & (ICSR_TACK | SW_DONE))) { +				unsigned char sr = iic_rd(pd, ICSR); + +				if (sr & (ICSR_AL   | ICSR_TACK | +					  ICSR_WAIT | ICSR_DTE)) { +					sh_mobile_i2c_isr(0, pd); +					udelay(150); +				} else { +					cpu_relax(); +				} +				time_left = time_before_eq(jiffies, j); +			} +		} else { +			/* The interrupt handler takes care of the rest... */ +			time_left = wait_event_timeout(pd->wait, +					pd->sr & (ICSR_TACK | SW_DONE), +					pd->adap.timeout); + +			/* 'stop_after_dma' tells if DMA xfer was complete */ +			i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, +						 pd->stop_after_dma); +		} -		if (!timeout) { +		if (!time_left) {  			dev_err(pd->dev, "Transfer request timed out\n");  			if (pd->dma_direction != DMA_NONE)  				sh_mobile_i2c_cleanup_dma(pd); @@ -696,14 +721,35 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,  	return err ?: num;  } +static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, +			      struct i2c_msg *msgs, +			      int num) +{ +	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); + +	pd->atomic_xfer = false; +	return sh_mobile_xfer(pd, msgs, num); +} + +static int sh_mobile_i2c_xfer_atomic(struct i2c_adapter *adapter, +				     struct i2c_msg *msgs, +				     int num) +{ +	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); + +	pd->atomic_xfer = true; +	return sh_mobile_xfer(pd, msgs, num); +} +  static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)  {  	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;  }  static const struct i2c_algorithm sh_mobile_i2c_algorithm = { -	.functionality	= sh_mobile_i2c_func, -	.master_xfer	= sh_mobile_i2c_xfer, +	.functionality = sh_mobile_i2c_func, +	.master_xfer = sh_mobile_i2c_xfer, +	.master_xfer_atomic = sh_mobile_i2c_xfer_atomic,  };  static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = { @@ -910,10 +956,38 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)  	return 0;  } +#ifdef CONFIG_PM_SLEEP +static int sh_mobile_i2c_suspend(struct device *dev) +{ +	struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev); + +	i2c_mark_adapter_suspended(&pd->adap); +	return 0; +} + +static int sh_mobile_i2c_resume(struct device *dev) +{ +	struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev); + +	i2c_mark_adapter_resumed(&pd->adap); +	return 0; +} + +static const struct dev_pm_ops sh_mobile_i2c_pm_ops = { +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend, +				      sh_mobile_i2c_resume) +}; + +#define DEV_PM_OPS (&sh_mobile_i2c_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ +  static struct platform_driver sh_mobile_i2c_driver = {  	.driver		= {  		.name		= "i2c-sh_mobile",  		.of_match_table = sh_mobile_i2c_dt_ids, +		.pm	= DEV_PM_OPS,  	},  	.probe		= sh_mobile_i2c_probe,  	.remove		= sh_mobile_i2c_remove, diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index f41f51a176a1..9aa8e65b511e 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -2322,7 +2322,7 @@ static int stm32f7_i2c_suspend(struct device *dev)  	i2c_mark_adapter_suspended(&i2c_dev->adap); -	if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { +	if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) {  		ret = stm32f7_i2c_regs_backup(i2c_dev);  		if (ret < 0) {  			i2c_mark_adapter_resumed(&i2c_dev->adap); @@ -2341,7 +2341,7 @@ static int stm32f7_i2c_resume(struct device *dev)  	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);  	int ret; -	if (!device_may_wakeup(dev) && !dev->power.wakeup_path) { +	if (!device_may_wakeup(dev) && !device_wakeup_path(dev)) {  		ret = pm_runtime_force_resume(dev);  		if (ret < 0)  			return ret; diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 573b5da145d1..63ebf722a424 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -549,17 +549,18 @@ put_sync_adapter:  static int i2c_device_remove(struct device *dev)  { -	struct i2c_client	*client = i2c_verify_client(dev); +	struct i2c_client	*client = to_i2c_client(dev);  	struct i2c_driver	*driver; -	int status = 0; - -	if (!client || !dev->driver) -		return 0;  	driver = to_i2c_driver(dev->driver);  	if (driver->remove) { +		int status; +  		dev_dbg(dev, "remove\n"); +  		status = driver->remove(client); +		if (status) +			dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status));  	}  	dev_pm_domain_detach(&client->dev, true); @@ -571,7 +572,8 @@ static int i2c_device_remove(struct device *dev)  	if (client->flags & I2C_CLIENT_HOST_NOTIFY)  		pm_runtime_put(&client->adapter->dev); -	return status; +	/* return always 0 because there is WIP to make remove-functions void */ +	return 0;  }  static void i2c_device_shutdown(struct device *dev)  | 
