[PATCH 4/7] i2c: nomadik: return proper fault codes
Dmitry Guzman
Dmitry.Guzman at mobileye.com
Tue Jun 23 09:31:51 PDT 2026
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 <Dmitry.Guzman at mobileye.com>
---
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
More information about the linux-arm-kernel
mailing list