diff options
author | Edward Hill <ecgh@chromium.org> | 2018-08-27 19:55:46 -0600 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-09-18 17:19:56 +0000 |
commit | 6836d4a0c832bd6e709f2f6868bfe50359ed076b (patch) | |
tree | b6e99555c254eec90368b1cfec72a018665affb7 | |
parent | 3e4d7ecbf0b548f2e3228e3429e256f02284a1dd (diff) | |
download | chrome-ec-6836d4a0c832bd6e709f2f6868bfe50359ed076b.tar.gz |
pd: Don't auto toggle when DRP state is not dual role.
When in PD_STATE_DRP_AUTO_TOGGLE, we were always enabling DRP
auto-toggle, even when drp_state is PD_DRP_TOGGLE_OFF or
PD_DRP_FORCE_SINK, which prevents us from acting as source.
This caused an infinite loop of entering and exiting low power
mode when a sink-only device was plugged into a PS8751 port when
the system is in S5/G3.
To fix this, only enable DRP auto-toggle when drp_state allows
us to be dual-role.
One problem with doing this is that the ANX3429 doesn't support
low power mode with auto-toggle disabled. Luckily, the ANX3429
will stay in low power mode when a sink-only device is connected.
BRANCH=none
BUG=b:72007056,b:111663127
TEST=sink device + ANX3429: low power mode [1]
TEST=sink device + PS8751: low power mode [1]
TEST=charger via hub + ANX3429: 50% chance fail to charge [2]
TEST=charger via hub + PS8751: starts charging
(all tests with Grunt in G3)
[1] dut-control pp3300_tcpc_mw -> 3.5
[2] b/72007056 still remains to be fixed.
Change-Id: Id190a3daa78847871288e66d8f229a485a6522e3
Signed-off-by: Edward Hill <ecgh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1194352
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1231362
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 | 9 | ||||
-rw-r--r-- | driver/tcpm/anx74xx.c | 59 |
2 files changed, 29 insertions, 39 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 1a13b4d710..ed7b73cfd0 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -3829,7 +3829,14 @@ void pd_task(void *u) pd_set_power_role(port, PD_ROLE_SOURCE); timeout = 2*MSEC; } else { - tcpm_enable_drp_toggle(port); + /* + * Staying in PD_STATE_DRP_AUTO_TOGGLE, + * always enter low power mode, and auto-toggle + * while in low power mode if drp_state allows + * us to be dual role. + */ + if (drp_state[port] == PD_DRP_TOGGLE_ON) + tcpm_enable_drp_toggle(port); pd[port].flags |= PD_FLAGS_LPM_REQUESTED; pd[port].flags |= PD_FLAGS_TCPC_DRP_TOGGLE; timeout = -1; diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c index cdbf14b644..f9a4b09089 100644 --- a/driver/tcpm/anx74xx.c +++ b/driver/tcpm/anx74xx.c @@ -145,27 +145,36 @@ static void anx74xx_set_power_mode(int port, int mode) /* Update cable cable det signal */ anx74xx_update_cable_det(port, mode); /* - * The final piece of entering low power mode is setting the - * RESET_L signal low, which is done via - * anx74xx_enter_low_power_mode which is called at least 10ms - * after setting cable_det low (above). + * Delay between setting cable_det low and setting RESET_L low + * as recommended the ANX3429 datasheet. */ + msleep(1); + /* Put chip into standby mode */ + board_set_tcpc_power_mode(port, mode); } } -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER -static int anx74xx_enter_low_power_mode(int port) +#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ + defined(CONFIG_USB_PD_TCPC_LOW_POWER) + +static int anx74xx_tcpc_drp_toggle(int port) { /* - * The delay between setting cable_det low (in anx74xx_set_power_mode) - * and setting RESET_L low in (board_set_tcpc_power_mode) is at least - * 1 ms. This should be taken care of by the PD_LM_DEBOUCE_US delay of - * 10ms, but we want to protect against any future tweaks of that value. + * The ANX3429 always auto-toggles when in low power mode. Since this is + * not configurable, there is nothing to do here. DRP auto-toggle will + * happen once low power mode is set via anx74xx_enter_low_power_mode(). + * Note: this means the ANX3429 auto-toggles in PD_DRP_FORCE_SINK mode, + * which is undesirable (b/72007056). */ - msleep(1); - board_set_tcpc_power_mode(port, ANX74XX_STANDBY_MODE); return EC_SUCCESS; } + +static int anx74xx_enter_low_power_mode(int port) +{ + anx74xx_set_power_mode(port, ANX74XX_STANDBY_MODE); + return EC_SUCCESS; +} + #endif void anx74xx_tcpc_set_vbus(int port, int enable) @@ -714,30 +723,6 @@ static int anx74xx_tcpm_set_cc(int port, int pull) return rv; } -#if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ - defined(CONFIG_USB_PD_TCPC_LOW_POWER) -static void anx74xx_handle_power_mode(int port, int mode) -{ - if (mode == ANX74XX_STANDBY_MODE) { - anx74xx_set_power_mode(port, mode); - } else if (anx[port].prev_mode != ANX74XX_NORMAL_MODE) { - /* - * TODO: Interrupt high follows CC line hence ignore multiple - * interrupts. - */ - anx74xx_tcpm_init(port); - } -} - -static int anx74xx_tcpc_drp_toggle(int port) -{ - /* DRP auto-toggle happens when the ANX3429 is in standby mode. */ - anx74xx_handle_power_mode(port, ANX74XX_STANDBY_MODE); - - return EC_SUCCESS; -} -#endif /* CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE && CONFIG_USB_PD_TCPC_LOW_POWER */ - static int anx74xx_tcpm_set_polarity(int port, int polarity) { int reg, mux_state, rv = EC_SUCCESS; @@ -1090,8 +1075,6 @@ const struct tcpm_drv anx74xx_tcpm_drv = { #if defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE) && \ defined(CONFIG_USB_PD_TCPC_LOW_POWER) .drp_toggle = &anx74xx_tcpc_drp_toggle, -#endif -#ifdef CONFIG_USB_PD_TCPC_LOW_POWER .enter_low_power_mode = &anx74xx_enter_low_power_mode, #endif }; |