From 8ddaa98673b5fd0d0c5da390a866e918d7dfc3a1 Mon Sep 17 00:00:00 2001 From: David Wu Date: Fri, 3 Jul 2020 11:45:40 +0800 Subject: [PATCH] i2c: rk3x: Add nack auto stop feature Signed-off-by: David Wu Change-Id: I8025e70dcc76ba433bb990db32c24e3d4bd9cd61 --- drivers/i2c/busses/i2c-rk3x.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index d3a1171b06c4..58e7d0ef1e51 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -92,6 +92,7 @@ enum { #define REG_CON1_AUTO_STOP BIT(0) #define REG_CON1_TRANSFER_AUTO_STOP BIT(1) +#define REG_CON1_NACK_AUTO_STOP BIT(2) /* Constants */ #define WAIT_TIMEOUT 1000 /* ms */ @@ -290,6 +291,9 @@ static bool rk3x_i2c_auto_stop(struct rk3x_i2c *i2c) if (!i2c->autostop_supported) return false; + if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) + con1 = REG_CON1_NACK_AUTO_STOP | REG_CON1_AUTO_STOP; + if (!i2c->is_last_msg) goto out; @@ -302,11 +306,15 @@ static bool rk3x_i2c_auto_stop(struct rk3x_i2c *i2c) con1 |= REG_CON1_TRANSFER_AUTO_STOP | REG_CON1_AUTO_STOP; i2c_writel(i2c, con1, REG_CON1); - i2c_writel(i2c, REG_INT_STOP | REG_INT_NAKRCV, REG_IEN); + if (con1 & REG_CON1_NACK_AUTO_STOP) + i2c_writel(i2c, REG_INT_STOP, REG_IEN); + else + i2c_writel(i2c, REG_INT_STOP | REG_INT_NAKRCV, REG_IEN); return true; out: + i2c_writel(i2c, con1, REG_CON1); return false; } @@ -595,8 +603,13 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id) ipd &= ~REG_INT_NAKRCV; if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - rk3x_i2c_stop(i2c, -ENXIO); - goto out; + if (i2c->autostop_supported) { + i2c->error = -ENXIO; + i2c->state = STATE_STOP; + } else { + rk3x_i2c_stop(i2c, -ENXIO); + goto out; + } } }