From: Stanley Chu <[email protected]>

Add deblock callback to perform I2C bus recovery through the reset
command. The recovery always resets the controller status, even if
the bus is not stuck.

Signed-off-by: Stanley Chu <[email protected]>
Signed-off-by: Jim Liu <[email protected]>
---
 drivers/i2c/npcm_i2c.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/npcm_i2c.c b/drivers/i2c/npcm_i2c.c
index cc1847893f6..acde0b03c68 100644
--- a/drivers/i2c/npcm_i2c.c
+++ b/drivers/i2c/npcm_i2c.c
@@ -215,7 +215,7 @@ static void npcm_i2c_reset(struct npcm_i2c_bus *bus)
 {
        struct npcm_i2c_regs *reg = bus->reg;
 
-       debug("%s: module %d\n", __func__, bus->num);
+       printf("%s: module %d\n", __func__, bus->num);
        /* disable & enable SMB moudle */
        clrbits_8(&reg->ctl2, SMBCTL2_ENABLE);
        setbits_8(&reg->ctl2, SMBCTL2_ENABLE);
@@ -250,7 +250,7 @@ static void npcm_i2c_recovery(struct npcm_i2c_bus *bus, u32 
addr)
        val = readb(&reg->ctl3);
        /* Skip recovery, bus not stucked */
        if ((val & SMBCTL3_SCL_LVL) && (val & SMBCTL3_SDA_LVL))
-               return;
+               goto reset;
 
        printf("Performing I2C bus %d recovery...\n", bus->num);
        /* SCL/SDA are not releaed, perform recovery */
@@ -281,6 +281,7 @@ static void npcm_i2c_recovery(struct npcm_i2c_bus *bus, u32 
addr)
        } else {
                printf("Fail to recover I2C bus %d\n", bus->num);
        }
+reset:
        npcm_i2c_reset(bus);
 }
 
@@ -513,7 +514,7 @@ static int npcm_i2c_xfer(struct udevice *dev,
        if (bus->started)
                npcm_i2c_send_stop(bus, true);
 
-       if (err)
+       if (err && err != I2C_ERR_NACK)
                npcm_i2c_recovery(bus, msg->addr);
 
        return ret;
@@ -560,6 +561,13 @@ static int npcm_i2c_set_bus_speed(struct udevice *dev,
        return npcm_i2c_init_clk(bus, speed);
 }
 
+static int npcm_i2c_deblock(struct udevice *dev)
+{
+       npcm_i2c_recovery(dev_get_priv(dev), 0);
+
+       return 0;
+}
+
 static int npcm_i2c_probe(struct udevice *dev)
 {
        struct npcm_i2c_bus *bus = dev_get_priv(dev);
@@ -626,6 +634,7 @@ static int npcm_i2c_probe(struct udevice *dev)
 static const struct dm_i2c_ops nuvoton_i2c_ops = {
        .xfer               = npcm_i2c_xfer,
        .set_bus_speed  = npcm_i2c_set_bus_speed,
+       .deblock        = npcm_i2c_deblock,
 };
 
 static const struct udevice_id nuvoton_i2c_of_match[] = {
-- 
2.34.1

Reply via email to