diff options
Diffstat (limited to 'common/charger_bq24725.c')
-rw-r--r-- | common/charger_bq24725.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/common/charger_bq24725.c b/common/charger_bq24725.c new file mode 100644 index 0000000000..5b70d0d0c5 --- /dev/null +++ b/common/charger_bq24725.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2012 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 bq24725 battery charger driver. + */ + +#include "board.h" +#include "charger.h" +#include "charger_bq24725.h" +#include "console.h" +#include "common.h" +#include "i2c.h" +#include "smart_battery.h" +#include "uart.h" +#include "util.h" + +/* Sense resistor configurations and macros */ +#define DEFAULT_SENSE_RESISTOR 10 +#define R_SNS CONFIG_BQ24725_R_SNS +#define R_AC CONFIG_BQ24725_R_AC +#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) +#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) + +/* Charger infomation + * charge voltage bitmask: 0111 1111 1111 0000 + * charge current bitmask: 0001 1111 1000 0000 + * input current bitmask : 0000 0000 1000 0000 + */ +static const struct charger_info bq24725_charger_info = { + .name = "bq24725", + .voltage_max = 19200, + .voltage_min = 1024, + .voltage_step = 16, + .current_max = REG_TO_CURRENT(8128, R_SNS), + .current_min = REG_TO_CURRENT(128, R_SNS), + .current_step = REG_TO_CURRENT(128, R_SNS), + .input_current_max = REG_TO_CURRENT(8064, R_AC), + .input_current_min = REG_TO_CURRENT(128, R_AC), + .input_current_step = REG_TO_CURRENT(128, R_AC), +}; + +/* bq24725 specific interfaces */ + +static int charger_set_input_current(int input_current) +{ + return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_INPUT_CURRENT, CURRENT_TO_REG(input_current, R_AC)); +} + +static int charger_get_input_current(int *input_current) +{ + int rv; + int reg; + + rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_INPUT_CURRENT, ®); + if (rv) + return rv; + + *input_current = REG_TO_CURRENT(reg, R_AC); + + return EC_SUCCESS; +} + +static int charger_manufacturer_id(int *id) +{ + return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_MANUFACTURE_ID, id); +} + +static int charger_device_id(int *id) +{ + return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_DEVICE_ID, id); +} + +static int charger_get_option(int *option) +{ + return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_CHARGE_OPTION, option); +} + +static int charger_set_option(int option) +{ + return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, + BQ24725_CHARGE_OPTION, option); +} + +/* charger interfaces */ +const struct charger_info *charger_get_info(void) +{ + return &bq24725_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 & OPTION_CHARGE_INHIBIT) + *status |= CHARGER_CHARGE_INHIBITED; + + return EC_SUCCESS; +} + +int charger_set_mode(int mode) +{ + int rv; + int option; + + rv = charger_get_option(&option); + if (rv) + return rv; + + if (mode & CHARGE_FLAG_INHIBIT_CHARGE) + option |= OPTION_CHARGE_INHIBIT; + else + option &= ~OPTION_CHARGE_INHIBIT; + return charger_set_option(option); +} + +int charger_get_current(int *current) +{ + int rv; + int reg; + + rv = i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + SB_CHARGING_CURRENT, ®); + if (rv) + return rv; + + *current = REG_TO_CURRENT(reg, R_SNS); + return EC_SUCCESS; +} + +int charger_set_current(int current) +{ + return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, + SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); +} + +int charger_get_voltage(int *voltage) +{ + return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, + SB_CHARGING_VOLTAGE, voltage); +} + +int charger_set_voltage(int voltage) +{ + return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, + SB_CHARGING_VOLTAGE, voltage); +} + +/* Initialization */ +int charger_init(void) +{ + /* bq24725 power on reset state: + * charger watch dog timer = 175sec + * charger input current limit = 4096 * 10 / RS_AC + */ + return EC_SUCCESS; +} + + +/* Console commands */ + +static void print_usage(void) +{ + uart_puts("Usage: charger [set_command value]\n"); + uart_puts(" charger input input_current_in_mA\n"); + uart_puts(" charger voltage voltage_limit_in_mV\n"); + uart_puts(" charger current current_limit_in_mA\n\n"); +} + +static int print_info(void) +{ + int rv; + int d; + const struct charger_info *info; + + uart_puts("Charger properties : now (max, min, step)\n"); + + /* info */ + info = charger_get_info(); + uart_printf(" name : %s\n", info->name); + + /* manufacturer id */ + rv = charger_manufacturer_id(&d); + if (rv) + return rv; + uart_printf(" manufacturer id: 0x%04x\n", d); + + /* device id */ + rv = charger_device_id(&d); + if (rv) + return rv; + uart_printf(" device id : 0x%04x\n", d); + + /* charge voltage limit */ + rv = charger_get_voltage(&d); + if (rv) + return rv; + uart_printf(" voltage : %5d (%5d, %4d, %3d)\n", d, + info->voltage_max, info->voltage_min, info->voltage_step); + + /* charge current limit */ + rv = charger_get_current(&d); + if (rv) + return rv; + uart_printf(" current : %5d (%5d, %4d, %3d)\n", d, + info->current_max, info->current_min, info->current_step); + + /* input current limit */ + rv = charger_get_input_current(&d); + if (rv) + return rv; + + uart_printf(" input current : %5d (%5d, %4d, %3d)\n", d, + info->input_current_max, info->input_current_min, + info->input_current_step); + + return EC_SUCCESS; +} + +static int command_charger(int argc, char **argv) +{ + int d; + char *endptr; + + if (argc != 3) { + if (argc != 1) + print_usage(); + return print_info(); + } + + if (strcasecmp(argv[1], "input") == 0) { + d = strtoi(argv[2], &endptr, 0); + if (*endptr) { + print_usage(); + return EC_ERROR_UNKNOWN; + } + return charger_set_input_current(d); + } else if (strcasecmp(argv[1], "current") == 0) { + d = strtoi(argv[2], &endptr, 0); + if (*endptr) { + print_usage(); + return EC_ERROR_UNKNOWN; + } + return charger_set_current(d); + } else if (strcasecmp(argv[1], "voltage") == 0) { + d = strtoi(argv[2], &endptr, 0); + if (*endptr) { + print_usage(); + return EC_ERROR_UNKNOWN; + } + return charger_set_voltage(d); + } else { + print_usage(); + return print_info(); + } + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(charger, command_charger); + |