summaryrefslogtreecommitdiff
path: root/driver/battery
diff options
context:
space:
mode:
authorPhilip Chen <philipchen@google.com>2017-12-06 22:46:16 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-11 19:37:46 -0800
commit40a693aea8e3d59d6d12c8370457bc25ccae0698 (patch)
tree9628b972f82d182e3aeae6cd96a649ecb8f9fc34 /driver/battery
parent1b53782145964ec226afbf910e23b1e68c0ac8dd (diff)
downloadchrome-ec-40a693aea8e3d59d6d12c8370457bc25ccae0698.tar.gz
battery/max17055: Support advanced config with battery profile
We've been using the basic configuration (EZ config) to initialize max17055. It doesn't require battery profile, but the accuracy of fuel gauge is not the best. With a full battery profile in place, we should extend our driver to import the battery profile for advanced config. It should boost the accuracy. BUG=b:69634899 CQ-DEPEND=CL:812481 BRANCH=none TEST=manually test on Scarlet rev2, 'battery' command shows reasonable reading no matter is_ez_config is set as 0 or not. Change-Id: Iaea2d3e20f5de4207a86d4fff5f1561aaba4d362 Signed-off-by: Philip Chen <philipchen@google.com> Reviewed-on: https://chromium-review.googlesource.com/813038 Commit-Ready: Philip Chen <philipchen@chromium.org> Tested-by: Philip Chen <philipchen@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'driver/battery')
-rw-r--r--driver/battery/max17055.c91
-rw-r--r--driver/battery/max17055.h123
2 files changed, 161 insertions, 53 deletions
diff --git a/driver/battery/max17055.c b/driver/battery/max17055.c
index 516cd1f429..cd0a379e8e 100644
--- a/driver/battery/max17055.c
+++ b/driver/battery/max17055.c
@@ -10,56 +10,13 @@
#include "extpower.h"
#include "hooks.h"
#include "i2c.h"
+#include "max17055.h"
#include "timer.h"
#include "util.h"
/* Console output macros */
#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
-#define MAX17055_ADDR 0x6c
-#define MAX17055_DEVICE_ID 0x4010
-
-#define REG_STATUS 0x00
-#define REG_AT_RATE 0x04
-#define REG_REMAINING_CAPACITY 0x05
-#define REG_STATE_OF_CHARGE 0x06
-#define REG_TEMPERATURE 0x08
-#define REG_VOLTAGE 0x09
-#define REG_CURRENT 0x0a
-#define REG_AVERAGE_CURRENT 0x0b
-#define REG_FULL_CHARGE_CAPACITY 0x10
-#define REG_TIME_TO_EMPTY 0x11
-#define REG_CONFIG 0x1D
-#define REG_AVERAGE_TEMPERATURE 0x16
-#define REG_CYCLE_COUNT 0x17
-#define REG_DESIGN_CAPACITY 0x18
-#define REG_AVERAGE_VOLTAGE 0x19
-#define REG_CHARGE_TERM_CURRENT 0x1e
-#define REG_TIME_TO_FULL 0x20
-#define REG_DEVICE_NAME 0x21
-#define REG_EMPTY_VOLTAGE 0x3a
-#define REG_FSTAT 0x3d
-#define REG_DQACC 0x45
-#define REG_DPACC 0x46
-#define REG_STATUS2 0xb0
-#define REG_HIBCFG 0xba
-#define REG_CONFIG2 0xbb
-#define REG_MODELCFG 0xdb
-
-/* Status reg (0x00) flags */
-#define STATUS_POR 0x0002
-#define STATUS_BST 0x0008
-
-/* Config reg (0x1d) flags */
-#define CONF_TSEL 0x8000
-
-/* FStat reg (0x3d) flags */
-#define FSTAT_DNR 0x0001
-
-/* ModelCfg reg (0xdb) flags */
-#define MODELCFG_REFRESH 0x8000
-#define MODELCFG_VCHG 0x0400
-
/*
* Convert the register values to the units that match
* smart battery protocol.
@@ -318,14 +275,35 @@ static int max17055_init_config(void)
{
int reg;
int hib_cfg;
+ int dqacc;
+ int dpacc;
+
int retries = 50;
- if (max17055_write(REG_DESIGN_CAPACITY, BATTERY_MAX17055_DESIGNCAP) ||
- max17055_write(REG_DQACC, BATTERY_MAX17055_DESIGNCAP / 32) ||
- max17055_write(REG_CHARGE_TERM_CURRENT, BATTERY_MAX17055_ICHGTERM)
- || max17055_write(REG_EMPTY_VOLTAGE, BATTERY_MAX17055_VEMPTY))
+ const struct max17055_batt_profile *config;
+
+ config = max17055_get_batt_profile();
+
+ if (config->is_ez_config) {
+ dqacc = config->design_cap / 32;
+ /* Choose the model for charge voltage > 4.275V. */
+ dpacc = dqacc * 51200 / config->design_cap;
+ } else {
+ dqacc = config->design_cap / 16;
+ dpacc = config->dpacc;
+ }
+
+ if (max17055_write(REG_DESIGN_CAPACITY, config->design_cap) ||
+ max17055_write(REG_DQACC, dqacc) ||
+ max17055_write(REG_CHARGE_TERM_CURRENT, config->ichg_term) ||
+ max17055_write(REG_EMPTY_VOLTAGE, config->v_empty_detect))
return EC_ERROR_UNKNOWN;
+ if (!config->is_ez_config) {
+ if (max17055_write(REG_LEARNCFG, config->learn_cfg))
+ return EC_ERROR_UNKNOWN;
+ }
+
/* Store the original HibCFG value. */
if (max17055_read(REG_HIBCFG, &hib_cfg))
return EC_ERROR_UNKNOWN;
@@ -336,11 +314,8 @@ static int max17055_init_config(void)
max17055_write(0x60, 0))
return EC_ERROR_UNKNOWN;
- /* Choose the model for charge voltage > 4.275V. */
- if (max17055_write(REG_DPACC, (BATTERY_MAX17055_DESIGNCAP / 32) *
- 51200 / BATTERY_MAX17055_DESIGNCAP))
- return EC_ERROR_UNKNOWN;
- if (max17055_write(REG_MODELCFG, (MODELCFG_REFRESH | MODELCFG_VCHG)))
+ if (max17055_write(REG_DPACC, dpacc) ||
+ max17055_write(REG_MODELCFG, (MODELCFG_REFRESH | MODELCFG_VCHG)))
return EC_ERROR_UNKNOWN;
/* Delay up to 500 ms until MODELCFG.REFRESH bit == 0. */
@@ -354,6 +329,16 @@ static int max17055_init_config(void)
if (!retries)
return EC_ERROR_TIMEOUT;
+ if (!config->is_ez_config) {
+ if (max17055_write(REG_RCOMP0, config->rcomp0) ||
+ max17055_write(REG_TEMPCO, config->tempco) ||
+ max17055_write(REG_QR_TABLE00, config->qr_table00) ||
+ max17055_write(REG_QR_TABLE10, config->qr_table10) ||
+ max17055_write(REG_QR_TABLE20, config->qr_table20) ||
+ max17055_write(REG_QR_TABLE30, config->qr_table30))
+ return EC_ERROR_UNKNOWN;
+ }
+
/* Restore the original HibCFG value. */
if (max17055_write(REG_HIBCFG, hib_cfg))
return EC_ERROR_UNKNOWN;
diff --git a/driver/battery/max17055.h b/driver/battery/max17055.h
new file mode 100644
index 0000000000..fb49e69c22
--- /dev/null
+++ b/driver/battery/max17055.h
@@ -0,0 +1,123 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Battery driver for MAX17055.
+ */
+
+#ifndef __CROS_EC_MAX17055_H
+#define __CROS_EC_MAX17055_H
+
+#define MAX17055_ADDR 0x6c
+#define MAX17055_DEVICE_ID 0x4010
+
+#define REG_STATUS 0x00
+#define REG_AT_RATE 0x04
+#define REG_REMAINING_CAPACITY 0x05
+#define REG_STATE_OF_CHARGE 0x06
+#define REG_TEMPERATURE 0x08
+#define REG_VOLTAGE 0x09
+#define REG_CURRENT 0x0a
+#define REG_AVERAGE_CURRENT 0x0b
+#define REG_FULL_CHARGE_CAPACITY 0x10
+#define REG_TIME_TO_EMPTY 0x11
+#define REG_QR_TABLE00 0x12
+#define REG_CONFIG 0x1D
+#define REG_AVERAGE_TEMPERATURE 0x16
+#define REG_CYCLE_COUNT 0x17
+#define REG_DESIGN_CAPACITY 0x18
+#define REG_AVERAGE_VOLTAGE 0x19
+#define REG_CHARGE_TERM_CURRENT 0x1e
+#define REG_TIME_TO_FULL 0x20
+#define REG_DEVICE_NAME 0x21
+#define REG_QR_TABLE10 0x22
+#define REG_LEARNCFG 0x28
+#define REG_QR_TABLE20 0x32
+#define REG_RCOMP0 0x38
+#define REG_TEMPCO 0x39
+#define REG_EMPTY_VOLTAGE 0x3a
+#define REG_FSTAT 0x3d
+#define REG_QR_TABLE30 0x42
+#define REG_DQACC 0x45
+#define REG_DPACC 0x46
+#define REG_STATUS2 0xb0
+#define REG_HIBCFG 0xba
+#define REG_CONFIG2 0xbb
+#define REG_MODELCFG 0xdb
+
+/* Status reg (0x00) flags */
+#define STATUS_POR 0x0002
+#define STATUS_BST 0x0008
+
+/* Config reg (0x1d) flags */
+#define CONF_TSEL 0x8000
+
+/* FStat reg (0x3d) flags */
+#define FSTAT_DNR 0x0001
+
+/* ModelCfg reg (0xdb) flags */
+#define MODELCFG_REFRESH 0x8000
+#define MODELCFG_VCHG 0x0400
+
+/*
+ * Before we have the battery fully characterized, we use these macros to
+ * convert basic battery parameters to max17055 reg values for ez config.
+ */
+
+/* Convert design capacity in mAh to max17055 0x18 reg value */
+#define MAX17055_DESIGNCAP_REG(bat_cap_mah) \
+ (bat_cap_mah * BATTERY_MAX17055_RSENSE / 5)
+/* Convert charge termination current in mA to max17055 0x1e reg value */
+#define MAX17055_ICHGTERM_REG(term_cur_ma) \
+ (((term_cur_ma * BATTERY_MAX17055_RSENSE) << 4) / 25)
+/*
+ * This macro converts empty voltage target (VE) and recovery voltage (VR)
+ * in mV to max17055 0x3a reg value. max17055 declares 0% (empty battery) at
+ * VE. max17055 reenables empty detection when the cell voltage rises above VR.
+ * VE ranges from 0 to 5110mV, and VR ranges from 0 to 5080mV.
+ */
+#define MAX17055_VEMPTY_REG(ve_mv, vr_mv) \
+ (((ve_mv / 10) << 7) | (vr_mv / 40))
+
+/*
+ * max17055 needs some special battery parameters for fuel gauge
+ * learning algorithm. Maxim can help characterize the battery pack
+ * to get a full parameter list. We create a data structure to store
+ * the battery parameters in the format of max17055 register values.
+ */
+struct max17055_batt_profile {
+ /* Design capacity of the cell (LSB = 5uVH / Rsense) */
+ uint16_t design_cap;
+ /* Charge termination current (LSB = 1.5625uV / Rsense) */
+ uint16_t ichg_term;
+ /* The combination of empty voltage target and recovery voltage */
+ uint16_t v_empty_detect;
+
+ /*
+ * The parameters below are used for advanced (non-EZ) config
+ * (dpacc, learn_cfg, tempco, qr_table00, qr_table10,
+ * qr_table20, and qr_table30)
+ */
+
+ /* Change in battery SOC between relaxation points (LSB = pct / 16) */
+ uint16_t dpacc;
+ /* Magic cell tuning parameters */
+ uint16_t learn_cfg;
+ uint16_t rcomp0;
+ uint16_t tempco;
+ uint16_t qr_table00;
+ uint16_t qr_table10;
+ uint16_t qr_table20;
+ uint16_t qr_table30;
+
+ /*
+ * If is_ez_config is nonzero, we only use design_cap, ichg_term,
+ * and v_empty_detect to config max17055 (a.k.a. EZ-config).
+ */
+ uint8_t is_ez_config;
+};
+
+/* Return the special battery parameters max17055 needs. */
+const struct max17055_batt_profile *max17055_get_batt_profile(void);
+
+#endif /* __CROS_EC_MAX17055_H */