summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijay Hiremath <vijay.p.hiremath@intel.com>2019-04-12 18:09:33 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-26 00:17:34 -0700
commit663e0baf89e661020ad640d2691177c95abae815 (patch)
treec2c89ba5ea142eec34f0923feddc718b04161e68
parent2362b119299e2122832656aa0a1affda74654ce6 (diff)
downloadchrome-ec-663e0baf89e661020ad640d2691177c95abae815.tar.gz
charger: Add basic driver code for ISL9241
The ISL9241 is a digitally configurable buck-boost battery charger that can support both Narrow Voltage Direct Charging (NVDC) and Hybrid Power Buck Boost (HPBB/Bypass) charging and switch between the modes using firmware control. BUG=b:131123775 BRANCH=none TEST=Able to boot intelrvp with charger & battery is charging Change-Id: If0736136778cbe7650ed7f03d04f4e011eedd1f6 Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com> Reviewed-on: https://chromium-review.googlesource.com/1579241 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Vijay P Hiremath <vijay.p.hiremath@intel.com> Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--driver/build.mk1
-rw-r--r--driver/charger/isl9241.c362
-rw-r--r--driver/charger/isl9241.h105
-rw-r--r--include/config.h4
4 files changed, 471 insertions, 1 deletions
diff --git a/driver/build.mk b/driver/build.mk
index 40ff37fc13..616bff8ef7 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -64,6 +64,7 @@ driver-$(CONFIG_CHARGER_BQ25892)+=charger/bq2589x.o
driver-$(CONFIG_CHARGER_BQ25895)+=charger/bq2589x.o
driver-$(CONFIG_CHARGER_ISL9237)+=charger/isl923x.o
driver-$(CONFIG_CHARGER_ISL9238)+=charger/isl923x.o
+driver-$(CONFIG_CHARGER_ISL9241)+=charger/isl9241.o
driver-$(CONFIG_CHARGER_MT6370)+=charger/rt946x.o
driver-$(CONFIG_CHARGER_RT9466)+=charger/rt946x.o
driver-$(CONFIG_CHARGER_RT9467)+=charger/rt946x.o
diff --git a/driver/charger/isl9241.c b/driver/charger/isl9241.c
new file mode 100644
index 0000000000..de6110a02b
--- /dev/null
+++ b/driver/charger/isl9241.c
@@ -0,0 +1,362 @@
+/* Copyright 2019 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.
+ *
+ * Renesas (Intersil) ISL-9241 battery charger driver.
+ */
+
+#include "adc.h"
+#include "battery.h"
+#include "battery_smart.h"
+#include "charger.h"
+#include "console.h"
+#include "common.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "isl9241.h"
+#include "system.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+
+#ifndef CONFIG_CHARGER_NARROW_VDC
+#error "ISL9241 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC."
+#endif
+
+/* Sense resistor default values in milli Ohm */
+#define ISL9241_DEFAULT_RS1 20 /* Input current sense resistor */
+#define ISL9241_DEFAULT_RS2 10 /* Battery charge current sense resistor */
+
+#define BOARD_RS1 CONFIG_CHARGER_SENSE_RESISTOR_AC
+#define BOARD_RS2 CONFIG_CHARGER_SENSE_RESISTOR
+
+#define BC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS2) / BOARD_RS2)
+#define BC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS2) / ISL9241_DEFAULT_RS2)
+
+#define AC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS1) / BOARD_RS1)
+#define AC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS1) / ISL9241_DEFAULT_RS1)
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+
+static int learn_mode;
+
+/* Mutex for CONTROL1 register, that can be updated from multiple tasks. */
+static struct mutex control1_mutex;
+
+/* Charger parameters */
+static const struct charger_info isl9241_charger_info = {
+ .name = CHARGER_NAME,
+ .voltage_max = CHARGE_V_MAX,
+ .voltage_min = CHARGE_V_MIN,
+ .voltage_step = CHARGE_V_STEP,
+ .current_max = BC_REG_TO_CURRENT(CHARGE_I_MAX),
+ .current_min = BC_REG_TO_CURRENT(CHARGE_I_MIN),
+ .current_step = BC_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 isl9241_read(int offset, int *value)
+{
+ return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value);
+}
+
+static inline int isl9241_write(int offset, int value)
+{
+ return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER, offset, value);
+}
+
+/* chip specific interfaces */
+
+/*****************************************************************************/
+/* Charger interfaces */
+int charger_set_input_current(int input_current)
+{
+ int rv;
+ uint16_t reg = AC_CURRENT_TO_REG(input_current);
+
+ rv = isl9241_write(ISL9241_REG_ADAPTER_CUR_LIMIT1, reg);
+ if (rv)
+ return rv;
+
+ return isl9241_write(ISL9241_REG_ADAPTER_CUR_LIMIT2, reg);
+}
+
+int charger_get_input_current(int *input_current)
+{
+ int rv;
+
+ rv = isl9241_read(ISL9241_REG_ADAPTER_CUR_LIMIT1, input_current);
+ if (rv)
+ return rv;
+
+ *input_current = AC_REG_TO_CURRENT(*input_current);
+ return EC_SUCCESS;
+}
+
+int charger_manufacturer_id(int *id)
+{
+ return isl9241_read(ISL9241_REG_MANUFACTURER_ID, id);
+}
+
+int charger_device_id(int *id)
+{
+ return isl9241_read(ISL9241_REG_DEVICE_ID, id);
+}
+
+int charger_get_option(int *option)
+{
+ int rv;
+ uint32_t controls;
+ int reg;
+
+ rv = isl9241_read(ISL9241_REG_CONTROL0, &reg);
+ if (rv)
+ return rv;
+
+ controls = reg;
+ rv = isl9241_read(ISL9241_REG_CONTROL1, &reg);
+ if (rv)
+ return rv;
+
+ controls |= reg << 16;
+ *option = controls;
+ return EC_SUCCESS;
+}
+
+int charger_set_option(int option)
+{
+ int rv;
+
+ rv = isl9241_write(ISL9241_REG_CONTROL0, option & 0xFFFF);
+ if (rv)
+ return rv;
+
+ return isl9241_write(ISL9241_REG_CONTROL1, (option >> 16) & 0xFFFF);
+}
+
+const struct charger_info *charger_get_info(void)
+{
+ return &isl9241_charger_info;
+}
+
+int charger_get_status(int *status)
+{
+ int rv;
+ int reg;
+
+ /* Level 2 charger */
+ *status = CHARGER_LEVEL_2;
+
+ /* Charge inhibit status */
+ rv = isl9241_read(ISL9241_REG_MIN_SYSTEM_VOLTAGE, &reg);
+ if (rv)
+ return rv;
+ if (!reg)
+ *status |= CHARGER_CHARGE_INHIBITED;
+
+ /* Battery present & AC present status */
+ rv = isl9241_read(ISL9241_REG_INFORMATION2, &reg);
+ if (rv)
+ return rv;
+ if (!(reg & ISL9241_INFORMATION2_BATGONE_PIN))
+ *status |= CHARGER_BATTERY_PRESENT;
+ if (reg & ISL9241_INFORMATION2_ACOK_PIN)
+ *status |= CHARGER_AC_PRESENT;
+
+ return EC_SUCCESS;
+}
+
+int charger_set_mode(int mode)
+{
+ int rv;
+
+ /*
+ * See crosbug.com/p/51196. Always disable learn mode unless it was set
+ * explicitly.
+ */
+ if (!learn_mode) {
+ rv = charger_discharge_on_ac(0);
+ if (rv)
+ return rv;
+ }
+
+ /*
+ * Charger inhibit
+ * MinSystemVoltage 0x00h = disables all battery charging
+ */
+ rv = isl9241_write(ISL9241_REG_MIN_SYSTEM_VOLTAGE,
+ mode & CHARGE_FLAG_INHIBIT_CHARGE ?
+ 0 : battery_get_info()->voltage_min);
+ if (rv)
+ return rv;
+
+ /* POR reset */
+ if (mode & CHARGE_FLAG_POR_RESET) {
+ rv = isl9241_write(ISL9241_REG_CONTROL3,
+ ISL9241_CONTROL3_DIGITAL_RESET);
+ }
+
+ return rv;
+}
+
+int charger_get_current(int *current)
+{
+ int rv;
+
+ rv = isl9241_read(ISL9241_REG_CHG_CURRENT_LIMIT, current);
+ if (rv)
+ return rv;
+
+ *current = BC_REG_TO_CURRENT(*current);
+ return EC_SUCCESS;
+}
+
+int charger_set_current(int current)
+{
+ return isl9241_write(ISL9241_REG_CHG_CURRENT_LIMIT,
+ BC_CURRENT_TO_REG(current));
+}
+
+int charger_get_voltage(int *voltage)
+{
+ return isl9241_read(ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage);
+}
+
+int charger_set_voltage(int voltage)
+{
+ return isl9241_write(ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage);
+}
+
+int charger_post_init(void)
+{
+ return EC_SUCCESS;
+}
+
+int charger_discharge_on_ac(int enable)
+{
+ int rv;
+ int control1;
+
+ mutex_lock(&control1_mutex);
+
+ rv = isl9241_read(ISL9241_REG_CONTROL1, &control1);
+ if (rv)
+ goto out;
+
+ if (enable)
+ control1 |= ISL9241_CONTROL1_LEARN_MODE;
+ else
+ control1 &= ~ISL9241_CONTROL1_LEARN_MODE;
+
+ rv = isl9241_write(ISL9241_REG_CONTROL1, control1);
+ if (!rv)
+ learn_mode = enable;
+
+out:
+ mutex_unlock(&control1_mutex);
+ return rv;
+}
+
+/*****************************************************************************/
+/* ISL-9241 initialization */
+static void isl9241_init(void)
+{
+ int reg;
+
+ const struct battery_info *bi = battery_get_info();
+
+ /*
+ * Set the MaxSystemVoltage to battery maximum,
+ * 0x00=disables switching charger states
+ */
+ if (isl9241_write(ISL9241_REG_MAX_SYSTEM_VOLTAGE, bi->voltage_max))
+ goto init_fail;
+
+ /*
+ * Set the MinSystemVoltage to battery minimum,
+ * 0x00=disables all battery charging
+ */
+ if (isl9241_write(ISL9241_REG_MIN_SYSTEM_VOLTAGE, bi->voltage_min))
+ goto init_fail;
+
+ /*
+ * Set control2 register to
+ * [15:13]: Trickle Charging Current (battery pre-charge current)
+ * [12] : Two-Level Adapter Current Limit (enable)
+ * [10:9] : Prochot# Debounce time (1000us)
+ */
+ if (isl9241_read(ISL9241_REG_CONTROL2, &reg))
+ goto init_fail;
+
+ if (isl9241_write(ISL9241_REG_CONTROL2,
+ reg | ISL9241_CONTROL2_TRICKLE_CHG_CURR(bi->precharge_current) |
+ ISL9241_CONTROL2_TWO_LEVEL_ADP_CURR |
+ ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000))
+ goto init_fail;
+
+ /*
+ * Set control3 register to
+ * [14]: ACLIM Reload (Do not reload)
+ */
+ if (isl9241_read(ISL9241_REG_CONTROL3, &reg))
+ goto init_fail;
+
+ if (isl9241_write(ISL9241_REG_CONTROL3,
+ reg | ISL9241_CONTROL3_ACLIM_RELOAD))
+ goto init_fail;
+
+ /*
+ * No need to proceed with the rest of init if we sysjump'd to this
+ * image as the input current limit has already been set.
+ */
+ if (system_jumped_to_this_image())
+ return;
+
+ /* Initialize the input current limit to the board's default. */
+ if (charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT))
+ goto init_fail;
+
+ return;
+
+init_fail:
+ CPRINTF("ISL9241_init failed!");
+}
+DECLARE_HOOK(HOOK_INIT, isl9241_init, HOOK_PRIO_INIT_I2C + 1);
+
+/*****************************************************************************/
+#ifdef CONFIG_CMD_CHARGER_DUMP
+static void dump_reg_range(int low, int high)
+{
+ int reg;
+ int regval;
+ int rv;
+
+ for (reg = low; reg <= high; reg++) {
+ CPRINTF("[%Xh] = ", reg);
+ rv = isl9241_read(reg, &regval);
+ if (!rv)
+ CPRINTF("0x%04x\n", regval);
+ else
+ CPRINTF("ERR (%d)\n", rv);
+ cflush();
+ }
+}
+
+static int command_isl9241_dump(int argc, char **argv)
+{
+ dump_reg_range(0x14, 0x15);
+ dump_reg_range(0x38, 0x40);
+ dump_reg_range(0x43, 0x43);
+ dump_reg_range(0x47, 0x4F);
+ dump_reg_range(0x80, 0x87);
+ dump_reg_range(0x90, 0x91);
+ dump_reg_range(0xFE, 0xFF);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(charger_dump, command_isl9241_dump, "",
+ "Dumps ISL9241 registers");
+#endif /* CONFIG_CMD_CHARGER_DUMP */
diff --git a/driver/charger/isl9241.h b/driver/charger/isl9241.h
new file mode 100644
index 0000000000..b0be2cb188
--- /dev/null
+++ b/driver/charger/isl9241.h
@@ -0,0 +1,105 @@
+/* Copyright 2019 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.
+ *
+ * Renesas (Intersil) ISL-9241 battery charger driver header.
+ */
+
+#ifndef __CROS_EC_ISL9241_H
+#define __CROS_EC_ISL9241_H
+
+#define ISL9241_ADDR 0x12 /* 7bit address 0001001 */
+#define I2C_ADDR_CHARGER ISL9241_ADDR
+
+#define CHARGER_NAME "ISL9241"
+#define CHARGE_V_MAX 18304
+#define CHARGE_V_MIN 64
+#define CHARGE_V_STEP 8
+#define CHARGE_I_MAX 6140
+#define CHARGE_I_MIN 4
+#define CHARGE_I_STEP 4
+#define INPUT_I_MAX 6140
+#define INPUT_I_MIN 4
+#define INPUT_I_STEP 4
+
+/* Registers */
+
+/*
+ * ChargeCurrentLimit [12:2] 11-bit (0x0000h = disables fast charging,
+ * trickle charging is allowed)
+ */
+#define ISL9241_REG_CHG_CURRENT_LIMIT 0x14
+
+/* MaxSystemVoltage [14:3] 12-bit, (0x0000h = disables switching) */
+#define ISL9241_REG_MAX_SYSTEM_VOLTAGE 0x15
+
+#define ISL9241_REG_CONTROL7 0x38
+#define ISL9241_REG_CONTROL0 0x39
+#define ISL9241_REG_INFORMATION1 0x3A
+#define ISL9241_REG_ADAPTER_CUR_LIMIT2 0x3B
+
+/* Configures various charger options */
+#define ISL9241_REG_CONTROL1 0x3C
+#define ISL9241_CONTROL1_LEARN_MODE BIT(12)
+
+/* Configures various charger options */
+#define ISL9241_REG_CONTROL2 0x3D
+/*
+ * 15:13 - Trickle Charging Current
+ * <000> 32mA (do not use)
+ * <001> 64mA
+ * <010> 96mA
+ * <011> 128mA (default)
+ * <100> 160mA
+ * <101> 192mA
+ * <110> 224mA
+ * <111> 256mA
+ */
+#define ISL9241_CONTROL2_TRICKLE_CHG_CURR(curr) ((((curr) >> 5) - 1) << 13)
+/* 12 - Two-Level Adapter Current Limit */
+#define ISL9241_CONTROL2_TWO_LEVEL_ADP_CURR BIT(12)
+/* 10:9 PROCHOT# debounce time in uS */
+#define ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000 (3 << 9)
+
+/* MinSystemVoltage [13:6] 8-bit (0x0000h = disables all battery charging) */
+#define ISL9241_REG_MIN_SYSTEM_VOLTAGE 0x3E
+
+#define ISL9241_REG_ADAPTER_CUR_LIMIT1 0x3F
+#define ISL9241_REG_ACOK_REFERENCE 0x40
+#define ISL9241_REG_CONTROL6 0x43
+#define ISL9241_REG_AC_PROCHOT 0x47
+#define ISL9241_REG_DC_PROCHOT 0x48
+#define ISL9241_REG_OTG_VOLTAGE 0x49
+#define ISL9241_REG_OTG_CURRENT 0x4A
+#define ISL9241_REG_VIN_VOLTAGE 0x4B
+
+/* Configures various charger options */
+#define ISL9241_REG_CONTROL3 0x4C
+/* 14: ACLIM Reload (0 - reload, 1 - Do not reload */
+#define ISL9241_CONTROL3_ACLIM_RELOAD BIT(14)
+/* 2: Digital Reset (0 - Idle, 1 - Reset */
+#define ISL9241_CONTROL3_DIGITAL_RESET BIT(2)
+
+/* Indicates various charger status */
+#define ISL9241_REG_INFORMATION2 0x4D
+/* 12: BATGONE pin status (0 = Battery is present, 1 = No battery) */
+#define ISL9241_INFORMATION2_BATGONE_PIN BIT(12)
+/* 14: ACOK pin status (0 = No adapter, 1 = Adapter is present) */
+#define ISL9241_INFORMATION2_ACOK_PIN BIT(14)
+
+#define ISL9241_REG_CONTROL4 0x4E
+#define ISL9241_REG_CONTROL5 0x4F
+#define ISL9241_REG_NTC_ADC_RESULTS 0x80
+#define ISL9241_REG_VBAT_ADC_RESULTS 0x81
+#define ISL9241_REG_TJ_ADC_RESULTS 0x82
+#define ISL9241_REG_IADP_ADC_RESULTS 0x83
+#define ISL9241_REG_DC_ADC_RESULTS 0x84
+#define ISL9241_REG_CC_ADC_RESULTS 0x85
+#define ISL9241_REG_VSYS_ADC_RESULTS 0x86
+#define ISL9241_REG_VIN_ADC_RESULTS 0x87
+#define ISL9241_REG_INFORMATION3 0x90
+#define ISL9241_REG_INFORMATION4 0x91
+#define ISL9241_REG_MANUFACTURER_ID 0xFE
+#define ISL9241_REG_DEVICE_ID 0xFF
+
+#endif /* __CROS_EC_ISL9241_H */
diff --git a/include/config.h b/include/config.h
index e7dc4e8da2..294490b3cf 100644
--- a/include/config.h
+++ b/include/config.h
@@ -685,6 +685,7 @@
#undef CONFIG_CHARGER_BQ25895
#undef CONFIG_CHARGER_ISL9237
#undef CONFIG_CHARGER_ISL9238
+#undef CONFIG_CHARGER_ISL9241
#undef CONFIG_CHARGER_MT6370
#undef CONFIG_CHARGER_RT9466
#undef CONFIG_CHARGER_RT9467
@@ -4149,7 +4150,8 @@
* Define CONFIG_CHARGER_NARROW_VDC for chargers that use a Narrow VDC power
* architecture.
*/
-#if defined(CONFIG_CHARGER_ISL9237) || defined(CONFIG_CHARGER_ISL9238)
+#if defined(CONFIG_CHARGER_ISL9237) || defined(CONFIG_CHARGER_ISL9238) || \
+ defined(CONFIG_CHARGER_ISL9241)
#define CONFIG_CHARGER_NARROW_VDC
#endif