aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c41
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)