diff options
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 21fbb340ad66..c41ca6354fc5 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -383,7 +383,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) | |||
383 | /* Enable the adapter */ | 383 | /* Enable the adapter */ |
384 | __i2c_dw_enable(dev, true); | 384 | __i2c_dw_enable(dev, true); |
385 | 385 | ||
386 | /* Enable interrupts */ | 386 | /* Clear and enable interrupts */ |
387 | i2c_dw_clear_int(dev); | ||
387 | dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); | 388 | dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); |
388 | } | 389 | } |
389 | 390 | ||
@@ -448,8 +449,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) | |||
448 | cmd |= BIT(9); | 449 | cmd |= BIT(9); |
449 | 450 | ||
450 | if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { | 451 | if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { |
452 | |||
453 | /* avoid rx buffer overrun */ | ||
454 | if (rx_limit - dev->rx_outstanding <= 0) | ||
455 | break; | ||
456 | |||
451 | dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD); | 457 | dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD); |
452 | rx_limit--; | 458 | rx_limit--; |
459 | dev->rx_outstanding++; | ||
453 | } else | 460 | } else |
454 | dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD); | 461 | dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD); |
455 | tx_limit--; buf_len--; | 462 | tx_limit--; buf_len--; |
@@ -502,8 +509,10 @@ i2c_dw_read(struct dw_i2c_dev *dev) | |||
502 | 509 | ||
503 | rx_valid = dw_readl(dev, DW_IC_RXFLR); | 510 | rx_valid = dw_readl(dev, DW_IC_RXFLR); |
504 | 511 | ||
505 | for (; len > 0 && rx_valid > 0; len--, rx_valid--) | 512 | for (; len > 0 && rx_valid > 0; len--, rx_valid--) { |
506 | *buf++ = dw_readl(dev, DW_IC_DATA_CMD); | 513 | *buf++ = dw_readl(dev, DW_IC_DATA_CMD); |
514 | dev->rx_outstanding--; | ||
515 | } | ||
507 | 516 | ||
508 | if (len > 0) { | 517 | if (len > 0) { |
509 | dev->status |= STATUS_READ_IN_PROGRESS; | 518 | dev->status |= STATUS_READ_IN_PROGRESS; |
@@ -561,6 +570,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
561 | dev->msg_err = 0; | 570 | dev->msg_err = 0; |
562 | dev->status = STATUS_IDLE; | 571 | dev->status = STATUS_IDLE; |
563 | dev->abort_source = 0; | 572 | dev->abort_source = 0; |
573 | dev->rx_outstanding = 0; | ||
564 | 574 | ||
565 | ret = i2c_dw_wait_bus_not_busy(dev); | 575 | ret = i2c_dw_wait_bus_not_busy(dev); |
566 | if (ret < 0) | 576 | if (ret < 0) |