summaryrefslogtreecommitdiff
path: root/common/usbc
diff options
context:
space:
mode:
authorAyushee <ayushee.shah@intel.com>2020-06-26 12:14:25 -0700
committerCommit Bot <commit-bot@chromium.org>2020-07-17 02:57:09 +0000
commit5270ea2b0cfc2ce699281c2e59ffce3546551d7e (patch)
tree04015789df81cfe1c8559a5d300ca80789ce0d58 /common/usbc
parent51cf32c16205af580dc1475ddf2c5731e199a133 (diff)
downloadchrome-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.c5
-rw-r--r--common/usbc/tbt_alt_mode.c5
-rw-r--r--common/usbc/usb_pd_dpm.c55
-rw-r--r--common/usbc/usb_pe_drp_sm.c68
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c7
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