From e79b32eb3d2f61a23c2c9ac75003315c964f91c9 Mon Sep 17 00:00:00 2001 From: Vijay Hiremath Date: Tue, 29 Mar 2016 18:08:25 -0700 Subject: Charger: BD99955: Implement charger interfaces BUG=none BRANCH=none TEST=Manually tested on Amenia prototype. Used 'charger' console command to get the details. Change-Id: I131c8501a4e1cedc2b7073eb43f4735a27c1a55f Signed-off-by: Vijay Hiremath Reviewed-on: https://chromium-review.googlesource.com/336286 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Shawn N --- driver/charger/bd99955.c | 179 ++++++++++++++++++++++++++++++++++++++++++++--- driver/charger/bd99955.h | 31 ++++++-- 2 files changed, 196 insertions(+), 14 deletions(-) diff --git a/driver/charger/bd99955.c b/driver/charger/bd99955.c index 0880668dd0..3563c4ff14 100644 --- a/driver/charger/bd99955.c +++ b/driver/charger/bd99955.c @@ -84,6 +84,53 @@ bd99955_write_cleanup: return rv; } +/* BD99955 local interfaces */ + +static int bd99955_charger_enable(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_CMD_CHGOP_SET2_CHG_EN; + else + reg &= ~BD99955_CMD_CHGOP_SET2_CHG_EN; + + return ch_raw_write16(BD99955_CMD_CHGOP_SET2, reg, + BD99955_EXTENDED_COMMAND); +} + +static int bd99955_por_reset(void) +{ + return ch_raw_write16(BD99955_CMD_SYSTEM_CTRL_SET, + BD99955_CMD_SYSTEM_CTRL_SET_OTPLD | + BD99955_CMD_SYSTEM_CTRL_SET_ALLRST, + BD99955_EXTENDED_COMMAND); +} + +static int bd99955_reset_to_zero(void) +{ + int rv; + + rv = charger_set_current(0); + if (rv) + return rv; + + return charger_set_voltage(0); +} + +static int bd99955_get_charger_op_status(int *status) +{ + return ch_raw_read16(BD99955_CMD_CHGOP_STATUS, status, + BD99955_EXTENDED_COMMAND); +} + + /* chip specific interfaces */ int charger_set_input_current(int input_current) @@ -120,12 +167,36 @@ int charger_device_id(int *id) int charger_get_option(int *option) { - return EC_ERROR_UNIMPLEMENTED; + int rv; + int reg; + + rv = ch_raw_read16(BD99955_CMD_CHGOP_SET1, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + *option = reg; + rv = ch_raw_read16(BD99955_CMD_CHGOP_SET2, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + *option |= reg << 16; + + return EC_SUCCESS; } int charger_set_option(int option) { - return EC_ERROR_UNIMPLEMENTED; + int rv; + + rv = ch_raw_write16(BD99955_CMD_CHGOP_SET1, option & 0xFFFF, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + return ch_raw_write16(BD99955_CMD_CHGOP_SET2, (option >> 16) & 0xFFFF, + BD99955_EXTENDED_COMMAND); } /* Charger interfaces */ @@ -137,14 +208,105 @@ const struct charger_info *charger_get_info(void) int charger_get_status(int *status) { + int rv; + int reg; + int ch_status; + + /* charger level */ *status = CHARGER_LEVEL_2; + /* charger enable/inhibit */ + rv = ch_raw_read16(BD99955_CMD_CHGOP_SET2, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + if (!(reg & BD99955_CMD_CHGOP_SET2_CHG_EN)) + *status |= CHARGER_CHARGE_INHIBITED; + + /* charger alarm enable/inhibit */ + rv = ch_raw_read16(BD99955_CMD_PROCHOT_CTRL_SET, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + if (!(reg & (BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 | + BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 | + BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 | + BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 | + BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0))) + *status |= CHARGER_ALARM_INHIBITED; + + rv = bd99955_get_charger_op_status(®); + if (rv) + return rv; + + /* power fail */ + if (!(reg & BD99955_CMD_CHGOP_STATUS_RBOOST_UV)) + *status |= CHARGER_POWER_FAIL; + + /* Safety signal ranges & battery presence */ + ch_status = (reg & BD99955_CMD_CHGOP_STATUS_BATTEMP0) | + ((reg & BD99955_CMD_CHGOP_STATUS_BATTEMP1) << 1) | + ((reg & BD99955_CMD_CHGOP_STATUS_BATTEMP2) << 2); + + *status |= CHARGER_BATTERY_PRESENT; + + switch (ch_status) { + case BD99955_CMD_CHGOP_STATUS_BATTEMP_COLD1: + *status |= CHARGER_RES_COLD; + break; + case BD99955_CMD_CHGOP_STATUS_BATTEMP_COLD2: + *status |= CHARGER_RES_COLD; + *status |= CHARGER_RES_UR; + break; + case BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT1: + case BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT2: + *status |= CHARGER_RES_HOT; + break; + case BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT3: + *status |= CHARGER_RES_HOT; + *status |= CHARGER_RES_OR; + break; + case BD99955_CMD_CHGOP_STATUS_BATTEMP_BATOPEN: + *status &= ~CHARGER_BATTERY_PRESENT; + default: + break; + } + + /* source of power */ + if (bd99955_extpower_is_present()) + *status |= CHARGER_AC_PRESENT; + return EC_SUCCESS; } int charger_set_mode(int mode) { - /* BD99955 does not support inhibit mode setting. */ + int rv; + int enable; + + if (mode & CHARGE_FLAG_INHIBIT_CHARGE) + enable = 0; + else + enable = 1; + + rv = bd99955_charger_enable(enable); + if (rv) + return rv; + + if (mode & CHARGE_FLAG_POR_RESET) { + rv = bd99955_por_reset(); + if (rv) + return rv; + } + + if (mode & CHARGE_FLAG_RESET_TO_ZERO) { + rv = bd99955_reset_to_zero(); + if (rv) + return rv; + } + return EC_SUCCESS; } @@ -214,13 +376,10 @@ int charger_discharge_on_ac(int enable) 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; - } + if (enable) + reg |= BD99955_CMD_CHGOP_SET2_BATT_LEARN; + else + reg &= ~BD99955_CMD_CHGOP_SET2_BATT_LEARN; return ch_raw_write16(BD99955_CMD_CHGOP_SET2, reg, BD99955_EXTENDED_COMMAND); diff --git a/driver/charger/bd99955.h b/driver/charger/bd99955.h index 0dc45b29ae..9b1da4baf2 100644 --- a/driver/charger/bd99955.h +++ b/driver/charger/bd99955.h @@ -52,7 +52,21 @@ enum bd99955_charge_port { #define BD99955_CMD_VBUS_VCC_STATUS 0x02 #define BD99955_CMD_VBUS_VCC_STATUS_VCC_DETECT (1 << 8) #define BD99955_CMD_VBUS_VCC_STATUS_VBUS_DETECT (1 << 0) + #define BD99955_CMD_CHGOP_STATUS 0x03 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP2 (1 << 10) +#define BD99955_CMD_CHGOP_STATUS_BATTEMP1 (1 << 9) +#define BD99955_CMD_CHGOP_STATUS_BATTEMP0 (1 << 8) +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_ROOMTEMP 0 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT1 1 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT2 2 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT3 3 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_COLD1 4 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_COLD2 5 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_DISABLE 6 +#define BD99955_CMD_CHGOP_STATUS_BATTEMP_BATOPEN 7 +#define BD99955_CMD_CHGOP_STATUS_RBOOST_UV (1 << 1) + #define BD99955_CMD_WDT_STATUS 0x04 #define BD99955_CMD_CUR_ILIM_VAL 0x05 #define BD99955_CMD_SEL_ILIM_VAL 0x06 @@ -64,8 +78,12 @@ enum bd99955_charge_port { #define BD99955_CMD_VIN_CTRL_SET_VBUS_PRIORITY (1 << 7) #define BD99955_CMD_VIN_CTRL_SET_VBUS_EN (1 << 6) #define BD99955_CMD_VIN_CTRL_SET_VCC_EN (1 << 5) + #define BD99955_CMD_CHGOP_SET1 0x0B #define BD99955_CMD_CHGOP_SET2 0x0C +#define BD99955_CMD_CHGOP_SET2_BATT_LEARN (1 << 8) +#define BD99955_CMD_CHGOP_SET2_CHG_EN (1 << 7) + #define BD99955_CMD_VBUSCLPS_TH_SET 0x0D #define BD99955_CMD_VCCCLPS_TH_SET 0x0E #define BD99955_CMD_CHGWDT_SET 0x0F @@ -86,6 +104,12 @@ enum bd99955_charge_port { #define BD99955_CMD_VBATOVP_SET 0x1E #define BD99955_CMD_IBATSHORT_SET 0x1F #define BD99955_CMD_PROCHOT_CTRL_SET 0x20 +#define BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 (1 << 4) +#define BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 (1 << 3) +#define BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 (1 << 2) +#define BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 (1 << 1) +#define BD99955_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0 (1 << 0) + #define BD99955_CMD_PROCHOT_ICRIT_SET 0x21 #define BD99955_CMD_PROCHOT_INORM_SET 0x22 #define BD99955_CMD_PROCHOT_IDCHG_SET 0x23 @@ -109,6 +133,9 @@ enum bd99955_charge_port { #define BD99955_CMD_IC_SET2 0x3B #define BD99955_CMD_SYSTEM_STATUS 0x3C #define BD99955_CMD_SYSTEM_CTRL_SET 0x3D +#define BD99955_CMD_SYSTEM_CTRL_SET_OTPLD (1 << 1) +#define BD99955_CMD_SYSTEM_CTRL_SET_ALLRST (1 << 0) + #define BD99955_CMD_EXT_PROTECT_SET 0x3E #define BD99955_CMD_EXT_MAP_SET 0x3F #define BD99955_CMD_VM_CTRL_SET 0x40 @@ -171,10 +198,6 @@ enum bd99955_charge_port { #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) - /* * Non-standard interface functions - bd99955 integrates additional * functionality not part of the standard charger interface. -- cgit v1.2.1