diff options
author | Scott <scollyer@chromium.org> | 2017-03-14 14:51:37 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-04-07 08:54:35 -0700 |
commit | ea57c36c18d6b811a58b5055969d0017f39b5162 (patch) | |
tree | 6f078f06efc6acf448104cb5ea2a82b4c94812e6 | |
parent | 672bffb2b34cdeb6d259794132c34d25e8e07a79 (diff) | |
download | chrome-ec-ea57c36c18d6b811a58b5055969d0017f39b5162.tar.gz |
servo_v4: Added dts_mode on/off control for DUT port connection
Added a new static variable disable_dts_mode. By default, DUT port
will attempt to connect as a DTS source. However, if disable_dts_mode
is set via a console command, the DUT port will connect as a regular
source device. Charging behavior is identical between the two modes.
In DTS mode, Rp is presented on both CC lines. When it's disabled Rp
is presented only on CC1. Added tables to support the appropriate VNC
and RD voltage thresholds.
BUG=b:36908939
BRANCH=servo
TEST=Tested with new console command 'dts on|off'. If new mode equals
the current mode, no action is taken. If the mode is different, then
verified that DUT port connects as DTS following 'dts on' and regular
SRC following 'dts off'. Verifed this when the command is issued when
connected to the DUT or disconnected. Validated that the H1 console is
present for DTS mode and not present when DTS mode is disabled.
Change-Id: Ie649709d6b2bbe947708d05eac42fde61d2677a8
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/468447
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/servo_v4/board.h | 13 | ||||
-rw-r--r-- | board/servo_v4/usb_pd_config.h | 56 | ||||
-rw-r--r-- | board/servo_v4/usb_pd_policy.c | 202 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 13 |
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 |