summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2016-03-29 01:48:47 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-03-31 14:53:52 -0700
commit55bd1930f1822d3f7947721e47004800a65b8095 (patch)
treed25a165650b826fdac88af91f921faa6b238e4b9 /driver
parent7aa42e2ba9a33530dd97bc5e814cd1b73d2cbb25 (diff)
downloadchrome-ec-55bd1930f1822d3f7947721e47004800a65b8095.tar.gz
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 <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/335537 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Vijay P Hiremath <vijay.p.hiremath@intel.com> Reviewed-by: Kevin K Wong <kevin.k.wong@intel.com> Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/charger/bd99955.c146
-rw-r--r--driver/charger/bd99955.h24
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, &reg,
+ 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, &reg,
+ 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 <r/w> <reg_hex> <cmd_type> | <val_hex>",
+ "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 */