]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
i2c: cdns: Add timeout for RXDV status bit polling
authorPadmarao Begari <padmarao.begari@amd.com>
Wed, 26 Nov 2025 15:12:35 +0000 (16:12 +0100)
committerMichal Simek <michal.simek@amd.com>
Fri, 19 Dec 2025 07:25:27 +0000 (08:25 +0100)
Add a timeout mechanism when waiting for the RXDV (Receive Data
Valid) status bit to be set before reading data from the FIFO.
This prevents infinite polling loops that could occur if the
hardware doesn't respond as expected.

The timeout is set to 1000ms (CDNS_I2C_RXDV_TIMEOUT_MS) and uses
the wait_for_bit_le32() function to poll the status register. If
the timeout expires, an error code is returned.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Reviewed-by: Heiko Schocher <hs@nabladev.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/ba53d57c179f3390b32bc6094f3ffb5f4cde931e.1764169953.git.michal.simek@amd.com
drivers/i2c/i2c-cdns.c

index 3f7cf8533ec763e44e12f10786f93342c0f229ce..4e9d4e44899a2103e3560976dffbcfbd08aa0fb8 100644 (file)
@@ -85,6 +85,8 @@ struct cdns_i2c_regs {
 
 #define CDNS_I2C_ARB_LOST_MAX_RETRIES  10
 
+#define CDNS_I2C_RXDV_TIMEOUT_MS       1000
+
 #ifdef DEBUG
 static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)
 {
@@ -349,6 +351,11 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
        hold_quirk = (i2c_bus->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx;
 
        while (recv_count && !is_arbitration_lost(regs)) {
+               int err = wait_for_bit_le32(&regs->status, CDNS_I2C_STATUS_RXDV,
+                                           true, CDNS_I2C_RXDV_TIMEOUT_MS, false);
+               if (err)
+                       return err;
+
                while (readl(&regs->status) & CDNS_I2C_STATUS_RXDV) {
                        if (recv_count < i2c_bus->fifo_depth &&
                            !i2c_bus->hold_flag) {
@@ -452,6 +459,10 @@ static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
                        ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf,
                                                  msg->len);
                }
+
+               if (ret == -ETIMEDOUT)
+                       return ret;
+
                if (ret == -EAGAIN) {
                        msg = message;
                        nmsgs = num_msgs;