From 7c2c5a9dc3779587f78a7c602cefeb667d210d41 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Wed, 11 Oct 2017 23:18:34 -0700 Subject: [PATCH] pd: Add "freeze" dual-role policy Add a new DRP policy to "freeze" the power role of each port, never toggling automatically, though manual role swaps may still occur. BUG=chromium:769895 BRANCH=servo TEST=On servo_v4, verify DUT port stays in SRC role and POWER port stays in SNK role while disconnected. Signed-off-by: Shawn Nematbakhsh Change-Id: Ibff3cd1ffaf0e884b030c231003763a57acbe02e Reviewed-on: https://chromium-review.googlesource.com/715276 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Vincent Palatin --- board/servo_v4/board.h | 4 ++++ common/usb_pd_protocol.c | 11 +++++++++-- include/config.h | 3 +++ include/ec_commands.h | 1 + include/usb_pd.h | 6 ++++++ util/ectool.c | 3 ++- 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h index 071599460b..a7ea1ec6e7 100644 --- a/board/servo_v4/board.h +++ b/board/servo_v4/board.h @@ -104,6 +104,10 @@ /* Override PD_ROLE_DEFAULT in usb_pd.h */ #define PD_ROLE_DEFAULT(port) ((port) ? PD_ROLE_SOURCE : PD_ROLE_SINK) +/* Don't automatically change roles */ +#undef CONFIG_USB_PD_INITIAL_DRP_STATE +#define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_FREEZE + /* Variable-current Rp no connect and Ra attach macros */ #define CC_NC(port, cc, sel) (pd_tcpc_cc_nc(port, cc, sel)) #define CC_RA(port, cc, sel) (pd_tcpc_cc_ra(port, cc, sel)) diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 46d5e4b25f..b5e8ed134a 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -95,7 +95,7 @@ enum vdm_states { #ifdef CONFIG_USB_PD_DUAL_ROLE /* Port dual-role state */ -enum pd_dual_role_states drp_state = PD_DRP_TOGGLE_OFF; +enum pd_dual_role_states drp_state = CONFIG_USB_PD_INITIAL_DRP_STATE; /* Last received source cap */ static uint32_t pd_src_caps[CONFIG_USB_PD_PORT_COUNT][PDO_MAX_OBJECTS]; @@ -1842,7 +1842,7 @@ void pd_task(void *u) set_state(port, PD_STATE_SRC_DISCONNECTED_DEBOUNCE); } -#if defined(CONFIG_USB_PD_DUAL_ROLE) && !defined(CONFIG_USB_PD_DTS) +#if defined(CONFIG_USB_PD_DUAL_ROLE) /* * Try.SRC state is embedded here. Wait for SNK * detect, or if timer expires, transition to @@ -1855,6 +1855,7 @@ void pd_task(void *u) get_time().val >= pd[port].try_src_marker) || (!(pd[port].flags & PD_FLAGS_TRY_SRC) && drp_state != PD_DRP_FORCE_SOURCE && + drp_state != PD_DRP_FREEZE && get_time().val >= next_role_swap)) { pd[port].power_role = PD_ROLE_SINK; set_state(port, PD_STATE_SNK_DISCONNECTED); @@ -3338,6 +3339,9 @@ static int command_pd(int argc, char **argv) case PD_DRP_TOGGLE_OFF: ccprintf("off\n"); break; + case PD_DRP_FREEZE: + ccprintf("freeze\n"); + break; case PD_DRP_FORCE_SINK: ccprintf("force sink\n"); break; @@ -3350,6 +3354,8 @@ static int command_pd(int argc, char **argv) pd_set_dual_role(PD_DRP_TOGGLE_ON); else if (!strcasecmp(argv[2], "off")) pd_set_dual_role(PD_DRP_TOGGLE_OFF); + else if (!strcasecmp(argv[2], "freeze")) + pd_set_dual_role(PD_DRP_FREEZE); else if (!strcasecmp(argv[2], "sink")) pd_set_dual_role(PD_DRP_FORCE_SINK); else if (!strcasecmp(argv[2], "source")) @@ -3557,6 +3563,7 @@ static const enum pd_dual_role_states dual_role_map[USB_PD_CTRL_ROLE_COUNT] = { [USB_PD_CTRL_ROLE_TOGGLE_OFF] = PD_DRP_TOGGLE_OFF, [USB_PD_CTRL_ROLE_FORCE_SINK] = PD_DRP_FORCE_SINK, [USB_PD_CTRL_ROLE_FORCE_SOURCE] = PD_DRP_FORCE_SOURCE, + [USB_PD_CTRL_ROLE_FREEZE] = PD_DRP_FREEZE, }; #ifdef CONFIG_USBC_SS_MUX diff --git a/include/config.h b/include/config.h index 7390e3d179..b4de2f8589 100644 --- a/include/config.h +++ b/include/config.h @@ -2518,6 +2518,9 @@ /* Define if this board can used TCPC-controlled DRP toggle */ #undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +/* Initial DRP / toggle policy */ +#define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_TOGGLE_OFF + /* * Define if VBUS source GPIOs (GPIO_USB_C*_5V_EN) are active-low (and named * (..._L) rather than default active-high. diff --git a/include/ec_commands.h b/include/ec_commands.h index 7736bd9069..373b23104b 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -3948,6 +3948,7 @@ enum usb_pd_control_role { USB_PD_CTRL_ROLE_TOGGLE_OFF = 2, USB_PD_CTRL_ROLE_FORCE_SINK = 3, USB_PD_CTRL_ROLE_FORCE_SOURCE = 4, + USB_PD_CTRL_ROLE_FREEZE = 5, USB_PD_CTRL_ROLE_COUNT }; diff --git a/include/usb_pd.h b/include/usb_pd.h index 816fe15517..bcb7df3ada 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -743,9 +743,15 @@ enum pd_cc_states { #ifdef CONFIG_USB_PD_DUAL_ROLE enum pd_dual_role_states { + /* While disconnected, toggle between src and sink */ PD_DRP_TOGGLE_ON, + /* Stay in src until disconnect, then stay in sink forever */ PD_DRP_TOGGLE_OFF, + /* Stay in current power role, don't switch. No auto-toggle support */ + PD_DRP_FREEZE, + /* Switch to sink */ PD_DRP_FORCE_SINK, + /* Switch to source */ PD_DRP_FORCE_SOURCE, }; /** diff --git a/util/ectool.c b/util/ectool.c index ff41538b44..03aa6812d1 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -4414,7 +4414,8 @@ int cmd_usb_mux(int argc, char *argv[]) int cmd_usb_pd(int argc, char *argv[]) { - const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source"}; + const char *role_str[] = {"", "toggle", "toggle-off", "sink", "source", + "freeze"}; const char *mux_str[] = {"", "none", "usb", "dp", "dock", "auto"}; const char *swap_str[] = {"", "dr_swap", "pr_swap", "vconn_swap"}; struct ec_params_usb_pd_control p;