summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid.Huang <David.Huang@quantatw.com>2017-04-17 15:26:15 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-04-19 00:54:43 +0000
commit7052b22aeae1227a8c268fcd81dca201e9ca3bee (patch)
treebba337e5491ee4be47bd0392986e179e0df795d1
parent39f4893aa93d446b012cd5cc4f3d1a14f479ff37 (diff)
downloadchrome-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.h2
-rw-r--r--board/cyan/bq24773.c306
-rw-r--r--board/cyan/bq24773.h122
-rw-r--r--board/cyan/build.mk2
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, &reg);
+#elif defined(CONFIG_CHARGER_BQ24773)
+ rv = raw_read8(REG_INPUT_CURRENT, &reg);
+#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, &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 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