Zero-length transfers currently return success without accessing the
bus. This makes every address appear present to i2c probe.

Issue the controller's SMBus quick command and wait for completion so
NACKs are reported to callers.

Signed-off-by: Robert Marko <[email protected]>
---
 drivers/i2c/at91_i2c.c | 9 ++++++---
 drivers/i2c/at91_i2c.h | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c
index cfae36c74d1..7a9e9c4d4e9 100644
--- a/drivers/i2c/at91_i2c.c
+++ b/drivers/i2c/at91_i2c.c
@@ -50,9 +50,12 @@ static int at91_i2c_xfer_msg(struct at91_i2c_bus *bus, 
struct i2c_msg *msg)
        u32 i;
        int ret = 0;
 
-       /* if there is no message to send/receive, just exit quietly */
-       if (msg->len == 0)
-               return ret;
+       /* An address-only transfer must still check for an ACK. */
+       if (msg->len == 0) {
+               readl(&reg->sr);
+               writel(TWI_CR_QUICK, &reg->cr);
+               return at91_wait_for_xfer(bus, TWI_SR_TXCOMP);
+       }
 
        readl(&reg->sr);
        if (is_read) {
diff --git a/drivers/i2c/at91_i2c.h b/drivers/i2c/at91_i2c.h
index 3915af83723..4b467c441aa 100644
--- a/drivers/i2c/at91_i2c.h
+++ b/drivers/i2c/at91_i2c.h
@@ -6,6 +6,7 @@
 #define        TWI_CR_MSEN             BIT(2)  /* Master Transfer Enable */
 #define        TWI_CR_STOP             BIT(1)  /* Send a Stop Condition */
 #define        TWI_CR_SVDIS            BIT(5)  /* Slave Transfer Disable */
+#define        TWI_CR_QUICK            BIT(6)  /* SMBus quick command */
 #define        TWI_CR_SWRST            BIT(7)  /* Software Reset */
 #define        TWI_CR_ACMEN            BIT(16) /* Alternative Command Mode 
Enable */
 #define        TWI_CR_ACMDIS           BIT(17) /* Alternative Command Mode 
Disable */
-- 
2.56.0

Reply via email to