diff options
-rw-r--r-- | chip/lm4/i2c.c | 15 | ||||
-rw-r--r-- | common/host_command_master.c | 6 | ||||
-rw-r--r-- | include/i2c.h | 8 |
3 files changed, 26 insertions, 3 deletions
diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c index 1f1797f1c1..0833dfb074 100644 --- a/chip/lm4/i2c.c +++ b/chip/lm4/i2c.c @@ -47,8 +47,8 @@ */ #define I2C_IDLE_US 500 -/* Maximum time we allow for an I2C transfer */ -#define I2C_TIMEOUT_US (100*MSEC) +/* Default maximum time we allow for an I2C transfer */ +#define I2C_TIMEOUT_DEFAULT_US (100 * MSEC) /* IRQ for each port */ static const uint32_t i2c_irqs[] = {LM4_IRQ_I2C0, LM4_IRQ_I2C1, LM4_IRQ_I2C2, @@ -64,6 +64,7 @@ struct i2c_port_data { int flags; /* Flags (I2C_XFER_*) */ int idx; /* Index into input/output data */ int err; /* Error code, if any */ + uint32_t timeout_us; /* Transaction timeout, or 0 to use default */ /* Task waiting on port, or TASK_ID_INVALID if none. */ int task_waiting; @@ -223,7 +224,7 @@ int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_size, task_trigger_irq(i2c_irqs[port]); /* Wait for transfer complete or timeout */ - events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, I2C_TIMEOUT_US); + events = task_wait_event_mask(TASK_EVENT_I2C_IDLE, pd->timeout_us); /* Disable interrupts */ LM4_I2C_MIMR(port) = 0x00; @@ -326,6 +327,11 @@ exit: return rv; } +void i2c_set_timeout(int port, uint32_t timeout) +{ + pdata[port].timeout_us = timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; +} + /*****************************************************************************/ /* Hooks */ @@ -387,6 +393,9 @@ static void i2c_init(void) for (i = 0; i < I2C_PORT_COUNT; i++) { pdata[i].task_waiting = TASK_ID_INVALID; task_enable_irq(i2c_irqs[i]); + + /* Use default timeout */ + i2c_set_timeout(i, 0); } } DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_DEFAULT); diff --git a/common/host_command_master.c b/common/host_command_master.c index 55e3befbee..23441d0a3a 100644 --- a/common/host_command_master.c +++ b/common/host_command_master.c @@ -9,12 +9,16 @@ #include "console.h" #include "host_command.h" #include "i2c.h" +#include "timer.h" #include "util.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_HOSTCMD, outstr) #define CPRINTF(format, args...) cprintf(CC_HOSTCMD, format, ## args) +/* Host command timeout */ +#define HOST_COMMAND_TIMEOUT_US SECOND + /* * Sends a command to the PD (protocol v3). * @@ -71,9 +75,11 @@ int pd_host_command(int command, int version, * length. */ i2c_lock(I2C_PORT_PD_MCU, 1); + i2c_set_timeout(I2C_PORT_PD_MCU, HOST_COMMAND_TIMEOUT_US); ret = i2c_xfer(I2C_PORT_PD_MCU, CONFIG_USB_PD_I2C_SLAVE_ADDR, &req_buf[0], outsize + sizeof(rq) + 1, &resp_buf[0], 2, I2C_XFER_START); + i2c_set_timeout(I2C_PORT_PD_MCU, 0); i2c_lock(I2C_PORT_PD_MCU, 0); if (ret) { CPRINTF("[%T i2c transaction 1 failed: %d]\n", ret); diff --git a/include/i2c.h b/include/i2c.h index ac572960df..9cb884ba19 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -126,6 +126,14 @@ int i2c_raw_mode(int port, int enable); */ void i2c_lock(int port, int lock); +/** + * Set the timeout for an I2C transaction. + * + * @param port Port to set timeout for + * @param timeout Timeout in usec, or 0 to use default + */ +void i2c_set_timeout(int port, uint32_t timeout); + /* Read a 16-bit register from the slave at 8-bit slave address <slaveaddr>, at * the specified 8-bit <offset> in the slave's address space. */ int i2c_read16(int port, int slave_addr, int offset, int *data); |