summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/lm4/i2c.c15
-rw-r--r--common/host_command_master.c6
-rw-r--r--include/i2c.h8
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);