diff options
author | Andrey Konovalov <andrey.konovalov@linaro.org> | 2013-05-25 14:25:05 +0400 |
---|---|---|
committer | Andrey Konovalov <andrey.konovalov@linaro.org> | 2013-05-25 14:25:05 +0400 |
commit | 373e42a25dcc53782c1b1eca086dadf8b5adb546 (patch) | |
tree | 8b9e56b9426a35486a5a5d6169edf0442b67b733 /drivers/i2c/busses/i2c-designware-core.c | |
parent | 30eb987e02b3481e8b9c41d564eed49928f91478 (diff) | |
parent | 0bfd8ffeff9dda08c69381d65c72e0aa58706ef6 (diff) |
Merge branch 'tracking-linux-3.x.y' into merge-linux-linaro-lsk
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-core.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 94fd8187540..2db362854d7 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -361,7 +361,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); - /* Enable interrupts */ + /* Clear and enable interrupts */ + i2c_dw_clear_int(dev); dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); } @@ -426,8 +427,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) cmd |= BIT(9); if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { + + /* avoid rx buffer overrun */ + if (rx_limit - dev->rx_outstanding <= 0) + break; + dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD); rx_limit--; + dev->rx_outstanding++; } else dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD); tx_limit--; buf_len--; @@ -480,8 +487,10 @@ i2c_dw_read(struct dw_i2c_dev *dev) rx_valid = dw_readl(dev, DW_IC_RXFLR); - for (; len > 0 && rx_valid > 0; len--, rx_valid--) + for (; len > 0 && rx_valid > 0; len--, rx_valid--) { *buf++ = dw_readl(dev, DW_IC_DATA_CMD); + dev->rx_outstanding--; + } if (len > 0) { dev->status |= STATUS_READ_IN_PROGRESS; @@ -539,6 +548,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) dev->msg_err = 0; dev->status = STATUS_IDLE; dev->abort_source = 0; + dev->rx_outstanding = 0; ret = i2c_dw_wait_bus_not_busy(dev); if (ret < 0) |