diff options
author | Edward Hill <ecgh@chromium.org> | 2018-08-27 19:29:04 -0600 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-09-18 15:38:20 +0000 |
commit | 4a3c3a5f8cb9f0f3d6053893312b7ffb916dbf5a (patch) | |
tree | 7e04ba844f68e6d02064521266837c2de06f46ae | |
parent | b68f118db581cb290364c18d929c839ec46dacb6 (diff) | |
download | chrome-ec-4a3c3a5f8cb9f0f3d6053893312b7ffb916dbf5a.tar.gz |
pd: Add PD_FLAGS_LPM_TRANSITION
Add PD_FLAGS_LPM_TRANSITION and use this to allow the PD task to call
tcpc_read/tcpc_write from tcpm_enter_low_power_mode() and tcpm_init().
BRANCH=none
BUG=b:111663127
TEST=PD and TCPC low power still work on Grunt
Change-Id: I12ddb58667c171068e1be6d136f22f2062959c8c
Signed-off-by: Edward Hill <ecgh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1194351
Reviewed-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1230998
Reviewed-by: Martin Roth <martinroth@chromium.org>
Commit-Queue: Martin Roth <martinroth@chromium.org>
Tested-by: Martin Roth <martinroth@chromium.org>
-rw-r--r-- | common/usb_pd_protocol.c | 37 | ||||
-rw-r--r-- | driver/tcpm/tcpci.c | 5 | ||||
-rw-r--r-- | include/usb_pd.h | 5 |
3 files changed, 21 insertions, 26 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index fdb327e159..d73c941808 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -379,15 +379,15 @@ static void handle_device_access(int port) } } -/* This can be called from any task. */ +/* + * This can be called from any task. If we are in the PD task, we can handle + * immediately. Otherwise, we need to notify the PD task via event. + */ void pd_device_accessed(int port) { - const int current_task = task_get_current(); - - /* If not in the PD TASK that owns data, marshal to that task */ - if (current_task == PD_PORT_TO_TASK_ID(port)) { + if (port == TASK_ID_TO_PD_PORT(task_get_current())) { /* Ignore any access to device while it is waking up */ - if (pd[port].tasks_waiting_on_reset & (1 << current_task)) + if (pd[port].flags & PD_FLAGS_LPM_TRANSITION) return; handle_device_access(port); @@ -399,14 +399,12 @@ void pd_device_accessed(int port) int pd_device_in_low_power(int port) { - const int current_task = task_get_current(); - /* * If we are actively waking the device up in the PD task, do not * let TCPC operation wait or retry because we are in low power mode. */ - if (port == TASK_ID_TO_PD_PORT(current_task) && - pd[port].tasks_waiting_on_reset & (1 << current_task)) + if (port == TASK_ID_TO_PD_PORT(task_get_current()) && + (pd[port].flags & PD_FLAGS_LPM_TRANSITION)) return 0; return pd[port].flags & PD_FLAGS_LPM_ENGAGED; @@ -416,19 +414,14 @@ static int reset_device_and_notify(int port) { int rv; int task, waiting_tasks; - const int current_task_mask = 1 << task_get_current(); /* This should only be called from the PD task */ assert(port == TASK_ID_TO_PD_PORT(task_get_current())); - /* - * Signal that this task is actively waiting for a wake up, which we - * use to skip recursive wake calls within the tcpc_init method and - * prevent pd_access from changing the HW status until we are done. - */ - atomic_or(&pd[port].tasks_waiting_on_reset, current_task_mask); - + pd[port].flags |= PD_FLAGS_LPM_TRANSITION; rv = tcpm_init(port); + pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION; + if (rv == EC_SUCCESS) CPRINTS("TCPC p%d init ready", port); else @@ -445,8 +438,7 @@ static int reset_device_and_notify(int port) /* Clear SW LPM state; the state machine will set it again if needed */ pd[port].flags &= ~PD_FLAGS_LPM_REQUESTED; - /* Wake up all waiting tasks (except this task). */ - waiting_tasks &= ~current_task_mask; + /* Wake up all waiting tasks. */ while (waiting_tasks) { task = __fls(waiting_tasks); waiting_tasks &= ~(1 << task); @@ -458,7 +450,7 @@ static int reset_device_and_notify(int port) void pd_wait_for_wakeup(int port) { - if (task_get_current() == PD_PORT_TO_TASK_ID(port)) { + if (port == TASK_ID_TO_PD_PORT(task_get_current())) { /* If we are in the PD task, we can directly reset */ reset_device_and_notify(port); } else { @@ -2102,6 +2094,7 @@ void pd_set_dual_role(int port, enum pd_dual_role_states state) PD_EVENT_UPDATE_DUAL_ROLE, 0); } +/* This must only be called from the PD task */ static void pd_update_dual_role_config(int port) { /* @@ -3872,7 +3865,9 @@ void pd_task(void *u) pd[port].low_power_time - now.val; if (time_left <= 0) { pd[port].flags |= PD_FLAGS_LPM_ENGAGED; + pd[port].flags |= PD_FLAGS_LPM_TRANSITION; tcpm_enter_low_power_mode(port); + pd[port].flags &= ~PD_FLAGS_LPM_TRANSITION; CPRINTS("TCPC p%d Enter Low Power Mode", port); timeout = -1; } else if (timeout < 0 || timeout > time_left) { diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index c22d995d71..250673b44a 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -274,10 +274,7 @@ int tcpci_tcpc_drp_toggle(int port, int enable) #ifdef CONFIG_USB_PD_TCPC_LOW_POWER int tcpci_enter_low_power_mode(int port) { - /* This uses the raw i2c write to bypass the pd_device_accessed call */ - return i2c_write8(tcpc_config[port].i2c_host_port, - tcpc_config[port].i2c_slave_addr, - TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE); + return tcpc_write(port, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE); } #endif diff --git a/include/usb_pd.h b/include/usb_pd.h index 0bf3b15ffe..29299b8acf 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -724,10 +724,13 @@ enum pd_states { #define PD_FLAGS_TS_DTS_PARTNER (1 << 16)/* partner has rp/rp or rd/rd */ /* * These PD_FLAGS_LPM* flags track the software state (PD_LPM_FLAGS_REQUESTED) - * and hardware state (PD_LPM_FLAGS_ENGAGED) of the TCPC lower power mode. + * and hardware state (PD_LPM_FLAGS_ENGAGED) of the TCPC low power mode. + * PD_FLAGS_LPM_TRANSITION is set while the HW is transitioning into or out of + * low power (when PD_LPM_FLAGS_ENGAGED is changing). */ #define PD_FLAGS_LPM_REQUESTED (1 << 17)/* Tracks SW LPM state */ #define PD_FLAGS_LPM_ENGAGED (1 << 18)/* Tracks HW LPM state */ +#define PD_FLAGS_LPM_TRANSITION (1 << 19)/* Tracks HW LPM transition */ /* Flags to clear on a disconnect */ #define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \ PD_FLAGS_PARTNER_DR_DATA | \ |