diff options
author | Dylan Lai <dylai@analogixsemi.com> | 2018-03-09 13:54:08 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-04-03 21:40:51 -0700 |
commit | 82a357a385f9eee75bfbca9911e404d54b0c3217 (patch) | |
tree | 7509a8b541a6541b1d56fce2a5d9008a9c4323c9 /board/pdeval-stm32f072 | |
parent | a9c7d6b0d73eaf0c48438124b40fc054183701aa (diff) | |
download | chrome-ec-82a357a385f9eee75bfbca9911e404d54b0c3217.tar.gz |
TCPM: Add TCPM driver for Analogix anx7447 chip
Driver implements TCPC for ANX7447 chip. Enable Type C
port for USB and DP alt mode.
BUG=b:73793947
BRANCH=NONE
TEST=tested compiled binary for pdeval-stm32f072 board with this patch.
Power contract establishment, port role swap, DP alt mode works fine.
Change-Id: Ic11e499fc5fb4aba7732c75e4cb2fee54828c616
Reviewed-on: https://chromium-review.googlesource.com/956790
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Scott Collyer <scollyer@chromium.org>
Diffstat (limited to 'board/pdeval-stm32f072')
-rw-r--r-- | board/pdeval-stm32f072/board.c | 11 | ||||
-rw-r--r-- | board/pdeval-stm32f072/board.h | 22 | ||||
-rw-r--r-- | board/pdeval-stm32f072/ec.tasklist | 3 | ||||
-rw-r--r-- | board/pdeval-stm32f072/gpio.inc | 3 | ||||
-rw-r--r-- | board/pdeval-stm32f072/usb_pd_policy.c | 128 |
5 files changed, 144 insertions, 23 deletions
diff --git a/board/pdeval-stm32f072/board.c b/board/pdeval-stm32f072/board.c index f5aa26d10b..a306d853ac 100644 --- a/board/pdeval-stm32f072/board.c +++ b/board/pdeval-stm32f072/board.c @@ -4,6 +4,7 @@ */ /* STM32F072-discovery board based USB PD evaluation configuration */ +#include "anx7447.h" #include "common.h" #include "ec_version.h" #include "gpio.h" @@ -52,15 +53,12 @@ void board_reset_pd_mcu(void) /* I2C ports */ const struct i2c_port_t i2c_ports[] = { - {"tcpc", I2C_PORT_TCPC, 100 /* kHz */, GPIO_I2C0_SCL, GPIO_I2C0_SDA} + {"tcpc", I2C_PORT_TCPC, 400 /* kHz */, GPIO_I2C0_SCL, GPIO_I2C0_SDA} }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = { - {I2C_PORT_TCPC, TCPC1_I2C_ADDR, &tcpci_tcpm_drv}, -#if CONFIG_USB_PD_PORT_COUNT >= 2 - {I2C_PORT_TCPC, TCPC2_I2C_ADDR, &tcpci_tcpm_drv}, -#endif + {I2C_PORT_TCPC, AN7447_TCPC3_I2C_ADDR, &anx7447_tcpm_drv} }; uint16_t tcpc_get_alert_status(void) @@ -69,9 +67,6 @@ uint16_t tcpc_get_alert_status(void) if (!gpio_get_level(GPIO_PD_MCU_INT)) { status = PD_STATUS_TCPC_ALERT_0; -#if CONFIG_USB_PD_PORT_COUNT >= 2 - status |= PD_STATUS_TCPC_ALERT_1; -#endif } return status; diff --git a/board/pdeval-stm32f072/board.h b/board/pdeval-stm32f072/board.h index df32ec2683..9100ab1a94 100644 --- a/board/pdeval-stm32f072/board.h +++ b/board/pdeval-stm32f072/board.h @@ -26,12 +26,21 @@ #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_CUSTOM_VDM #define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_PORT_COUNT 2 +#define CONFIG_USB_PD_PORT_COUNT 1 #define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_VBUS_DETECT_TCPC +#define CONFIG_USB_PD_TCPM_ANX7447 +#define CONFIG_USB_PD_TCPM_MUX + +#undef CONFIG_USB_PD_INITIAL_DRP_STATE +#define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_TOGGLE_ON + +#undef CONFIG_USB_PD_PULLUP +#define CONFIG_USB_PD_PULLUP TYPEC_RP_USB /* fake board specific type-C power constants */ #define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 650000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 15000 @@ -43,12 +52,13 @@ #define I2C_PORT_TCPC 0 #define I2C_PORT_PD_MCU 0 -/* TCPC I2C slave addresses */ -#define TCPC1_I2C_ADDR 0x9c -#define TCPC2_I2C_ADDR 0x9e - /* Timer selection */ +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP +/* delay to turn on/off vconn */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + /* USB Configuration */ #define CONFIG_USB #define CONFIG_USB_PID 0x500f diff --git a/board/pdeval-stm32f072/ec.tasklist b/board/pdeval-stm32f072/ec.tasklist index fd87fc0237..f58f5e3a7c 100644 --- a/board/pdeval-stm32f072/ec.tasklist +++ b/board/pdeval-stm32f072/ec.tasklist @@ -20,5 +20,4 @@ TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(PDCMD, pd_command_task,NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE) + TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/pdeval-stm32f072/gpio.inc b/board/pdeval-stm32f072/gpio.inc index cd3c601a0a..f71d69441e 100644 --- a/board/pdeval-stm32f072/gpio.inc +++ b/board/pdeval-stm32f072/gpio.inc @@ -16,6 +16,9 @@ GPIO(LED_U, PIN(C, 6), GPIO_OUT_LOW) GPIO(LED_D, PIN(C, 7), GPIO_OUT_LOW) GPIO(LED_L, PIN(C, 8), GPIO_OUT_LOW) GPIO(LED_R, PIN(C, 9), GPIO_OUT_LOW) +GPIO(USB_C0_DVDDIO, PIN(C, 14), GPIO_OUT_HIGH) +GPIO(USB_C0_AVDD33, PIN(C, 15), GPIO_OUT_HIGH) +GPIO(VBUS_PMIC_CTRL, PIN(A, 4), GPIO_OUT_LOW) /* * I2C pins should be configured as inputs until I2C module is diff --git a/board/pdeval-stm32f072/usb_pd_policy.c b/board/pdeval-stm32f072/usb_pd_policy.c index 73add50ca4..9b81222d58 100644 --- a/board/pdeval-stm32f072/usb_pd_policy.c +++ b/board/pdeval-stm32f072/usb_pd_policy.c @@ -3,6 +3,7 @@ * found in the LICENSE file. */ +#include "anx7447.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -12,6 +13,7 @@ #include "task.h" #include "timer.h" #include "util.h" +#include "usb_mux.h" #include "usb_pd.h" #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) @@ -23,15 +25,25 @@ static int vbus_present; const uint32_t pd_src_pdo[] = { - PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), }; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_FIXED(5000, 900, PDO_FIXED_FLAGS), + PDO_BATT(5000, 21000, 30000), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +#if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447) +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0, + .driver = &anx7447_usb_mux_driver, + }, +}; +#endif + int pd_is_valid_input_voltage(int mv) { return 1; @@ -42,6 +54,34 @@ void pd_transition_voltage(int idx) /* No-operation: we are always 5V */ } +#ifdef CONFIG_USB_PD_TCPM_ANX7447 +int pd_set_power_supply_ready(int port) +{ + /* Disable charging */ + anx7447_board_charging_enable(port, 0); + + /* Provide VBUS */ + gpio_set_level(GPIO_VBUS_PMIC_CTRL, 1); + anx7447_set_power_supply_ready(port); + + /* notify host of power info change */ + + CPRINTS("Enable VBUS, port%d", port); + + return EC_SUCCESS; +} + +void pd_power_supply_reset(int port) +{ + /* Disable VBUS */ + anx7447_power_supply_reset(port); + gpio_set_level(GPIO_VBUS_PMIC_CTRL, 0); + CPRINTS("Disable VBUS, port%d", port); + + /* Enable charging */ + anx7447_board_charging_enable(port, 1); +} +#else int pd_set_power_supply_ready(int port) { /* Turn on the "up" LED when we output VBUS */ @@ -57,6 +97,7 @@ void pd_power_supply_reset(int port) /* Disable VBUS */ CPRINTS("Disable VBUS", port); } +#endif /* CONFIG_USB_PD_TCPM_ANX7447 */ void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) @@ -117,7 +158,7 @@ int pd_check_power_swap(int port) * otherwise assume our role is fixed (not in S0 or console command * to fix our role). */ - return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0; + return pd_get_dual_role() == PD_DRP_TOGGLE_ON; } int pd_check_data_swap(int port, int data_role) @@ -126,6 +167,18 @@ int pd_check_data_swap(int port, int data_role) return 1; } +#ifdef CONFIG_USBC_VCONN_SWAP +int pd_check_vconn_swap(int port) +{ + /* + * Allow vconn swap as long as we are acting as a dual role device, + * otherwise assume our role is fixed (not in S0 or console command + * to fix our role). + */ + return pd_get_dual_role() == PD_DRP_TOGGLE_ON; +} +#endif + void pd_execute_data_swap(int port, int data_role) { } @@ -138,8 +191,24 @@ void pd_check_dr_role(int port, int dr_role, int flags) { } /* ----------------- Vendor Defined Messages ------------------ */ +const uint32_t vdo_idh = VDO_IDH(1, /* data caps as USB host */ + 0, /* data caps as USB device */ + IDH_PTYPE_PERIPH, + 0, /* supports alt modes */ + 0x0000); + +const uint32_t vdo_product = VDO_PRODUCT(0x0000, 0x0000); + +static int svdm_response_identity(int port, uint32_t *payload) +{ + payload[VDO_I(IDH)] = vdo_idh; + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + return VDO_I(PRODUCT) + 1; +} + const struct svdm_response svdm_rsp = { - .identity = NULL, + .identity = &svdm_response_identity, .svids = NULL, .modes = NULL, }; @@ -186,6 +255,7 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, #ifdef CONFIG_USB_PD_ALT_MODE_DFP static int dp_flags[CONFIG_USB_PD_PORT_COUNT]; +static uint32_t dp_status[CONFIG_USB_PD_PORT_COUNT]; static void svdm_safe_dp_mode(int port) { @@ -224,24 +294,66 @@ static int svdm_dp_status(int port, uint32_t *payload) static int svdm_dp_config(int port, uint32_t *payload) { int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); + +#ifdef CONFIG_USB_PD_TCPM_ANX7447 + mux_state_t mux_state = TYPEC_MUX_NONE; + if (pd_get_polarity(port)) + mux_state |= MUX_POLARITY_INVERTED; +#endif + + CPRINTS("pin_mode = %d\n", pin_mode); + if (!pin_mode) + return 0; + +#if defined(CONFIG_USB_PD_TCPM_MUX) && defined(CONFIG_USB_PD_TCPM_ANX7447) + switch (pin_mode) { + case MODE_DP_PIN_A: + case MODE_DP_PIN_C: + case MODE_DP_PIN_E: + mux_state |= TYPEC_MUX_DP; + usb_muxes[port].driver->set(port, mux_state); + break; + case MODE_DP_PIN_B: + case MODE_DP_PIN_D: + case MODE_DP_PIN_F: + mux_state |= TYPEC_MUX_DOCK; + usb_muxes[port].driver->set(port, mux_state); + break; + } +#endif + /* board_set_usb_mux(port, TYPEC_MUX_DP, pd_get_polarity(port)); */ payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(MODE_DP_PIN_E, /* pin mode */ + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ 1, /* DPv1.3 signaling */ 2); /* UFP connected */ return 2; -}; +} static void svdm_dp_post_config(int port) { dp_flags[port] |= DP_FLAGS_DP_ON; if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING)) return; + +#ifdef CONFIG_USB_PD_TCPM_ANX7447 + anx7447_tcpc_update_hpd_status(port, 1, 0); +#endif } static int svdm_dp_attention(int port, uint32_t *payload) { +#ifdef CONFIG_USB_PD_TCPM_ANX7447 + int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); + int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); + + CPRINTS("Attention: 0x%x\n", payload[1]); + anx7447_tcpc_update_hpd_status(port, lvl, irq); +#endif + dp_status[port] = payload[1]; + /* ack */ return 1; } @@ -249,7 +361,9 @@ static int svdm_dp_attention(int port, uint32_t *payload) static void svdm_exit_dp_mode(int port) { svdm_safe_dp_mode(port); - /* gpio_set_level(PORT_TO_HPD(port), 0); */ +#ifdef CONFIG_USB_PD_TCPM_ANX7447 + anx7447_tcpc_clear_hpd_status(port); +#endif } static int svdm_enter_gfu_mode(int port, uint32_t mode_caps) |