diff options
author | Alec Berg <alecaberg@chromium.org> | 2015-10-20 15:37:11 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-10-22 17:40:31 -0700 |
commit | 7e81bebb48274055ace613796b9d1ede45c8c9d7 (patch) | |
tree | 2a02ef3b96049225f30369e82b2f2b9f007eda20 /common/usb_pd_protocol.c | |
parent | 0f4e6d217d930c6f3b849f232b1260aed099f260 (diff) | |
download | chrome-ec-7e81bebb48274055ace613796b9d1ede45c8c9d7.tar.gz |
tcpc: re-initialize tcpc if it reboots while tcpm is running
On TCPC startup, set an alert to notify TCPM that we have been
reset. When TCPM gets this notification, it should re-send
initial TCPC parameters. If we were in a stable contract as
a sink, make sure we don't reset connection. If not, then
reset PD protocol state machine to the default state.
This fixes a bug where if the TCPC reboots while the TCPM is
still running, then the TCPC would not get re-initialized and
therefore no PD communication would not work. This also fixes
it such that if we are in a stable contract as a sink and the
TCPC reboots, then we don't lose power.
BUG=chrome-os-partner:46676
BRANCH=none
TEST=tested on glados. reboot PD MCU with and without a charger
plugged in and verify that PD communication works after the
reboot. verify that with a charger, we don't lose power.
also tested with a hoho plugged in during reboot.
Change-Id: I84fec4577b0daf5891bd8461d3f3d925014a5ecf
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/307187
Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'common/usb_pd_protocol.c')
-rw-r--r-- | common/usb_pd_protocol.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 9ddccb80c4..8154d9ecee 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -285,6 +285,10 @@ static inline void set_state(int port, enum pd_states next_state) #else /* CONFIG_USB_PD_DUAL_ROLE */ if (next_state == PD_STATE_SRC_DISCONNECTED) { #endif + /* If we are source, make sure VBUS is off */ + if (pd[port].power_role == PD_ROLE_SOURCE) + pd_power_supply_reset(port); + pd[port].dev_id = 0; pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK; #ifdef CONFIG_CHARGE_MANAGER @@ -1406,9 +1410,11 @@ void pd_task(void) /* Ensure the power supply is in the default state */ pd_power_supply_reset(port); +#ifdef CONFIG_USB_PD_TCPC /* Initialize TCPM driver and wait for TCPC to be ready */ tcpm_init(port); CPRINTF("[%T TCPC p%d ready]\n", port); +#endif /* Disable TCPC RX until connection is established */ tcpm_set_rx_enable(port, 0); @@ -1460,6 +1466,36 @@ void pd_task(void) * messages */ tcpc_run(port, evt); +#else + /* if TCPC has reset, then need to initialize it again */ + if (evt & PD_EVENT_TCPC_RESET) { + CPRINTF("[%T TCPC p%d reset!]\n", port); + tcpm_init(port); + + /* Ensure CC termination is default */ + tcpm_set_cc(port, PD_ROLE_DEFAULT == PD_ROLE_SOURCE ? + TYPEC_CC_RP : + TYPEC_CC_RD); + + /* + * If we have a stable contract in the default role, + * then simply update TCPC with some missing info + * so that we can continue without resetting PD comms. + * Otherwise, go to the default disconnected state + * and force renegotiation. + */ + if ((PD_ROLE_DEFAULT == PD_ROLE_SINK && + pd[port].task_state == PD_STATE_SNK_READY) || + (PD_ROLE_DEFAULT == PD_ROLE_SOURCE && + pd[port].task_state == PD_STATE_SRC_READY)) { + tcpm_set_polarity(port, pd[port].polarity); + tcpm_set_msg_header(port, pd[port].power_role, + pd[port].data_role); + tcpm_set_rx_enable(port, 1); + } else { + set_state(port, PD_DEFAULT_STATE); + } + } #endif /* process any potential incoming message */ @@ -1538,10 +1574,6 @@ void pd_task(void) new_cc_state = PD_CC_AUDIO_ACC; } else { /* No UFP */ -#ifdef CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP - /* No connection any more, remove VBUS */ - pd_power_supply_reset(port); -#endif set_state(port, PD_STATE_SRC_DISCONNECTED); timeout = 5*MSEC; break; @@ -1761,7 +1793,6 @@ void pd_task(void) set_state(port, PD_STATE_SRC_READY); } else { /* The sink did not ack, cut the power... */ - pd_power_supply_reset(port); set_state(port, PD_STATE_SRC_DISCONNECTED); } break; @@ -2510,7 +2541,6 @@ void pd_task(void) if (pd[port].polarity) cc1 = cc2; if (cc1 == TYPEC_CC_VOLT_OPEN) { - pd_power_supply_reset(port); set_state(port, PD_STATE_SRC_DISCONNECTED); /* Debouncing */ timeout = 10*MSEC; |