diff options
32 files changed, 853 insertions, 644 deletions
diff --git a/board/honeybuns/board.c b/board/honeybuns/board.c index bdcedf5599..b16b9b6ed3 100644 --- a/board/honeybuns/board.c +++ b/board/honeybuns/board.c @@ -164,62 +164,6 @@ const void * const usb_strings[] = { }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - if (mux == TYPEC_MUX_NONE) { - /* put the mux in the high impedance state */ - gpio_set_level(GPIO_SS_MUX_OE_L, 1); - /* Disable display hardware */ - gpio_set_level(GPIO_BRIDGE_RESET_L, 0); - gpio_set_level(GPIO_SPLITTER_RESET_L, 0); - /* Put the USB hub under reset */ - hx3_enable(0); - return; - } - - /* Trigger USB Hub configuration */ - hx3_enable(1); - - if ((mux == TYPEC_MUX_DOCK) || (mux == TYPEC_MUX_USB)) { - /* Low selects USB Dock */ - gpio_set_level(GPIO_SS_MUX_SEL, 0); - } else if (mux == TYPEC_MUX_DP) { - /* high selects display port */ - gpio_set_level(GPIO_SS_MUX_SEL, 1); - } - - /* clear OE line to make mux active */ - gpio_set_level(GPIO_SS_MUX_OE_L, 0); - - if (mux != TYPEC_MUX_USB) { - /* Enable display hardware */ - gpio_set_level(GPIO_BRIDGE_RESET_L, 1); - gpio_set_level(GPIO_SPLITTER_RESET_L, 1); - } -} - -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - int oe_disabled = gpio_get_level(GPIO_SS_MUX_OE_L); - int dp_4lanes = gpio_get_level(GPIO_SS_MUX_SEL); - - if (oe_disabled) { - *usb_str = NULL; - *dp_str = NULL; - return 0; - } - - if (dp_4lanes) { - *dp_str = "DP_4LANE"; - *usb_str = NULL; - } else { - *dp_str = "DP_2LANE"; - *usb_str = "DOCK"; - } - return 1; -} - /** * USB configuration * Any type-C device with alternate mode capabilities must have the following @@ -279,4 +223,3 @@ const struct bos_context bos_ctx = { .descp = (void *)&bos_desc, .size = sizeof(struct my_bos), }; - diff --git a/board/honeybuns/build.mk b/board/honeybuns/build.mk index ff4b39a2ce..84b222d16a 100644 --- a/board/honeybuns/build.mk +++ b/board/honeybuns/build.mk @@ -11,4 +11,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o hx3.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_mux.o usb_pd_policy.o diff --git a/board/honeybuns/usb_mux.c b/board/honeybuns/usb_mux.c new file mode 100644 index 0000000000..ea8a56910f --- /dev/null +++ b/board/honeybuns/usb_mux.c @@ -0,0 +1,84 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Honeybuns-custom USB mux driver. */ + +#include "common.h" +#include "gpio.h" +#include "usb_mux.h" +#include "util.h" + +void board_set_usb_switches(int port, enum usb_switch setting) +{ + /* Not implemented */ +} + +static int board_init_usb_mux(int port) +{ + return EC_SUCCESS; +} + +static int board_set_usb_mux(int port, mux_state_t mux_state) +{ + if (!(mux_state & (MUX_USB_ENABLED | MUX_DP_ENABLED))) { + /* put the mux in the high impedance state */ + gpio_set_level(GPIO_SS_MUX_OE_L, 1); + /* Disable display hardware */ + gpio_set_level(GPIO_BRIDGE_RESET_L, 0); + gpio_set_level(GPIO_SPLITTER_RESET_L, 0); + /* Put the USB hub under reset */ + hx3_enable(0); + return EC_SUCCESS; + } + + /* Trigger USB Hub configuration */ + hx3_enable(1); + + if (mux_state & MUX_USB_ENABLED) + /* Low selects USB Dock */ + gpio_set_level(GPIO_SS_MUX_SEL, 0); + else + /* high selects display port */ + gpio_set_level(GPIO_SS_MUX_SEL, 1); + + /* clear OE line to make mux active */ + gpio_set_level(GPIO_SS_MUX_OE_L, 0); + + if (mux_state & MUX_DP_ENABLED) { + /* Enable display hardware */ + gpio_set_level(GPIO_BRIDGE_RESET_L, 1); + gpio_set_level(GPIO_SPLITTER_RESET_L, 1); + } + + return EC_SUCCESS; +} + +static int board_get_usb_mux(int port, mux_state_t *mux_state) +{ + int oe_disabled = gpio_get_level(GPIO_SS_MUX_OE_L); + int dp_4lanes = gpio_get_level(GPIO_SS_MUX_SEL); + + if (oe_disabled) + *mux_state = 0; + else if (dp_4lanes) + *mux_state = MUX_DP_ENABLED; + else + *mux_state = MUX_USB_ENABLED | MUX_DP_ENABLED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver board_custom_usb_mux_driver = { + .init = board_init_usb_mux, + .set = board_set_usb_mux, + .get = board_get_usb_mux, +}; + +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0, + .driver = &board_custom_usb_mux_driver, + }, +}; diff --git a/board/honeybuns/usb_pd_policy.c b/board/honeybuns/usb_pd_policy.c index 6f2f33505d..65c056f102 100644 --- a/board/honeybuns/usb_pd_policy.c +++ b/board/honeybuns/usb_pd_policy.c @@ -15,6 +15,7 @@ #include "timer.h" #include "util.h" #include "usb.h" +#include "usb_mux.h" #include "usb_pd.h" @@ -253,7 +254,7 @@ static int dp_config(int port, uint32_t *payload) if (PD_DP_CFG_DPON(payload[1])) gpio_set_level(GPIO_PD_SBU_ENABLE, 1); /* Get the DP lanes (or DP+USB SS depending on the mode) */ - board_set_usb_mux(port, mux, USB_SWITCH_CONNECT, pd_get_polarity(port)); + usb_mux_set(port, mux, USB_SWITCH_CONNECT, pd_get_polarity(port)); return 1; } diff --git a/board/oak/board.c b/board/oak/board.c index 26de4075d5..bf94c726e2 100644 --- a/board/oak/board.c +++ b/board/oak/board.c @@ -21,7 +21,6 @@ #include "i2c.h" #include "keyboard_raw.h" #include "lid_switch.h" -#include "pi3usb30532.h" #include "pi3usb9281.h" #include "power.h" #include "power_button.h" @@ -33,6 +32,7 @@ #include "temp_sensor_chip.h" #include "thermal.h" #include "timer.h" +#include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "util.h" @@ -164,6 +164,17 @@ struct ec_thermal_config thermal_params[] = { }; BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0x54 << 1, + .driver = &pi3usb30532_usb_mux_driver, + }, + { + .port_addr = 0x55 << 1, + .driver = &pi3usb30532_usb_mux_driver, + }, +}; + static int discharging_on_ac; /** @@ -172,7 +183,6 @@ static int discharging_on_ac; */ static int usb_switch_state[CONFIG_USB_PD_PORT_COUNT]; static struct mutex usb_switch_lock[CONFIG_USB_PD_PORT_COUNT]; -static uint8_t ss_mux_mode[CONFIG_USB_PD_PORT_COUNT]; /** * Store the current DP hardware route. @@ -350,62 +360,6 @@ void board_set_usb_switches(int port, enum usb_switch setting) mutex_unlock(&usb_switch_lock[port]); } -/** - * Set USB3.0/DP mux. - * - * @param port the type-C port to change - * @param mux mux setting in enum typec_mux - * @param usb USB2.0 switch - * @param polarity 0 or 1 - */ -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - const uint8_t modes[] = { - [TYPEC_MUX_NONE] = PI3USB30532_MODE_POWERON, - [TYPEC_MUX_USB] = PI3USB30532_MODE_USB, - [TYPEC_MUX_DP] = PI3USB30532_MODE_DP, - [TYPEC_MUX_DOCK] = PI3USB30532_MODE_DP_USB, - }; - - /* Configure USB2.0 */ - board_set_usb_switches(port, usb); - - /* Configure superspeed lanes */ - ss_mux_mode[port] = modes[mux] | (polarity ? PI3USB30532_BIT_SWAP : 0); - pi3usb30532_set_switch(port, ss_mux_mode[port]); - CPRINTS("usb/dp mux: port(%d) typec_mux(%d) usb2(%d) polarity(%d)", - port, mux, usb, polarity); -} - -/** - * Get USB/DP mux state. - * - * @param port the type-C port to check - * @param dp_str return DP mux status in "DP1", "DP2" or NULL - * @param usb_str return USB mux status in "USB1", "USB2" or NULL - * - * @return superspeed lane enable or not. - */ -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - const char *dp, *usb; - int has_ss, has_dp, has_usb, polarity; - int mode = ss_mux_mode[port]; - - polarity = mode & PI3USB30532_BIT_SWAP; - dp = polarity ? "DP2" : "DP1"; - usb = polarity ? "USB2" : "USB1"; - - has_ss = mode & (PI3USB30532_BIT_DP | PI3USB30532_BIT_USB); - has_dp = mode & PI3USB30532_BIT_DP; - has_usb = mode & PI3USB30532_BIT_USB; - *dp_str = has_dp ? dp : NULL; - *usb_str = has_usb ? usb : NULL; - - return has_ss ? 1 : 0; -} - static void hpd_irq_deferred(void) { gpio_set_level(GPIO_USB_DP_HPD, 1); diff --git a/board/oak/board.h b/board/oak/board.h index f653a344e9..940aa87b3d 100644 --- a/board/oak/board.h +++ b/board/oak/board.h @@ -93,15 +93,9 @@ #define CONFIG_CMD_HOSTCMD /* Drivers */ -#define CONFIG_USB_SWITCH_PI3USB30532 -/* - * 8-bit USB type-C switch I2C addresses: - * port 0: 0x54 << 1 - * port 1: 0x55 << 1 - */ -#define CONFIG_USB_SWITCH_I2C_ADDRS {0x54 << 1, 0x55 << 1} +/* USB Mux */ +#define CONFIG_USB_MUX_PI3USB30532 /* BC 1.2 charger */ -#define CONFIG_USB_SWITCH_PI3USB30532 #define CONFIG_USB_SWITCH_PI3USB9281 #define CONFIG_USB_SWITCH_PI3USB9281_CHIP_COUNT 2 @@ -120,7 +114,7 @@ #define I2C_PORT_PERICOM 0 #define I2C_PORT_THERMAL 0 #define I2C_PORT_PD_MCU 1 -#define I2C_PORT_USB_SWITCH 1 +#define I2C_PORT_USB_MUX 1 #define I2C_PORT_TCPC 1 /* Timer selection */ diff --git a/board/oak/usb_pd_policy.c b/board/oak/usb_pd_policy.c index 26911a8e0f..e60f8745db 100644 --- a/board/oak/usb_pd_policy.c +++ b/board/oak/usb_pd_policy.c @@ -15,6 +15,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) @@ -246,8 +247,8 @@ static void svdm_safe_dp_mode(int port) { /* make DP interface safe until configure */ dp_flags[port] = 0; - board_set_usb_mux(port, TYPEC_MUX_NONE, - USB_SWITCH_CONNECT, pd_get_polarity(port)); + usb_mux_set(port, TYPEC_MUX_NONE, + USB_SWITCH_CONNECT, pd_get_polarity(port)); } static int svdm_enter_dp_mode(int port, uint32_t mode_caps) @@ -280,8 +281,8 @@ 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); - board_set_usb_mux(port, TYPEC_MUX_DP, - USB_SWITCH_CONNECT, pd_get_polarity(port)); + usb_mux_set(port, TYPEC_MUX_DP, + USB_SWITCH_CONNECT, 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 */ diff --git a/board/ryu/board.c b/board/ryu/board.c index 0cbfd80014..d7b3d2893d 100644 --- a/board/ryu/board.c +++ b/board/ryu/board.c @@ -346,68 +346,6 @@ void board_set_usb_switches(int port, enum usb_switch setting) pi3usb9281_set_switches(port, usb_switch_state); } -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - /* reset everything */ - gpio_set_level(GPIO_USBC_MUX_CONF0, 0); - gpio_set_level(GPIO_USBC_MUX_CONF1, 0); - gpio_set_level(GPIO_USBC_MUX_CONF2, 0); - - /* Set D+/D- switch to appropriate level */ - board_set_usb_switches(port, usb); - - if (mux == TYPEC_MUX_NONE) - /* everything is already disabled, we can return */ - return; - - gpio_set_level(GPIO_USBC_MUX_CONF0, polarity); - - if (mux == TYPEC_MUX_USB || mux == TYPEC_MUX_DOCK) - /* USB 3.0 uses 2 superspeed lanes */ - gpio_set_level(GPIO_USBC_MUX_CONF2, 1); - - if (mux == TYPEC_MUX_DP || mux == TYPEC_MUX_DOCK) - /* DP uses available superspeed lanes (x2 or x4) */ - gpio_set_level(GPIO_USBC_MUX_CONF1, 1); -} - -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - int has_usb, has_dp, polarity; - - has_usb = gpio_get_level(GPIO_USBC_MUX_CONF2); - has_dp = gpio_get_level(GPIO_USBC_MUX_CONF1); - polarity = gpio_get_level(GPIO_USBC_MUX_CONF0); - - if (has_dp) - *dp_str = polarity ? "DP2" : "DP1"; - else - *dp_str = NULL; - - if (has_usb) - *usb_str = polarity ? "USB2" : "USB1"; - else - *usb_str = NULL; - - return has_dp || has_usb; -} - -void board_flip_usb_mux(int port) -{ - int has_usb, has_dp, polarity; - enum typec_mux mux; - - has_usb = gpio_get_level(GPIO_USBC_MUX_CONF2); - has_dp = gpio_get_level(GPIO_USBC_MUX_CONF1); - polarity = gpio_get_level(GPIO_USBC_MUX_CONF0); - mux = has_usb && has_dp ? TYPEC_MUX_DOCK : - (has_dp ? TYPEC_MUX_DP : - (has_usb ? TYPEC_MUX_USB : TYPEC_MUX_NONE)); - - board_set_usb_mux(port, mux, usb_switch_state, !polarity); -} - /** * Discharge battery when on AC power for factory test. */ diff --git a/board/ryu/build.mk b/board/ryu/build.mk index 4671ea0c7c..7d6e69851d 100644 --- a/board/ryu/build.mk +++ b/board/ryu/build.mk @@ -10,4 +10,4 @@ CHIP_FAMILY:=stm32f3 CHIP_VARIANT:=stm32f373 board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_mux.o usb_pd_policy.o diff --git a/board/ryu/usb_mux.c b/board/ryu/usb_mux.c new file mode 100644 index 0000000000..e77a8f228b --- /dev/null +++ b/board/ryu/usb_mux.c @@ -0,0 +1,67 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Ryu-custom USB mux driver. */ + +#include "common.h" +#include "gpio.h" +#include "usb_mux.h" +#include "util.h" + +static int board_init_usb_mux(int port) +{ + return EC_SUCCESS; +} + +static int board_set_usb_mux(int port, mux_state_t mux_state) +{ + /* reset everything */ + gpio_set_level(GPIO_USBC_MUX_CONF0, 0); + gpio_set_level(GPIO_USBC_MUX_CONF1, 0); + gpio_set_level(GPIO_USBC_MUX_CONF2, 0); + + if (!(mux_state & (MUX_USB_ENABLED | MUX_DP_ENABLED))) + /* everything is already disabled, we can return */ + return EC_SUCCESS; + + gpio_set_level(GPIO_USBC_MUX_CONF0, mux_state & MUX_POLARITY_INVERTED); + + if (mux_state & MUX_USB_ENABLED) + /* USB 3.0 uses 2 superspeed lanes */ + gpio_set_level(GPIO_USBC_MUX_CONF2, 1); + + if (mux_state & MUX_DP_ENABLED) + /* DP uses available superspeed lanes (x2 or x4) */ + gpio_set_level(GPIO_USBC_MUX_CONF1, 1); + + return EC_SUCCESS; +} + +static int board_get_usb_mux(int port, mux_state_t *mux_state) +{ + *mux_state = 0; + + if (gpio_get_level(GPIO_USBC_MUX_CONF2)) + *mux_state |= MUX_USB_ENABLED; + if (gpio_get_level(GPIO_USBC_MUX_CONF1)) + *mux_state |= MUX_DP_ENABLED; + if (gpio_get_level(GPIO_USBC_MUX_CONF0)) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver board_custom_usb_mux_driver = { + .init = board_init_usb_mux, + .set = board_set_usb_mux, + .get = board_get_usb_mux, +}; + +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0, + .driver = &board_custom_usb_mux_driver, + }, +}; diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h index c28a5469f5..2b7f89b9d8 100644 --- a/board/ryu/usb_pd_config.h +++ b/board/ryu/usb_pd_config.h @@ -13,6 +13,7 @@ #include "clock.h" #include "gpio.h" #include "registers.h" +#include "usb_mux.h" /* Timer selection for baseband PD communication */ #define TIM_CLOCK_PD_TX_C0 3 @@ -172,7 +173,7 @@ static inline void pd_config_init(int port, uint8_t power_role) pd_tx_init(); /* Reset mux ... for NONE polarity doesn't matter */ - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); gpio_set_level(GPIO_USBC_VCONN1_EN_L, 1); gpio_set_level(GPIO_USBC_VCONN2_EN_L, 1); diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c index 2e9ad58bf0..6a22a76a16 100644 --- a/board/ryu/usb_pd_policy.c +++ b/board/ryu/usb_pd_policy.c @@ -16,6 +16,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) @@ -244,7 +245,7 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, CPRINTF("Current: %dmA\n", payload[1]); break; case VDO_CMD_FLIP: - board_flip_usb_mux(port); + usb_mux_flip(port); break; #ifdef CONFIG_USB_PD_LOGGING case VDO_CMD_GET_LOG: @@ -263,7 +264,7 @@ static uint32_t dp_status; static void svdm_safe_dp_mode(int port) { /* make DP interface safe until configure */ - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_CONNECT, 0); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_CONNECT, 0); dp_flags = 0; dp_status = 0; } @@ -304,7 +305,7 @@ static int svdm_dp_config(int port, uint32_t *payload) if (!pin_mode) return 0; - board_set_usb_mux(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP, + usb_mux_set(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP, USB_SWITCH_CONNECT, pd_get_polarity(port)); payload[0] = VDO(USB_SID_DISPLAYPORT, 1, diff --git a/board/ryu_p4p5/board.c b/board/ryu_p4p5/board.c index 7a333610a1..2432eac06e 100644 --- a/board/ryu_p4p5/board.c +++ b/board/ryu_p4p5/board.c @@ -29,6 +29,7 @@ #include "spi.h" #include "task.h" #include "usb.h" +#include "usb_mux.h" #include "usb_pd.h" #include "usb_spi.h" #include "usb-stm32f3.h" @@ -167,11 +168,22 @@ struct pi3usb9281_config pi3usb9281_chips[] = { BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) == CONFIG_USB_SWITCH_PI3USB9281_CHIP_COUNT); +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0, + .driver = &p5_board_custom_usb_mux_driver, + }, +}; + /* Initialize board. */ static void board_init(void) { struct charge_port_info charge_none, charge_vbus; + /* Select P4 driver for old boards due to different GPIO config */ + if (board_get_version() < 5) + usb_muxes[0].driver = &p4_board_custom_usb_mux_driver; + /* Initialize all pericom charge suppliers to 0 */ charge_none.voltage = USB_BC12_CHARGE_VOLTAGE; charge_none.current = 0; @@ -287,124 +299,6 @@ void board_set_usb_switches(int port, enum usb_switch setting) pi3usb9281_set_switches(port, usb_switch_state); } -/* TODO(crosbug.com/p/38333) remove me */ -#define GPIO_USBC_SS1_USB_MODE_L GPIO_USBC_MUX_CONF0 -#define GPIO_USBC_SS2_USB_MODE_L GPIO_USBC_MUX_CONF1 -#define GPIO_USBC_SS_EN_L GPIO_USBC_MUX_CONF2 - -void p4_board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - /* reset everything */ - gpio_set_level(GPIO_USBC_SS_EN_L, 1); - gpio_set_level(GPIO_USBC_DP_MODE_L, 1); - gpio_set_level(GPIO_USBC_DP_POLARITY, 1); - gpio_set_level(GPIO_USBC_SS1_USB_MODE_L, 1); - gpio_set_level(GPIO_USBC_SS2_USB_MODE_L, 1); - - /* Set D+/D- switch to appropriate level */ - board_set_usb_switches(port, usb); - - if (mux == TYPEC_MUX_NONE) - /* everything is already disabled, we can return */ - return; - - if (mux == TYPEC_MUX_USB || mux == TYPEC_MUX_DOCK) { - /* USB 3.0 uses 2 superspeed lanes */ - gpio_set_level(polarity ? GPIO_USBC_SS2_USB_MODE_L : - GPIO_USBC_SS1_USB_MODE_L, 0); - } - - if (mux == TYPEC_MUX_DP || mux == TYPEC_MUX_DOCK) { - /* DP uses available superspeed lanes (x2 or x4) */ - gpio_set_level(GPIO_USBC_DP_POLARITY, polarity); - gpio_set_level(GPIO_USBC_DP_MODE_L, 0); - } - /* switch on superspeed lanes */ - gpio_set_level(GPIO_USBC_SS_EN_L, 0); -} - -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - if (board_get_version() < 5) { - /* P4/EVT or older boards */ - /* TODO(crosbug.com/p/38333) remove this */ - p4_board_set_usb_mux(port, mux, usb, polarity); - return; - } - - /* reset everything */ - gpio_set_level(GPIO_USBC_MUX_CONF0, 0); - gpio_set_level(GPIO_USBC_MUX_CONF1, 0); - gpio_set_level(GPIO_USBC_MUX_CONF2, 0); - - /* Set D+/D- switch to appropriate level */ - board_set_usb_switches(port, usb); - - if (mux == TYPEC_MUX_NONE) - /* everything is already disabled, we can return */ - return; - - gpio_set_level(GPIO_USBC_MUX_CONF0, polarity); - - if (mux == TYPEC_MUX_USB || mux == TYPEC_MUX_DOCK) - /* USB 3.0 uses 2 superspeed lanes */ - gpio_set_level(GPIO_USBC_MUX_CONF2, 1); - - if (mux == TYPEC_MUX_DP || mux == TYPEC_MUX_DOCK) - /* DP uses available superspeed lanes (x2 or x4) */ - gpio_set_level(GPIO_USBC_MUX_CONF1, 1); -} - -int p4_board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - int has_ss = !gpio_get_level(GPIO_USBC_SS_EN_L); - int has_usb = !gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) || - !gpio_get_level(GPIO_USBC_SS2_USB_MODE_L); - int has_dp = !gpio_get_level(GPIO_USBC_DP_MODE_L); - - if (has_dp) - *dp_str = gpio_get_level(GPIO_USBC_DP_POLARITY) ? "DP2" : "DP1"; - else - *dp_str = NULL; - - if (has_usb) - *usb_str = gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) ? - "USB2" : "USB1"; - else - *usb_str = NULL; - - return has_ss; -} - -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - int has_usb, has_dp, polarity; - - if (board_get_version() < 5) { - /* P4/EVT or older boards */ - /* TODO(crosbug.com/p/38333) remove this */ - return p4_board_get_usb_mux(port, dp_str, usb_str); - } - - has_usb = gpio_get_level(GPIO_USBC_MUX_CONF2); - has_dp = gpio_get_level(GPIO_USBC_MUX_CONF1); - polarity = gpio_get_level(GPIO_USBC_MUX_CONF0); - - if (has_dp) - *dp_str = polarity ? "DP2" : "DP1"; - else - *dp_str = NULL; - - if (has_usb) - *usb_str = polarity ? "USB2" : "USB1"; - else - *usb_str = NULL; - - return has_dp || has_usb; -} - /** * Discharge battery when on AC power for factory test. */ diff --git a/board/ryu_p4p5/board.h b/board/ryu_p4p5/board.h index c7c5a9193d..52bc499d47 100644 --- a/board/ryu_p4p5/board.h +++ b/board/ryu_p4p5/board.h @@ -208,6 +208,10 @@ enum usb_strings { /* The lower the input voltage, the higher the power efficiency. */ #define PD_PREFER_LOW_VOLTAGE +/* Mux driver functions differ by board revision */ +extern const struct usb_mux_driver p4_board_custom_usb_mux_driver; +extern const struct usb_mux_driver p5_board_custom_usb_mux_driver; + /* Discharge battery when on AC power for factory test. */ int board_discharge_on_ac(int enable); diff --git a/board/ryu_p4p5/build.mk b/board/ryu_p4p5/build.mk index 4671ea0c7c..7d6e69851d 100644 --- a/board/ryu_p4p5/build.mk +++ b/board/ryu_p4p5/build.mk @@ -10,4 +10,4 @@ CHIP_FAMILY:=stm32f3 CHIP_VARIANT:=stm32f373 board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_mux.o usb_pd_policy.o diff --git a/board/ryu_p4p5/usb_mux.c b/board/ryu_p4p5/usb_mux.c new file mode 100644 index 0000000000..03689fc468 --- /dev/null +++ b/board/ryu_p4p5/usb_mux.c @@ -0,0 +1,121 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Ryu-custom USB mux driver. */ + +#include "common.h" +#include "gpio.h" +#include "usb_mux.h" +#include "util.h" + +static int board_init_usb_mux(int port) +{ + return EC_SUCCESS; +} + +static int board_set_usb_mux(int port, mux_state_t mux_state) +{ + /* reset everything */ + gpio_set_level(GPIO_USBC_MUX_CONF0, 0); + gpio_set_level(GPIO_USBC_MUX_CONF1, 0); + gpio_set_level(GPIO_USBC_MUX_CONF2, 0); + + if (!(mux_state & (MUX_USB_ENABLED | MUX_DP_ENABLED))) + /* everything is already disabled, we can return */ + return EC_SUCCESS; + + gpio_set_level(GPIO_USBC_MUX_CONF0, mux_state & MUX_POLARITY_INVERTED); + + if (mux_state & MUX_USB_ENABLED) + /* USB 3.0 uses 2 superspeed lanes */ + gpio_set_level(GPIO_USBC_MUX_CONF2, 1); + + if (mux_state & MUX_DP_ENABLED) + /* DP uses available superspeed lanes (x2 or x4) */ + gpio_set_level(GPIO_USBC_MUX_CONF1, 1); + + return EC_SUCCESS; +} + +/* TODO(crosbug.com/p/38333) remove me */ +#define GPIO_USBC_SS1_USB_MODE_L GPIO_USBC_MUX_CONF0 +#define GPIO_USBC_SS2_USB_MODE_L GPIO_USBC_MUX_CONF1 +#define GPIO_USBC_SS_EN_L GPIO_USBC_MUX_CONF2 + +static int p4_board_set_usb_mux(int port, mux_state_t mux_state) +{ + int polarity = mux_state & MUX_POLARITY_INVERTED; + + /* reset everything */ + gpio_set_level(GPIO_USBC_SS_EN_L, 1); + gpio_set_level(GPIO_USBC_DP_MODE_L, 1); + gpio_set_level(GPIO_USBC_DP_POLARITY, 1); + gpio_set_level(GPIO_USBC_SS1_USB_MODE_L, 1); + gpio_set_level(GPIO_USBC_SS2_USB_MODE_L, 1); + + if (!(mux_state & (MUX_USB_ENABLED | MUX_DP_ENABLED))) + /* everything is already disabled, we can return */ + return EC_SUCCESS; + + if (mux_state & MUX_USB_ENABLED) + /* USB 3.0 uses 2 superspeed lanes */ + gpio_set_level(polarity ? GPIO_USBC_SS2_USB_MODE_L : + GPIO_USBC_SS1_USB_MODE_L, 0); + + if (mux_state & MUX_DP_ENABLED) { + /* DP uses available superspeed lanes (x2 or x4) */ + gpio_set_level(GPIO_USBC_DP_POLARITY, polarity); + gpio_set_level(GPIO_USBC_DP_MODE_L, 0); + } + + /* switch on superspeed lanes */ + gpio_set_level(GPIO_USBC_SS_EN_L, 0); + + return EC_SUCCESS; +} + +static int board_get_usb_mux(int port, mux_state_t *mux_state) +{ + *mux_state = 0; + + if (gpio_get_level(GPIO_USBC_MUX_CONF2)) + *mux_state |= MUX_USB_ENABLED; + if (gpio_get_level(GPIO_USBC_MUX_CONF1)) + *mux_state |= MUX_DP_ENABLED; + if (gpio_get_level(GPIO_USBC_MUX_CONF0)) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +static int p4_board_get_usb_mux(int port, mux_state_t *mux_state) +{ + *mux_state = 0; + + if (!gpio_get_level(GPIO_USBC_SS1_USB_MODE_L) || + !gpio_get_level(GPIO_USBC_SS2_USB_MODE_L)) + *mux_state |= MUX_USB_ENABLED; + + if (!gpio_get_level(GPIO_USBC_DP_MODE_L)) + *mux_state |= MUX_DP_ENABLED; + + if (gpio_get_level(GPIO_USBC_DP_POLARITY)) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver p4_board_custom_usb_mux_driver = { + .init = board_init_usb_mux, + .set = p4_board_set_usb_mux, + .get = p4_board_get_usb_mux, +}; + +const struct usb_mux_driver p5_board_custom_usb_mux_driver = { + .init = board_init_usb_mux, + .set = board_set_usb_mux, + .get = board_get_usb_mux, +}; + diff --git a/board/ryu_p4p5/usb_pd_config.h b/board/ryu_p4p5/usb_pd_config.h index 31e675eb55..7a4df7a6a1 100644 --- a/board/ryu_p4p5/usb_pd_config.h +++ b/board/ryu_p4p5/usb_pd_config.h @@ -13,6 +13,7 @@ #include "clock.h" #include "gpio.h" #include "registers.h" +#include "usb_mux.h" /* Timer selection for baseband PD communication */ #define TIM_CLOCK_PD_TX_C0 3 @@ -171,7 +172,7 @@ static inline void pd_config_init(int port, uint8_t power_role) pd_tx_init(); /* Reset mux ... for NONE polarity doesn't matter */ - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); gpio_set_level(GPIO_USBC_VCONN1_EN_L, 1); gpio_set_level(GPIO_USBC_VCONN2_EN_L, 1); diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index 161fc135fc..c162f760a1 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -403,36 +403,6 @@ const struct i2c_port_t i2c_ports[] = { }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); -struct usb_port_mux -{ - enum gpio_signal ss1_en_l; - enum gpio_signal ss2_en_l; - enum gpio_signal dp_mode_l; - enum gpio_signal dp_polarity; - enum gpio_signal ss1_dp_mode; - enum gpio_signal ss2_dp_mode; -}; - -const struct usb_port_mux usb_muxes[] = { - { - .ss1_en_l = GPIO_USB_C0_SS1_EN_L, - .ss2_en_l = GPIO_USB_C0_SS2_EN_L, - .dp_mode_l = GPIO_USB_C0_DP_MODE_L, - .dp_polarity = GPIO_USB_C0_DP_POLARITY, - .ss1_dp_mode = GPIO_USB_C0_SS1_DP_MODE, - .ss2_dp_mode = GPIO_USB_C0_SS2_DP_MODE, - }, - { - .ss1_en_l = GPIO_USB_C1_SS1_EN_L, - .ss2_en_l = GPIO_USB_C1_SS2_EN_L, - .dp_mode_l = GPIO_USB_C1_DP_MODE_L, - .dp_polarity = GPIO_USB_C1_DP_POLARITY, - .ss1_dp_mode = GPIO_USB_C1_SS1_DP_MODE, - .ss2_dp_mode = GPIO_USB_C1_SS2_DP_MODE, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_COUNT); - void board_set_usb_switches(int port, enum usb_switch setting) { /* If switch is not changing then return */ @@ -446,90 +416,6 @@ void board_set_usb_switches(int port, enum usb_switch setting) mutex_unlock(&usb_switch_lock[port]); } -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity) -{ - const struct usb_port_mux *usb_mux = usb_muxes + port; - - /* reset everything */ - gpio_set_level(usb_mux->ss1_en_l, 1); - gpio_set_level(usb_mux->ss2_en_l, 1); - gpio_set_level(usb_mux->dp_mode_l, 1); - gpio_set_level(usb_mux->dp_polarity, 1); - gpio_set_level(usb_mux->ss1_dp_mode, 1); - gpio_set_level(usb_mux->ss2_dp_mode, 1); - - /* Set D+/D- switch to appropriate level */ - board_set_usb_switches(port, usb); - - if (mux == TYPEC_MUX_NONE) - /* everything is already disabled, we can return */ - return; - - if (mux == TYPEC_MUX_USB || mux == TYPEC_MUX_DOCK) { - /* USB 3.0 uses 2 superspeed lanes */ - gpio_set_level(polarity ? usb_mux->ss2_dp_mode : - usb_mux->ss1_dp_mode, 0); - } - - if (mux == TYPEC_MUX_DP || mux == TYPEC_MUX_DOCK) { - /* DP uses available superspeed lanes (x2 or x4) */ - gpio_set_level(usb_mux->dp_polarity, polarity); - gpio_set_level(usb_mux->dp_mode_l, 0); - } - /* switch on superspeed lanes */ - gpio_set_level(usb_mux->ss1_en_l, 0); - gpio_set_level(usb_mux->ss2_en_l, 0); -} - -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str) -{ - const struct usb_port_mux *usb_mux = usb_muxes + port; - int has_ss, has_usb, has_dp; - const char *dp, *usb; - - has_ss = !gpio_get_level(usb_mux->ss1_en_l); - has_usb = !gpio_get_level(usb_mux->ss1_dp_mode) || - !gpio_get_level(usb_mux->ss2_dp_mode); - has_dp = !gpio_get_level(usb_mux->dp_mode_l); - dp = gpio_get_level(usb_mux->dp_polarity) ? - "DP2" : "DP1"; - usb = gpio_get_level(usb_mux->ss1_dp_mode) ? - "USB2" : "USB1"; - - *dp_str = has_dp ? dp : NULL; - *usb_str = has_usb ? usb : NULL; - - return has_ss; -} - -void board_flip_usb_mux(int port) -{ - const struct usb_port_mux *usb_mux = usb_muxes + port; - int usb_polarity; - - /* Flip DP polarity */ - gpio_set_level(usb_mux->dp_polarity, - !gpio_get_level(usb_mux->dp_polarity)); - - /* Flip USB polarity if enabled */ - if (gpio_get_level(usb_mux->ss1_dp_mode) && - gpio_get_level(usb_mux->ss2_dp_mode)) - return; - usb_polarity = gpio_get_level(usb_mux->ss1_dp_mode); - - /* - * Disable both sides first so that we don't enable both at the - * same time accidentally. - */ - gpio_set_level(usb_mux->ss1_dp_mode, 1); - gpio_set_level(usb_mux->ss2_dp_mode, 1); - - gpio_set_level(usb_mux->ss1_dp_mode, !usb_polarity); - gpio_set_level(usb_mux->ss2_dp_mode, usb_polarity); -} - - int board_get_battery_soc(void) { return batt_soc; diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h index 84401ad9fa..1d54501e61 100644 --- a/board/samus_pd/board.h +++ b/board/samus_pd/board.h @@ -22,7 +22,6 @@ #define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGE_RAMP #undef CONFIG_CMD_HASH -#undef CONFIG_CMD_TYPEC #undef CONFIG_CMD_I2C_SCAN #undef CONFIG_CMD_I2C_XFER /* Minimum ilim = 500 mA */ diff --git a/board/samus_pd/build.mk b/board/samus_pd/build.mk index af7ff42076..fa58b7833e 100644 --- a/board/samus_pd/build.mk +++ b/board/samus_pd/build.mk @@ -11,4 +11,4 @@ CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f07x board-y=board.o -board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_mux.o usb_pd_policy.o diff --git a/board/samus_pd/usb_mux.c b/board/samus_pd/usb_mux.c new file mode 100644 index 0000000000..e37dd08037 --- /dev/null +++ b/board/samus_pd/usb_mux.c @@ -0,0 +1,117 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Samus PD-custom USB mux driver. */ + +#include "common.h" +#include "gpio.h" +#include "usb_mux.h" +#include "util.h" + +struct usb_port_mux { + enum gpio_signal ss1_en_l; + enum gpio_signal ss2_en_l; + enum gpio_signal dp_mode_l; + enum gpio_signal dp_polarity; + enum gpio_signal ss1_dp_mode; + enum gpio_signal ss2_dp_mode; +}; + +static const struct usb_port_mux mux_gpios[] = { + { + .ss1_en_l = GPIO_USB_C0_SS1_EN_L, + .ss2_en_l = GPIO_USB_C0_SS2_EN_L, + .dp_mode_l = GPIO_USB_C0_DP_MODE_L, + .dp_polarity = GPIO_USB_C0_DP_POLARITY, + .ss1_dp_mode = GPIO_USB_C0_SS1_DP_MODE, + .ss2_dp_mode = GPIO_USB_C0_SS2_DP_MODE, + }, + { + .ss1_en_l = GPIO_USB_C1_SS1_EN_L, + .ss2_en_l = GPIO_USB_C1_SS2_EN_L, + .dp_mode_l = GPIO_USB_C1_DP_MODE_L, + .dp_polarity = GPIO_USB_C1_DP_POLARITY, + .ss1_dp_mode = GPIO_USB_C1_SS1_DP_MODE, + .ss2_dp_mode = GPIO_USB_C1_SS2_DP_MODE, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(mux_gpios) == CONFIG_USB_PD_PORT_COUNT); + + +static int board_init_usb_mux(int port) +{ + return EC_SUCCESS; +} + +static int board_set_usb_mux(int port, mux_state_t mux_state) +{ + const struct usb_port_mux *usb_mux = mux_gpios + port; + int polarity = mux_state & MUX_POLARITY_INVERTED; + + /* reset everything */ + gpio_set_level(usb_mux->ss1_en_l, 1); + gpio_set_level(usb_mux->ss2_en_l, 1); + gpio_set_level(usb_mux->dp_mode_l, 1); + gpio_set_level(usb_mux->dp_polarity, 1); + gpio_set_level(usb_mux->ss1_dp_mode, 1); + gpio_set_level(usb_mux->ss2_dp_mode, 1); + + if (!(mux_state & (MUX_USB_ENABLED | MUX_DP_ENABLED))) + /* everything is already disabled, we can return */ + return EC_SUCCESS; + + if (mux_state & MUX_USB_ENABLED) + /* USB 3.0 uses 2 superspeed lanes */ + gpio_set_level(polarity ? usb_mux->ss2_dp_mode : + usb_mux->ss1_dp_mode, 0); + + if (mux_state & MUX_DP_ENABLED) { + /* DP uses available superspeed lanes (x2 or x4) */ + gpio_set_level(usb_mux->dp_polarity, polarity); + gpio_set_level(usb_mux->dp_mode_l, 0); + } + + /* switch on superspeed lanes */ + gpio_set_level(usb_mux->ss1_en_l, 0); + gpio_set_level(usb_mux->ss2_en_l, 0); + + return EC_SUCCESS; +} + +static int board_get_usb_mux(int port, mux_state_t *mux_state) +{ + const struct usb_port_mux *usb_mux = mux_gpios + port; + + *mux_state = 0; + + if (!gpio_get_level(usb_mux->ss1_dp_mode) || + !gpio_get_level(usb_mux->ss2_dp_mode)) + *mux_state |= MUX_USB_ENABLED; + + if (!gpio_get_level(usb_mux->dp_mode_l)) + *mux_state |= MUX_DP_ENABLED; + + if (gpio_get_level(usb_mux->dp_polarity)) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver board_custom_usb_mux_driver = { + .init = board_init_usb_mux, + .set = board_set_usb_mux, + .get = board_get_usb_mux, +}; + +struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = { + { + .port_addr = 0, + .driver = &board_custom_usb_mux_driver, + }, + { + .port_addr = 1, + .driver = &board_custom_usb_mux_driver, + }, +}; diff --git a/board/samus_pd/usb_pd_config.h b/board/samus_pd/usb_pd_config.h index 43272bfbaf..d303ae3a51 100644 --- a/board/samus_pd/usb_pd_config.h +++ b/board/samus_pd/usb_pd_config.h @@ -6,6 +6,7 @@ #include "adc.h" #include "chip/stm32/registers.h" #include "gpio.h" +#include "usb_mux.h" /* USB Power delivery board configuration */ @@ -242,7 +243,7 @@ static inline void pd_config_init(int port, uint8_t power_role) pd_tx_init(); /* Reset mux ... for NONE polarity doesn't matter */ - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, 0); if (port == 0) { gpio_set_level(GPIO_USB_C0_CC1_VCONN1_EN_L, 1); diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c index b196e3f9d3..119c1ccc32 100644 --- a/board/samus_pd/usb_pd_policy.c +++ b/board/samus_pd/usb_pd_policy.c @@ -15,6 +15,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) @@ -252,7 +253,7 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, CPRINTF("Current: %dmA\n", payload[1]); break; case VDO_CMD_FLIP: - board_flip_usb_mux(port); + usb_mux_flip(port); break; case VDO_CMD_GET_LOG: pd_log_recv_vdm(port, cnt, payload); @@ -269,7 +270,7 @@ static uint32_t dp_status[CONFIG_USB_PD_PORT_COUNT]; static void svdm_safe_dp_mode(int port) { /* make DP interface safe until configure */ - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_CONNECT, 0); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_CONNECT, 0); dp_flags[port] = 0; dp_status[port] = 0; } @@ -310,8 +311,8 @@ static int svdm_dp_config(int port, uint32_t *payload) if (!pin_mode) return 0; - board_set_usb_mux(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP, - USB_SWITCH_CONNECT, pd_get_polarity(port)); + usb_mux_set(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP, + USB_SWITCH_CONNECT, pd_get_polarity(port)); payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 1d1f71dbbb..25774cd62e 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -19,6 +19,7 @@ #include "task.h" #include "timer.h" #include "util.h" +#include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" #include "version.h" @@ -271,8 +272,8 @@ static inline void set_state(int port, enum pd_states next_state) pd_dfp_exit_mode(port, 0, 0); #endif #ifdef CONFIG_USBC_SS_MUX - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd[port].polarity); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd[port].polarity); #endif #ifdef CONFIG_USBC_VCONN tcpm_set_vconn(port, 0); @@ -787,14 +788,14 @@ static void pd_set_data_role(int port, int role) * If new data role is UFP, then disconnect the SS mux. */ if (role == PD_ROLE_DFP) - board_set_usb_mux(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd[port].polarity); + usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd[port].polarity); else - board_set_usb_mux(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, - pd[port].polarity); + usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_DISCONNECT, + pd[port].polarity); #else - board_set_usb_mux(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, - pd[port].polarity); + usb_mux_set(port, TYPEC_MUX_USB, USB_SWITCH_CONNECT, + pd[port].polarity); #endif #endif pd_update_roles(port); @@ -1333,6 +1334,11 @@ void pd_task(void) /* Disable TCPC RX until connection is established */ tcpm_set_rx_enable(port, 0); +#ifdef CONFIG_USBC_SS_MUX + /* Initialize USB mux to its default state */ + usb_mux_init(port); +#endif + /* Initialize PD protocol state variables for each port. */ pd[port].power_role = PD_ROLE_DEFAULT; pd[port].vdm_state = VDM_STATE_DONE; @@ -1473,9 +1479,9 @@ void pd_task(void) /* Enable VBUS */ if (pd_set_power_supply_ready(port)) { #ifdef CONFIG_USBC_SS_MUX - board_set_usb_mux(port, TYPEC_MUX_NONE, - USB_SWITCH_DISCONNECT, - pd[port].polarity); + usb_mux_set(port, TYPEC_MUX_NONE, + USB_SWITCH_DISCONNECT, + pd[port].polarity); #endif break; } @@ -2801,54 +2807,6 @@ DECLARE_CONSOLE_COMMAND(pd, command_pd, "USB PD", NULL); -#ifdef CONFIG_USBC_SS_MUX -#ifdef CONFIG_CMD_TYPEC -static int command_typec(int argc, char **argv) -{ - const char * const mux_name[] = {"none", "usb", "dp", "dock"}; - char *e; - int port; - enum typec_mux mux = TYPEC_MUX_NONE; - int i; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[1], &e, 10); - if (*e || port >= CONFIG_USB_PD_PORT_COUNT) - return EC_ERROR_PARAM1; - - if (argc < 3) { - const char *dp_str, *usb_str; - ccprintf("Port C%d: polarity:CC%d\n", - port, pd_get_polarity(port) + 1); - if (board_get_usb_mux(port, &dp_str, &usb_str)) - ccprintf("Superspeed %s%s%s\n", - dp_str ? dp_str : "", - dp_str && usb_str ? "+" : "", - usb_str ? usb_str : ""); - else - ccprintf("No Superspeed connection\n"); - - return EC_SUCCESS; - } - - for (i = 0; i < ARRAY_SIZE(mux_name); i++) - if (!strcasecmp(argv[2], mux_name[i])) - mux = i; - board_set_usb_mux(port, mux, mux == TYPEC_MUX_NONE ? - USB_SWITCH_DISCONNECT : - USB_SWITCH_CONNECT, - pd_get_polarity(port)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(typec, command_typec, - "<port> [none|usb|dp|dock]", - "Control type-C connector muxing", - NULL); -#endif /* CONFIG_CMD_TYPEC */ -#endif /* CONFIG_USBC_SS_MUX */ - #ifdef HAS_TASK_HOSTCMD static int hc_pd_ports(struct host_cmd_handler_args *args) @@ -2898,11 +2856,11 @@ static int hc_usb_pd_control(struct host_cmd_handler_args *args) #ifdef CONFIG_USBC_SS_MUX if (p->mux != USB_PD_CTRL_MUX_NO_CHANGE) - board_set_usb_mux(p->port, typec_mux_map[p->mux], - typec_mux_map[p->mux] == TYPEC_MUX_NONE ? - USB_SWITCH_DISCONNECT : - USB_SWITCH_CONNECT, - pd_get_polarity(p->port)); + usb_mux_set(p->port, typec_mux_map[p->mux], + typec_mux_map[p->mux] == TYPEC_MUX_NONE ? + USB_SWITCH_DISCONNECT : + USB_SWITCH_CONNECT, + pd_get_polarity(p->port)); #endif /* CONFIG_USBC_SS_MUX */ if (args->version == 0) { diff --git a/driver/build.mk b/driver/build.mk index 998cd9cbce..97d80521b3 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -60,9 +60,14 @@ driver-$(CONFIG_USB_PD_TCPM_TCPCI)+=tcpm/tcpci.o # USB switches driver-$(CONFIG_USB_SWITCH_PI3USB9281)+=usb_switch_pi3usb9281.o -driver-$(CONFIG_USB_SWITCH_PI3USB30532)+=usb_switch_pi3usb30532.o driver-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o +# USB mux high-level driver +driver-$(CONFIG_USBC_SS_MUX)+=usb_mux.o + +# USB muxes +driver-$(CONFIG_USB_MUX_PI3USB30532)+=usb_mux_pi3usb30532.o + # Firmware Update driver-$(CONFIG_SB_FIRMWARE_UPDATE)+=battery/sb_fw_update.o diff --git a/driver/pi3usb30532.h b/driver/pi3usb30532.h index c24edeb976..96c963204b 100644 --- a/driver/pi3usb30532.h +++ b/driver/pi3usb30532.h @@ -10,6 +10,8 @@ #include <inttypes.h> +#include "usb_pd.h" + /* USB switch registers */ #define PI3USB30532_REG_ADDR 0x00 #define PI3USB30532_REG_VENDOR 0x01 @@ -62,17 +64,4 @@ #define PI3USB30532_MODE_DP_USB_SWAP (PI3USB30532_MODE_DP_USB | \ PI3USB30532_BIT_SWAP) - -/* Reads PI3USB30532 register */ -int pi3usb30532_read(uint8_t chip_idx, uint8_t reg); - -/* Writes PI3USB30532 register */ -int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val); - -/* Writes PI3USB30532 control register */ -int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode); - -/* Resets PI3USB30532 to power on default value */ -int pi3usb30532_reset(uint8_t chip_idx); - #endif /* __CROS_EC_PI3USB30532_H */ diff --git a/driver/usb_mux.c b/driver/usb_mux.c new file mode 100644 index 0000000000..04427f7615 --- /dev/null +++ b/driver/usb_mux.c @@ -0,0 +1,150 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* USB mux high-level driver. */ + +#include "common.h" +#include "console.h" +#include "usb_mux.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) + +static int enable_debug_prints; + +void usb_mux_init(int port) +{ + const struct usb_mux *mux = &usb_muxes[port]; + int res; + + ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_COUNT); + res = mux->driver->init(mux->port_addr); + if (res) + CPRINTS("Error initializing mux port(%d): %d", port, res); +} + +/* + * TODO(crbug.com/505480): Setting muxes often involves I2C transcations, + * which can block. Consider implementing an asynchronous task. + */ +void usb_mux_set(int port, enum typec_mux mux_mode, + enum usb_switch usb_mode, int polarity) +{ + const struct usb_mux *mux = &usb_muxes[port]; + int res; + mux_state_t mux_state; + + /* Configure USB2.0 */ + board_set_usb_switches(port, usb_mode); + + /* Configure superspeed lanes */ + mux_state = polarity ? mux_mode | MUX_POLARITY_INVERTED : mux_mode; + res = mux->driver->set(mux->port_addr, mux_state); + if (res) { + CPRINTS("Error setting mux port(%d): %d", port, res); + return; + } + + if (enable_debug_prints) + CPRINTS( + "usb/dp mux: port(%d) typec_mux(%d) usb2(%d) polarity(%d)", + port, mux_mode, usb_mode, polarity); +} + +int usb_mux_get(int port, const char **dp_str, const char **usb_str) +{ + const struct usb_mux *mux = &usb_muxes[port]; + int res; + mux_state_t mux_state; + const char *dp, *usb; + + res = mux->driver->get(mux->port_addr, &mux_state); + if (res) { + CPRINTS("Error setting mux port(%d): %d", port, res); + return 0; + } + + dp = mux_state & MUX_POLARITY_INVERTED ? "DP2" : "DP1"; + usb = mux_state & MUX_POLARITY_INVERTED ? "USB2" : "USB1"; + + *dp_str = mux_state & MUX_DP_ENABLED ? dp : NULL; + *usb_str = mux_state & MUX_USB_ENABLED ? usb : NULL; + + return *dp_str || *usb_str; +} + +void usb_mux_flip(int port) +{ + const struct usb_mux *mux = &usb_muxes[port]; + int res; + mux_state_t mux_state; + + res = mux->driver->get(mux->port_addr, &mux_state); + if (res) { + CPRINTS("Error getting mux port(%d): %d", port, res); + return; + } + + if (mux_state & MUX_POLARITY_INVERTED) + mux_state &= ~MUX_POLARITY_INVERTED; + else + mux_state |= MUX_POLARITY_INVERTED; + + res = mux->driver->set(mux->port_addr, mux_state); + if (res) + CPRINTS("Error setting mux port(%d): %d", port, res); +} + +#ifdef CONFIG_CMD_TYPEC +static int command_typec(int argc, char **argv) +{ + const char * const mux_name[] = {"none", "usb", "dp", "dock"}; + char *e; + int port; + enum typec_mux mux = TYPEC_MUX_NONE; + int i; + + if (argc == 2 && !strcasecmp(argv[1], "debug")) { + enable_debug_prints = 1; + return EC_SUCCESS; + } + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + port = strtoi(argv[1], &e, 10); + if (*e || port >= CONFIG_USB_PD_PORT_COUNT) + return EC_ERROR_PARAM1; + + if (argc < 3) { + const char *dp_str, *usb_str; + ccprintf("Port C%d: polarity:CC%d\n", + port, pd_get_polarity(port) + 1); + if (usb_mux_get(port, &dp_str, &usb_str)) + ccprintf("Superspeed %s%s%s\n", + dp_str ? dp_str : "", + dp_str && usb_str ? "+" : "", + usb_str ? usb_str : ""); + else + ccprintf("No Superspeed connection\n"); + + return EC_SUCCESS; + } + + for (i = 0; i < ARRAY_SIZE(mux_name); i++) + if (!strcasecmp(argv[2], mux_name[i])) + mux = i; + usb_mux_set(port, mux, mux == TYPEC_MUX_NONE ? + USB_SWITCH_DISCONNECT : + USB_SWITCH_CONNECT, + pd_get_polarity(port)); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(typec, command_typec, + "[port|debug] [none|usb|dp|dock]", + "Control type-C connector muxing", + NULL); +#endif diff --git a/driver/usb_mux_pi3usb30532.c b/driver/usb_mux_pi3usb30532.c new file mode 100644 index 0000000000..ceb80c9368 --- /dev/null +++ b/driver/usb_mux_pi3usb30532.c @@ -0,0 +1,109 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Pericom PI3USB30532 USB port switch driver. + */ + +#include "common.h" +#include "i2c.h" +#include "pi3usb30532.h" +#include "usb_mux.h" +#include "util.h" + +static int pi3usb30532_read(int i2c_addr, uint8_t reg, uint8_t *val) +{ + int read, res; + + /* + * First byte read will be slave address (ignored). + * Second byte read will be vendor ID. + * Third byte read will be selection control. + */ + res = i2c_read16(I2C_PORT_USB_MUX, i2c_addr, 0, &read); + if (res) + return res; + + if (reg == PI3USB30532_REG_VENDOR) + *val = read & 0xff; + else if (reg == PI3USB30532_REG_CONTROL) + *val = (read >> 8) & 0xff; + + return EC_SUCCESS; +} + +static int pi3usb30532_write(int i2c_addr, uint8_t reg, uint8_t val) +{ + if (reg != PI3USB30532_REG_CONTROL) + return EC_ERROR_UNKNOWN; + + return i2c_write8(I2C_PORT_USB_MUX, i2c_addr, 0, val); +} + +static int pi3usb30532_reset(int i2c_addr) +{ + return pi3usb30532_write( + i2c_addr, + PI3USB30532_REG_CONTROL, + (PI3USB30532_MODE_POWERDOWN & PI3USB30532_CTRL_MASK) | + PI3USB30532_CTRL_RSVD); +} + +static int pi3usb30532_init(int i2c_addr) +{ + uint8_t val; + int res; + + res = pi3usb30532_reset(i2c_addr); + if (res) + return res; + res = pi3usb30532_read(i2c_addr, PI3USB30532_REG_VENDOR, &val); + if (res) + return res; + if (val != PI3USB30532_VENDOR_ID) + return EC_ERROR_UNKNOWN; + + return EC_SUCCESS; +} + +/* Writes control register to set switch mode */ +static int pi3usb30532_set_mux(int i2c_addr, mux_state_t mux_state) +{ + uint8_t reg = 0; + + if (mux_state & MUX_USB_ENABLED) + reg |= PI3USB30532_MODE_USB; + if (mux_state & MUX_DP_ENABLED) + reg |= PI3USB30532_MODE_DP; + if (mux_state & MUX_POLARITY_INVERTED) + reg |= PI3USB30532_BIT_SWAP; + + return pi3usb30532_write(i2c_addr, PI3USB30532_REG_CONTROL, + reg | PI3USB30532_CTRL_RSVD); +} + +/* Reads control register and updates mux_state accordingly */ +static int pi3usb30532_get_mux(int i2c_addr, mux_state_t *mux_state) +{ + uint8_t reg, res; + + *mux_state = 0; + res = pi3usb30532_read(i2c_addr, PI3USB30532_REG_CONTROL, ®); + if (res) + return res; + + if (reg & PI3USB30532_MODE_USB) + *mux_state |= MUX_USB_ENABLED; + if (reg & PI3USB30532_MODE_DP) + *mux_state |= MUX_DP_ENABLED; + if (reg & PI3USB30532_BIT_SWAP) + *mux_state |= MUX_POLARITY_INVERTED; + + return EC_SUCCESS; +} + +const struct usb_mux_driver pi3usb30532_usb_mux_driver = { + .init = pi3usb30532_init, + .set = pi3usb30532_set_mux, + .get = pi3usb30532_get_mux, +}; diff --git a/driver/usb_switch_pi3usb30532.c b/driver/usb_switch_pi3usb30532.c deleted file mode 100644 index 1688278ae6..0000000000 --- a/driver/usb_switch_pi3usb30532.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2015 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Pericom PI3USB30532 USB port switch driver. - */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "timer.h" -#include "pi3usb30532.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -#define INTERNAL_READ_ERROR(code) (EC_ERROR_INTERNAL_FIRST + code) -#define IS_READ_ERROR(code) ((code) > EC_ERROR_INTERNAL_FIRST) - -/* 8-bit I2C address */ -static const int pi3usb30532_addrs[] = CONFIG_USB_SWITCH_I2C_ADDRS; - -int pi3usb30532_read(uint8_t chip_idx, uint8_t reg) -{ - int res, val; - int addr = pi3usb30532_addrs[chip_idx]; - - res = i2c_read8(I2C_PORT_USB_SWITCH, addr, reg, &val); - if (res) - return INTERNAL_READ_ERROR(res); - - return val; -} - -int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val) -{ - int res; - int addr = pi3usb30532_addrs[chip_idx]; - - res = i2c_write8(I2C_PORT_USB_SWITCH, addr, reg, val); - if (res) - CPUTS("PI3USB30532 I2C write failed"); - - return res; -} - -/* Writes control register to set switch mode */ -int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode) -{ - return pi3usb30532_write(chip_idx, PI3USB30532_REG_CONTROL, - (mode & PI3USB30532_CTRL_MASK) | - PI3USB30532_CTRL_RSVD); -} - -int pi3usb30532_reset(uint8_t chip_idx) -{ - return pi3usb30532_set_switch(chip_idx, PI3USB30532_MODE_POWERDOWN); -} - -static void pi3usb30532_init(void) -{ - int i, res, val; - - for (i = 0; i < ARRAY_SIZE(pi3usb30532_addrs); i++) { - res = pi3usb30532_reset(i); - if (res) - CPRINTS("PI3USB30532 [%d] init failed", i); - - val = pi3usb30532_read(i, PI3USB30532_REG_VENDOR); - if (IS_READ_ERROR(val)) { - CPRINTS("PI3USB30532 [%d] read failed", i); - continue; - } - - if (val != PI3USB30532_VENDOR_ID) - CPRINTS("PI3USB30532 [%d] invalid ID 0x%02x", i, val); - - } -} -DECLARE_HOOK(HOOK_INIT, pi3usb30532_init, HOOK_PRIO_LAST); diff --git a/include/config.h b/include/config.h index f7af2ba28b..76436708ca 100644 --- a/include/config.h +++ b/include/config.h @@ -1630,8 +1630,8 @@ /* Number of Pericom PI3USB9281 chips present in system */ #undef CONFIG_USB_SWITCH_PI3USB9281_CHIP_COUNT -/* Support the Pericom PI3USB30532. */ -#undef CONFIG_USB_SWITCH_PI3USB30532 +/* Support the Pericom PI3USB30532 USB3.0/DP1.2 Matrix Switch */ +#undef CONFIG_USB_MUX_PI3USB30532 /*****************************************************************************/ /* USB GPIO config */ diff --git a/include/usb_mux.h b/include/usb_mux.h new file mode 100644 index 0000000000..d451e9cf1c --- /dev/null +++ b/include/usb_mux.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* USB mux driver */ + +#ifndef __CROS_EC_USB_MUX_H +#define __CROS_EC_USB_MUX_H + +#include "usb_pd.h" + +/* USB-C mux state */ +typedef uint8_t mux_state_t; + +/* Mux state attributes */ +#define MUX_USB_ENABLED (1 << 0) /* USB is enabled */ +#define MUX_DP_ENABLED (1 << 1) /* DP is enabled */ +#define MUX_POLARITY_INVERTED (1 << 2) /* Polarity is inverted */ + +/* Mux modes, decoded to attributes */ +enum typec_mux { + TYPEC_MUX_NONE = 0, /* Open switch */ + TYPEC_MUX_USB = MUX_USB_ENABLED, /* USB only */ + TYPEC_MUX_DP = MUX_DP_ENABLED, /* DP only */ + TYPEC_MUX_DOCK = MUX_USB_ENABLED | /* Both USB and DP */ + MUX_DP_ENABLED, +}; + +/* Mux driver function pointers */ +struct usb_mux_driver { + /** + * Initialize USB mux. + * + * @param port_addr Port/address driver-defined parameter. + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*init)(int port_addr); + + /** + * Set USB mux state. + * + * @param port_addr Port/address driver-defined parameter. + * @param mux_state State to set mux to. + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*set)(int port_addr, mux_state_t mux_state); + + /** + * Get current state of USB mux. + * + * @param port_addr Port / address driver-defined parameter. + * @param mux_state Gets set to current state of mux. + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*get)(int port_addr, mux_state_t *mux_state); +}; + +/* Describes a USB mux present in the system */ +struct usb_mux { + /* + * Driver-defined parameter, typically an i2c slave address + * (for i2c muxes) or a port number (for GPIO 'muxes'). + */ + const int port_addr; + /* Mux driver */ + const struct usb_mux_driver *driver; +}; + +/* Supported USB mux drivers */ +extern const struct usb_mux_driver pi3usb30532_usb_mux_driver; + +/* USB muxes present in system, ordered by PD port #, defined at board-level */ +extern struct usb_mux usb_muxes[]; + +/** + * Initialize USB mux to its default state. + * + * @param port Port number. + */ +void usb_mux_init(int port); + +/** + * Configure superspeed muxes on type-C port. + * + * @param port port number. + * @param mux_mode mux selected function. + * @param usb_config usb2.0 selected function. + * @param polarity plug polarity (0=CC1, 1=CC2). + */ +void usb_mux_set(int port, enum typec_mux mux_mode, + enum usb_switch usb_config, int polarity); + +/** + * Query superspeed mux status on type-C port. + * + * @param port port number. + * @param dp_str pointer to the DP string to return. + * @param usb_str pointer to the USB string to return. + * @return Non-zero if superspeed connection is enabled; otherwise, zero. + */ +int usb_mux_get(int port, const char **dp_str, const char **usb_str); + +/** + * Flip the superspeed muxes on type-C port. + * + * This is used for factory test automation. Note that this function should + * only flip the superspeed muxes and leave CC lines alone. Without further + * changes, this function MUST ONLY be used for testing purpose, because + * the protocol layer loses track of the superspeed polarity and DP/USB3.0 + * connection may break. + * + * @param port port number. + */ +void usb_mux_flip(int port); +#endif diff --git a/include/usb_pd.h b/include/usb_pd.h index 8b915a14c4..e9edebb526 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1186,14 +1186,6 @@ extern const int pd_snk_pdo_cnt; */ int pd_get_source_pdo(const uint32_t **src_pdo); -/* Muxing for the USB type C */ -enum typec_mux { - TYPEC_MUX_NONE, - TYPEC_MUX_USB, - TYPEC_MUX_DP, - TYPEC_MUX_DOCK, -}; - enum usb_switch { USB_SWITCH_CONNECT, USB_SWITCH_DISCONNECT, @@ -1209,39 +1201,6 @@ enum usb_switch { void board_set_usb_switches(int port, enum usb_switch setting); /** - * Configure superspeed muxes on type-C port. - * - * @param port port number. - * @param mux selected function. - * @param polarity plug polarity (0=CC1, 1=CC2). - */ -void board_set_usb_mux(int port, enum typec_mux mux, - enum usb_switch usb, int polarity); - -/** - * Query superspeed mux status on type-C port. - * - * @param port port number. - * @param dp_str pointer to the DP string to return. - * @param usb_str pointer to the USB string to return. - * @return Non-zero if superspeed connection is enabled; otherwise, zero. - */ -int board_get_usb_mux(int port, const char **dp_str, const char **usb_str); - -/** - * Flip the superspeed muxes on type-C port. - * - * This is used for factory test automation. Note that this function should - * only flip the superspeed muxes and leave CC lines alone. Without further - * changes, this function MUST ONLY be used for testing purpose, because - * the protocol layer loses track of the superspeed polarity and DP/USB3.0 - * connection may break. - * - * @param port port number. - */ -void board_flip_usb_mux(int port); - -/** * Request that a host event be sent to notify the AP of a PD power event. * * @param mask host event mask. |