i2c: Add configurable I2C transfer timeout
This patch introduces CONFIG_I2C_TRANSFER_TIMEOUT_US, which controls how long to wait for an I2C devices to produce/accept all the data bytes in a single transfer. (The device can delay transfer by stretching the clock of the ack bit.) The default value of this new setting is 500ms. Existing code had timeouts anywhere from tens of milliseconds to a full second beween various drivers. Drivers can still have their own shorter timeouts for setup/communication with the I2C host controller (as opposed to transactions with I2C devices on the bus.) In general, the timeout is not meant to be reached except in situations where there is already serious problem with the boot, and serves to make sure that some useful diagnostic output is produced on the console. Change-Id: I6423122f32aad1dbcee0bfe240cdaa8cb512791f Signed-off-by: Jes B. Klinke <jbk@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/62278 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
committed by
Julius Werner
parent
ca82e6161a
commit
19baa9d51e
@@ -13,6 +13,8 @@
|
||||
|
||||
/* Use a ~10ms timeout for various operations */
|
||||
#define DW_I2C_TIMEOUT_US 10000
|
||||
/* Timeout for waiting for FIFO to flush */
|
||||
#define DW_I2C_FLUSH_TIMEOUT_US 160000
|
||||
|
||||
/* High and low times in different speed modes (in ns) */
|
||||
enum {
|
||||
@@ -290,7 +292,7 @@ static enum cb_err dw_i2c_wait_for_bus_idle(struct dw_i2c_regs *regs)
|
||||
struct stopwatch sw;
|
||||
|
||||
/* Start timeout for up to 16 bytes in FIFO */
|
||||
stopwatch_init_usecs_expire(&sw, 16 * DW_I2C_TIMEOUT_US);
|
||||
stopwatch_init_usecs_expire(&sw, DW_I2C_FLUSH_TIMEOUT_US);
|
||||
|
||||
while (!stopwatch_expired(&sw)) {
|
||||
uint32_t status = read32(®s->status);
|
||||
@@ -316,7 +318,7 @@ static enum cb_err dw_i2c_transfer_byte(struct dw_i2c_regs *regs,
|
||||
struct stopwatch sw;
|
||||
uint32_t cmd = CMD_DATA_CMD; /* Read op */
|
||||
|
||||
stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US);
|
||||
stopwatch_init_usecs_expire(&sw, CONFIG_I2C_TRANSFER_TIMEOUT_US);
|
||||
|
||||
if (!(segment->flags & I2C_M_RD)) {
|
||||
/* Write op only: Wait for FIFO not full */
|
||||
@@ -409,7 +411,7 @@ static enum cb_err _dw_i2c_transfer(unsigned int bus, const struct i2c_msg *segm
|
||||
}
|
||||
|
||||
/* Wait for interrupt status to indicate transfer is complete */
|
||||
stopwatch_init_usecs_expire(&sw, DW_I2C_TIMEOUT_US);
|
||||
stopwatch_init_usecs_expire(&sw, CONFIG_I2C_TRANSFER_TIMEOUT_US);
|
||||
while (!(read32(®s->raw_intr_stat) & INTR_STAT_STOP_DET)) {
|
||||
if (stopwatch_expired(&sw)) {
|
||||
printk(BIOS_ERR, "I2C stop bit not received\n");
|
||||
@@ -436,7 +438,7 @@ static enum cb_err _dw_i2c_transfer(unsigned int bus, const struct i2c_msg *segm
|
||||
}
|
||||
|
||||
/* Flush the RX FIFO in case it is not empty */
|
||||
stopwatch_init_usecs_expire(&sw, 16 * DW_I2C_TIMEOUT_US);
|
||||
stopwatch_init_usecs_expire(&sw, DW_I2C_FLUSH_TIMEOUT_US);
|
||||
while (read32(®s->status) & STATUS_RX_FIFO_NOT_EMPTY) {
|
||||
if (stopwatch_expired(&sw)) {
|
||||
printk(BIOS_ERR, "I2C timeout flushing RX FIFO\n");
|
||||
|
Reference in New Issue
Block a user