summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2015-05-08 16:44:43 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-08 21:49:02 +0000
commit26410eedde5f9e0a25a140ede8c132a43978b623 (patch)
tree10cf62f1febf0737e2bbc9c4bde02826eba50f0b
parent377384e40023b613fb7369e6043247a93272b05f (diff)
downloadchrome-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.mk1
-rw-r--r--driver/charger/isl9237.c233
-rw-r--r--driver/charger/isl9237.h250
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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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, &reg);
+ if (rv)
+ return rv;
+
+ controls = reg;
+ rv = raw_read16(ISL9237_REG_CONTROL1, &reg);
+ 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, &reg);
+ 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 */