diff options
author | Sam Hurst <shurst@google.com> | 2018-07-09 12:34:34 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-07-31 23:51:10 +0000 |
commit | d37ceabbb055045b9b7bb02571e3bb73e1504ff7 (patch) | |
tree | 8e2c20d86ccaf94b9094a85fbb16a6c89d016d80 | |
parent | 5673e6f67974dcd22617ed592fbb4a9712568df1 (diff) | |
download | chrome-ec-d37ceabbb055045b9b7bb02571e3bb73e1504ff7.tar.gz |
eve: Delay charge port selection until VBUS is stable or 1s has passed
When a charge port is selected and VBUS is 5V, the inrush current causes
VBUS to droop which could signal a sink disconnection.
To mitigate this problem, charge port selection is delayed until VBUS
is stable or 1s has passed. Before 1s has passed, PD will hopefully have
negotiated a VBUS voltage of at least 9V.
This CL is also a workaround for the issue outlined in b:74753447
Signed-off-by: Sam Hurst <shurst@chromium.org>
BUG=b:69439094
BRANCH=None
TEST=`make -j buildall`
Manual tested with Belkin Express Dock and Moshi audio adapter.
Test Belkin with following configuration:
PORT0: PORT1:
Belkin OPEN
OPEN Belkin
Belkin Blackcat
Blackcat Belkin
Belkin EC terminal output:
Port 0:
[654.645288 TCPC p0 Exit Low Power Mode]
C0 st14
C0 st15
C0 st17
C0 st18
C0 st19
Requested 5000 V 3000 mA (for 900/900 mA)
C0 st20
C0 st21
C0 st22
C0 st23
C0 st24
C0 st23
C0 st26
C0 st27
C0 st28
C0 st29
[655.375668 New chg p0]
C0 st5
[655.380708 Ramp reset: st1]
[655.381704 CL: p0 s8 i500 v5000]
[655.392598 New chg p0]
[655.393574 Ramp reset: st1]
[655.394504 CL: p0 s2 i3000 v5000]
C0 Req [4] 15000mV 3000mA
[655.512126 New chg p0]
[655.514456 Ramp reset: st1]
C0 st715219 CL: p0 s0 ]
C0 st8
[655.639762 Ramp reset: st1]
[655.640301 CL: p0 s0 i3000 v15000]
[656.688735 AC on]
[657.385539 Ramp p0 st5 3000mA 3000mA]
[657.471108 Battery 70% / 7h:36 to empty]
[659.721858 charge_request(8800mV, 5376mA)]
[660.973258 charge_request(8800mV, 3712mA)]
[697.506594 Battery 71% / 1h:1 to full]
Port 1:
[729.384242 TCPC p1 Exit Low Power Mode]
C1 st2
C1 st3
C1 st14
C1 st15
C1 st17
C1 st18
C1 st19
Requested 5000 V 3000 mA (for 900/900 mA)
C1 st20
C1 st21
C1 st22
C1 st23
C1 st24
C1 st23
C1 st26
C1 st27
C1 st28
C1 st29
[730.339719 New chg p1]
[730.340602 Ramp reset: st1]
[C1 st5
730.341457 CL: p1 s8 i500 v5000]
[730.356552 New chg p1]
[730.357311 Ramp reset: st1]
[730.358095 CL: p1 s2 i3000 v5000]
C1 Req [4] 15000mV 3000mA
[730.478577 New chg p1]
[730.480986 Ramp reset: st1]
[730.481829 CL:Cp1 s0 i500 v15]
C1 st8
[730.607116 Ramp reset: st1]
[730.607813 CL: p1 s0 i3000 v15000]
[731.654877 AC on]
[732.345420 Ramp p1 st5 3000mA 3000mA]
[732.589802 Battery 71% / 10h:28 to empty]
[734.340030 charge_request(8800mV, 5376mA)]
[735.091263 charge_request(8800mV, 3712mA)]
[767.879314 Battery 72% / 1h:1 to full]
Tested Moshi with followint configuration:
Port0: Port1:
Moshi-pwr OPEN
OPEN Moshi-pwr
Moshi-pwr Blackcat
Blackcat Moshi-pwr
Moshi-audio OPEN
OPEN Moshi-audio
Moshi-audio Blackcat
Blackcat Moshi-pwr
Moshi-pwr-audio OPEN
OPEN Moshi-pwr-audio
Moshi-pwr-audio Blackcat
Blackcat Moshi-pwr-audio
Moshi EC terminal output:
[2330.883267 TCPC p0 Low Power Mode]
[2330.883664 TCPC p0 reset!]
[2330.916049 TCPC p0 Low Power Mode]
[2330.916475 TCPC p0 reset!]
[2330.934010 TCPC p0 Exit Low Power Mode]
C0 st14
C0 st15
C0 st17
C0 st18
C0 st19
Requested 5000 V 3000 mA (for 3000/3000 mA)
C0 st20
C0 st21
C0 st22
C0 st23
C0 st24
C0 st23
C0 st26
C0 st23
C0 st27
C0 st28
C0 st29
[2332.398132 New chg p0]
[2332.398883 Ramp reset: st1]
[2332.399745 CL: p0 s8 i500 v5000]
C0 st5
[2332.476132 New chg p0]
[2332.476933 Ramp reset: st1]
[2332.477705 CL: p0 s2 i3000 v5000]
C0 Req [4] 15000mV 2970mA
[2332.493597 New cCg p0C0 st7
]
[2332[2332.5001C0 st8
[2332.674727 Ramp reset: st1]
[2332.675510 CL: p0 s0 i2970 v15000]
[2333.668216 AC on]
[2334.403481 Ramp p0 st5 2970mA 2970mA]
[2334.450155 Battery 80% / 11h:18 to empty]
[2335.448877 charge_request(8800mV, 5376mA)]
[2336.699875 charge_request(8800mV, 3712mA)]
[2356.466385 Battery 81% / 1h:1 to full]
Change-Id: Iba909c252094c0e5ca4cf974aabcfe1eaf002efd
Reviewed-on: https://chromium-review.googlesource.com/1157554
Reviewed-by: Duncan Laurie <dlaurie@google.com>
Commit-Queue: Duncan Laurie <dlaurie@google.com>
Tested-by: Duncan Laurie <dlaurie@google.com>
-rw-r--r-- | board/eve/board.h | 1 | ||||
-rw-r--r-- | driver/charger/bd9995x.c | 121 | ||||
-rw-r--r-- | include/config.h | 3 |
3 files changed, 125 insertions, 0 deletions
diff --git a/board/eve/board.h b/board/eve/board.h index 7441b07d39..05cdba3cdb 100644 --- a/board/eve/board.h +++ b/board/eve/board.h @@ -167,6 +167,7 @@ #define CONFIG_USB_PD_DISCHARGE_TCPC #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +#define CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT #define CONFIG_USB_PD_LOGGING #define CONFIG_USB_PD_LOG_SIZE 512 #define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 diff --git a/driver/charger/bd9995x.c b/driver/charger/bd9995x.c index c43549900c..39af5c9d86 100644 --- a/driver/charger/bd9995x.c +++ b/driver/charger/bd9995x.c @@ -35,6 +35,37 @@ /* Console output macros */ #define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT +/* + * Used in a check to determine if VBUS is within the + * range of some VOLTAGE +/- VBUS_DELTA, where voltage + * is measured in mV. + */ +#define VBUS_DELTA 1000 + +/* VBUS is debounced if it's stable for this length of time */ +#define VBUS_MSEC (100*MSEC) + +/* VBUS debouncing sample interval */ +#define VBUS_CHECK_MSEC (10*MSEC) + +/* Time to wait before VBUS debouncing begins */ +#define STABLE_TIMEOUT (500*MSEC) + +/* Maximum time to wait until VBUS is debounced */ +#define DEBOUNCE_TIMEOUT (500*MSEC) + +enum vstate {START, STABLE, DEBOUNCE}; +static enum vstate vbus_state; + +static int vbus_voltage; +static uint64_t debounce_time; +static uint64_t vbus_timeout; +static int port_update; +static int select_update; +static int select_input_port_update; +#endif + /* Charger parameters */ static const struct charger_info bd9995x_charger_info = { .name = CHARGER_NAME, @@ -1048,7 +1079,12 @@ int bd9995x_is_vbus_provided(enum bd9995x_charge_port port) return !!reg; } +#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT +static int bd9995x_select_input_port_private(enum bd9995x_charge_port port, + int select) +#else int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) +#endif { int rv; int reg; @@ -1093,6 +1129,49 @@ select_input_port_exit: return rv; } +#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT +int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) +{ + port_update = port; + select_update = select; + vbus_state = START; + select_input_port_update = 1; + task_wake(TASK_ID_USB_CHG); + + return EC_SUCCESS; +} + +static inline int bd9995x_vbus_test(int value, int limit) +{ + uint32_t hi_value = limit + VBUS_DELTA; + uint32_t lo_value = limit - VBUS_DELTA; + + return ((value > lo_value) && (value < hi_value)); +} + +static int bd9995x_vbus_debounce(enum bd9995x_charge_port port) +{ + int vbus_reg; + int voltage; + + vbus_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? + BD9995X_CMD_VBUS_VAL : BD9995X_CMD_VCC_VAL; + if (ch_raw_read16(vbus_reg, &voltage, BD9995X_EXTENDED_COMMAND)) + voltage = 0; + + if (!bd9995x_vbus_test(voltage, vbus_voltage)) { + vbus_voltage = voltage; + debounce_time = get_time().val + VBUS_MSEC; + } else { + if (get_time().val >= debounce_time) + return 1; + } + + return 0; +} +#endif + + #ifdef CONFIG_CHARGER_BATTERY_TSENSE int bd9995x_get_battery_temp(int *temp_ptr) { @@ -1192,6 +1271,11 @@ void usb_charger_task(void *u) int vbus_reg, voltage; #endif +#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT + select_input_port_update = 0; + vbus_voltage = 0; +#endif + for (port = 0; port < CONFIG_USB_PD_PORT_COUNT; port++) { bc12_detected_type[port] = CHARGE_SUPPLIER_NONE; bd9995x_enable_vbus_detect_interrupts(port, 1); @@ -1269,6 +1353,43 @@ void usb_charger_task(void *u) } initialized = 1; +#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT +/* + * When a charge port is selected and VBUS is 5V, the inrush current on some + * devices causes VBUS to droop, which could signal a sink disconnection. + * + * To mitigate the problem, charge port selection is delayed until VBUS + * is stable or one second has passed. Hopefully PD has negotiated a VBUS + * voltage of at least 9V before the one second timeout. + */ + if (select_input_port_update) { + sleep_usec = VBUS_CHECK_MSEC; + changed = 0; + + switch (vbus_state) { + case START: + vbus_timeout = get_time().val + STABLE_TIMEOUT; + vbus_state = STABLE; + break; + case STABLE: + if (get_time().val > vbus_timeout) { + vbus_state = DEBOUNCE; + vbus_timeout = get_time().val + + DEBOUNCE_TIMEOUT; + } + break; + case DEBOUNCE: + if (bd9995x_vbus_debounce(port_update) || + get_time().val > vbus_timeout) { + select_input_port_update = 0; + bd9995x_select_input_port_private( + port_update, select_update); + } + break; + } + } +#endif + /* * Re-read interrupt registers immediately if we got an * interrupt. We're dealing with multiple independent diff --git a/include/config.h b/include/config.h index 415cba7b21..83472a7c5a 100644 --- a/include/config.h +++ b/include/config.h @@ -2371,6 +2371,9 @@ /* Define if this board can used TCPC-controlled DRP toggle */ #undef CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE +/* Define to reduces VBUS droop caused by inrush current during charging */ +#undef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT + /* Initial DRP / toggle policy */ #define CONFIG_USB_PD_INITIAL_DRP_STATE PD_DRP_TOGGLE_OFF |