summaryrefslogtreecommitdiff
path: root/common/usb_pd_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usb_pd_protocol.c')
-rw-r--r--common/usb_pd_protocol.c61
1 files changed, 44 insertions, 17 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 7d9ade5e2c..8ca0bbb6fc 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -94,13 +94,13 @@ static const int debug_level;
#define PD_SNK_CAP_RETRIES 3
/*
- * The time that we allow the source to send any messages after an explicit
- * contract is established. 200ms was chosen somewhat arbitrarily as it should
- * be long enough for sources to decide to send a message if they were going to,
- * but not so long that a "low power charger connected" notification would be
- * shown in the chrome OS UI.
+ * The time that we allow the port partner to send any messages after an
+ * explicit contract is established. 200ms was chosen somewhat arbitrarily as
+ * it should be long enough for sources to decide to send a message if they were
+ * going to, but not so long that a "low power charger connected" notification
+ * would be shown in the chrome OS UI.
*/
-#define SNK_READY_HOLD_OFF_US (200 * MSEC)
+#define READY_HOLD_OFF_US (200 * MSEC)
enum vdm_states {
VDM_STATE_ERR_BUSY = -3,
@@ -243,12 +243,12 @@ static struct pd_protocol {
uint8_t rev;
#endif
/*
- * Time at which the port acting as a sink can start to request for
- * higher power and interrogate the port partner. Some port partners
- * are really chatty after the initial request so we allow this time for
- * the port partner to send any messages in order to avoid a collision.
+ * Some port partners are really chatty after an explicit contract is
+ * established. Therefore, we allow this time for the port partner to
+ * send any messages in order to avoid a collision of sending messages
+ * of our own.
*/
- uint64_t snk_ready_holdoff_timer;
+ uint64_t ready_state_holdoff_timer;
} pd[CONFIG_USB_PD_PORT_COUNT];
#ifdef CONFIG_COMMON_RUNTIME
@@ -692,8 +692,8 @@ static inline void set_state(int port, enum pd_states next_state)
ppc_clear_oc_event_counter(port);
}
#endif /* CONFIG_USBC_PPC */
- /* Clear the SNK_READY holdoff timer. */
- pd[port].snk_ready_holdoff_timer = 0;
+ /* Clear the holdoff timer since the port is disconnected. */
+ pd[port].ready_state_holdoff_timer = 0;
/*
* We should not clear any flags when transitioning back to the
@@ -1717,11 +1717,14 @@ static void handle_ctrl_request(int port, uint16_t head,
} else if (pd[port].power_role == PD_ROLE_SINK) {
/*
* Give the source some time to send any messages before
- * we start our interrogation.
+ * we start our interrogation. Add some jitter of up to
+ * 100ms, taken from the current system time, to prevent
+ * multiple collisions.
*/
if (pd[port].task_state == PD_STATE_SNK_TRANSITION)
- pd[port].snk_ready_holdoff_timer =
- get_time().val + SNK_READY_HOLD_OFF_US;
+ pd[port].ready_state_holdoff_timer =
+ get_time().val + READY_HOLD_OFF_US
+ + (get_time().le.lo % (100 * MSEC));
set_state(port, PD_STATE_SNK_READY);
pd_set_input_current_limit(port, pd[port].curr_limit,
@@ -3281,6 +3284,18 @@ void pd_task(void *u)
res = send_control(port, PD_CTRL_PS_RDY);
if (res >= 0) {
timeout = 10*MSEC;
+
+ /*
+ * Give the sink some time to send any messages
+ * before we may send messages of our own. Add
+ * some jitter of up to 100ms, taken from the
+ * current system time, to prevent multiple
+ * collisions.
+ */
+ pd[port].ready_state_holdoff_timer =
+ get_time().val + READY_HOLD_OFF_US
+ + (get_time().le.lo % (100 * MSEC));
+
/* it'a time to ping regularly the sink */
set_state(port, PD_STATE_SRC_READY);
} else {
@@ -3292,6 +3307,17 @@ void pd_task(void *u)
timeout = PD_T_SOURCE_ACTIVITY;
/*
+ * Don't send any traffic yet until our holdoff timer
+ * has expired. Some devices are chatty once we reach
+ * the SRC_READY state and we may end up in a collision
+ * of messages if we try to immediately send our
+ * interrogations.
+ */
+ if (get_time().val <=
+ pd[port].ready_state_holdoff_timer)
+ break;
+
+ /*
* Don't send any PD traffic if we woke up due to
* incoming packet or if VDO response pending to avoid
* collisions.
@@ -3791,7 +3817,8 @@ void pd_task(void *u)
* of messages if we try to immediately send our
* interrogations.
*/
- if (get_time().val <= pd[port].snk_ready_holdoff_timer)
+ if (get_time().val <=
+ pd[port].ready_state_holdoff_timer)
break;
/*