diff options
author | Scott Collyer <scollyer@google.com> | 2018-01-18 14:31:30 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-01-22 22:07:17 -0800 |
commit | f793f81b8b9bd82f14a18adf3f179df78a813261 (patch) | |
tree | ea5f7919d16efae2d259779ed3065875820d54b5 /driver | |
parent | c06d7fea8f6b8235e9a7dcbb76e2a637189f9d2e (diff) | |
download | chrome-ec-f793f81b8b9bd82f14a18adf3f179df78a813261.tar.gz |
bd9995x: Clear VSYS_PRIORITY when Vbat > Vbat_min
VSYS_PRIORITY in the register VIN_CTRL_SET is set during bd9995x
initialization to ensure VSYS remains up and stable during deeply
discharged battery conditions. However, outside of this case, this bit
should remain cleared.
If set, there the input current limit is disabled between the time
that the boost converter is enabled (USB_SUS = 0) and charging is
enabled (CHG_EN = 1). This can lead to too much current being drawn
which results in the connecting port shutting off VBUS due to its
overcurrent protection. This has been observed when attempting to
charge one DUT from another chromebook port, or with a Type C only
charger.
This CL adds a check in the bd99965x driver implementation of
charger_get_voltage() that compares the current battery voltage to
its minimum voltage. If it's higher, then it's not a deeply discharged
battery and VSYS_PRIORITY can be cleared.
BUG=chromium:69143827,71814128
BRANCH=coral,eve
TEST=Tested with 2 Coral DUTs. Verified that VSYS_PRIORITY gets
cleared when the charger state machine gets the charger
parameters. Also verified that I can repeatedly initated charging from
one Coral device to another. Without this fix, this would fail most of
the of the time. Also tested Eve with deeply discharged battery to
make sure the startup conditon still works.
Change-Id: I5230560fa98e5bf16921eb4f2c70802eb962e7f3
Signed-off-by: Scott Collyer <scollyer@google.com>
Reviewed-on: https://chromium-review.googlesource.com/875178
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/charger/bd9995x.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/driver/charger/bd9995x.c b/driver/charger/bd9995x.c index 9ab2f55a47..7cdbdc4893 100644 --- a/driver/charger/bd9995x.c +++ b/driver/charger/bd9995x.c @@ -55,6 +55,11 @@ static enum bd9995x_command charger_map_cmd = BD9995X_INVALID_COMMAND; /* Mutex for active register set control. */ static struct mutex bd9995x_map_mutex; +/* Tracks the state of VSYS_PRIORITY */ +static int vsys_priority; +/* Mutex for VIN_CTRL_SET register */ +static struct mutex bd9995x_vin_mutex; + #ifdef HAS_TASK_USB_CHG /* USB switch */ static enum usb_switch usb_switch_state[BD9995X_CHARGE_PORT_COUNT] = { @@ -772,6 +777,36 @@ int charger_set_current(int current) int charger_get_voltage(int *voltage) { + if (vsys_priority) { + int batt_volt_measured; + int reg; + int rv; + + /* Get battery voltage as reported by charger */ + batt_volt_measured = bd9995x_get_battery_voltage(); + if (batt_volt_measured > (battery_get_info()->voltage_min + + BD9995X_VSYS_PRECHARGE_OFFSET_MV)) { + /* + * Battery is not deeply discharged. Clear the + * VSYS_PRIORITY bit to ensure that input current limit + * is always active. + */ + mutex_lock(&bd9995x_vin_mutex); + if (!ch_raw_read16(BD9995X_CMD_VIN_CTRL_SET, ®, + BD9995X_EXTENDED_COMMAND)) { + reg &= ~BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; + rv = ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, + reg, + BD9995X_EXTENDED_COMMAND); + + /* Mirror the state of this bit */ + if (!rv) + vsys_priority = 0; + } + mutex_unlock(&bd9995x_vin_mutex); + } + } + return ch_raw_read16(BD9995X_CMD_CHG_VOLTAGE, voltage, BD9995X_BAT_CHG_COMMAND); } @@ -911,6 +946,8 @@ static void bd9995x_init(void) reg |= BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, reg, BD9995X_EXTENDED_COMMAND); + /* Mirror the state of this bit */ + vsys_priority = 1; /* Define battery charging profile */ bd9995x_battery_charging_profile_settings(); @@ -1016,10 +1053,11 @@ int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) int rv; int reg; + mutex_lock(&bd9995x_vin_mutex); rv = ch_raw_read16(BD9995X_CMD_VIN_CTRL_SET, ®, BD9995X_EXTENDED_COMMAND); if (rv) - return rv; + goto select_input_port_exit; if (select) { if (port == BD9995X_CHARGE_PORT_VBUS) { @@ -1048,8 +1086,11 @@ int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) panic("Invalid charge port"); } - return ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, reg, + rv = ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, reg, BD9995X_EXTENDED_COMMAND); +select_input_port_exit: + mutex_unlock(&bd9995x_vin_mutex); + return rv; } #ifdef CONFIG_CHARGER_BATTERY_TSENSE |