I2C documentation Documentation/i2c/fault-codes.rst defines fault codes for different negative results in I2C transmittion. Previously, i2c-nomadik driver didn't implement them properly - it returned ETIMEDOUT on most errors and EIO on master arbitration lost.
To comply with the documentation, return the proper fault codes for different conditions, namely: - EAGAIN if arbitration lost - EOVERFLOW if message is too long (>2047 bytes) - ENXIO if target address is not acknowledged - EIO on other errors detected by controller (for example, NACK on data) - ETIMEDOUT if driver gets timeout waiting for message completion without any fault condition detected by the controller (for example, too long message, or SDA/SCL line stuck on 0). Signed-off-by: Dmitry Guzman <[email protected]> --- drivers/i2c/busses/i2c-nomadik.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 3eb06988c026e5c573fcf55d83de7136b5ca7ac9..e19ace904e79cd2d83171d9f38fc103a6c5e023b 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -226,6 +226,18 @@ static const char *abort_causes[] = { "overflow, maxsize is 2047 bytes", }; +/* Linux fault codes for controller abort causes */ +static int fault_codes[] = { + ENXIO, + EIO, + EIO, + EAGAIN, + EIO, + EIO, + EOVERFLOW, + EIO +}; + static inline void i2c_set_bit(void __iomem *reg, u32 mask) { writel(readl(reg) | mask, reg); @@ -653,6 +665,8 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *priv, u16 flags) cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" : abort_causes[cause]); + priv->result = -fault_codes[cause]; + status = priv->result; } init_hw(priv); @@ -865,7 +879,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) /* Master Arbitration lost interrupt */ case I2C_IT_MAL: - priv->result = -EIO; + priv->result = -EAGAIN; init_hw(priv); i2c_set_bit(priv->virtbase + I2C_ICR, I2C_IT_MAL); -- 2.43.0
