summaryrefslogtreecommitdiff
path: root/common/usbc/tbt_alt_mode.c
diff options
context:
space:
mode:
authorAyushee <ayushee.shah@intel.com>2020-10-08 16:28:35 -0700
committerCommit Bot <commit-bot@chromium.org>2020-10-14 20:33:10 +0000
commit913b68e8e43d5700e3432148b33428e1e1ce0d79 (patch)
tree425c5caf498b167ac1b8c0cf9cf57c21c18d4633 /common/usbc/tbt_alt_mode.c
parentc7c8840bae1d3e833655a2b09b6deb5a47db680b (diff)
downloadchrome-ec-913b68e8e43d5700e3432148b33428e1e1ce0d79.tar.gz
TBT:Add support for exit mode SOP'/SOP'' on chipset transition
When chipset is transitioning to a new state or on sysjump, the EC re-negotiates to enter an alternate mode on booting up. This commit adds support for exiting Thunderbolt mode for SOP' and SOP'' for active cable on chipset transition and also moves all the alternate mode exit rotines to their respective files. It also delays deleting the SVID data until after the EXIT_MODE message has ACKed and avoids pd_dfp_exit_mode() from changing the alternate mode's internal states. This commit also makes sure that the mux is set to safe state before exiting the alternate mode and it is reconfigured according to the port's current data role on receiving ACK/NAK from the cable/port partner. BUG=b:151169925, b:159717794 BRANCH=none TEST=On reboot, able to exit and re-enter into DisplayPort mode, Thunderbolt mode with passive cable and thunderbolt mode with active cable. Change-Id: If1e48e9f31cd678e23fe89bd3494551b5d1a78f1 Signed-off-by: Ayushee <ayushee.shah@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2415082 Reviewed-by: Abe Levkoy <alevkoy@chromium.org> Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'common/usbc/tbt_alt_mode.c')
-rw-r--r--common/usbc/tbt_alt_mode.c76
1 files changed, 54 insertions, 22 deletions
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c
index 619d8a5b2e..4e65e7eff7 100644
--- a/common/usbc/tbt_alt_mode.c
+++ b/common/usbc/tbt_alt_mode.c
@@ -13,6 +13,7 @@
#include "compile_time_macros.h"
#include "console.h"
#include "tcpm.h"
+#include "usb_common.h"
#include "usb_mux.h"
#include "usb_pd.h"
#include "usb_pd_dpm.h"
@@ -68,7 +69,9 @@
* with a partner. It may be fixed in b/159495742, in which case this
* logic is unneeded.
*/
+/* TODO:b/169169804 :Add entry, exit and retry flags for individual port */
static bool retry_done;
+static bool exit_request;
static int tbt_prints(const char *string, int port)
{
@@ -110,24 +113,30 @@ void tbt_init(int port)
bool tbt_is_active(int port)
{
- return tbt_state[port] == TBT_ACTIVE;
+ return tbt_state[port] != TBT_INACTIVE &&
+ tbt_state[port] != TBT_START;
}
-void tbt_teardown(int port)
+static void tbt_exit_done(int port)
{
- tbt_prints("teardown", port);
- tbt_state[port] = TBT_INACTIVE;
- retry_done = false;
-}
-
-static void tbt_entry_failed(int port)
-{
- tbt_prints("alt mode protocol failed!", port);
tbt_state[port] = TBT_INACTIVE;
+
+ if (exit_request) {
+ tbt_prints("Exited alternate mode", port);
+ return;
+ }
+
retry_done = false;
+ tbt_prints("alt mode protocol failed!", port);
dpm_set_mode_entry_done(port);
}
+void tbt_exit_mode_request(void)
+{
+ retry_done = true;
+ exit_request = true;
+}
+
static bool tbt_response_valid(int port, enum tcpm_transmit_type type,
char *cmdt, int vdm_cmd)
{
@@ -142,7 +151,7 @@ static bool tbt_response_valid(int port, enum tcpm_transmit_type type,
if ((st != TBT_INACTIVE && state_vdm_cmd[st] != vdm_cmd) ||
(get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE &&
type != TCPC_TX_SOP)) {
- tbt_entry_failed(port);
+ tbt_exit_done(port);
return false;
}
return true;
@@ -173,6 +182,7 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count,
{
struct pd_discovery *disc;
const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]);
+ int opos_sop, opos_sop_prime;
if (!tbt_response_valid(port, type, "ACK", vdm_cmd))
return;
@@ -197,38 +207,53 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count,
tbt_prints("enter mode SOP", port);
break;
case TBT_ACTIVE:
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
+ tbt_prints("exit mode SOP", port);
+ opos_sop = pd_alt_mode(port, TCPC_TX_SOP, USB_VID_INTEL);
+
+ /* Clear Thunderbolt related signals */
+ pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_VID_INTEL, opos_sop);
+ set_usb_mux_with_current_data_role(port);
+ if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) {
tbt_active_cable_exit_mode(port);
- else {
+ } else {
/*
* Exit Mode process is complete; go to inactive state.
*/
- tbt_prints("exit mode SOP", port);
- tbt_state[port] = TBT_INACTIVE;
retry_done = false;
}
break;
case TBT_EXIT_SOP:
+ set_usb_mux_with_current_data_role(port);
if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
tbt_active_cable_exit_mode(port);
else {
if (retry_done)
/* retried enter mode, still failed, give up */
- tbt_entry_failed(port);
+ tbt_exit_done(port);
else
tbt_retry_enter_mode(port);
}
break;
case TBT_EXIT_SOP_PRIME_PRIME:
+ tbt_prints("exit mode SOP''", port);
tbt_state[port] = TBT_EXIT_SOP_PRIME;
+ set_usb_mux_with_current_data_role(port);
break;
case TBT_EXIT_SOP_PRIME:
+ tbt_prints("exit mode SOP'", port);
if (retry_done) {
/*
* Exit mode process is complete; go to inactive state.
*/
- tbt_prints("exit mode SOP'", port);
- tbt_entry_failed(port);
+ tbt_exit_done(port);
+ opos_sop_prime =
+ pd_alt_mode(port, TCPC_TX_SOP_PRIME,
+ USB_VID_INTEL);
+
+ /* Clear Thunderbolt related signals */
+ pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, USB_VID_INTEL,
+ opos_sop_prime);
+ set_usb_mux_with_current_data_role(port);
} else {
tbt_retry_enter_mode(port);
}
@@ -244,7 +269,7 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count,
/* Invalid or unexpected negotiation state */
CPRINTF("%s called with invalid state %d\n",
__func__, tbt_state[port]);
- tbt_entry_failed(port);
+ tbt_exit_done(port);
break;
}
}
@@ -268,6 +293,7 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd)
break;
case TBT_ACTIVE:
/* Exit SOP got NAK'ed */
+ set_usb_mux_with_current_data_role(port);
if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
tbt_active_cable_exit_mode(port);
else {
@@ -278,27 +304,30 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd)
break;
case TBT_EXIT_SOP:
/* Exit SOP got NAK'ed */
+ set_usb_mux_with_current_data_role(port);
if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
tbt_active_cable_exit_mode(port);
else {
if (retry_done)
/* Retried enter mode, still failed, give up */
- tbt_entry_failed(port);
+ tbt_exit_done(port);
else
tbt_retry_enter_mode(port);
}
break;
case TBT_EXIT_SOP_PRIME_PRIME:
+ set_usb_mux_with_current_data_role(port);
tbt_prints("exit mode SOP'' failed", port);
tbt_state[port] = TBT_EXIT_SOP_PRIME;
break;
case TBT_EXIT_SOP_PRIME:
+ set_usb_mux_with_current_data_role(port);
if (retry_done) {
/*
* Exit mode process is complete; go to inactive state.
*/
tbt_prints("exit mode SOP' failed", port);
- tbt_entry_failed(port);
+ tbt_exit_done(port);
} else {
tbt_retry_enter_mode(port);
}
@@ -306,7 +335,7 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd)
default:
CPRINTS("C%d: NAK for cmd %d in state %d", port,
vdm_cmd, tbt_state[port]);
- tbt_entry_failed(port);
+ tbt_exit_done(port);
break;
}
}
@@ -398,6 +427,7 @@ int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm,
if (!(modep && modep->opos))
return -1;
+ usb_mux_set_safe_mode(port);
vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
VDO_OPOS(modep->opos) |
VDO_CMDT(CMDT_INIT) |
@@ -411,6 +441,7 @@ int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm,
if (!(modep && modep->opos))
return -1;
+ usb_mux_set_safe_mode(port);
vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
VDO_OPOS(modep->opos) |
VDO_CMDT(CMDT_INIT) |
@@ -425,6 +456,7 @@ int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm,
if (!(modep && modep->opos))
return -1;
+ usb_mux_set_safe_mode(port);
vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) |
VDO_OPOS(modep->opos) |
VDO_CMDT(CMDT_INIT) |