aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorGeorge Cherian <george.cherian@cavium.com>2018-02-27 13:26:19 +0000
committerWolfram Sang <wsa@the-dreams.de>2018-03-17 21:57:44 +0100
commite349d7d08e7044caf37a36409305edbd5af013c7 (patch)
tree6f9452cfc36d0baac54a3233275194d6dfb2d4e1 /drivers/i2c
parenti2c: xlp9xx: Check for Bus state before every transfer (diff)
downloadlinux-dev-e349d7d08e7044caf37a36409305edbd5af013c7.tar.xz
linux-dev-e349d7d08e7044caf37a36409305edbd5af013c7.zip
i2c: xlp9xx: Handle NACK on DATA properly
In case we receive NACK on DATA we shouldn't be resetting the controller, rather we should issue STOP command. This will terminate the current transaction and -EIO is returned. While at that handle the SMBus Quick Command properly. We shouldn't be setting the XLP9XX_I2C_CMD_READ/WRITE for such transactions. Signed-off-by: George Cherian <george.cherian@cavium.com> Reviewed-by: Jan Glauber <jglauber@cavium.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 42dd1fa0b644..eb8913eba0c5 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -352,7 +352,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
/* set cmd reg */
cmd = XLP9XX_I2C_CMD_START;
- cmd |= (priv->msg_read ? XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE);
+ if (msg->len)
+ cmd |= (priv->msg_read ?
+ XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE);
if (last_msg)
cmd |= XLP9XX_I2C_CMD_STOP;
@@ -361,12 +363,12 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS);
timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft);
- if (priv->msg_err) {
+ if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) {
dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err);
- if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR)
- xlp9xx_i2c_init(priv);
- return (priv->msg_err & XLP9XX_I2C_INTEN_NACKADDR) ?
- -ENXIO : -EIO;
+ xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, XLP9XX_I2C_CMD_STOP);
+ return -EIO;
+ } else if (priv->msg_err & XLP9XX_I2C_INTEN_NACKADDR) {
+ return -ENXIO;
}
if (timeleft == 0) {