summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/servo_v4/board.h13
-rw-r--r--board/servo_v4/usb_pd_config.h56
-rw-r--r--board/servo_v4/usb_pd_policy.c202
-rw-r--r--common/usb_pd_protocol.c13
4 files changed, 204 insertions, 80 deletions
diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h
index dad2c8642b..629e19b38e 100644
--- a/board/servo_v4/board.h
+++ b/board/servo_v4/board.h
@@ -181,5 +181,18 @@ int pd_tcpc_cc_nc(int port, int cc_volt, int cc_sel);
*/
int pd_tcpc_cc_ra(int port, int cc_volt, int cc_sel);
+/**
+ * Set Rp or Rd resistor for CC lines
+ *
+ * This function is used to configure the CC pullup or pulldown resistor to
+ * the requested value.
+ *
+ * @param port USB-C port number
+ * @param cc_pull 1 for Rp and 0 for Rd
+ * @param rp_value If cc_pull == 1, the value of Rp to use
+ * @return 1 if cc_pull == 1 and Rp is invalid, otherwise 0
+ */
+int pd_set_rp_rd(int port, int cc_pull, int rp_value);
+
#endif /* !__ASSEMBLER__ */
#endif /* __CROS_EC_BOARD_H */
diff --git a/board/servo_v4/usb_pd_config.h b/board/servo_v4/usb_pd_config.h
index 838ead71d7..56c8d3aa02 100644
--- a/board/servo_v4/usb_pd_config.h
+++ b/board/servo_v4/usb_pd_config.h
@@ -220,62 +220,6 @@ static inline void pd_tx_init(void)
gpio_config_module(MODULE_USB_PD, 1);
}
-static inline int pd_set_rp_rd(int port, int cc_pull, int rp_value)
-{
- /* Set Rd for CC1/CC2 to High-Z. */
- gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_INPUT);
- /* Set Rp for CC1/CC2 to High-Z. */
- gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP3A0, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_INPUT);
-
- if (cc_pull == TYPEC_CC_RP) {
- /*
- * CC values for Debug sources (DTS)
- *
- * Source type Mode of Operation CC1 CC2
- * ---------------------------------------------
- * DTS Default USB Power Rp3A0 Rp1A5
- * DTS USB-C @ 1.5 A Rp1A5 RpUSB
- * DTS USB-C @ 3 A Rp3A0 RpUSB
- */
- switch (rp_value) {
- case TYPEC_RP_USB:
- gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_OUT_HIGH);
- gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_OUT_HIGH);
- break;
- case TYPEC_RP_1A5:
- gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_OUT_HIGH);
- gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_OUT_HIGH);
- break;
- case TYPEC_RP_3A0:
- gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_OUT_HIGH);
- gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_OUT_HIGH);
- break;
- case TYPEC_RP_RESERVED:
- /*
- * This case can be used to force a detach event since
- * all values are set to inputs above. Nothing else to
- * set.
- */
- break;
- default:
- return EC_ERROR_INVAL;
- }
-
- } else if (cc_pull == TYPEC_CC_RD) {
- /* DTS in SNK mode presents Rd on CC1/CC2 */
- gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_OUT_LOW);
- gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_OUT_LOW);
- }
-
- return EC_SUCCESS;
-}
-
static inline void pd_set_host_mode(int port, int enable)
{
/*
diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c
index 3268b343fd..019b35f763 100644
--- a/board/servo_v4/usb_pd_policy.c
+++ b/board/servo_v4/usb_pd_policy.c
@@ -57,19 +57,32 @@ struct vbus_prop {
static struct vbus_prop vbus[CONFIG_USB_PD_PORT_COUNT];
static struct vbus_prop vbus_pend;
static uint8_t vbus_rp = TYPEC_RP_RESERVED;
+static int disable_dts_mode;
-/* Voltage thresholds for no connect */
-static int pd_src_vnc[TYPEC_RP_RESERVED][2] = {
+/* Voltage thresholds for no connect in DTS mode */
+static int pd_src_vnc_dts[TYPEC_RP_RESERVED][2] = {
{PD_SRC_3_0_VNC_MV, PD_SRC_1_5_VNC_MV},
{PD_SRC_1_5_VNC_MV, PD_SRC_DEF_VNC_MV},
{PD_SRC_3_0_VNC_MV, PD_SRC_DEF_VNC_MV},
};
-/* Voltage thresholds for Ra attach */
-static int pd_src_rd_threshold[TYPEC_RP_RESERVED][2] = {
+/* Voltage thresholds for Ra attach in DTS mode */
+static int pd_src_rd_threshold_dts[TYPEC_RP_RESERVED][2] = {
{PD_SRC_3_0_RD_THRESH_MV, PD_SRC_1_5_RD_THRESH_MV},
{PD_SRC_1_5_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV},
{PD_SRC_3_0_RD_THRESH_MV, PD_SRC_DEF_RD_THRESH_MV},
};
+/* Voltage thresholds for no connect in normal SRC mode */
+static int pd_src_vnc[TYPEC_RP_RESERVED] = {
+ PD_SRC_DEF_VNC_MV,
+ PD_SRC_1_5_VNC_MV,
+ PD_SRC_3_0_VNC_MV,
+};
+/* Voltage thresholds for Ra attach in normal SRC mode */
+static int pd_src_rd_threshold[TYPEC_RP_RESERVED] = {
+ PD_SRC_DEF_RD_THRESH_MV,
+ PD_SRC_1_5_RD_THRESH_MV,
+ PD_SRC_3_0_RD_THRESH_MV,
+};
static void board_manage_dut_port(void)
{
@@ -94,12 +107,9 @@ static void board_manage_dut_port(void)
}
/* Check if Rp setting needs to change from current value */
- if (vbus_rp != rp) {
+ if (vbus_rp != rp)
/* Present new Rp value */
tcpm_select_rp_value(DUT, rp);
- /* Save new Rp value for DUT port */
- vbus_rp = rp;
- }
/*
* If CHG vbus voltage/current doesn't match the DUT port value, then
@@ -181,33 +191,160 @@ static void board_update_chg_vbus(int max_ma, int vbus_mv)
int pd_tcpc_cc_nc(int port, int cc_volt, int cc_sel)
{
int rp_index;
+ int nc;
/* Can never be called from CHG port as it's sink only */
if (port == CHG)
return 0;
rp_index = vbus_rp;
- /* Ensure that rp_index doens't exceed the array size */
+ /*
+ * If rp_index > 2, then always return not connected. This case should
+ * only happen when all Rp GPIO controls are tri-stated.
+ */
if (rp_index >= TYPEC_RP_RESERVED)
- rp_index = 0;
+ return 1;
- return cc_volt >= pd_src_vnc[rp_index][cc_sel];
+ /* Select the correct voltage threshold for current Rp and DTS mode */
+ if (disable_dts_mode)
+ nc = cc_volt >= pd_src_vnc[rp_index];
+ else
+ nc = cc_volt >= pd_src_vnc_dts[rp_index][cc_sel];
+
+ return nc;
}
int pd_tcpc_cc_ra(int port, int cc_volt, int cc_sel)
{
int rp_index;
+ int ra;
/* Can never be called from CHG port as it's sink only */
if (port == CHG)
return 0;
rp_index = vbus_rp;
- /* Ensure that rp_index doens't exceed the array size */
+ /*
+ * If rp_index > 2, then can't be Ra. This case should
+ * only happen when all Rp GPIO controls are tri-stated.
+ */
if (rp_index >= TYPEC_RP_RESERVED)
- rp_index = 0;
+ return 0;
+
+ /* Select the correct voltage threshold for current Rp and DTS mode */
+ if (disable_dts_mode)
+ ra = cc_volt < pd_src_rd_threshold[rp_index];
+ else
+ ra = cc_volt < pd_src_rd_threshold_dts[rp_index][cc_sel];
+
+ return ra;
+}
+
+static int board_set_rp(int rp)
+{
+ if (disable_dts_mode) {
+ /*
+ * DTS mode is disabled, so only present the requested Rp value
+ * on CC1 and leave all Rp/Rd resistors on CC2 disconnected.
+ */
+ switch (rp) {
+ case TYPEC_RP_USB:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_1A5:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_3A0:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_RESERVED:
+ /*
+ * This case can be used to force a detach event since
+ * all values are set to inputs above. Nothing else to
+ * set.
+ */
+ break;
+ default:
+ return EC_ERROR_INVAL;
+ }
+ } else {
+ /* DTS mode is enabled. The rp parameter is used to select the
+ * Type C current limit to advertise. The combinations of Rp on
+ * each CC line is shown in the table below.
+ *
+ * CC values for Debug sources (DTS)
+ *
+ * Source type Mode of Operation CC1 CC2
+ * ---------------------------------------------
+ * DTS Default USB Power Rp3A0 Rp1A5
+ * DTS USB-C @ 1.5 A Rp1A5 RpUSB
+ * DTS USB-C @ 3 A Rp3A0 RpUSB
+ */
+ switch (rp) {
+ case TYPEC_RP_USB:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_OUT_HIGH);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_1A5:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_OUT_HIGH);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_3A0:
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_OUT_HIGH);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_OUT_HIGH);
+ break;
+ case TYPEC_RP_RESERVED:
+ /*
+ * This case can be used to force a detach event since
+ * all values are set to inputs above. Nothing else to
+ * set.
+ */
+ break;
+ default:
+ return EC_ERROR_INVAL;
+ }
+ }
+ /* Save new Rp value for DUT port */
+ vbus_rp = rp;
+
+ return EC_SUCCESS;
+}
+
+int pd_set_rp_rd(int port, int cc_pull, int rp_value)
+{
+ int rv = EC_SUCCESS;
+
+ /* By default disconnect all Rp/Rd resistors from both CC lines */
+ /* Set Rd for CC1/CC2 to High-Z. */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_INPUT);
+ /* Set Rp for CC1/CC2 to High-Z. */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP3A0, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RP3A0, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC1_RP1A5, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RP1A5, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC1_RPUSB, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_RPUSB, GPIO_INPUT);
+
+ /* Set TX Hi-Z */
+ gpio_set_flags(GPIO_USB_DUT_CC1_TX_DATA, GPIO_INPUT);
+ gpio_set_flags(GPIO_USB_DUT_CC2_TX_DATA, GPIO_INPUT);
+
+ if (cc_pull == TYPEC_CC_RP) {
+ rv = board_set_rp(rp_value);
+ } else if (cc_pull == TYPEC_CC_RD) {
+ /*
+ * The DUT port uses a captive cable. If can present Rd on both
+ * CC1 and CC2. If DTS mode is enabled, then present Rd on both
+ * CC lines. However, if DTS mode is disabled only present Rd on
+ * CC1.
+ */
+ gpio_set_flags(GPIO_USB_DUT_CC1_RD, GPIO_OUT_LOW);
+ if (!disable_dts_mode)
+ gpio_set_flags(GPIO_USB_DUT_CC2_RD, GPIO_OUT_LOW);
+ }
- return cc_volt < pd_src_rd_threshold[rp_index][cc_sel];
+ return rv;
}
int board_select_rp_value(int port, int rp)
@@ -401,3 +538,40 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload,
const struct svdm_amode_fx supported_modes[] = {};
const int supported_modes_cnt = ARRAY_SIZE(supported_modes);
+
+static int command_dts(int argc, char **argv)
+{
+ int disable_dts_new;
+ int val;
+
+ if (argc < 2) {
+ /* Get current CCD status */
+ ccprintf("dts mode: %s\n", disable_dts_mode ? "off" : "on");
+ return EC_SUCCESS;
+ }
+
+ if (!parse_bool(argv[1], &val))
+ return EC_ERROR_PARAM2;
+
+ disable_dts_new = val ^ 1;
+ if (disable_dts_new != disable_dts_mode) {
+ /* Force detach */
+ pd_power_supply_reset(DUT);
+ /* Always set to 0 here so both CC lines are changed */
+ disable_dts_mode = 0;
+ /* Remove Rp/Rd on both CC lines */
+ board_select_rp_value(DUT, TYPEC_RP_RESERVED);
+ /* Accept new disable_dts value */
+ disable_dts_mode = disable_dts_new;
+ /* Some time for DUT to detach */
+ msleep(100);
+ /* Present RP_USB on CC1 and CC2 based on disable_dts_mode */
+ board_select_rp_value(DUT, TYPEC_RP_USB);
+ ccprintf("dts mode: %s\n", disable_dts_mode ? "off" : "on");
+ }
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(dts, command_dts,
+ "off|on",
+ "Servo_v4 DTS mode on/off");
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 2986e84843..b92641e5c8 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -3015,22 +3015,15 @@ defined(CONFIG_CASE_CLOSED_DEBUG_EXTERNAL)
if (pd[port].power_role == PD_ROLE_SOURCE) {
/* Source: detect disconnect by monitoring CC */
tcpm_get_cc(port, &cc1, &cc2);
-#ifdef CONFIG_USB_PD_DTS
- /* If accessory becomes detached */
- if (cc1 != TYPEC_CC_VOLT_RD ||
- cc2 != TYPEC_CC_VOLT_RD) {
- set_state(port, PD_STATE_SRC_DISCONNECTED);
- /* Debouncing */
- timeout = 10*MSEC;
- ccd_set_mode(CCD_MODE_DISABLED);
- }
-#endif
if (pd[port].polarity)
cc1 = cc2;
if (cc1 == TYPEC_CC_VOLT_OPEN) {
set_state(port, PD_STATE_SRC_DISCONNECTED);
/* Debouncing */
timeout = 10*MSEC;
+#ifdef CONFIG_USB_PD_DTS
+ ccd_set_mode(CCD_MODE_DISABLED);
+#endif
#ifdef CONFIG_USB_PD_DUAL_ROLE
/*
* If Try.SRC is configured, then ATTACHED_SRC