diff options
author | Alec Berg <alecaberg@chromium.org> | 2015-05-08 16:46:03 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-05-27 02:39:48 +0000 |
commit | 111c893524f226435b4c851db8e05d5f16ab4c0e (patch) | |
tree | 9442e194d623387113c544694ba9a6bf6b5a2023 | |
parent | 5b5f737d8f6f1be15d4ab5f42f290d20576307c4 (diff) | |
download | chrome-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.c | 51 | ||||
-rw-r--r-- | chip/stm32/registers.h | 1 | ||||
-rw-r--r-- | include/usb_pd_tcpc.h | 12 |
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 * |