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 | |
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>
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 5 | ||||
-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 | ||||
-rw-r--r-- | include/usb_dp_alt_mode.h | 9 | ||||
-rw-r--r-- | include/usb_pd_dpm.h | 14 | ||||
-rw-r--r-- | include/usb_pe_sm.h | 28 | ||||
-rw-r--r-- | include/usb_tbt_alt_mode.h | 9 | ||||
-rw-r--r-- | test/fake_usbc.c | 8 |
11 files changed, 139 insertions, 74 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c index dde6b771c9..8de23095d5 100644 --- a/common/usb_pd_alt_mode_dfp.c +++ b/common/usb_pd_alt_mode_dfp.c @@ -15,6 +15,7 @@ #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_tcpm.h" +#include "usb_tbt_alt_mode.h" #include "usbc_ppc.h" #include "util.h" @@ -1248,6 +1249,10 @@ __overridable int svdm_tbt_compat_enter_mode(int port, uint32_t mode_caps) __overridable void svdm_tbt_compat_exit_mode(int port) { + if (IS_ENABLED(CONFIG_USB_PD_TCPMV2)) { + usb_mux_set_safe_mode(port); + tbt_teardown(port); + } } __overridable int svdm_tbt_compat_status(int port, uint32_t *payload) 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 diff --git a/include/usb_dp_alt_mode.h b/include/usb_dp_alt_mode.h index 5fa703e109..4aceecd4ec 100644 --- a/include/usb_dp_alt_mode.h +++ b/include/usb_dp_alt_mode.h @@ -24,6 +24,15 @@ void dp_init(int port); /* + * Returns True if DisplayPort mode is in active state + * + * @param port USB-C port number + * @return True if DisplayPort mode is in active state + * False otherwise + */ +bool dp_is_active(int port); + +/* * Handles received DisplayPort VDM ACKs. * * @param port USB-C port number diff --git a/include/usb_pd_dpm.h b/include/usb_pd_dpm.h index 22fb2d71bd..d431256e18 100644 --- a/include/usb_pd_dpm.h +++ b/include/usb_pd_dpm.h @@ -27,6 +27,13 @@ void dpm_init(int port); void dpm_set_mode_entry_done(int port); /* + * Informs the DPM that Exit Mode request is received + * + * @param port USB-C port number + */ +void dpm_set_mode_exit_request(int port); + +/* * Informs the DPM that a VDM ACK was received. * * @param port USB-C port number @@ -59,4 +66,11 @@ void dpm_vdm_naked(int port, enum tcpm_transmit_type type, uint16_t svid, */ void dpm_attempt_mode_entry(int port); +/* + * Drives the Policy Engine through exit mode process for each active mode + * + * @param port USB-C port number + */ +void dpm_attempt_mode_exit(int port); + #endif /* __CROS_EC_USB_DPM_H */ diff --git a/include/usb_pe_sm.h b/include/usb_pe_sm.h index 1da649b865..511bf263b5 100644 --- a/include/usb_pe_sm.h +++ b/include/usb_pe_sm.h @@ -33,17 +33,16 @@ enum pe_dpm_request { DPM_REQUEST_SEND_PING = BIT(6), DPM_REQUEST_SOURCE_CAP = BIT(7), DPM_REQUEST_NEW_POWER_LEVEL = BIT(8), - DPM_REQUEST_EXIT_DP_MODE = BIT(9), - DPM_REQUEST_VDM = BIT(10), - DPM_REQUEST_BIST_RX = BIT(11), - DPM_REQUEST_BIST_TX = BIT(12), - DPM_REQUEST_SNK_STARTUP = BIT(13), - DPM_REQUEST_SRC_STARTUP = BIT(14), - DPM_REQUEST_HARD_RESET_SEND = BIT(15), - DPM_REQUEST_SOFT_RESET_SEND = BIT(16), - DPM_REQUEST_PORT_DISCOVERY = BIT(17), - DPM_REQUEST_SEND_ALERT = BIT(18), - DPM_REQUEST_ENTER_USB = BIT(19), + DPM_REQUEST_VDM = BIT(9), + DPM_REQUEST_BIST_RX = BIT(10), + DPM_REQUEST_BIST_TX = BIT(11), + DPM_REQUEST_SNK_STARTUP = BIT(12), + DPM_REQUEST_SRC_STARTUP = BIT(13), + DPM_REQUEST_HARD_RESET_SEND = BIT(14), + DPM_REQUEST_SOFT_RESET_SEND = BIT(15), + DPM_REQUEST_PORT_DISCOVERY = BIT(16), + DPM_REQUEST_SEND_ALERT = BIT(17), + DPM_REQUEST_ENTER_USB = BIT(18), }; /** @@ -115,13 +114,6 @@ void pe_got_soft_reset(int port); void pe_hard_reset_sent(int port); /** - * Exit DP mode - * - * @param port USB-C port number - */ -void pe_exit_dp_mode(int port); - -/** * Get the id of the current Policy Engine state * * @param port USB-C port number diff --git a/include/usb_tbt_alt_mode.h b/include/usb_tbt_alt_mode.h index 186c2f8139..c46c471035 100644 --- a/include/usb_tbt_alt_mode.h +++ b/include/usb_tbt_alt_mode.h @@ -23,6 +23,15 @@ void tbt_init(int port); /* + * Returns True if Thunderbolt mode is in active state + * + * @param port USB-C port number + * @return True if Thunderbolt mode is in active state + * False otherwise + */ +bool tbt_is_active(int port); + +/* * Handles received Thunderbolt VDM ACKs. * * @param port USB-C port number diff --git a/test/fake_usbc.c b/test/fake_usbc.c index 7536fa5e97..37d1c0bf09 100644 --- a/test/fake_usbc.c +++ b/test/fake_usbc.c @@ -266,10 +266,18 @@ void dpm_set_mode_entry_done(int port) { } +void dpm_set_mode_exit_request(int port) +{ +} + void dpm_attempt_mode_entry(int port) { } +void dpm_attempt_mode_exit(int port) +{ +} + static enum tcpc_rp_value lcl_rp; __overridable void typec_select_src_current_limit_rp(int port, enum tcpc_rp_value rp) |