From 12a941187b49248f3e114f39b092eaa18096c31a Mon Sep 17 00:00:00 2001 From: Hsu Henry Date: Tue, 24 Feb 2015 13:37:28 +0800 Subject: Charger: add new charger BQ24717 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://chromium-review.googlesource.com/251946 Reviewed-by: Mohammed Habibulla Reviewed-by: Aaron Durbin (cherry picked from commit 3030883c121b545c977f6eb68b51e142694b35ae) Reviewed-on: https://chromium-review.googlesource.com/269310 Tested-by: 挺倫 林 Reviewed-by: Shawn N Commit-Queue: 挺倫 林 --- driver/build.mk | 1 + driver/charger/bq24717.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++ driver/charger/bq24717.h | 131 ++++++++++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 driver/charger/bq24717.c create mode 100644 driver/charger/bq24717.h 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, ®); + 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, ®); + 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 */ -- cgit v1.2.1