Commit 61e6fe59 authored by Christian Eggers's avatar Christian Eggers Committed by Wolfram Sang
Browse files

i2c: imx: Don't generate STOP condition if arbitration has been lost



If arbitration is lost, the master automatically changes to slave mode.
I2SR_IBB may or may not be reset by hardware. Raising a STOP condition
by resetting I2CR_MSTA has no effect and will not clear I2SR_IBB.

So calling i2c_imx_bus_busy() is not required and would busy-wait until
timeout.

Signed-off-by: default avatarChristian Eggers <ceggers@arri.de>
Tested (not extensively) on Vybrid VF500 (Toradex VF50):
Tested-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
Acked-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Cc: stable@vger.kernel.org # Requires trivial backporting, simple remove
                           # the 3rd argument from the calls to
                           # i2c_imx_bus_busy().
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent 1de67a3d
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -615,6 +615,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;
@@ -778,8 +780,11 @@ 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);
		if (!i2c_imx->stopped)
			i2c_imx_bus_busy(i2c_imx, 0, false);
	} else {
		/*
@@ -905,8 +910,11 @@ 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);
				if (!i2c_imx->stopped)
					i2c_imx_bus_busy(i2c_imx, 0, atomic);
			} else {
				/*