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:
parent
7c1884ae9b
commit
1193049c0a
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue