diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-12-05 22:40:43 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-01-07 18:44:31 +0000 |
commit | 09ad65d4ad2409223c5778ee2807fb68e27bfc1d (patch) | |
tree | c5778efbda54d09f8040437c938c71bf5b4757af | |
parent | 140aa369049a616a4d07de1a0f3f4c946b11ac40 (diff) | |
download | chrome-ec-09ad65d4ad2409223c5778ee2807fb68e27bfc1d.tar.gz |
pd: fix bug when forcing port to sink
When changing a port that is sourcing power to a force sink role,
then make sure VBUS is turned off before going to SNK_DISCONNECTED.
BUG=chrome-os-partner:34036
BRANCH=samus
TEST=test on plankton with samus. verify can change from source to
sink multiple times with no problems
Change-Id: I781f6f4395845f949d00b322e4e87c150aeba187
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/233755
-rw-r--r-- | common/usb_pd_protocol.c | 22 | ||||
-rw-r--r-- | include/usb_pd.h | 1 |
2 files changed, 19 insertions, 4 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index ff3f28d697..225a9c1c8a 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -302,7 +302,7 @@ static const char * const pd_state_names[] = { "SRC_TRANSITION", "SRC_READY", "SRC_GET_SNK_CAP", "SRC_DR_SWAP", #ifdef CONFIG_USB_PD_DUAL_ROLE "SRC_SWAP_INIT", "SRC_SWAP_SNK_DISABLE", "SRC_SWAP_SRC_DISABLE", - "SRC_SWAP_STANDBY", + "SRC_SWAP_STANDBY", "SRC_TO_FORCE_SINK", #endif /* CONFIG_USB_PD_DUAL_ROLE */ "SOFT_RESET", "HARD_RESET_SEND", "HARD_RESET_EXECUTE", "BIST", }; @@ -1516,9 +1516,7 @@ void pd_set_dual_role(enum pd_dual_role_states state) (drp_state == PD_DRP_FORCE_SINK || (drp_state == PD_DRP_TOGGLE_OFF && pd[i].task_state == PD_STATE_SRC_DISCONNECTED))) { - pd[i].power_role = PD_ROLE_SINK; - set_state(i, PD_STATE_SNK_DISCONNECTED); - pd_set_host_mode(i, 0); + set_state(i, PD_STATE_SRC_TO_FORCE_SINK); task_wake(PORT_TO_TASK_ID(i)); } @@ -2064,6 +2062,22 @@ void pd_task(void) PD_STATE_SNK_DISCONNECTED); } break; + case PD_STATE_SRC_TO_FORCE_SINK: + /* + * Transition from Source to force sink role. Disable + * VBUS and wait for VBUS to turn off + */ + if (pd[port].last_state != pd[port].task_state) + pd_power_supply_reset(port); + + if (pd_snk_is_vbus_provided(port)) { + /* When VBUS is off, go to SNK_DISCONNECTED */ + pd_set_host_mode(port, 0); + pd[port].power_role = PD_ROLE_SINK; + set_state(port, PD_STATE_SNK_DISCONNECTED); + timeout = 10*MSEC; + } + break; case PD_STATE_SUSPENDED: pd_rx_disable_monitoring(port); pd_hw_release(port); diff --git a/include/usb_pd.h b/include/usb_pd.h index 0f080c24e0..b43d78464c 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -595,6 +595,7 @@ enum pd_states { PD_STATE_SRC_SWAP_SNK_DISABLE, PD_STATE_SRC_SWAP_SRC_DISABLE, PD_STATE_SRC_SWAP_STANDBY, + PD_STATE_SRC_TO_FORCE_SINK, #endif /* CONFIG_USB_PD_DUAL_ROLE */ PD_STATE_SOFT_RESET, |