From 4826d592ce100cd7b5086c4b0949ae3034b5a394 Mon Sep 17 00:00:00 2001 From: Vijay Hiremath Date: Thu, 17 Mar 2016 11:21:34 -0700 Subject: Driver: bd99955: Add ROHM bd99955 initial charger driver BUG=none BRANCH=none TEST=Manually tested on Amenia prototype. Used 'charger' console command to check the charger properties. Used 'battery' console command to check the battery charging. Change-Id: Ic8787bfa3e0e3a615542b9cf72e6404fccc96e18 Signed-off-by: Vijay Hiremath Reviewed-on: https://chromium-review.googlesource.com/334021 Commit-Ready: Vijay P Hiremath Tested-by: Vijay P Hiremath Reviewed-by: Shawn N --- driver/build.mk | 1 + driver/charger/bd99955.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++ driver/charger/bd99955.h | 166 +++++++++++++++++++++++++++++++++ include/config.h | 1 + 4 files changed, 402 insertions(+) create mode 100644 driver/charger/bd99955.c create mode 100644 driver/charger/bd99955.h diff --git a/driver/build.mk b/driver/build.mk index 1a33ee714e..13aae200bc 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -30,6 +30,7 @@ driver-$(CONFIG_BATTERY_SAMUS)+=battery/samus.o driver-$(CONFIG_BATTERY_SMART)+=battery/smart.o # Battery charger ICs +driver-$(CONFIG_CHARGER_BD99955)+=charger/bd99955.o driver-$(CONFIG_CHARGER_BQ24192)+=charger/bq24192.o driver-$(CONFIG_CHARGER_BQ24707A)+=charger/bq24707a.o driver-$(CONFIG_CHARGER_BQ24715)+=charger/bq24715.o diff --git a/driver/charger/bd99955.c b/driver/charger/bd99955.c new file mode 100644 index 0000000000..27b50cade1 --- /dev/null +++ b/driver/charger/bd99955.c @@ -0,0 +1,234 @@ +/* Copyright 2016 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. + * + * ROHM BD99955 battery charger driver. + */ + +#include "battery.h" +#include "battery_smart.h" +#include "bd99955.h" +#include "charger.h" +#include "console.h" +#include "i2c.h" +#include "task.h" +#include "util.h" + +/* Console output macros */ +#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) + +/* Charger parameters */ +static const struct charger_info bd99955_charger_info = { + .name = CHARGER_NAME, + .voltage_max = CHARGE_V_MAX, + .voltage_min = CHARGE_V_MIN, + .voltage_step = CHARGE_V_STEP, + .current_max = CHARGE_I_MAX, + .current_min = CHARGE_I_MIN, + .current_step = CHARGE_I_STEP, + .input_current_max = INPUT_I_MAX, + .input_current_min = INPUT_I_MIN, + .input_current_step = INPUT_I_STEP, +}; + +/* Charge command code map */ +static enum BD99955_COMMANDS charger_map_cmd = BD99955_INVALID_COMMAND; + +static struct mutex bd99955_map_mutex; + +static inline int ch_raw_read16(int cmd, int *param, + enum BD99955_COMMANDS map_cmd) +{ + int rv; + + /* Map the Charge command code to appropriate region */ + mutex_lock(&bd99955_map_mutex); + if (charger_map_cmd != map_cmd) { + rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, + BD99955_CMD_MAP_SET, map_cmd); + if (rv) + goto bd99955_read_cleanup; + + charger_map_cmd = map_cmd; + } + + rv = i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, cmd, param); + +bd99955_read_cleanup: + mutex_unlock(&bd99955_map_mutex); + + return rv; +} + +static inline int ch_raw_write16(int cmd, int param, + enum BD99955_COMMANDS map_cmd) +{ + int rv; + + /* Map the Charge command code to appropriate region */ + mutex_lock(&bd99955_map_mutex); + if (charger_map_cmd != map_cmd) { + rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, + BD99955_CMD_MAP_SET, map_cmd); + if (rv) + goto bd99955_write_cleanup; + + charger_map_cmd = map_cmd; + } + + rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, cmd, param); + +bd99955_write_cleanup: + mutex_unlock(&bd99955_map_mutex); + + return rv; +} + +/* chip specific interfaces */ + +int charger_set_input_current(int input_current) +{ + int rv; + + /* Input current step 32 mA */ + input_current &= ~0x1F; + + rv = ch_raw_write16(BD99955_CMD_IBUS_LIM_SET, input_current, + BD99955_BAT_CHG_COMMAND); + if (rv) + return rv; + + return ch_raw_write16(BD99955_CMD_ICC_LIM_SET, input_current, + BD99955_BAT_CHG_COMMAND); +} + +int charger_get_input_current(int *input_current) +{ + int rv; + + rv = ch_raw_read16(BD99955_CMD_IBUS_LIM_SET, input_current, + BD99955_BAT_CHG_COMMAND); + if (rv) + return rv; + + return ch_raw_read16(BD99955_CMD_ICC_LIM_SET, input_current, + BD99955_BAT_CHG_COMMAND); +} + +int charger_manufacturer_id(int *id) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +int charger_device_id(int *id) +{ + return ch_raw_read16(BD99955_CMD_CHIP_ID, id, BD99955_EXTENDED_COMMAND); +} + +int charger_get_option(int *option) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +int charger_set_option(int option) +{ + return EC_ERROR_UNIMPLEMENTED; +} + +/* Charger interfaces */ + +const struct charger_info *charger_get_info(void) +{ + return &bd99955_charger_info; +} + +int charger_get_status(int *status) +{ + *status = CHARGER_LEVEL_2; + + return EC_SUCCESS; +} + +int charger_set_mode(int mode) +{ + /* BD99955 does not support inhibit mode setting. */ + return EC_SUCCESS; +} + +int charger_get_current(int *current) +{ + return ch_raw_read16(BD99955_CMD_CHG_CURRENT, current, + BD99955_BAT_CHG_COMMAND); +} + +int charger_set_current(int current) +{ + /* Charge current step 64 mA */ + current &= ~0x3F; + + return ch_raw_write16(BD99955_CMD_CHG_CURRENT, current, + BD99955_BAT_CHG_COMMAND); +} + +int charger_get_voltage(int *voltage) +{ + return ch_raw_read16(BD99955_CMD_CHG_VOLTAGE, voltage, + BD99955_BAT_CHG_COMMAND); +} + +int charger_set_voltage(int voltage) +{ + /* + * The BD99955 will drop voltage to as low as requested. As the + * charger state machine will pass in 0 voltage, protect the system + * voltage by capping to the minimum. The reason is that the BD99955 + * only can regulate the system voltage which will kill the board's + * power if below 0. + */ + if (voltage == 0) { + const struct battery_info *bi = battery_get_info(); + + voltage = bi->voltage_min; + } + + /* Charge voltage step 16 mV */ + voltage &= ~0x0F; + return ch_raw_write16(BD99955_CMD_CHG_VOLTAGE, voltage, + BD99955_BAT_CHG_COMMAND); +} + +int charger_post_init(void) +{ + int rv; + + /* + * TODO: Disable charger & re-enable to initialize it. + */ + rv = charger_discharge_on_ac(1); + if (rv) + return rv; + + return charger_discharge_on_ac(0); +} + +int charger_discharge_on_ac(int enable) +{ + int rv; + int reg; + + rv = ch_raw_read16(BD99955_CMD_CHGOP_SET2, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + if (enable) { + reg |= BD99955_CHGOP_SET2_BATT_LEARN; + reg &= ~BD99955_CHGOP_SET2_CHG_EN; + } else { + reg &= ~BD99955_CHGOP_SET2_BATT_LEARN; + reg |= BD99955_CHGOP_SET2_CHG_EN; + } + + return ch_raw_write16(BD99955_CMD_CHGOP_SET2, reg, + BD99955_EXTENDED_COMMAND); +} diff --git a/driver/charger/bd99955.h b/driver/charger/bd99955.h new file mode 100644 index 0000000000..e027f8e357 --- /dev/null +++ b/driver/charger/bd99955.h @@ -0,0 +1,166 @@ +/* Copyright 2016 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. + * + * ROHM BD99955 battery charger driver. + */ + +#ifndef __CROS_EC_BD99955_H +#define __CROS_EC_BD99955_H + +#define BD99955_ADDR 0x12 /* 7bit address 0001_001 */ +#define I2C_ADDR_CHARGER BD99955_ADDR + +/* BD99955 commands to change the command code map */ +enum BD99955_COMMANDS { + BD99955_BAT_CHG_COMMAND, + BD99955_EXTENDED_COMMAND, + BD99955_DEBUG_COMMAND, + BD99955_INVALID_COMMAND +}; + +/* Charger parameters */ +#define CHARGER_NAME "bd99955" +#define CHARGE_V_MAX 19200 +#define CHARGE_V_MIN 3072 +#define CHARGE_V_STEP 16 +#define CHARGE_I_MAX 16320 +#define CHARGE_I_MIN 0 +#define CHARGE_I_OFF 0 +#define CHARGE_I_STEP 64 +#define INPUT_I_MAX 16352 +#define INPUT_I_MIN 0 +#define INPUT_I_STEP 32 + +/* Battery Charger Commands */ +#define BD99955_CMD_CHG_CURRENT 0x14 +#define BD99955_CMD_CHG_VOLTAGE 0x15 +#define BD99955_CMD_IBUS_LIM_SET 0x3C +#define BD99955_CMD_ICC_LIM_SET 0x3D +#define BD99955_CMD_PROTECT_SET 0x3E +#define BD99955_CMD_MAP_SET 0x3F + +/* Extended commands */ +#define BD99955_CMD_CHGSTM_STATUS 0x00 +#define BD99955_CMD_VBAT_VSYS_STATUS 0x01 +#define BD99955_CMD_VBUS_VCC_STATUS 0x02 +#define BD99955_CMD_CHGOP_STATUS 0x03 +#define BD99955_CMD_WDT_STATUS 0x04 +#define BD99955_CMD_CUR_ILIM_VAL 0x05 +#define BD99955_CMD_SEL_ILIM_VAL 0x06 +#define BD99955_CMD_EXT_IBUS_LIM_SET 0x07 +#define BD99955_CMD_EXT_ICC_LIM_SET 0x08 +#define BD99955_CMD_IOTG_LIM_SET 0x09 +#define BD99955_CMD_VIN_CTRL_SET 0x0A +#define BD99955_CMD_CHGOP_SET1 0x0B +#define BD99955_CMD_CHGOP_SET2 0x0C +#define BD99955_CMD_VBUSCLPS_TH_SET 0x0D +#define BD99955_CMD_VCCCLPS_TH_SET 0x0E +#define BD99955_CMD_CHGWDT_SET 0x0F +#define BD99955_CMD_BATTWDT_SET 0x10 +#define BD99955_CMD_VSYSREG_SETa 0x11 +#define BD99955_CMD_VSYSVAL_THH_SET 0x12 +#define BD99955_CMD_VSYSVAL_THL_SET 0x13 +#define BD99955_CMD_ITRICH_SET 0x14 +#define BD99955_CMD_IPRECH_SET 0x15 +#define BD99955_CMD_ICHG_SET 0x16 +#define BD99955_CMD_ITERM_SET 0x17 +#define BD99955_CMD_VPRECHG_TH_SET 0x18 +#define BD99955_CMD_VRBOOST_SET 0x19 +#define BD99955_CMD_VFASTCHG_REG_SET1 0x1A +#define BD99955_CMD_VFASTCHG_REG_SET2 0x1B +#define BD99955_CMD_VFASTCHG_REG_SET3 0x1C +#define BD99955_CMD_VRECHG_SET 0x1D +#define BD99955_CMD_VBATOVP_SET 0x1E +#define BD99955_CMD_IBATSHORT_SET 0x1F +#define BD99955_CMD_PROCHOT_CTRL_SET 0x20 +#define BD99955_CMD_PROCHOT_ICRIT_SET 0x21 +#define BD99955_CMD_PROCHOT_INORM_SET 0x22 +#define BD99955_CMD_PROCHOT_IDCHG_SET 0x23 +#define BD99955_CMD_PROCHOT_VSYS_SET 0x24 +#define BD99955_CMD_PMON_IOUT_CTRL_SET 0x25 +#define BD99955_CMD_PMON_DACIN_VAL 0x26 +#define BD99955_CMD_IOUT_DACIN_VAL 0x27 +#define BD99955_CMD_VCC_UCD_SET 0x28 +#define BD99955_CMD_VCC_UCD_STATUS 0x29 +#define BD99955_CMD_VCC_IDD_STATUS 0x2A +#define BD99955_CMD_VCC_UCD_FCTRL_SET 0x2B +#define BD99955_CMD_VCC_UCD_FCTRL_EN 0x2C +#define BD99955_CMD_VBUS_UCD_SET 0x30 +#define BD99955_CMD_VBUS_UCD_STATUS 0x31 +#define BD99955_CMD_VBUS_IDD_STATUS 0x32 +#define BD99955_CMD_VBUS_UCD_FCTRL_SET 0x33 +#define BD99955_CMD_VBUS_UCD_FCTRL_EN 0x34 +#define BD99955_CMD_CHIP_ID 0x38 +#define BD99955_CMD_CHIP_REV 0x39 +#define BD99955_CMD_IC_SET1 0x3A +#define BD99955_CMD_IC_SET2 0x3B +#define BD99955_CMD_SYSTEM_STATUS 0x3C +#define BD99955_CMD_SYSTEM_CTRL_SET 0x3D +#define BD99955_CMD_EXT_PROTECT_SET 0x3E +#define BD99955_CMD_EXT_MAP_SET 0x3F +#define BD99955_CMD_VM_CTRL_SET 0x40 +#define BD99955_CMD_THERM_WINDOW_SET1 0x41 +#define BD99955_CMD_THERM_WINDOW_SET2 0x42 +#define BD99955_CMD_THERM_WINDOW_SET3 0x43 +#define BD99955_CMD_THERM_WINDOW_SET4 0x44 +#define BD99955_CMD_THERM_WINDOW_SET5 0x45 +#define BD99955_CMD_IBATP_TH_SET 0x46 +#define BD99955_CMD_IBATM_TH_SET 0x47 +#define BD99955_CMD_VBAT_TH_SET 0x48 +#define BD99955_CMD_THERM_TH_SET 0x49 +#define BD99955_CMD_IACP_TH_SET 0x4A +#define BD99955_CMD_VACP_TH_SET 0x4B +#define BD99955_CMD_VBUS_TH_SET 0x4C +#define BD99955_CMD_VCC_TH_SET 0x4D +#define BD99955_CMD_VSYS_TH_SET 0x4E +#define BD99955_CMD_EXTIADP_TH_SET 0x4F +#define BD99955_CMD_IBATP_VAL 0x50 +#define BD99955_CMD_IBATP_AVE_VAL 0x51 +#define BD99955_CMD_IBATM_VAL 0x52 +#define BD99955_CMD_IBATM_AVE_VAL 0x53 +#define BD99955_CMD_VBAT_VAL 0x54 +#define BD99955_CMD_VBAT_AVE_VAL 0x55 +#define BD99955_CMD_THERM_VAL 0x56 +#define BD99955_CMD_VTH_VAL 0x57 +#define BD99955_CMD_IACP_VAL 0x58 +#define BD99955_CMD_IACP_AVE_VAL 0x59 +#define BD99955_CMD_VACP_VAL 0x5A +#define BD99955_CMD_VACP_AVE_VAL 0x5B +#define BD99955_CMD_VBUS_VAL 0x5C +#define BD99955_CMD_VBUS_AVE_VAL 0x5D +#define BD99955_CMD_VCC_VAL 0x5E +#define BD99955_CMD_VCC_AVE_VAL 0x5F +#define BD99955_CMD_VSYS_VAL 0x60 +#define BD99955_CMD_VSYS_AVE_VAL 0x61 +#define BD99955_CMD_EXTIADP_VAL 0x62 +#define BD99955_CMD_EXTIADP_AVE_VAL 0x63 +#define BD99955_CMD_VACPCLPS_TH_SET 0x64 +#define BD99955_CMD_INT0_SET 0x68 +#define BD99955_CMD_INT1_SET 0x69 +#define BD99955_CMD_INT2_SET 0x6A +#define BD99955_CMD_INT3_SET 0x6B +#define BD99955_CMD_INT4_SET 0x6C +#define BD99955_CMD_INT5_SET 0x6D +#define BD99955_CMD_INT6_SET 0x6E +#define BD99955_CMD_INT7_SET 0x6F +#define BD99955_CMD_INT0_STATUS 0x70 +#define BD99955_CMD_INT1_STATUS 0x71 +#define BD99955_CMD_INT2_STATUS 0x72 +#define BD99955_CMD_INT3_STATUS 0x73 +#define BD99955_CMD_INT4_STATUS 0x74 +#define BD99955_CMD_INT5_STATUS 0x75 +#define BD99955_CMD_INT6_STATUS 0x76 +#define BD99955_CMD_INT7_STATUS 0x77 +#define BD99955_CMD_REG0 0x78 +#define BD99955_CMD_REG1 0x79 +#define BD99955_CMD_OTPREG0 0x7A +#define BD99955_CMD_OTPREG1 0x7B +#define BD99955_CMD_SMBREG 0x7C +#define BD99955_CMD_DEBUG_MODE_SET 0x7F + +/* Charger operation control setting 2 */ +#define BD99955_CHGOP_SET2_CHG_EN (1 << 7) +#define BD99955_CHGOP_SET2_BATT_LEARN (1 << 8) + +#endif /* __CROS_EC_BD99955_H */ diff --git a/include/config.h b/include/config.h index 196990ac05..225aaedf4d 100644 --- a/include/config.h +++ b/include/config.h @@ -337,6 +337,7 @@ #undef CONFIG_CHARGER_ADC_AMON_BMON /* Compile charger-specific code for these chargers (pick at most one) */ +#undef CONFIG_CHARGER_BD99955 #undef CONFIG_CHARGER_BQ24707A #undef CONFIG_CHARGER_BQ24715 #undef CONFIG_CHARGER_BQ24725 -- cgit v1.2.1