summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2018-05-01 10:58:14 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-14 23:56:58 -0700
commitf11169fa8d1ec6f6982306727f0bf0c8a7bd410b (patch)
tree4890f1f0579b263592ec52915a363ed9b7f90d7f
parent163263c9a3eedacff191b50a9da55fd1454fcc86 (diff)
downloadchrome-ec-f11169fa8d1ec6f6982306727f0bf0c8a7bd410b.tar.gz
tcpci: Adjust pd task event/wake when processing alerts
Processing of TCPC alerts takes place in the PDCMD task and the result of processing alerts is to wake the PD task. When the PD task runs, it's possible that it may attempt to put the TCPC into low power mode prior to the remainder of the alert processing function completing. So there may be pending TCPC accesses in the alert handler function which called subsequent to the PD task putting the TCPC into low power mode. The TCPC access in the PDCMD task will cause the TCPC to exit low power mode. With the ANX7447 TCPC, this process will repeat indefinitely. This CL replaces the calls to task_set_event and task_wake with indications stored in a local variable. Then at the end of the function the task_set_event is made if necessary. This change in order removes one guaranteed source of pending TCPC accesses from causing the TCPC to exit low power mode. BRANCH=none BUG=b:77544959 TEST=Was using Salea logic analyzer and testing in conjunction with low power mode. Verified that prior to this change I2C accesses were attempted and NAKd after the command I2CIDLE was sent on the bus. Also tested basic type C operation as both SNK/SRC. Change-Id: I8879c655a48a2b16e0445522497002482dc9ca33 Signed-off-by: Scott Collyer <scollyer@google.com> Reviewed-on: https://chromium-review.googlesource.com/1044868 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--driver/tcpm/tcpci.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 76d01adeae..d4518ae608 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -309,6 +309,7 @@ static int register_mask_reset(int port)
void tcpci_tcpc_alert(int port)
{
int status;
+ uint32_t pd_event = 0;
/* Read the Alert register from the TCPC */
tcpm_alert_status(port, &status);
@@ -317,8 +318,7 @@ void tcpci_tcpc_alert(int port)
* so, perform tcpc_init inline.
*/
if (register_mask_reset(port))
- task_set_event(PD_PORT_TO_TASK_ID(port),
- PD_EVENT_TCPC_RESET, 0);
+ pd_event |= PD_EVENT_TCPC_RESET;
/*
* Clear alert status for everything except RX_STATUS, which shouldn't
@@ -330,7 +330,7 @@ void tcpci_tcpc_alert(int port)
if (status & TCPC_REG_ALERT_CC_STATUS) {
/* CC status changed, wake task */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
+ pd_event |= PD_EVENT_CC;
}
if (status & TCPC_REG_ALERT_POWER_STATUS) {
int reg = 0;
@@ -342,17 +342,17 @@ void tcpci_tcpc_alert(int port)
#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
/* Update charge manager with new VBUS state */
usb_charger_vbus_change(port, tcpc_vbus[port]);
- task_wake(PD_PORT_TO_TASK_ID(port));
+ pd_event |= TASK_EVENT_WAKE;
#endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC && CONFIG_USB_CHARGER */
}
if (status & TCPC_REG_ALERT_RX_STATUS) {
/* message received */
- task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0);
+ pd_event |= PD_EVENT_RX;
}
if (status & TCPC_REG_ALERT_RX_HARD_RST) {
/* hard reset received */
pd_execute_hard_reset(port);
- task_wake(PD_PORT_TO_TASK_ID(port));
+ pd_event |= TASK_EVENT_WAKE;
}
if (status & TCPC_REG_ALERT_TX_COMPLETE) {
/* transmit complete */
@@ -360,6 +360,16 @@ void tcpci_tcpc_alert(int port)
TCPC_TX_COMPLETE_SUCCESS :
TCPC_TX_COMPLETE_FAILED);
}
+
+ /*
+ * Wait until all possible TCPC accesses in this function are complete
+ * prior to setting events and/or waking the pd task. When the PD
+ * task is woken and runs (which will happen during I2C transactions in
+ * this function), the pd task may put the TCPC into low power mode and
+ * the next I2C transaction to the TCPC will cause it to wake again.
+ */
+ if (pd_event)
+ task_set_event(PD_PORT_TO_TASK_ID(port), pd_event, 0);
}
/*