diff options
author | David.Huang <David.Huang@quantatw.com> | 2017-04-17 15:26:15 +0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2017-04-19 00:54:43 +0000 |
commit | 7052b22aeae1227a8c268fcd81dca201e9ca3bee (patch) | |
tree | bba337e5491ee4be47bd0392986e179e0df795d1 | |
parent | 39f4893aa93d446b012cd5cc4f3d1a14f479ff37 (diff) | |
download | chrome-ec-7052b22aeae1227a8c268fcd81dca201e9ca3bee.tar.gz |
Cyan: Change charge voltage for battery
Change battery charge voltage based on Cycle Count or State of Health
for different battery.
BRANCH=cyan
BUG=b:37484779
TEST=Use console command "charger" to check charge voltage with
different battery.
Change-Id: I21d3c09148c251baaa5455862fcdc179a7fbf264
Signed-off-by: David Huang <David.Huang@quantatw.com>
Reviewed-on: https://chromium-review.googlesource.com/479177
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r-- | board/cyan/board.h | 2 | ||||
-rw-r--r-- | board/cyan/bq24773.c | 306 | ||||
-rw-r--r-- | board/cyan/bq24773.h | 122 | ||||
-rw-r--r-- | board/cyan/build.mk | 2 |
4 files changed, 430 insertions, 2 deletions
diff --git a/board/cyan/board.h b/board/cyan/board.h index 4e9a26bd90..3ce9cf2f4d 100644 --- a/board/cyan/board.h +++ b/board/cyan/board.h @@ -48,7 +48,7 @@ #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_SMART #define CONFIG_CHARGER_V2 -#define CONFIG_CHARGER_BQ24770 +#define CONFIG_CHARGER_CYAN_BQ24770 #define CONFIG_CHARGER_ILIM_PIN_DISABLED #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 diff --git a/board/cyan/bq24773.c b/board/cyan/bq24773.c new file mode 100644 index 0000000000..1fa9034bce --- /dev/null +++ b/board/cyan/bq24773.c @@ -0,0 +1,306 @@ +/* Copyright (c) 2014 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 bq24773 battery charger driver. + */ + +#include "battery_smart.h" +#include "battery.h" +#include "bq24773.h" +#include "charger.h" +#include "console.h" +#include "common.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_CHARGER, outstr) +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) + +/* + * on the I2C version of the charger, + * some registers are 8-bit only (eg input current) + * and they are shifted by 6 bits compared to the SMBUS version (bq24770). + */ +#define REG8_SHIFT 6 +#define R8 (1 << (REG8_SHIFT)) +/* 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) +#define REG8_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS) * R8) +#define CURRENT_TO_REG8(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR / R8) + +static int prev_charge_inhibited = -1; + +/* Charger parameters */ +static const struct charger_info bq2477x_charger_info = { + .name = CHARGER_NAME, + .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), +}; + +/* chip specific interfaces */ + +int charger_set_input_current(int input_current) +{ +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + return raw_write16(REG_INPUT_CURRENT, + CURRENT_TO_REG(input_current, R_AC)); +#elif defined(CONFIG_CHARGER_BQ24773) + return raw_write8(REG_INPUT_CURRENT, + CURRENT_TO_REG8(input_current, R_AC)); +#endif +} + +int charger_get_input_current(int *input_current) +{ + int rv; + int reg; + +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + rv = raw_read16(REG_INPUT_CURRENT, ®); +#elif defined(CONFIG_CHARGER_BQ24773) + rv = raw_read8(REG_INPUT_CURRENT, ®); +#endif + if (rv) + return rv; + +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + *input_current = REG_TO_CURRENT(reg, R_AC); +#elif defined(CONFIG_CHARGER_BQ24773) + *input_current = REG8_TO_CURRENT(reg, R_AC); +#endif + return EC_SUCCESS; +} + +int charger_manufacturer_id(int *id) +{ +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + return raw_read16(REG_MANUFACTURE_ID, id); +#elif defined(CONFIG_CHARGER_BQ24773) + *id = 0x40; /* TI */ + return EC_SUCCESS; +#endif +} + +int charger_device_id(int *id) +{ +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + return raw_read16(REG_DEVICE_ADDRESS, id); +#elif defined(CONFIG_CHARGER_BQ24773) + return raw_read8(REG_DEVICE_ADDRESS, id); +#endif +} + +int charger_get_option(int *option) +{ + return raw_read16(REG_CHARGE_OPTION0, option); +} + +int charger_set_option(int option) +{ + prev_charge_inhibited = option & CHARGE_FLAG_INHIBIT_CHARGE; + return raw_write16(REG_CHARGE_OPTION0, option); +} + +/* Charger interfaces */ + +const struct charger_info *charger_get_info(void) +{ + return &bq2477x_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 & OPTION0_CHARGE_INHIBIT) + *status |= CHARGER_CHARGE_INHIBITED; + + return EC_SUCCESS; +} + +int charger_set_mode(int mode) +{ + int rv; + int option, i; + + if ((mode & CHARGE_FLAG_INHIBIT_CHARGE) == + prev_charge_inhibited) + return EC_SUCCESS; + + /* + * Refer to crosbug.com/p/45575. If LEARN is enabled, + * read one more time to make sure it's not + * bogus value. + */ + for (i = 0; i < 2; i++) { + rv = charger_get_option(&option); + if (rv) + return rv; + else { + if (!(option & OPTION0_LEARN_ENABLE)) + break; + } + } + + if (mode & CHARGE_FLAG_INHIBIT_CHARGE) + option |= OPTION0_CHARGE_INHIBIT; + else + option &= ~OPTION0_CHARGE_INHIBIT; + return charger_set_option(option); +} + +int charger_get_current(int *current) +{ + int rv; + int reg; + + rv = raw_read16(REG_CHARGE_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 raw_write16(REG_CHARGE_CURRENT, CURRENT_TO_REG(current, R_SNS)); +} + +int charger_get_voltage(int *voltage) +{ + return raw_read16(REG_MAX_CHARGE_VOLTAGE, voltage); +} + +static int battery_charge_voltage_check(void) +{ + int fcc, dc, soh, rv, change = 0; + char device[10]; + + if (!battery_device_name(device, sizeof(device))) { + if (!strcasecmp(device, "AC15A3J")) { + rv = battery_full_charge_capacity(&fcc); + rv &= battery_design_capacity(&dc); + if (!rv) { + soh = fcc*100/dc; + if (soh <= 95) { + change = 1; + return change; + } + } + } + } + return change; +} + +int charger_set_voltage(int voltage) +{ + char device[10]; + + if (battery_charge_voltage_check()) { + if (voltage != 0) { + if (!battery_device_name(device, sizeof(device))) { + if (!strcasecmp(device, "AC15A3J")) + voltage = 12900; + } + } + } + + voltage = charger_closest_voltage(voltage); + + return raw_write16(REG_MAX_CHARGE_VOLTAGE, voltage); +} + +/* Charging power state initialization */ +int charger_post_init(void) +{ + int rv, option; +#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED + int option2; +#endif + + rv = charger_get_option(&option); + if (rv) + return rv; + + option &= ~OPTION0_LEARN_ENABLE; + + rv = charger_set_option(option); + if (rv) + return rv; + +#ifndef BOARD_SAMUS + /* Turn off PROCHOT warning */ + rv = raw_read16(REG_PROCHOT_OPTION1, &option); + if (rv) + return rv; + + option &= ~PROCHOT_OPTION1_SELECTOR_MASK; + + rv = raw_write16(REG_PROCHOT_OPTION1, option); +#else + /* On Samus, use PROCHOT warning to detect charging problems */ + /* Turn on PROCHOT warning */ + rv = raw_write16(REG_PROCHOT_OPTION1, 0x8120); + /* Set PROCHOT ICRIT warning when IADP is >120% of IDPM */ + rv |= raw_write16(REG_PROCHOT_OPTION0, 0x1b54); +#endif + + if (rv) + return rv; + +#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED + /* Read the external ILIM pin enabled flag. */ + rv = raw_read16(REG_CHARGE_OPTION2, &option2); + if (rv) + return rv; + + /* Set ILIM pin disabled if it is currently enabled. */ + if (option2 & OPTION2_EN_EXTILIM) { + option2 &= ~OPTION2_EN_EXTILIM; + rv = raw_write16(REG_CHARGE_OPTION2, option2); + } + return rv; +#else + return EC_SUCCESS; +#endif +} + +int charger_discharge_on_ac(int enable) +{ + int rv; + int option; + + rv = charger_get_option(&option); + if (rv) + return rv; + + if (enable) + rv = charger_set_option(option | OPTION0_LEARN_ENABLE); + else + rv = charger_set_option(option & ~OPTION0_LEARN_ENABLE); + + return rv; +} diff --git a/board/cyan/bq24773.h b/board/cyan/bq24773.h new file mode 100644 index 0000000000..d93d1a0dbc --- /dev/null +++ b/board/cyan/bq24773.h @@ -0,0 +1,122 @@ +/* Copyright (c) 2014 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 bq24773 battery charger driver. + */ + +#ifndef __CROS_EC_BQ24773_H +#define __CROS_EC_BQ24773_H + +/* for i2c_read and i2c_write functions. */ +#include "i2c.h" + +/* I2C address */ +#define BQ24770_ADDR (0x12) +#define BQ24773_ADDR (0x6a << 1) + +/* Chip specific commands */ +#define BQ24770_CHARGE_OPTION0 0x12 +#define BQ24770_CHARGE_OPTION1 0x3B +#define BQ24770_CHARGE_OPTION2 0x38 +#define BQ24770_PROCHOT_OPTION0 0x3C +#define BQ24770_PROCHOT_OPTION1 0x3D +#define BQ24770_CHARGE_CURRENT 0x14 +#define BQ24770_MAX_CHARGE_VOLTAGE 0x15 +#define BQ24770_MIN_SYSTEM_VOLTAGE 0x3E +#define BQ24770_INPUT_CURRENT 0x3F +#define BQ24770_MANUFACTURE_ID 0xFE +#define BQ24770_DEVICE_ADDRESS 0xFF + +#define BQ24773_CHARGE_OPTION0 0x00 +#define BQ24773_CHARGE_OPTION1 0x02 +#define BQ24773_PROCHOT_OPTION0 0x04 +#define BQ24773_PROCHOT_OPTION1 0x06 +#define BQ24773_PROCHOT_STATUS 0x08 +#define BQ24773_DEVICE_ADDRESS 0x09 +#define BQ24773_CHARGE_CURRENT 0x0A +#define BQ24773_MAX_CHARGE_VOLTAGE 0x0C +#define BQ24773_MIN_SYSTEM_VOLTAGE 0x0E +#define BQ24773_INPUT_CURRENT 0x0F +#define BQ24773_CHARGE_OPTION2 0x10 + +/* Option bits */ +#define OPTION0_CHARGE_INHIBIT (1 << 0) +#define OPTION0_LEARN_ENABLE (1 << 5) + +#define OPTION2_EN_EXTILIM (1 << 7) + +/* Prochot Option bits */ +#define PROCHOT_OPTION1_SELECTOR_MASK 0x7f /* [6:0] PROCHOT SELECTOR */ + +/* ChargeCurrent Register - 0x14 (mA) */ +#define CHARGE_I_OFF 0 +#define CHARGE_I_MIN 128 +#define CHARGE_I_MAX 8128 +#define CHARGE_I_STEP 64 + +/* MaxChargeVoltage Register - 0x15 (mV) */ +#define CHARGE_V_MIN 1024 +#define CHARGE_V_MAX 19200 +#define CHARGE_V_STEP 16 + +/* InputCurrent Register - 0x3f (mA) */ +#define INPUT_I_MIN 128 +#define INPUT_I_MAX 8128 +#define INPUT_I_STEP 64 + +#ifdef CONFIG_CHARGER_CYAN_BQ24770 + #define CHARGER_NAME "bq24770" + #define I2C_ADDR_CHARGER BQ24770_ADDR + + #define REG_CHARGE_OPTION0 BQ24770_CHARGE_OPTION0 + #define REG_CHARGE_OPTION1 BQ24770_CHARGE_OPTION1 + #define REG_CHARGE_OPTION2 BQ24770_CHARGE_OPTION2 + #define REG_PROCHOT_OPTION0 BQ24770_PROCHOT_OPTION0 + #define REG_PROCHOT_OPTION1 BQ24770_PROCHOT_OPTION1 + #define REG_CHARGE_CURRENT BQ24770_CHARGE_CURRENT + #define REG_MAX_CHARGE_VOLTAGE BQ24770_MAX_CHARGE_VOLTAGE + #define REG_MIN_SYSTEM_VOLTAGE BQ24770_MIN_SYSTEM_VOLTAGE + #define REG_INPUT_CURRENT BQ24770_INPUT_CURRENT + #define REG_MANUFACTURE_ID BQ24770_MANUFACTURE_ID + #define REG_DEVICE_ADDRESS BQ24770_DEVICE_ADDRESS + +#elif defined(CONFIG_CHARGER_BQ24773) + #define CHARGER_NAME "bq24773" + #define I2C_ADDR_CHARGER BQ24773_ADDR + + #define REG_CHARGE_OPTION0 BQ24773_CHARGE_OPTION0 + #define REG_CHARGE_OPTION1 BQ24773_CHARGE_OPTION1 + #define REG_CHARGE_OPTION2 BQ24773_CHARGE_OPTION2 + #define REG_PROCHOT_OPTION0 BQ24773_PROCHOT_OPTION0 + #define REG_PROCHOT_OPTION1 BQ24773_PROCHOT_OPTION1 + #define REG_CHARGE_CURRENT BQ24773_CHARGE_CURRENT + #define REG_MAX_CHARGE_VOLTAGE BQ24773_MAX_CHARGE_VOLTAGE + #define REG_MIN_SYSTEM_VOLTAGE BQ24773_MIN_SYSTEM_VOLTAGE + #define REG_INPUT_CURRENT BQ24773_INPUT_CURRENT + #define REG_DEVICE_ADDRESS BQ24773_DEVICE_ADDRESS +#endif + +#ifdef CONFIG_CHARGER_BQ24773 +static inline int raw_read8(int offset, int *value) +{ + return i2c_read8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +static inline int raw_write8(int offset, int value) +{ + return i2c_write8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} +#endif + +static inline int raw_read16(int offset, int *value) +{ + return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +static inline int raw_write16(int offset, int value) +{ + return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +#endif /* __CROS_EC_BQ24773_H */ diff --git a/board/cyan/build.mk b/board/cyan/build.mk index 51dfe75e15..088814e643 100644 --- a/board/cyan/build.mk +++ b/board/cyan/build.mk @@ -10,5 +10,5 @@ CHIP:=mec1322 CHIP_SPI_SIZE_KB:=512 -board-y=board.o led.o +board-y=board.o led.o bq24773.o board-$(CONFIG_BATTERY_SMART)+=battery.o |