summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index a8cd1959c426..2d6b14aa2085 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -7119,16 +7119,32 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
}
}
if (events & TCPM_SOURCING_VBUS) {
- tcpm_log(port, "sourcing vbus");
/*
* In fast role swap case TCPC autonomously sources vbus. Set vbus_source
- * true as TCPM wouldn't have called tcpm_set_vbus.
+ * true conditionally as TCPM wouldn't have called tcpm_set_vbus.
+ * If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
+ * be true.
*
- * When vbus is sourced on the command on TCPM i.e. TCPM called
- * tcpm_set_vbus to source vbus, vbus_source would already be true.
+ * When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
+ * handling TCPM_FRS_EVENT above transitions the state to AMS_START
+ * with upcoming_state FR_SWAP_SEND.
*/
- port->vbus_source = true;
- _tcpm_pd_vbus_on(port);
+
+ if (tcpm_port_is_source(port) ||
+ tcpm_port_is_debug_source(port) ||
+ (port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
+ port->state == FR_SWAP_SEND ||
+ port->state == FR_SWAP_SEND_TIMEOUT ||
+ port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
+ port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
+ port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
+ tcpm_log(port, "sourcing vbus");
+ port->vbus_source = true;
+ _tcpm_pd_vbus_on(port);
+ } else {
+ tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
+ tcpm_states[port->state]);
+ }
}
if (events & TCPM_PORT_CLEAN) {
tcpm_log(port, "port clean");