summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2018-07-09 12:34:34 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-07-31 23:51:10 +0000
commitd37ceabbb055045b9b7bb02571e3bb73e1504ff7 (patch)
tree8e2c20d86ccaf94b9094a85fbb16a6c89d016d80
parent5673e6f67974dcd22617ed592fbb4a9712568df1 (diff)
downloadchrome-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.h1
-rw-r--r--driver/charger/bd9995x.c121
-rw-r--r--include/config.h3
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