summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-12-05 22:40:43 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-07 18:44:31 +0000
commit09ad65d4ad2409223c5778ee2807fb68e27bfc1d (patch)
treec5778efbda54d09f8040437c938c71bf5b4757af
parent140aa369049a616a4d07de1a0f3f4c946b11ac40 (diff)
downloadchrome-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.c22
-rw-r--r--include/usb_pd.h1
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,