diff options
author | Ayushee <ayushee.shah@intel.com> | 2020-06-26 12:14:25 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-07-17 02:57:09 +0000 |
commit | 5270ea2b0cfc2ce699281c2e59ffce3546551d7e (patch) | |
tree | 04015789df81cfe1c8559a5d300ca80789ce0d58 /common/usbc | |
parent | 51cf32c16205af580dc1475ddf2c5731e199a133 (diff) | |
download | chrome-ec-5270ea2b0cfc2ce699281c2e59ffce3546551d7e.tar.gz |
TCPMv2: Add common exit mode for all the alternate modes
When chipset is transitioning to a new state or on sysjump, the SOC
re-negotiates to enter an alternate mode on booting up.
This commit:
1. Adds a common DPM function to check for all the active alternate modes
one at a time, construct the VDM and send the DPM request to exit the
mode.
2. Marks thunderbolt mode as inactive in DFP's thunderbolt mode exit
function.
BUG=b:152235216
BRANCH=None
TEST=Tested on volteer:
1. On connecting a DP dongle, able to enter into DP alternate mode
on reboot
2. On connecting a Thunderbolt dock, able to enter into Thunderbolt
mode on reboot
Change-Id: I7da6a4b08cab9abb3446c0dafdc7c9e9378ef00e
Signed-off-by: Ayushee <ayushee.shah@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2270877
Tested-by: Abe Levkoy <alevkoy@chromium.org>
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Commit-Queue: Abe Levkoy <alevkoy@chromium.org>
Diffstat (limited to 'common/usbc')
-rw-r--r-- | common/usbc/dp_alt_mode.c | 5 | ||||
-rw-r--r-- | common/usbc/tbt_alt_mode.c | 5 | ||||
-rw-r--r-- | common/usbc/usb_pd_dpm.c | 55 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 68 | ||||
-rw-r--r-- | common/usbc/usb_tc_drp_acc_trysrc_sm.c | 7 |
5 files changed, 84 insertions, 56 deletions
diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c index 569c64d7ca..cc5305c0c3 100644 --- a/common/usbc/dp_alt_mode.c +++ b/common/usbc/dp_alt_mode.c @@ -51,6 +51,11 @@ static const uint8_t state_vdm_cmd[DP_STATE_COUNT] = { [DP_ENTER_RETRY] = CMD_ENTER_MODE, }; +bool dp_is_active(int port) +{ + return dp_state[port] == DP_ACTIVE; +} + void dp_init(int port) { dp_state[port] = DP_START; diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c index 57b0da41b8..ee4c78285e 100644 --- a/common/usbc/tbt_alt_mode.c +++ b/common/usbc/tbt_alt_mode.c @@ -56,6 +56,11 @@ void tbt_init(int port) tbt_state[port] = TBT_START; } +bool tbt_is_active(int port) +{ + return tbt_state[port] == TBT_ACTIVE; +} + void tbt_teardown(int port) { tbt_prints("teardown", port); diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c index 9a79aeaa10..e2f2c4d356 100644 --- a/common/usbc/usb_pd_dpm.c +++ b/common/usbc/usb_pd_dpm.c @@ -29,11 +29,13 @@ static struct { bool mode_entry_done; + bool mode_exit_request; } dpm[CONFIG_USB_PD_PORT_MAX_COUNT]; void dpm_init(int port) { dpm[port].mode_entry_done = false; + dpm[port].mode_exit_request = false; } void dpm_set_mode_entry_done(int port) @@ -41,6 +43,16 @@ void dpm_set_mode_entry_done(int port) dpm[port].mode_entry_done = true; } +void dpm_set_mode_exit_request(int port) +{ + dpm[port].mode_exit_request = true; +} + +static inline void dpm_clear_mode_exit_request(int port) +{ + dpm[port].mode_exit_request = false; +} + void dpm_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, uint32_t *vdm) { @@ -159,3 +171,46 @@ void dpm_attempt_mode_entry(int port) pe_dpm_request(port, DPM_REQUEST_VDM); } + +void dpm_attempt_mode_exit(int port) +{ + int opos; + uint16_t svid; + uint32_t vdm; + + if (!dpm[port].mode_exit_request) + return; + + /* TODO: Add exit mode support for SOP' and SOP'' */ + + if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + tbt_is_active(port)) + svid = USB_VID_INTEL; + else if (dp_is_active(port)) + svid = USB_SID_DISPLAYPORT; + else { + /* Clear exit mode request */ + dpm_clear_mode_exit_request(port); + return; + } + + opos = pd_alt_mode(port, TCPC_TX_SOP, svid); + if (opos > 0 && pd_dfp_exit_mode(port, TCPC_TX_SOP, svid, opos)) { + /* + * TODO b/159717794: Delay deleting the data until after the + * EXIT_MODE message is has ACKed. Unfortunately the callers + * of this function expect the mode to be cleaned up before + * return. + */ + vdm = VDO(svid, 1, /* Structured */ + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPC_TX_SOP)) | + VDO_OPOS(opos) | VDO_CMDT(CMDT_INIT) | CMD_EXIT_MODE); + + if (!pd_setup_vdm_request(port, TCPC_TX_SOP, &vdm, 1)) { + dpm_clear_mode_exit_request(port); + return; + } + + pe_dpm_request(port, DPM_REQUEST_VDM); + } +} diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 110ef413ed..beffd61d60 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -475,8 +475,6 @@ static struct policy_engine { struct pd_discovery discovery[DISCOVERY_TYPE_COUNT]; /* Active alternate modes */ struct partner_active_modes partner_amodes[AMODE_TYPE_COUNT]; - /* Alternate mode object position */ - int8_t alt_opos; /* Partner type to send */ enum tcpm_transmit_type tx_type; @@ -1076,35 +1074,6 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, task_wake(PD_PORT_TO_TASK_ID(port)); } -/* TODO: Add a common exit routine for all the alternate modes */ -void pe_exit_dp_mode(int port) -{ - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); - - if (opos <= 0) - return; - - /* - * TODO: Delay deleting the data until after the - * the EXIT_MODE message is sent. - * Unfortunately the callers of this function expect - * the mode to be cleaned up before return. - */ - CPRINTS("C%d Exiting DP mode", port); - if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT, - opos)) - return; - - /* - * Save the opos to be used with the message. - * Request a message to be sent to exit the mode. - */ - pe[port].alt_opos = opos; - pe_dpm_request(port, DPM_REQUEST_EXIT_DP_MODE); - } -} - static void pe_handle_detach(void) { const int port = TASK_ID_TO_PD_PORT(task_get_current()); @@ -1192,28 +1161,6 @@ static bool common_src_snk_dpm_requests(int port) PD_T_DISCOVER_IDENTITY; } return true; - } else if (PE_CHK_DPM_REQUEST(port, - DPM_REQUEST_EXIT_DP_MODE)) { - PE_CLR_DPM_REQUEST(port, - DPM_REQUEST_EXIT_DP_MODE); - /* - * Init VDM CMD_EXIT_MODE message. - * alt_opos must be set with the opos to be sent. - * TODO: Convert this to use DPM_REQUEST_VDM. - */ - pe[port].tx_type = TCPC_TX_SOP; - pe[port].vdm_data[0] = VDO( - USB_SID_DISPLAYPORT, - 1, /* structured */ - VDO_SVDM_VERS( - pd_get_vdo_ver(port, TCPC_TX_SOP)) | - VDO_OPOS(pe[port].alt_opos) | - VDO_CMDT(CMDT_INIT) | - CMD_EXIT_MODE); - pe[port].vdm_cnt = 1; - set_state_pe(port, PE_VDM_REQUEST_DPM); - return true; - } else if (PE_CHK_DPM_REQUEST(port, DPM_REQUEST_VDM)) { PE_CLR_DPM_REQUEST(port, DPM_REQUEST_VDM); @@ -2137,6 +2084,14 @@ static void pe_src_ready_run(int port) return; } + /* + * TODO b/155890173: Combine the entry and exit mode requests + * so that there is only a single entry point into DPM. + */ + + /* No DPM requests; attempt mode exit if needed */ + dpm_attempt_mode_exit(port); + /* No DPM requests; attempt mode entry if needed */ dpm_attempt_mode_entry(port); } @@ -2879,6 +2834,13 @@ static void pe_snk_ready_run(int port) return; } + /* + * TODO b/155890173: Combine the entry and exit mode requests + * so that there is only a single entry point into DPM. + */ + /* No DPM requests; attempt mode exit if needed */ + dpm_attempt_mode_exit(port); + /* No DPM requests; attempt mode entry if needed */ dpm_attempt_mode_entry(port); } diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index 5b068fb1f2..b2f137b93e 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -14,6 +14,7 @@ #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_dpm.h" #include "usb_pe_sm.h" #include "usb_prl_sm.h" #include "usb_sm.h" @@ -1432,7 +1433,7 @@ void tc_event_check(int port, int evt) if (evt & PD_EVENT_SYSJUMP) { for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - pe_exit_dp_mode(i); + dpm_set_mode_exit_request(i); notify_sysjump_ready(); } } @@ -1553,10 +1554,10 @@ static void handle_new_power_state(int port) if (chipset_in_or_transitioning_to_state( CHIPSET_STATE_ANY_OFF)) { /* - * The SoC will negotiate DP mode again when it + * The SoC will negotiate alternate mode again when it * boots up */ - pe_exit_dp_mode(port); + dpm_set_mode_exit_request(port); /* * The following function will disconnect both USB and |