mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 06:31:31 +00:00
i2c: mxs_i2c: Squash endless loop
The endless waiting for a bit to be set can cause a hang, add a timeout so we prevent such situation. A testcase for such a hang is below. The testcase assumes a device to be present at address 0x50 and a device to NOT be present at address 0x42 . Also note that the "sleep 1" induced delays are imperative for this bug to manifest . i2c read 0x42 0x0.2 0x10 0x42000000 ; sleep 1 ; \ i2c read 0x50 0x0.2 0x10 0x42000000 ; sleep 1 ; \ i2c read 0x42 0x0.2 0x10 0x42000000 The expected result of the above command is: Error reading the chip. Error reading the chip. While without this patch, we observe a hang in the last read from 0x42 precisely when waiting for this bit to be set. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Fabio Estevam <fabio.estevam@freescale.com> Cc: Heiko Schocher <hs@denx.de> Cc: Stefano Babic <sbabic@denx.de>
This commit is contained in:
parent
2035d77d79
commit
124913556c
1 changed files with 12 additions and 3 deletions
|
@ -150,6 +150,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||||
{
|
{
|
||||||
struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
|
struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE;
|
||||||
uint32_t tmp = 0;
|
uint32_t tmp = 0;
|
||||||
|
int timeout = MXS_I2C_MAX_TIMEOUT;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -169,9 +170,17 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (!(i & 3)) {
|
if (!(i & 3)) {
|
||||||
while (readl(&i2c_regs->hw_i2c_queuestat) &
|
while (--timeout) {
|
||||||
I2C_QUEUESTAT_RD_QUEUE_EMPTY)
|
tmp = readl(&i2c_regs->hw_i2c_queuestat);
|
||||||
;
|
if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
debug("MXS I2C: Failed receiving data!\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
tmp = readl(&i2c_regs->hw_i2c_queuedata);
|
tmp = readl(&i2c_regs->hw_i2c_queuedata);
|
||||||
}
|
}
|
||||||
buffer[i] = tmp & 0xff;
|
buffer[i] = tmp & 0xff;
|
||||||
|
|
Loading…
Add table
Reference in a new issue