Skip to content

Commit

Permalink
drivers: i3c: mcux: tighten the FIFO read
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
mjchen0 authored and carlescufi committed Oct 27, 2023
1 parent 7c1884a commit 1193049
Showing 1 changed file with 8 additions and 19 deletions.
27 changes: 8 additions & 19 deletions drivers/i3c/i3c_mcux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down

0 comments on commit 1193049

Please sign in to comment.