summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2022-08-11 13:43:03 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2022-08-11 13:43:03 +0200
commitad4fa274907bbc78ebabb015b4351d5f9226f081 (patch)
tree3eb033a3d6bedb50459ea0181e5180e1531d00e8 /drivers/i2c
parent3fcf4400a7b051bdbe9fc175b88336519099ff22 (diff)
parent3a0f44a7839d475c58720c4091d5e008215cd166 (diff)
downloadbarebox-ad4fa274907bbc78ebabb015b4351d5f9226f081.tar.gz
barebox-ad4fa274907bbc78ebabb015b4351d5f9226f081.tar.xz
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-bcm283x.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-bcm283x.c b/drivers/i2c/busses/i2c-bcm283x.c
index 097f73d983..fdba3b91bd 100644
--- a/drivers/i2c/busses/i2c-bcm283x.c
+++ b/drivers/i2c/busses/i2c-bcm283x.c
@@ -147,7 +147,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: 10bit read initilization\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -178,7 +178,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for data in FIFO\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -197,7 +197,7 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for space in FIFO\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
@@ -216,16 +216,23 @@ static int bcm283x_i2c_msg_xfer(struct bcm283x_i2c *bcm_i2c,
if (ret) {
dev_err(dev, "timeout: waiting for transfer to end\n");
- return ret;
+ goto out;
}
if (reg_s & BSC_S_ERR)
goto nack;
- writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
- writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c);
- return 0;
+ goto out;
nack:
dev_dbg(dev, "device with addr %x didn't ACK\n", msg->addr);
- return -EREMOTEIO;
+ writel(BSC_S_ERR, &bcm_i2c->regs->s);
+ timeout = calc_byte_timeout_us(bcm_i2c->bitrate);
+ // Wait for end of transfer so BSC has time to send STOP condition
+ readl_poll_timeout(&bcm_i2c->regs->s, reg_s, ~reg_s & BSC_S_TA, timeout);
+ ret = -EREMOTEIO;
+out:
+ // Return to default state for next xfer
+ writel(BSC_S_DONE | BSC_S_ERR | BSC_S_CLKT, &bcm_i2c->regs->s);
+ writel(BSC_C_CLEAR1 | BSC_C_I2CEN, &bcm_i2c->regs->c);
+ return ret;
}
static int bcm283x_i2c_xfer(struct i2c_adapter *adapter,