diff options
-rw-r--r-- | drivers/i2c/busses/i2c-xlp9xx.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 1f41a4f89c08..8a873975cf12 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c | |||
@@ -191,28 +191,43 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) | |||
191 | if (priv->len_recv) { | 191 | if (priv->len_recv) { |
192 | /* read length byte */ | 192 | /* read length byte */ |
193 | rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); | 193 | rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); |
194 | |||
195 | /* | ||
196 | * We expect at least 2 interrupts for I2C_M_RECV_LEN | ||
197 | * transactions. The length is updated during the first | ||
198 | * interrupt, and the buffer contents are only copied | ||
199 | * during subsequent interrupts. If in case the interrupts | ||
200 | * get merged we would complete the transaction without | ||
201 | * copying out the bytes from RX fifo. To avoid this now we | ||
202 | * drain the fifo as and when data is available. | ||
203 | * We drained the rlen byte already, decrement total length | ||
204 | * by one. | ||
205 | */ | ||
206 | |||
207 | len--; | ||
194 | if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) { | 208 | if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) { |
195 | rlen = 0; /*abort transfer */ | 209 | rlen = 0; /*abort transfer */ |
196 | priv->msg_buf_remaining = 0; | 210 | priv->msg_buf_remaining = 0; |
197 | priv->msg_len = 0; | 211 | priv->msg_len = 0; |
198 | } else { | 212 | xlp9xx_i2c_update_rlen(priv); |
199 | *buf++ = rlen; | 213 | return; |
200 | if (priv->client_pec) | ||
201 | ++rlen; /* account for error check byte */ | ||
202 | /* update remaining bytes and message length */ | ||
203 | priv->msg_buf_remaining = rlen; | ||
204 | priv->msg_len = rlen + 1; | ||
205 | } | 214 | } |
215 | |||
216 | *buf++ = rlen; | ||
217 | if (priv->client_pec) | ||
218 | ++rlen; /* account for error check byte */ | ||
219 | /* update remaining bytes and message length */ | ||
220 | priv->msg_buf_remaining = rlen; | ||
221 | priv->msg_len = rlen + 1; | ||
206 | xlp9xx_i2c_update_rlen(priv); | 222 | xlp9xx_i2c_update_rlen(priv); |
207 | priv->len_recv = false; | 223 | priv->len_recv = false; |
208 | } else { | ||
209 | len = min(priv->msg_buf_remaining, len); | ||
210 | for (i = 0; i < len; i++, buf++) | ||
211 | *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); | ||
212 | |||
213 | priv->msg_buf_remaining -= len; | ||
214 | } | 224 | } |
215 | 225 | ||
226 | len = min(priv->msg_buf_remaining, len); | ||
227 | for (i = 0; i < len; i++, buf++) | ||
228 | *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); | ||
229 | |||
230 | priv->msg_buf_remaining -= len; | ||
216 | priv->msg_buf = buf; | 231 | priv->msg_buf = buf; |
217 | 232 | ||
218 | if (priv->msg_buf_remaining) | 233 | if (priv->msg_buf_remaining) |