summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2018-01-18 14:31:30 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-22 22:07:17 -0800
commitf793f81b8b9bd82f14a18adf3f179df78a813261 (patch)
treeea5f7919d16efae2d259779ed3065875820d54b5 /driver
parentc06d7fea8f6b8235e9a7dcbb76e2a637189f9d2e (diff)
downloadchrome-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.c45
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, &reg,
+ 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, &reg,
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