summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-05-08 16:46:03 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-05-27 02:39:48 +0000
commit111c893524f226435b4c851db8e05d5f16ab4c0e (patch)
tree9442e194d623387113c544694ba9a6bf6b5a2023
parent5b5f737d8f6f1be15d4ab5f42f290d20576307c4 (diff)
downloadchrome-ec-111c893524f226435b4c851db8e05d5f16ab4c0e.tar.gz
pd: stm32f0: modify i2c driver to support TCPCI
Modify the stm32f0 i2c driver to support the new TCPC interface. BUG=none BRANCH=none TEST=test on oak Change-Id: Ibcb205e67d59d99a97dce090bd84bbb714ad5032 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/270173 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/i2c-stm32f0.c51
-rw-r--r--chip/stm32/registers.h1
-rw-r--r--include/usb_pd_tcpc.h12
3 files changed, 63 insertions, 1 deletions
diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c
index 4e599efa9a..b1b530e600 100644
--- a/chip/stm32/i2c-stm32f0.c
+++ b/chip/stm32/i2c-stm32f0.c
@@ -14,6 +14,8 @@
#include "registers.h"
#include "task.h"
#include "timer.h"
+#include "usb_pd_tcpc.h"
+#include "usb_pd_tcpm.h"
#include "util.h"
/* Console output macros */
@@ -203,10 +205,31 @@ static void i2c_process_command(void)
host_packet_receive(&i2c_packet);
}
+#ifdef TCPCI_I2C_SLAVE
+static void i2c_send_tcpc_response(int len)
+{
+ /* host_buffer data range, beyond this length, will return 0xec */
+ tx_index = 0;
+ tx_end = len;
+
+ /* enable transmit interrupt and use irq to send data back */
+ STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE;
+}
+
+static void i2c_process_tcpc_command(int read, int addr, int len)
+{
+ tcpc_i2c_process(read, TCPC_ADDR_TO_PORT(addr), len, &host_buffer[0],
+ i2c_send_tcpc_response);
+}
+#endif
+
static void i2c_event_handler(int port)
{
int i2c_isr;
static int rx_pending, buf_idx;
+#ifdef TCPCI_I2C_SLAVE
+ int addr;
+#endif
i2c_isr = STM32_I2C_ISR(port);
@@ -248,6 +271,16 @@ static void i2c_event_handler(int port)
/* Stop condition on bus */
if (i2c_isr & STM32_I2C_ISR_STOP) {
+#ifdef TCPCI_I2C_SLAVE
+ /*
+ * if tcpc is being addressed, and we received a stop
+ * while rx is pending, then this is a write only to
+ * the tcpc.
+ */
+ addr = STM32_I2C_ISR_ADDCODE(STM32_I2C_ISR(port));
+ if (rx_pending && ADDR_IS_TCPC(addr))
+ i2c_process_tcpc_command(0, addr, buf_idx);
+#endif
rx_pending = 0;
tx_pending = 0;
@@ -299,7 +332,16 @@ static void i2c_event_handler(int port)
*/
STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE;
- i2c_process_command();
+#ifdef TCPCI_I2C_SLAVE
+ addr = STM32_I2C_ISR_ADDCODE(
+ STM32_I2C_ISR(port));
+ if (ADDR_IS_TCPC(addr))
+ i2c_process_tcpc_command(1, addr,
+ buf_idx);
+ else
+#endif
+ i2c_process_command();
+
/* Reset host buffer after end of transfer */
rx_pending = 0;
tx_pending = 1;
@@ -489,6 +531,13 @@ static void i2c_init(void)
STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN;
#endif
STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_HOSTCMD_I2C_SLAVE_ADDR;
+#ifdef TCPCI_I2C_SLAVE
+ /*
+ * Configure TCPC address with OA2[1] masked so that we respond
+ * to CONFIG_TCPC_I2C_BASE_ADDR and CONFIG_TCPC_I2C_BASE_ADDR + 2.
+ */
+ STM32_I2C_OAR2(I2C_PORT_EC) = 0x8100 | CONFIG_TCPC_I2C_BASE_ADDR;
+#endif
task_enable_irq(IRQ_SLAVE);
#endif
}
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index f9ff3d1c69..749da6ed78 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -483,6 +483,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_I2C_ISR_ALERT (1 << 13)
#define STM32_I2C_ISR_BUSY (1 << 15)
#define STM32_I2C_ISR_DIR (1 << 16)
+#define STM32_I2C_ISR_ADDCODE(isr) (((isr) >> 16) & 0xfe)
#define STM32_I2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C))
#define STM32_I2C_ICR_ADDRCF (1 << 3)
#define STM32_I2C_ICR_NACKCF (1 << 4)
diff --git a/include/usb_pd_tcpc.h b/include/usb_pd_tcpc.h
index b954c6f7ae..0ddeab23d2 100644
--- a/include/usb_pd_tcpc.h
+++ b/include/usb_pd_tcpc.h
@@ -12,6 +12,18 @@
#define CONFIG_TCPC_I2C_BASE_ADDR 0x9c
#endif
+/* If we are a TCPC but do not a TCPM, then we implement the slave TCPCI */
+#if defined(CONFIG_USB_PD_TCPC) && !defined(CONFIG_USB_PD_TCPM_STUB)
+#define TCPCI_I2C_SLAVE
+#endif
+
+#ifdef TCPCI_I2C_SLAVE
+/* Convert TCPC address to type-C port number */
+#define TCPC_ADDR_TO_PORT(addr) (((addr) - CONFIG_TCPC_I2C_BASE_ADDR) >> 1)
+/* Check if the i2c address belongs to TCPC */
+#define ADDR_IS_TCPC(addr) (((addr) & 0xfc) == CONFIG_TCPC_I2C_BASE_ADDR)
+#endif
+
/**
* Process incoming TCPCI I2C command
*