AnsweredAssumed Answered

imx6solo  i2c bus busy issue

Question asked by huang peter on Aug 30, 2019
Latest reply on Aug 30, 2019 by igorpadykov

system: linux 4.1.15

soc:imx6s

1.some time i2c work error ,log is

i2c i2c-1: master_xfer[0] W, addr=0x18, len=2
[ 1.625649] i2c i2c-1: <i2c_imx_xfer>
[ 1.625657] i2c i2c-1: <i2c_imx_start>
[ 1.625715] <i2c_imx_bus_busy>
[ 1.625722] <i2c_imx_bus_busy> I2C bus is busy temp 83
[ 1.625733] i2c i2c-1: <i2c_imx_xfer> exit with: error: -11

 

2.if i2c bus busy happen,hi was always busy and  i2c sdl sck no wave form。

 

3. device tree config

imx6qdl.dtsi

i2c2 = &i2c3;

 

i2c3: i2c@021a8000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
reg = <0x021a8000 0x4000>;
interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_I2C3>;
status = "disabled";
};

 

imx6qdl-sabresd.dtsi

&i2c2{
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";

 

4.the log code is i2c-imx.c

/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/

static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
{
unsigned long orig_jiffies = jiffies;
unsigned int temp;

dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);

while (1) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);

/* check for arbitration lost */
if (temp & I2SR_IAL) {
temp &= ~I2SR_IAL;
printk("<%s> is busy temp %x\n", __func__,temp);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
return -EAGAIN;
}

if (for_busy && (temp & I2SR_IBB))
break;
if (!for_busy && !(temp & I2SR_IBB))
break;
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C bus is busy\n", __func__);
return -ETIMEDOUT;
}
schedule();
}

return 0;
}

Outcomes