Hi Pavel,
Are you absolutely sure?
The LS2088A reference manual I have (from 10/2016) says explicitly about both IBAL and IBIF:
"This bit must be cleared by software, by writing a one to it. A write of zero has no effect."
Both bits are flagged with "w1c" in the "W"-row of the register diagram.
Since the current code writes a zero to IBAL, I think either the code or the reference manual must be wrong.
Note that I am assuming the purpose is to clear the IBAL flag.
And as mentioned, there are these structs defined which provide different implementations for operations like clearing IBSR:
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
.devtype = IMX1_I2C,
.regshift = IMX_I2C_REGSHIFT,
.clk_div = imx_i2c_clk_div,
.ndivs = ARRAY_SIZE(imx_i2c_clk_div),
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C,
.i2cr_ien_opcode = I2CR_IEN_OPCODE_1,
};
static const struct imx_i2c_hwdata imx21_i2c_hwdata = {
.devtype = IMX21_I2C,
.regshift = IMX_I2C_REGSHIFT,
.clk_div = imx_i2c_clk_div,
.ndivs = ARRAY_SIZE(imx_i2c_clk_div),
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W0C,
.i2cr_ien_opcode = I2CR_IEN_OPCODE_1,
};
static struct imx_i2c_hwdata vf610_i2c_hwdata = {
.devtype = VF610_I2C,
.regshift = VF610_I2C_REGSHIFT,
.clk_div = vf610_i2c_clk_div,
.ndivs = ARRAY_SIZE(vf610_i2c_clk_div),
.i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C,
.i2cr_ien_opcode = I2CR_IEN_OPCODE_0,
};
Note especially that the last one has I2SR_CLR_OPCODE_W1C, named same as the flag from the register diagram.
Should i2c_mx_bus_busy() not use .i2sr_clr_opcode to clear flags from IBSR, instead of the current approach?
[edit]
Also, I just noticed this at the end of i2c_mx_bus_busy():
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
u8 status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C bus is busy\n", __func__);
if ((status & (I2SR_ICF | I2SR_IBB | I2CR_TXAK)) != 0) {
imx_i2c_write_reg(status & ~I2SR_IAL, i2c_imx,
IMX_I2C_I2CR);
imx_i2c_fixup(i2c_imx);
}
return -ETIMEDOUT;
}
Note that it reads flags from the status register, then it writes the same flags to the control register.
Is that also correct? Is not the purpose of this code to clear status flags?
If the TCF (I2SR_ICF) flag is set in status, this code will set the MDIS bit in control.
And that will actually disable the I2C module, according to our reference manual...
[/edit]
Best regards,
Martin Etnestad