Kangheui Won has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/47360 )
Change subject: drivers/i2c/dw: Check for TX_ABORT in transfer ......................................................................
drivers/i2c/dw: Check for TX_ABORT in transfer
When the host sends data in i2c bus, device might not send ACK. It means that data is not processed on the device side, but for now we don't check for that condition thus wait for the response which will not come.
Designware i2c detect such situation and set TX_ABORT bit. Checking for the bit will enable other layers to immediately retry rather than wait-timeout-retry cycle.
BUG=b:168838505 BRANCH=zork TEST=test on zork devices, now we see "Tx abort detected" instead of I2C timeout for tpm initializtion.
Change-Id: Ib0163fbce55ccc99f677dbb096f67a58d2ef2bda --- M src/drivers/i2c/designware/dw_i2c.c 1 file changed, 10 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/60/47360/1
diff --git a/src/drivers/i2c/designware/dw_i2c.c b/src/drivers/i2c/designware/dw_i2c.c index 3181e7a..5601bcf 100644 --- a/src/drivers/i2c/designware/dw_i2c.c +++ b/src/drivers/i2c/designware/dw_i2c.c @@ -419,6 +419,14 @@ /* Read to clear INTR_STAT_STOP_DET */ read32(®s->clear_stop_det_intr);
+ /* Check TX abort */ + if (read32(®s->raw_intr_stat) & INTR_STAT_TX_ABORT) { + printk(BIOS_ERR, "I2C TX abort detected\n"); + /* clear INTR_STAT_TX_ABORT */ + read32(®s->clear_tx_abrt_intr); + goto out; + } + /* Wait for the bus to go idle */ if (dw_i2c_wait_for_bus_idle(regs)) { printk(BIOS_ERR, "I2C timeout waiting for bus %u idle\n", bus); @@ -747,8 +755,8 @@ write32(®s->rx_thresh, 0); write32(®s->tx_thresh, 0);
- /* Enable stop detection interrupt */ - write32(®s->intr_mask, INTR_STAT_STOP_DET); + /* Enable stop detection and TX abort interrupt */ + write32(®s->intr_mask, INTR_STAT_STOP_DET | INTR_STAT_TX_ABORT);
printk(BIOS_INFO, "DW I2C bus %u at %p (%u KHz)\n", bus, regs, speed / KHz);