]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
i2c: microchip: fix ack sending logic
authorConor Dooley <conor.dooley@microchip.com>
Wed, 26 Oct 2022 07:49:18 +0000 (08:49 +0100)
committerHeiko Schocher <hs@denx.de>
Mon, 14 Nov 2022 06:20:10 +0000 (07:20 +0100)
"Master receive mode" was not correctly sending ACKs/NACKs in the
interrupt handler. Bring the handling of M_SLAR_ACK, M_RX_DATA_ACKED &
M_RX_DATA_NACKED in line with the Linux driver.

Fixes: 0dc0d1e094 ("i2c: Add Microchip PolarFire SoC I2C driver")
Reported-by: Shravan Chippa <shravan.chippa@microchip.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Padmarao Begari <padmarao.begari@microchip.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
drivers/i2c/i2c-microchip.c

index 12f65d0af75a30593bdfca5bdfff2d4afc99dd56..3a27459386846ee5e2dbee0495a0126183a5b081 100644 (file)
@@ -2,8 +2,9 @@
 /*
  * Microchip I2C controller driver
  *
- * Copyright (C) 2021 Microchip Technology Inc.
+ * Copyright (C) 2021-2022 Microchip Technology Inc.
  * Padmarao Begari <padmarao.begari@microchip.com>
+ * Conor Dooley <conor.dooley@microchip.com>
  */
 #include <common.h>
 #include <clk.h>
@@ -265,16 +266,27 @@ static int mpfs_i2c_service_handler(struct mpfs_i2c_bus *bus)
                }
                break;
        case STATUS_M_SLAR_ACK:
-               ctrl = readl(bus->base + MPFS_I2C_CTRL);
-               ctrl |= CTRL_AA;
-               writel(ctrl, bus->base + MPFS_I2C_CTRL);
-               if (bus->msg_len == 0) {
+               if (bus->msg_len > 1u) {
+                       ctrl = readl(bus->base + MPFS_I2C_CTRL);
+                       ctrl |= CTRL_AA;
+                       writel(ctrl, bus->base + MPFS_I2C_CTRL);
+               } else if (bus->msg_len == 1u) {
+                       ctrl = readl(bus->base + MPFS_I2C_CTRL);
+                       ctrl &= ~CTRL_AA;
+                       writel(ctrl, bus->base + MPFS_I2C_CTRL);
+               } else {
+                       ctrl = readl(bus->base + MPFS_I2C_CTRL);
+                       ctrl |= CTRL_AA;
+                       writel(ctrl, bus->base + MPFS_I2C_CTRL);
                        /* On the last byte to be transmitted, send STOP */
                        mpfs_i2c_stop(bus);
                        finish = true;
                }
                break;
        case STATUS_M_RX_DATA_ACKED:
+               mpfs_i2c_empty_rx(bus);
+               break;
+       case STATUS_M_RX_DATA_NACKED:
                mpfs_i2c_empty_rx(bus);
                if (bus->msg_len == 0) {
                        /* On the last byte to be transmitted, send STOP */
@@ -283,7 +295,6 @@ static int mpfs_i2c_service_handler(struct mpfs_i2c_bus *bus)
                }
                break;
        case STATUS_M_TX_DATA_NACK:
-       case STATUS_M_RX_DATA_NACKED:
        case STATUS_M_SLAR_NACK:
        case STATUS_M_SLAW_NACK:
                bus->msg_err = -ENXIO;