summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHsu Henry <Henry.Hsu@quantatw.com>2015-02-24 13:37:28 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-03-04 18:59:11 +0000
commit3030883c121b545c977f6eb68b51e142694b35ae (patch)
treebf27a7aa1426ed7708f3293b3e3aa8383ec3c7ba
parent5777b471acf7e2ed89a9aa080f3b59e0283e6f63 (diff)
downloadchrome-ec-3030883c121b545c977f6eb68b51e142694b35ae.tar.gz
Charger: add new charger BQ24717 driver
BUG=chrome-os-partner:36311 BRANCH=banjo TEST=Use board banjo and enable BQ24717 config. The 4S battery works properly. (BQ24715 limit the charge voltage to 0x3ff0) Change-Id: I3abf53373a667002c73a8429981b75671236a485 Signed-off-by: Henry Hsu <Henry.Hsu@quantatw.com> Reviewed-on: https://chromium-review.googlesource.com/251946 Reviewed-by: Mohammed Habibulla <moch@chromium.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r--driver/build.mk1
-rw-r--r--driver/charger/bq24717.c223
-rw-r--r--driver/charger/bq24717.h131
3 files changed, 355 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk
index f9c31b143b..e845723d45 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -22,6 +22,7 @@ driver-$(CONFIG_BATTERY_SMART)+=battery/smart.o
driver-$(CONFIG_CHARGER_BQ24192)+=charger/bq24192.o
driver-$(CONFIG_CHARGER_BQ24707A)+=charger/bq24707a.o
driver-$(CONFIG_CHARGER_BQ24715)+=charger/bq24715.o
+driver-$(CONFIG_CHARGER_BQ24717)+=charger/bq24717.o
driver-$(CONFIG_CHARGER_BQ24725)+=charger/bq24725.o
driver-$(CONFIG_CHARGER_BQ24738)+=charger/bq24738.o
diff --git a/driver/charger/bq24717.c b/driver/charger/bq24717.c
new file mode 100644
index 0000000000..3ec7bb6fad
--- /dev/null
+++ b/driver/charger/bq24717.c
@@ -0,0 +1,223 @@
+/* Copyright (c) 2015 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.
+ *
+ * TI bq24717 battery charger driver.
+ */
+
+#include "battery_smart.h"
+#include "bq24717.h"
+#include "charger.h"
+#include "console.h"
+#include "common.h"
+#include "util.h"
+
+/* Sense resistor configurations and macros */
+#define DEFAULT_SENSE_RESISTOR 10
+#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR
+#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC
+#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS))
+#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR)
+
+/* Note: it is assumed that the sense resistors are 10mOhm. */
+
+static const struct charger_info bq24717_charger_info = {
+ .name = "bq24717",
+ .voltage_max = CHARGE_V_MAX,
+ .voltage_min = CHARGE_V_MIN,
+ .voltage_step = CHARGE_V_STEP,
+ .current_max = REG_TO_CURRENT(CHARGE_I_MAX, R_SNS),
+ .current_min = REG_TO_CURRENT(CHARGE_I_MIN, R_SNS),
+ .current_step = REG_TO_CURRENT(CHARGE_I_STEP, R_SNS),
+ .input_current_max = REG_TO_CURRENT(INPUT_I_MAX, R_AC),
+ .input_current_min = REG_TO_CURRENT(INPUT_I_MIN, R_AC),
+ .input_current_step = REG_TO_CURRENT(INPUT_I_STEP, R_AC),
+};
+
+int charger_set_input_current(int input_current)
+{
+ return sbc_write(BQ24717_INPUT_CURRENT,
+ CURRENT_TO_REG(input_current, R_AC));
+}
+
+int charger_get_input_current(int *input_current)
+{
+ int rv;
+ int reg;
+
+ rv = sbc_read(BQ24717_INPUT_CURRENT, &reg);
+ if (rv)
+ return rv;
+
+ *input_current = REG_TO_CURRENT(reg, R_AC);
+
+ return EC_SUCCESS;
+}
+
+int charger_manufacturer_id(int *id)
+{
+ return sbc_read(BQ24717_MANUFACTURER_ID, id);
+}
+
+int charger_device_id(int *id)
+{
+ return sbc_read(BQ24717_DEVICE_ID, id);
+}
+
+int charger_get_option(int *option)
+{
+ return sbc_read(BQ24717_CHARGE_OPTION, option);
+}
+
+int charger_set_option(int option)
+{
+ return sbc_write(BQ24717_CHARGE_OPTION, option);
+}
+
+/* Charger interfaces */
+
+const struct charger_info *charger_get_info(void)
+{
+ return &bq24717_charger_info;
+}
+
+int charger_get_status(int *status)
+{
+ int rv;
+ int option;
+
+ rv = charger_get_option(&option);
+ if (rv)
+ return rv;
+
+ /* Default status */
+ *status = CHARGER_LEVEL_2;
+
+ if ((option & OPT_CHARGE_INHIBIT_MASK) == OPT_CHARGE_DISABLE)
+ *status |= CHARGER_CHARGE_INHIBITED;
+
+ return EC_SUCCESS;
+}
+
+int charger_set_mode(int mode)
+{
+ int rv;
+ int option;
+
+ rv = charger_get_option(&option);
+ if (rv)
+ return rv;
+
+ option &= ~OPT_CHARGE_INHIBIT_MASK;
+ if (mode & CHARGE_FLAG_INHIBIT_CHARGE)
+ option |= OPT_CHARGE_DISABLE;
+ else
+ option |= OPT_CHARGE_ENABLE;
+ return charger_set_option(option);
+}
+
+int charger_get_current(int *current)
+{
+ int rv;
+ int reg;
+
+ rv = sbc_read(SB_CHARGING_CURRENT, &reg);
+ if (rv)
+ return rv;
+
+ *current = REG_TO_CURRENT(reg, R_SNS);
+ return EC_SUCCESS;
+}
+
+int charger_set_current(int current)
+{
+ current = charger_closest_current(current);
+
+ return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS));
+}
+
+/* The voltage setting needs to be cached to work with the current
+ * charging infrastructure and state machine. The reason is that
+ * the state machine expects to be able to set a 0V charging voltage.
+ * The bq24717 does not allow this in the hardware register. Therefore
+ * 0V is handled specially to appease the state machine. */
+static int cached_voltage;
+
+int charger_get_voltage(int *voltage)
+{
+ int ret;
+
+ if (cached_voltage == 0) {
+ *voltage = cached_voltage;
+ return EC_SUCCESS;
+ }
+
+ ret = sbc_read(SB_CHARGING_VOLTAGE, &cached_voltage);
+
+ if (ret == EC_SUCCESS)
+ *voltage = cached_voltage;
+
+ return ret;
+}
+
+int charger_set_voltage(int voltage)
+{
+ cached_voltage = voltage;
+
+#ifdef CONFIG_CHARGE_NVDC_OFF_VOLTAGE
+ if (voltage == 0)
+ voltage = CONFIG_CHARGE_NVDC_OFF_VOLTAGE;
+#endif
+
+ return sbc_write(SB_CHARGING_VOLTAGE, voltage);
+}
+
+/* Charging power state initialization */
+int charger_post_init(void)
+{
+ int rv;
+ int option;
+
+ rv = charger_get_option(&option);
+ if (rv)
+ return rv;
+
+ /* Ensure 40KHz audio frequency limit is not set */
+ option &= ~OPT_AUDIO_FREQ_LIMIT_MASK;
+
+ /* Always monitor adapter current (40X multiplier). */
+ option |= OPT_FIX_IOUT_ALWAYS;
+ option &= ~OPT_IOUT_MASK;
+
+ /* Ensure learn mode is disabled */
+ option &= ~OPT_LEARN_MASK;
+
+ /* Enable dynamic power management */
+ option |= OPT_IDPM_ENABLE;
+
+ rv = charger_set_option(option);
+ if (rv)
+ return rv;
+
+ rv = charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT);
+ return rv;
+}
+
+int charger_discharge_on_ac(int enable)
+{
+ int rv;
+ int option;
+
+ rv = charger_get_option(&option);
+ if (rv)
+ return rv;
+
+ option &= ~OPT_LEARN_MASK;
+ if (enable)
+ option |= OPT_LEARN_ENABLE;
+ else
+ option |= OPT_LEARN_DISABLE;
+ rv = charger_set_option(option);
+
+ return rv;
+}
diff --git a/driver/charger/bq24717.h b/driver/charger/bq24717.h
new file mode 100644
index 0000000000..5bcc55fe16
--- /dev/null
+++ b/driver/charger/bq24717.h
@@ -0,0 +1,131 @@
+/* Copyright (c) 2015 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.
+ *
+ * TI bq24717 battery charger driver.
+ */
+
+#ifndef __CROS_EC_CHARGER_BQ24717_H
+#define __CROS_EC_CHARGER_BQ24717_H
+
+/* NOTES:
+ * If battery is not present keep charge current register (0x14) at 0.
+ * Max charge voltage (0x15) needs to be programmed before 0x14.
+ */
+
+/* Chip specific registers */
+#define BQ24717_CHARGE_OPTION 0x12
+#define BQ24717_CHARGE_CURRENT 0x14
+#define BQ24717_MAX_CHARGE_VOLTAGE 0x15
+#define BQ24717_MIN_SYSTEM_VOLTAGE 0x3e
+#define BQ24717_INPUT_CURRENT 0x3f
+#define BQ24717_MANUFACTURER_ID 0xfe
+#define BQ24717_DEVICE_ID 0xff
+
+/* ChargeOption Register - 0x12 */
+#define OPT_LOWPOWER_MASK (1 << 15)
+#define OPT_LOWPOWER_DSCHRG_I_MON_ON (0 << 15)
+#define OPT_LOWPOWER_DSCHRG_I_MON_OFF (1 << 15)
+#define OPT_WATCHDOG_MASK (3 << 13)
+#define OPT_WATCHDOG_DISABLE (0 << 13)
+#define OPT_WATCHDOG_44SEC (1 << 13)
+#define OPT_WATCHDOG_88SEC (2 << 13)
+#define OPT_WATCHDOG_175SEC (3 << 13)
+#define OPT_SYSOVP_MASK (1 << 12)
+#define OPT_SYSOVP_15P1_3SEC_20P2_4SEC (0 << 12)
+#define OPT_SYSOVP_17P0_3SEC_22P7_4SEC (1 << 12)
+#define OPT_SYSOVP_STATUS_MASK (1 << 11)
+#define OPT_SYSOVP_STATUS (1 << 11)
+#define OPT_AUDIO_FREQ_LIMIT_MASK (1 << 10)
+#define OPT_AUDIO_FREQ_NO_LIMIT (0 << 10)
+#define OPT_AUDIO_FREQ_40KHZ_LIMIT (1 << 10)
+#define OPT_SWITCH_FREQ_MASK (3 << 8)
+#define OPT_SWITCH_FREQ_600KHZ (0 << 8)
+#define OPT_SWITCH_FREQ_800KHZ (1 << 8)
+#define OPT_SWITCH_FREQ_1MHZ (2 << 8)
+#define OPT_SWITCH_FREQ_800KHZ_DUP (3 << 8)
+#define OPT_ACOC_MASK (1 << 7)
+#define OPT_ACOC_DISABLED (0 << 7)
+#define OPT_ACOC_333PCT_IPDM (1 << 7)
+#define OPT_LSFET_OCP_MASK (1 << 6)
+#define OPT_LSFET_OCP_250MV (0 << 6)
+#define OPT_LSFET_OCP_350MV (1 << 6)
+#define OPT_LEARN_MASK (1 << 5)
+#define OPT_LEARN_DISABLE (0 << 5)
+#define OPT_LEARN_ENABLE (1 << 5)
+#define OPT_IOUT_MASK (1 << 4)
+#define OPT_IOUT_40X (0 << 4)
+#define OPT_IOUT_16X (1 << 4)
+#define OPT_FIX_IOUT_MASK (1 << 3)
+#define OPT_FIX_IOUT_IDPM_EN (0 << 3)
+#define OPT_FIX_IOUT_ALWAYS (1 << 3)
+#define OPT_LDO_MODE_MASK (1 << 2)
+#define OPT_LDO_DISABLE (0 << 2)
+#define OPT_LDO_ENABLE (1 << 2)
+#define OPT_IDPM_MASK (1 << 1)
+#define OPT_IDPM_DISABLE (0 << 1)
+#define OPT_IDPM_ENABLE (1 << 1)
+#define OPT_CHARGE_INHIBIT_MASK (1 << 0)
+#define OPT_CHARGE_ENABLE (0 << 0)
+#define OPT_CHARGE_DISABLE (1 << 0)
+
+
+/* ChargeCurrent Register - 0x14
+ * The ChargeCurrent register controls a DAC. Therefore
+ * the below definitions are cummulative. */
+#define CHARGE_I_64MA (1 << 6)
+#define CHARGE_I_128MA (1 << 7)
+#define CHARGE_I_256MA (1 << 8)
+#define CHARGE_I_512MA (1 << 9)
+#define CHARGE_I_1024MA (1 << 10)
+#define CHARGE_I_2048MA (1 << 11)
+#define CHARGE_I_4096MA (1 << 12)
+#define CHARGE_I_OFF (0)
+#define CHARGE_I_MIN (128)
+#define CHARGE_I_MAX (8128)
+#define CHARGE_I_STEP (64)
+
+/* MaxChargeVoltage Register - 0x15
+ * The MaxChargeVoltage register controls a DAC. Therefore
+ * the below definitions are cummulative. */
+#define CHARGE_V_16MV (1 << 4)
+#define CHARGE_V_32MV (1 << 5)
+#define CHARGE_V_64MV (1 << 6)
+#define CHARGE_V_128MV (1 << 7)
+#define CHARGE_V_256MV (1 << 8)
+#define CHARGE_V_512MV (1 << 9)
+#define CHARGE_V_1024MV (1 << 10)
+#define CHARGE_V_2048MV (1 << 11)
+#define CHARGE_V_4096MV (1 << 12)
+#define CHARGE_V_8192MV (1 << 13)
+#define CHARGE_V_16384MV (1 << 14)
+#define CHARGE_V_MIN (4096)
+#define CHARGE_V_MAX (18000)
+#define CHARGE_V_STEP (16)
+
+/* MinSystemVoltage Register - 0x3e
+ * The MinSystemVoltage register controls a DAC. Therefore
+ * the below definitions are cummulative. */
+#define MIN_SYS_V_256MV (1 << 8)
+#define MIN_SYS_V_512MV (1 << 9)
+#define MIN_SYS_V_1024MV (1 << 10)
+#define MIN_SYS_V_2048MV (1 << 11)
+#define MIN_SYS_V_4096MV (1 << 12)
+#define MIN_SYS_V_8192MV (1 << 13)
+#define MIN_SYS_V_MIN (4096)
+
+/* InputCurrent Register - 0x3f
+ * The InputCurrent register controls a DAC. Therefore
+ * the below definitions are cummulative. */
+#define INPUT_I_64MA (1 << 6)
+#define INPUT_I_128MA (1 << 7)
+#define INPUT_I_256MA (1 << 8)
+#define INPUT_I_512MA (1 << 9)
+#define INPUT_I_1024MA (1 << 10)
+#define INPUT_I_2048MA (1 << 11)
+#define INPUT_I_4096MA (1 << 12)
+#define INPUT_I_MIN (128)
+#define INPUT_I_MAX (8064)
+#define INPUT_I_STEP (64)
+
+#endif /* __CROS_EC_CHARGER_BQ24717_H */