summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/honeybuns/board.c57
-rw-r--r--board/honeybuns/build.mk2
-rw-r--r--board/honeybuns/usb_mux.c84
-rw-r--r--board/honeybuns/usb_pd_policy.c3
-rw-r--r--board/oak/board.c70
-rw-r--r--board/oak/board.h12
-rw-r--r--board/oak/usb_pd_policy.c9
-rw-r--r--board/ryu/board.c62
-rw-r--r--board/ryu/build.mk2
-rw-r--r--board/ryu/usb_mux.c67
-rw-r--r--board/ryu/usb_pd_config.h3
-rw-r--r--board/ryu/usb_pd_policy.c7
-rw-r--r--board/ryu_p4p5/board.c130
-rw-r--r--board/ryu_p4p5/board.h4
-rw-r--r--board/ryu_p4p5/build.mk2
-rw-r--r--board/ryu_p4p5/usb_mux.c121
-rw-r--r--board/ryu_p4p5/usb_pd_config.h3
-rw-r--r--board/samus_pd/board.c114
-rw-r--r--board/samus_pd/board.h1
-rw-r--r--board/samus_pd/build.mk2
-rw-r--r--board/samus_pd/usb_mux.c117
-rw-r--r--board/samus_pd/usb_pd_config.h3
-rw-r--r--board/samus_pd/usb_pd_policy.c9
-rw-r--r--common/usb_pd_protocol.c86
-rw-r--r--driver/build.mk7
-rw-r--r--driver/pi3usb30532.h15
-rw-r--r--driver/usb_mux.c150
-rw-r--r--driver/usb_mux_pi3usb30532.c109
-rw-r--r--driver/usb_switch_pi3usb30532.c85
-rw-r--r--include/config.h4
-rw-r--r--include/usb_mux.h116
-rw-r--r--include/usb_pd.h41
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, &reg);
+ 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.