diff options
author | Rong Chang <rongchang@chromium.org> | 2015-05-08 16:44:43 +0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-08 21:49:02 +0000 |
commit | 26410eedde5f9e0a25a140ede8c132a43978b623 (patch) | |
tree | 10cf62f1febf0737e2bbc9c4bde02826eba50f0b | |
parent | 377384e40023b613fb7369e6043247a93272b05f (diff) | |
download | chrome-ec-26410eedde5f9e0a25a140ede8c132a43978b623.tar.gz |
charger: Add Intersil charger ISL9237
ISL9237 is a buck-boost narrow output voltage DC charger. This change
provides interfaces to satisfy external dependencies for
charge_state_v2.
ISL9237's charging voltage control is different from smart battery
chargers. And there's no SBC compatible charging mode and status. So
this CL modified charger_set_voltage() behavior by controlling VSYS
voltage.
BRANCH=none
BUG=none
TEST=ran on reworked glados
Signed-off-by: Rong Chang <rongchang@chromium.org>
Change-Id: Ibbbf805bbbe1ee06f87a41cde3e39acbf2e105b4
Reviewed-on: https://chromium-review.googlesource.com/272882
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Commit-Queue: Aaron Durbin <adurbin@chromium.org>
Trybot-Ready: Aaron Durbin <adurbin@chromium.org>
Tested-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/charger/isl9237.c | 233 | ||||
-rw-r--r-- | driver/charger/isl9237.h | 250 |
3 files changed, 484 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 997726fe24..aff6f45aa1 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -35,6 +35,7 @@ driver-$(CONFIG_CHARGER_BQ24773)+=charger/bq24773.o driver-$(CONFIG_CHARGER_BQ25890)+=charger/bq2589x.o driver-$(CONFIG_CHARGER_BQ25892)+=charger/bq2589x.o driver-$(CONFIG_CHARGER_BQ25895)+=charger/bq2589x.o +driver-$(CONFIG_CHARGER_ISL9237)+=charger/isl9237.o # I/O expander driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander_pca9534.o diff --git a/driver/charger/isl9237.c b/driver/charger/isl9237.c new file mode 100644 index 0000000000..29257f85f7 --- /dev/null +++ b/driver/charger/isl9237.c @@ -0,0 +1,233 @@ +/* Copyright 2015 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. + * + * Intersil ISL9237 battery charger driver. + */ + +#include "battery.h" +#include "battery_smart.h" +#include "charger.h" +#include "console.h" +#include "common.h" +#include "i2c.h" +#include "isl9237.h" +#include "util.h" + +#define DEFAULT_R_AC 20 +#define DEFAULT_R_SNS 10 +#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC +#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR +#define REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_SNS / R_SNS) +#define CURRENT_TO_REG(CUR) ((CUR) * R_SNS / DEFAULT_R_SNS) +#define AC_REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_AC / R_AC) +#define AC_CURRENT_TO_REG(CUR) ((CUR) * R_AC / DEFAULT_R_AC) + +/* Charger parameters */ +static const struct charger_info isl9237_charger_info = { + .name = CHARGER_NAME, + .voltage_max = CHARGE_V_MAX, + .voltage_min = CHARGE_V_MIN, + .voltage_step = CHARGE_V_STEP, + .current_max = REG_TO_CURRENT(CHARGE_I_MAX), + .current_min = REG_TO_CURRENT(CHARGE_I_MIN), + .current_step = REG_TO_CURRENT(CHARGE_I_STEP), + .input_current_max = AC_REG_TO_CURRENT(INPUT_I_MAX), + .input_current_min = AC_REG_TO_CURRENT(INPUT_I_MIN), + .input_current_step = AC_REG_TO_CURRENT(INPUT_I_STEP), +}; + +static inline int raw_read8(int offset, int *value) +{ + return i2c_read8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +static inline int raw_read16(int offset, int *value) +{ + return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +static inline int raw_write16(int offset, int value) +{ + return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value); +} + +static int isl9237_set_current(uint16_t current) +{ + return raw_write16(ISL9237_REG_CHG_CURRENT, CURRENT_TO_REG(current)); +} + +static int isl9237_set_voltage(uint16_t voltage) +{ + return raw_write16(ISL9237_REG_SYS_VOLTAGE_MAX, voltage); +} + +/* chip specific interfaces */ + +int charger_set_input_current(int input_current) +{ + int rv; + uint16_t reg = AC_CURRENT_TO_REG(input_current); + + rv = raw_write16(ISL9237_REG_ADAPTER_CURRENT1, reg); + if (rv) + return rv; + + return raw_write16(ISL9237_REG_ADAPTER_CURRENT2, reg); +} + +int charger_get_input_current(int *input_current) +{ + int rv; + int reg; + + rv = raw_read16(ISL9237_REG_ADAPTER_CURRENT1, ®); + if (rv) + return rv; + + *input_current = AC_REG_TO_CURRENT(reg); + return EC_SUCCESS; +} + +int charger_manufacturer_id(int *id) +{ + int rv; + int reg; + + rv = raw_read16(ISL9237_REG_MANUFACTURER_ID, ®); + if (rv) + return rv; + + *id = reg; + return EC_SUCCESS; +} + +int charger_device_id(int *id) +{ + int rv; + int reg; + + rv = raw_read16(ISL9237_REG_DEVICE_ID, ®); + if (rv) + return rv; + + *id = reg; + return EC_SUCCESS; +} + +int charger_get_option(int *option) +{ + int rv; + uint32_t controls; + int reg; + + rv = raw_read8(ISL9237_REG_CONTROL0, ®); + if (rv) + return rv; + + controls = reg; + rv = raw_read16(ISL9237_REG_CONTROL1, ®); + if (rv) + return rv; + + controls |= reg << 16; + *option = controls; + return EC_SUCCESS; +} + +int charger_set_option(int option) +{ + int rv; + uint16_t reg; + + reg = option & 0xffff; + rv = raw_write16(ISL9237_REG_CONTROL0, reg); + + if (rv) + return rv; + + reg = (option >> 16) & 0xffff; + return raw_write16(ISL9237_REG_CONTROL1, reg); +} + +/* Charger interfaces */ + +const struct charger_info *charger_get_info(void) +{ + return &isl9237_charger_info; +} + +int charger_get_status(int *status) +{ + *status = CHARGER_LEVEL_2; + + return EC_SUCCESS; +} + +int charger_set_mode(int mode) +{ + /* ISL9237 does not support inhibit mode setting. */ + return EC_SUCCESS; +} + +int charger_get_current(int *current) +{ + int rv; + int reg; + + rv = raw_read16(ISL9237_REG_CHG_CURRENT, ®); + if (rv) + return rv; + + *current = REG_TO_CURRENT(reg); + return EC_SUCCESS; +} + +int charger_set_current(int current) +{ + return isl9237_set_current(current); +} + +int charger_get_voltage(int *voltage) +{ + return raw_read16(ISL9237_REG_SYS_VOLTAGE_MAX, voltage); +} + +int charger_set_voltage(int voltage) +{ + /* The ISL9237 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 ISL9237 + * 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; + } + + return isl9237_set_voltage(voltage); +} + +int charger_post_init(void) +{ + return EC_SUCCESS; +} + +int charger_discharge_on_ac(int enable) +{ + int rv; + int control1; + + rv = raw_read16(ISL9237_REG_CONTROL1, &control1); + if (rv) + return rv; + + control1 &= ~ISL9237_C1_LEARN_MODE_AUTOEXIT; + if (enable) + control1 |= ISL9237_C1_LEARN_MODE_ENABLE; + else + control1 &= ~ISL9237_C1_LEARN_MODE_ENABLE; + + return raw_write16(ISL9237_REG_CONTROL1, control1); +} + diff --git a/driver/charger/isl9237.h b/driver/charger/isl9237.h new file mode 100644 index 0000000000..30e5ed970d --- /dev/null +++ b/driver/charger/isl9237.h @@ -0,0 +1,250 @@ +/* Copyright 2015 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. + * + * Intersil ISL-9237 battery charger driver. + */ + +#ifndef __CROS_EC_CHARGER_ISL9237_H +#define __CROS_EC_CHARGER_ISL9237_H + +#define ISL9237_ADDR 0x12 /* 7bit address 0001001 */ + +/* Registers */ +#define ISL9237_REG_CHG_CURRENT 0x14 +#define ISL9237_REG_ADAPTER_CURRENT1 0x3f +#define ISL9237_REG_ADAPTER_CURRENT2 0x3b +#define ISL9237_REG_SYS_VOLTAGE_MAX 0x15 +#define ISL9237_REG_SYS_VOLTAGE_MIN 0x3e +#define ISL9237_REG_PROCHOT_AC 0x47 +#define ISL9237_REG_PROCHOT_DC 0x48 +#define ISL9237_REG_T1_T2 0x38 +#define ISL9237_REG_CONTROL1 0x3c +#define ISL9237_REG_CONTROL2 0x3d +#define ISL9237_REG_INFO 0x3a +#define ISL9237_REG_OTG_VOLTAGE 0x49 +#define ISL9237_REG_OTG_CURRENT 0x4a +#define ISL9237_REG_MANUFACTURER_ID 0xfe +#define ISL9237_REG_DEVICE_ID 0xff +#define ISL9237_REG_PROCHOT_TIME 0x39 +#define ISL9237_REG_CONTROL0 0x39 + +/* Sense resistor default values in mOhm */ +#define ISL9237_DEFAULT_SENSE_RESISTOR_AC 20 +#define ISL9237_DEFAULT_SENSE_RESISTOR 10 + +/* Maximum charging current register value */ +#define ISL9237_CURRENT_REG_MAX 0x17c0 /* bit<12:2> 10111110000 */ + +/* 2-level adpater current limit duration T1 & T2 in micro seconds */ +#define ISL9237_T1_10000 0x00 +#define ISL9237_T1_20000 0x01 +#define ISL9237_T1_15000 0x02 +#define ISL9237_T1_5000 0x03 +#define ISL9237_T1_1000 0x04 +#define ISL9237_T1_500 0x05 +#define ISL9237_T1_100 0x06 +#define ISL9237_T1_0 0x07 +#define ISL9237_T2_10 (0x00 << 8) +#define ISL9237_T2_100 (0x01 << 8) +#define ISL9237_T2_500 (0x02 << 8) +#define ISL9237_T2_1000 (0x03 << 8) +#define ISL9237_T2_300 (0x04 << 8) +#define ISL9237_T2_750 (0x05 << 8) +#define ISL9237_T2_2000 (0x06 << 8) +#define ISL9237_T2_10000 (0x07 << 8) + +#define ISL9237_SYS_VOLTAGE_REG_MAX 13824 +#define ISL9237_SYS_VOLTAGE_REG_MIN 2048 + +/* PROCHOT# debounce time and duration time in micro seconds */ +#define ISL9237_PROCHOT_DURATION_10000 (0 << 6) +#define ISL9237_PROCHOT_DURATION_20000 (1 << 6) +#define ISL9237_PROCHOT_DURATION_15000 (2 << 6) +#define ISL9237_PROCHOT_DURATION_5000 (3 << 6) +#define ISL9237_PROCHOT_DURATION_1000 (4 << 6) +#define ISL9237_PROCHOT_DURATION_500 (5 << 6) +#define ISL9237_PROCHOT_DURATION_100000 (6 << 6) +#define ISL9237_PROCHOT_DURATION_0 (7 << 6) +#define ISL9237_PROCHOT_DURATION_MASK (7 << 6) + +#define ISL9237_PROCHOT_DEBOUNCE_10 (0 << 9) +#define ISL9237_PROCHOT_DEBOUNCE_100 (1 << 9) +#define ISL9237_PROCHOT_DEBOUNCE_500 (2 << 9) +#define ISL9237_PROCHOT_DEBOUNCE_1000 (3 << 9) +#define ISL9237_PROCHOT_DEBOUNCE_MASK (3 << 9) + +/* Maximum PROCHOT register value */ +#define ISL9237_PROCHOT_AC_REG_MAX 6400 +#define ISL9237_PROCHOT_DC_REG_MAX 12800 + +/* Control0: adapter voltage regulation reference */ +#define ISL9237_C0_VREG_REF_3900 0 +#define ISL9237_C0_VREG_REF_4200 1 +#define ISL9237_C0_VREG_REF_4500 2 +#define ISL9237_C0_VREG_REF_4800 3 +#define ISL9237_C0_VREG_REF_MASK 0x03 + +/* Control0: disable adapter voltaqe regulation */ +#define ISL9237_C0_DISABLE_VREG (1 << 2) + +/* Control0: battery DCHOT reference for RS2 == 20mOhm */ +#define ISL9237_C0_DCHOT_6A (0 << 3) +#define ISL9237_C0_DCHOT_5A (1 << 3) +#define ISL9237_C0_DCHOT_4A (2 << 3) +#define ISL9237_C0_DCHOT_3A (3 << 3) +#define ISL9237_C0_DCHOT_MASK (3 << 3) + +/* Control1: general purpose comparator debounce time in micro second */ +#define ISL9237_C1_GP_DEBOUNCE_2 (0 << 14) +#define ISL9237_C1_GP_DEBOUNCE_12 (1 << 14) +#define ISL9237_C1_GP_DEBOUNCE_2000 (2 << 14) +#define ISL9237_C1_GP_DEBOUNCE_5000000 (3 << 14) +#define ISL9237_C1_GP_DEBOUNCE_MASK (3 << 14) + +/* Control1: learn mode */ +#define ISL9237_C1_LEARN_MODE_AUTOEXIT (1 << 13) +#define ISL9237_C1_LEARN_MODE_ENABLE (1 << 12) + +/* Control1: OTG enable */ +#define ISL9237_C1_OTG (1 << 11) + +/* Control1: audio filter */ +#define ISL9237_C1_AUDIO_FILTER (1 << 10) + +/* Control1: switch frequency */ +#define ISL9237_C1_SWITCH_FREQ_PROG (0 << 7) /* 1000kHz or PROG */ +#define ISL9237_C1_SWITCH_FREQ_913K (1 << 7) +#define ISL9237_C1_SWITCH_FREQ_839K (2 << 7) +#define ISL9237_C1_SWITCH_FREQ_777K (3 << 7) +#define ISL9237_C1_SWITCH_FREQ_723K (4 << 7) +#define ISL9237_C1_SWITCH_FREQ_676K (5 << 7) +#define ISL9237_C1_SWITCH_FREQ_635K (6 << 7) +#define ISL9237_C1_SWITCH_FREQ_599K (7 << 7) +#define ISL9237_C1_SWITCH_FREQ_MASK (7 << 7) + +/* Control1: turbo mode */ +#define ISL9237_C1_TURBO_MODE (1 << 6) + +/* Control1: AMON & BMON */ +#define ISL9237_C1_DISABLE_MON (1 << 5) +#define ISL9237_C1_SELECT_BMON (1 << 4) + +/* Control1: PSYS, VSYS, VSYSLO */ +#define ISL9237_C1_ENABLE_PSYS (1 << 3) +#define ISL9237_C1_ENABLE_VSYS (1 << 2) +#define ISL9237_C1_VSYSLO_REF_6000 0 +#define ISL9237_C1_VSYSLO_REF_6300 1 +#define ISL9237_C1_VSYSLO_REF_6600 2 +#define ISL9237_C1_VSYSLO_REF_6900 3 +#define ISL9237_C1_VSYSLO_REF_MASK 3 + +/* Control2: trickle charging current in mA */ +#define ISL9237_C2_TRICKLE_256 (0 << 14) +#define ISL9237_C2_TRICKLE_128 (1 << 14) +#define ISL9237_C2_TRICKLE_64 (2 << 14) +#define ISL9237_C2_TRICKLE_512 (3 << 14) +#define ISL9237_C2_TRICKLE_MASK (3 << 14) + +/* Control2: OTGEN debounce time in ms */ +#define ISL9237_C2_OTG_DEBOUNCE_1300 (0 << 13) +#define ISL9237_C2_OTG_DEBOUNCE_150 (1 << 13) +#define ISL9237_C2_OTG_DEBOUNCE_MASK (1 << 13) + +/* Control2: 2-level adapter over current */ +#define ISL9237_C2_2LVL_OVERCURRENT (1 << 12) + +/* Control2: adapter insertion debounce time in ms */ +#define ISL9237_C2_ADAPTER_DEBOUNCE_1300 (0 << 11) +#define ISL9237_C2_ADAPTER_DEBOUNCE_150 (1 << 11) +#define ISL9237_C2_ADAPTER_DEBOUNCE_MASK (1 << 11) + +/* Control2: PROCHOT debounce time in uS */ +#define ISL9237_C2_PROCHOT_DEBOUNCE_10 (0 << 9) +#define ISL9237_C2_PROCHOT_DEBOUNCE_100 (1 << 9) +#define ISL9237_C2_PROCHOT_DEBOUNCE_500 (2 << 9) +#define ISL9237_C2_PROCHOT_DEBOUNCE_1000 (3 << 9) +#define ISL9237_C2_PROCHOT_DEBOUNCE_MASK (3 << 9) + +/* Control2: min PROCHOT duration in uS */ +#define ISL9237_C2_PROCHOT_DURATION_10000 (0 << 6) +#define ISL9237_C2_PROCHOT_DURATION_20000 (1 << 6) +#define ISL9237_C2_PROCHOT_DURATION_15000 (2 << 6) +#define ISL9237_C2_PROCHOT_DURATION_5000 (3 << 6) +#define ISL9237_C2_PROCHOT_DURATION_1000 (4 << 6) +#define ISL9237_C2_PROCHOT_DURATION_500 (5 << 6) +#define ISL9237_C2_PROCHOT_DURATION_100 (6 << 6) +#define ISL9237_C2_PROCHOT_DURATION_0 (7 << 6) +#define ISL9237_C2_PROCHOT_DURATION_MASK (7 << 6) + +/* Control2: turn off ASGATE in OTG mode */ +#define ISL9237_C2_ASGATE_OFF (1 << 5) + +/* Control2: CMIN, general purpose comparator reference in mV */ +#define ISL9237_C2_CMIN_2000 (0 << 4) +#define ISL9237_C2_CMIN_1200 (1 << 4) + +/* Control2: general purpose comparator enable */ +#define ISL9237_C2_COMPARATOR (1 << 3) + +/* Control2: invert CMOUT, general purpose comparator output, polarity */ +#define ISL9237_C2_INVERT_CMOUT (1 << 2) + +/* Control2: disable WOC, way over current */ +#define ISL9237_C2_WOC_OFF (1 << 1) + +/* Control2: PSYS gain in uA/W */ +#define ISL9237_C2_PSYS_GAIN_1_44 0 +#define ISL9237_C2_PSYS_GAIN_0_36 1 + +/* OTG voltage limit in mV, current limit in mA */ +#define ISL9237_OTG_VOLTAGE_MIN 4864 +#define ISL9237_OTG_VOLTAGE_MAX 5376 +#define ISL9237_OTG_CURRENT_MAX 4096 + +/* Info register fields */ +#define ISL9237_INFO_PROG_RESISTOR_MASK 0xf +#define ISL9237_INFO_TRICKLE_ACTIVE_MASK (1 << 4) +#define ISL9237_INFO_PSTATE_SHIFT 5 +#define ISL9237_INFO_PSTATE_MASK 3 + +enum isl9237_power_stage { + BUCK_MODE, + BOOST_MODE, + BUCK_BOOST_MODE, + REVERSE_BUCK_MODE +}; + +#define ISL9237_INFO_FSM_STATE_SHIFT 7 +#define ISL9237_INFO_FSM_STATE_MASK 7 + +enum isl9237_fsm_state { + FSM_OFF, + FSM_BAT, + FSM_ADPT, + FSM_ACOK, + FSM_VSYS, + FSM_CHRG, + FSM_ENTOG, + FSM_OTG +}; + +#define ISL9237_INFO_VSYSLO (1 << 10) +#define ISL9237_INFO_DCHOT (1 << 11) +#define ISL9237_INFO_ACHOT (1 << 12) + + +#define CHARGER_NAME "isl9237" +#define CHARGE_V_MAX ISL9237_SYS_VOLTAGE_REG_MAX +#define CHARGE_V_MIN ISL9237_SYS_VOLTAGE_REG_MIN +#define CHARGE_V_STEP 8 +#define CHARGE_I_MAX ISL9237_CURRENT_REG_MAX +#define CHARGE_I_MIN 4 +#define CHARGE_I_OFF 0 +#define CHARGE_I_STEP 4 +#define INPUT_I_MAX ISL9237_CURRENT_REG_MAX +#define INPUT_I_MIN 4 +#define INPUT_I_STEP 4 + +#define I2C_ADDR_CHARGER ISL9237_ADDR +#endif /* __CROS_EC_CHARGER_ISL9237_H */ |