drivers: i3c: mcux: tighten the FIFO read

At high i3c rates, the mcux_i3c_do_one_xfer_read()
could get into an infinite loop where the rx_count
kept returning 0 but the complete status bit
was never set. I believe the problem was that
the function was not emptying the FIFO fast enough,
so tighten the loop that processes the FIFO.

Signed-off-by: Mike J. Chen <mjchen@google.com>
This commit is contained in:
Mike J. Chen 2023-10-16 17:19:36 -07:00 committed by Carles Cufí
parent 7c1884ae9b
commit 1193049c0a

View file

@ -879,9 +879,7 @@ static int mcux_i3c_recover_bus(const struct device *dev)
*/
static int mcux_i3c_do_one_xfer_read(I3C_Type *base, uint8_t *buf, uint8_t buf_sz)
{
int rx_count;
bool completed = false;
bool overflow = false;
int ret = 0;
int offset = 0;
@ -908,28 +906,19 @@ static int mcux_i3c_do_one_xfer_read(I3C_Type *base, uint8_t *buf, uint8_t buf_s
}
/*
* Transfer data from FIFO into buffer.
* Transfer data from FIFO into buffer. Read
* in a tight loop to reduce chance of losing
* FIFO data when the i3c speed is high.
*/
rx_count = mcux_i3c_fifo_rx_count_get(base);
while (rx_count > 0) {
uint8_t data = (uint8_t)base->MRDATAB;
if (offset < buf_sz) {
buf[offset] = data;
offset += 1;
} else {
overflow = true;
while (offset < buf_sz) {
if (mcux_i3c_fifo_rx_count_get(base) == 0) {
break;
}
rx_count -= 1;
buf[offset++] = (uint8_t)base->MRDATAB;
}
}
if (overflow) {
ret = -EINVAL;
} else {
ret = offset;
}
ret = offset;
one_xfer_read_out:
return ret;