From 55bd1930f1822d3f7947721e47004800a65b8095 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Tue, 29 Mar 2016 01:48:47 -0700 Subject: charger: bd99955: Add support for extended features Add support for charge port switching and extpower detection, which are not part of the standard charger API. In addition, add a console command for dumping all regs, which is helpful for debug. BUG=chrome-os-partner:51722 TEST=Manual with subsequent commit. Verify kevin charges at 3A input current when zinger is inserted, and verify battery actually charges. BRANCH=None Change-Id: I98a0c0142d26facc0e0b9ef7f1dcd003ebffd9c1 Signed-off-by: Shawn Nematbakhsh Reviewed-on: https://chromium-review.googlesource.com/335537 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Vijay P Hiremath Reviewed-by: Kevin K Wong Reviewed-by: Mary Ruthven --- driver/charger/bd99955.c | 146 +++++++++++++++++++++++++++++++++++++++++++---- driver/charger/bd99955.h | 24 +++++++- 2 files changed, 157 insertions(+), 13 deletions(-) diff --git a/driver/charger/bd99955.c b/driver/charger/bd99955.c index 27b50cade1..0880668dd0 100644 --- a/driver/charger/bd99955.c +++ b/driver/charger/bd99955.c @@ -32,12 +32,12 @@ static const struct charger_info bd99955_charger_info = { }; /* Charge command code map */ -static enum BD99955_COMMANDS charger_map_cmd = BD99955_INVALID_COMMAND; +static enum bd99955_command 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) + enum bd99955_command map_cmd) { int rv; @@ -61,7 +61,7 @@ bd99955_read_cleanup: } static inline int ch_raw_write16(int cmd, int param, - enum BD99955_COMMANDS map_cmd) + enum bd99955_command map_cmd) { int rv; @@ -104,15 +104,8 @@ int charger_set_input_current(int input_current) 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); + return ch_raw_read16(BD99955_CMD_CUR_ILIM_VAL, input_current, + BD99955_EXTENDED_COMMAND); } int charger_manufacturer_id(int *id) @@ -232,3 +225,132 @@ int charger_discharge_on_ac(int enable) return ch_raw_write16(BD99955_CMD_CHGOP_SET2, reg, BD99955_EXTENDED_COMMAND); } + +/*** Non-standard interface functions ***/ + +int bd99955_extpower_is_present(void) +{ + int reg; + + if (ch_raw_read16(BD99955_CMD_VBUS_VCC_STATUS, ®, + BD99955_EXTENDED_COMMAND)) + return 0; + + reg &= (BD99955_CMD_VBUS_VCC_STATUS_VCC_DETECT | + BD99955_CMD_VBUS_VCC_STATUS_VBUS_DETECT); + return !!reg; +} + +int bd99955_select_input_port(enum bd99955_charge_port port) +{ + int rv; + int reg; + + rv = ch_raw_read16(BD99955_CMD_VIN_CTRL_SET, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + if (port == BD99955_CHARGE_PORT_NONE) { + reg &= ~(BD99955_CMD_VIN_CTRL_SET_VBUS_EN | + BD99955_CMD_VIN_CTRL_SET_VBUS_EN); + } else if (port == BD99955_CHARGE_PORT_VBUS) { + reg |= BD99955_CMD_VIN_CTRL_SET_VBUS_EN; + reg &= ~BD99955_CMD_VIN_CTRL_SET_VCC_EN; + } else if (port == BD99955_CHARGE_PORT_VCC) { + reg |= BD99955_CMD_VIN_CTRL_SET_VCC_EN; + reg &= ~BD99955_CMD_VIN_CTRL_SET_VBUS_EN; + } else { + /* Invalid charge port */ + panic("Invalid charge port"); + } + + return ch_raw_write16(BD99955_CMD_VIN_CTRL_SET, reg, + BD99955_EXTENDED_COMMAND); +} + +#ifdef CONFIG_CMD_CHARGER +static int read_bat(uint8_t cmd) +{ + int read = 0; + + ch_raw_read16(cmd, &read, BD99955_BAT_CHG_COMMAND); + return read; +} + +static int read_ext(uint8_t cmd) +{ + int read = 0; + + ch_raw_read16(cmd, &read, BD99955_EXTENDED_COMMAND); + return read; +} + +/* Dump all readable registers on bd99955 */ +static int console_bd99955_dump_regs(int argc, char **argv) +{ + int i; + uint8_t regs[] = { 0x14, 0x15, 0x3c, 0x3d, 0x3e, 0x3f }; + + /* Battery group registers */ + for (i = 0; i < ARRAY_SIZE(regs); ++i) + ccprintf("BAT REG %4x: %4x\n", regs[i], read_bat(regs[i])); + + /* Extended group registers */ + for (i = 0; i < 0x7f; ++i) + ccprintf("EXT REG %4x: %4x\n", i, read_ext(i)); + + return 0; +} +DECLARE_CONSOLE_COMMAND(bd99955_dump, console_bd99955_dump_regs, + NULL, + "Dump all charger registers", + NULL); + +static int console_command_bd99955(int argc, char **argv) +{ + int rv, reg, data, val; + char rw, *e; + enum bd99955_command cmd; + + rw = argv[1][0]; + if (rw == 'r') { + if (argc < 4) + return EC_ERROR_PARAM_COUNT; + } else if (rw == 'w') { + if (argc < 5) + return EC_ERROR_PARAM_COUNT; + } else + return EC_ERROR_PARAM_COUNT; + + reg = strtoi(argv[2], &e, 16); + if (*e || reg < 0) + return EC_ERROR_PARAM2; + + cmd = strtoi(argv[3], &e, 0); + if (*e || cmd < 0) + return EC_ERROR_INVAL; + + if (argc == 5) { + val = strtoi(argv[4], &e, 16); + if (*e || val < 0) + return EC_ERROR_INVAL; + } + + if (rw == 'r') + rv = ch_raw_read16(reg, &data, cmd); + else { + rv = ch_raw_write16(reg, val, cmd); + if (rv == EC_SUCCESS) + rv = ch_raw_read16(reg, &data, cmd); + } + + CPRINTS("register 0x%x [%d] = 0x%x [%d]", reg, reg, data, data); + + return rv; +} +DECLARE_CONSOLE_COMMAND(bd99955, console_command_bd99955, + "bd99955 | ", + "Read or write a charger register", + NULL); +#endif /* CONFIG_CMD_CHARGER */ diff --git a/driver/charger/bd99955.h b/driver/charger/bd99955.h index e027f8e357..0dc45b29ae 100644 --- a/driver/charger/bd99955.h +++ b/driver/charger/bd99955.h @@ -12,13 +12,19 @@ #define I2C_ADDR_CHARGER BD99955_ADDR /* BD99955 commands to change the command code map */ -enum BD99955_COMMANDS { +enum bd99955_command { BD99955_BAT_CHG_COMMAND, BD99955_EXTENDED_COMMAND, BD99955_DEBUG_COMMAND, BD99955_INVALID_COMMAND }; +enum bd99955_charge_port { + BD99955_CHARGE_PORT_VBUS, + BD99955_CHARGE_PORT_VCC, + BD99955_CHARGE_PORT_NONE, +}; + /* Charger parameters */ #define CHARGER_NAME "bd99955" #define CHARGE_V_MAX 19200 @@ -44,6 +50,8 @@ enum BD99955_COMMANDS { #define BD99955_CMD_CHGSTM_STATUS 0x00 #define BD99955_CMD_VBAT_VSYS_STATUS 0x01 #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_WDT_STATUS 0x04 #define BD99955_CMD_CUR_ILIM_VAL 0x05 @@ -52,6 +60,10 @@ enum BD99955_COMMANDS { #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_VIN_CTRL_SET_PP_BOTH_THRU (1 << 11) +#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_VBUSCLPS_TH_SET 0x0D @@ -163,4 +175,14 @@ enum BD99955_COMMANDS { #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. + */ + +/* Return true if extpower is present on their input port. */ +int bd99955_extpower_is_present(void); +/* Select input port from {VCC, VBUS, NONE}. */ +int bd99955_select_input_port(enum bd99955_charge_port port); + #endif /* __CROS_EC_BD99955_H */ -- cgit v1.2.1