summaryrefslogtreecommitdiff
path: root/driver/charger
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-01-03 13:11:43 -0700
committerCommit Bot <commit-bot@chromium.org>2020-03-16 19:11:43 +0000
commitbf3e265541b3596359ae3d579657e07598c02ae5 (patch)
tree27521d2ac9788cf746cb31d666bfaa1394b685c5 /driver/charger
parentd3f1c78324eff32285a7be3959508428471ad497 (diff)
downloadchrome-ec-bf3e265541b3596359ae3d579657e07598c02ae5.tar.gz
SM5803: Initial driver
New driver for the SM5803 chip. It includes the core charger driver functions implemented, as well as access functions to control the charger's GPIO and a basic interrupt handler for the chip. BUG=b:146651778 BRANCH=None TEST=able to charge battery on franken-doo Change-Id: I84c734351a739d2472c8c0ad45929ff5929fc6d8 Signed-off-by: Diana Z <dzigterman@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2055767 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
Diffstat (limited to 'driver/charger')
-rw-r--r--driver/charger/sm5803.c408
-rw-r--r--driver/charger/sm5803.h216
2 files changed, 624 insertions, 0 deletions
diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c
new file mode 100644
index 0000000000..2cb1d2a524
--- /dev/null
+++ b/driver/charger/sm5803.c
@@ -0,0 +1,408 @@
+/* Copyright 2020 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.
+ *
+ * Silicon Mitus SM5803 Buck-Boost Charger
+ */
+#include "battery_smart.h"
+#include "charger.h"
+#include "gpio.h"
+#include "i2c.h"
+#include "sm5803.h"
+#include "throttle_ap.h"
+#include "usb_charge.h"
+
+#ifndef CONFIG_CHARGER_NARROW_VDC
+#error "SM5803 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC."
+#endif
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
+static const struct charger_info sm5803_charger_info = {
+ .name = CHARGER_NAME,
+ .voltage_max = CHARGE_V_MAX,
+ .voltage_min = CHARGE_V_MIN,
+ .voltage_step = CHARGE_V_STEP,
+ .current_max = CHARGE_I_MAX,
+ .current_min = CHARGE_I_MIN,
+ .current_step = CHARGE_I_STEP,
+ .input_current_max = INPUT_I_MAX,
+ .input_current_min = INPUT_I_MIN,
+ .input_current_step = INPUT_I_STEP,
+};
+
+
+static inline enum ec_error_list chg_read8(int chgnum, int offset, int *value)
+{
+ return i2c_read8(chg_chips[chgnum].i2c_port,
+ chg_chips[chgnum].i2c_addr_flags,
+ offset, value);
+}
+
+static inline enum ec_error_list chg_write8(int chgnum, int offset, int value)
+{
+ return i2c_write8(chg_chips[chgnum].i2c_port,
+ chg_chips[chgnum].i2c_addr_flags,
+ offset, value);
+}
+
+static inline enum ec_error_list meas_read8(int chgnum, int offset, int *value)
+{
+ return i2c_read8(chg_chips[chgnum].i2c_port,
+ SM5803_ADDR_MEAS_FLAGS,
+ offset, value);
+}
+
+static inline enum ec_error_list meas_write8(int chgnum, int offset, int value)
+{
+ return i2c_write8(chg_chips[chgnum].i2c_port,
+ SM5803_ADDR_MEAS_FLAGS,
+ offset, value);
+}
+
+static inline enum ec_error_list main_read8(int chgnum, int offset, int *value)
+{
+ return i2c_read8(chg_chips[chgnum].i2c_port,
+ SM5803_ADDR_MAIN_FLAGS,
+ offset, value);
+}
+
+static inline enum ec_error_list main_write8(int chgnum, int offset, int value)
+{
+ return i2c_write8(chg_chips[chgnum].i2c_port,
+ SM5803_ADDR_MAIN_FLAGS,
+ offset, value);
+}
+
+enum ec_error_list sm5803_configure_gpio0(int chgnum,
+ enum sm5803_gpio0_modes mode)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = main_read8(chgnum, SM5803_REG_GPIO0_CTRL, &reg);
+ if (rv)
+ return rv;
+
+ reg &= ~SM5803_GPIO0_MODE_MASK;
+ reg |= mode << 1;
+
+ rv = main_write8(chgnum, SM5803_REG_GPIO0_CTRL, reg);
+ return rv;
+}
+
+enum ec_error_list sm5803_set_gpio0_level(int chgnum, int level)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = main_read8(chgnum, SM5803_REG_GPIO0_CTRL, &reg);
+ if (rv)
+ return rv;
+
+ if (level)
+ reg |= SM5803_GPIO0_VAL;
+ else
+ reg &= ~SM5803_GPIO0_VAL;
+
+ rv = main_write8(chgnum, SM5803_REG_GPIO0_CTRL, reg);
+ return rv;
+}
+
+static void sm5803_init(int chgnum)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ /* Set default input current */
+ reg = SM5803_CURRENT_TO_REG(CONFIG_CHARGER_INPUT_CURRENT)
+ & SM5803_CHG_ILIM_RAW;
+ rv = chg_write8(chgnum, SM5803_REG_CHG_ILIM, reg);
+
+ /* Configure TINT and Vbus interrupts to fire */
+ rv |= main_write8(chgnum, SM5803_REG_INT2_EN, SM5803_INT2_TINT
+ & SM5803_INT2_VBUS);
+
+ /* Set Vbus interrupt levels for 3.5V and 4.0V */
+ rv |= meas_write8(chgnum, SM5803_REG_VBUS_LOW_TH,
+ SM5803_VBUS_LOW_LEVEL);
+ rv |= meas_write8(chgnum, SM5803_REG_VBUS_HIGH_TH,
+ SM5803_VBUS_HIGH_LEVEL);
+
+ /* Set TINT for 360K (steps are in 0.43K) */
+ rv |= meas_write8(chgnum, SM5803_REG_TINT_HIGH_TH, 0xD1);
+
+ if (rv)
+ CPRINTS("%s %d: Failed initialization", CHARGER_NAME, chgnum);
+}
+
+static enum ec_error_list sm5803_post_init(int chgnum)
+{
+ /* Nothing to do, charger is always powered */
+ return EC_SUCCESS;
+}
+
+/*
+ * Process interrupt registers and report any Vbus changes. Pull PROCHOT low if
+ * charger has gotten too hot.
+ */
+void sm5803_handle_interrupt(int chgnum)
+{
+ enum ec_error_list rv;
+ int int_reg, vbus_reg;
+
+ /* Note: Interrupt register is clear on read */
+ rv = main_read8(chgnum, SM5803_REG_INT2_REQ, &int_reg);
+ if (rv) {
+ CPRINTS("%s %d: Failed read int2 register", CHARGER_NAME,
+ chgnum);
+ return;
+ }
+
+ if (int_reg & SM5803_INT2_TINT) {
+ CPRINTS("%s %d: High temp, throttling AP", CHARGER_NAME,
+ chgnum);
+ throttle_ap(THROTTLE_ON, THROTTLE_HARD, THROTTLE_SRC_THERMAL);
+ }
+
+ if (int_reg & SM5803_INT2_VBUS) {
+ /* TODO(b/146651778): Check whether we're sourcing Vbus */
+ rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_MSB, &vbus_reg);
+ if (vbus_reg <= SM5803_VBUS_LOW_LEVEL)
+ usb_charger_vbus_change(chgnum, 0);
+ else if (vbus_reg >= SM5803_VBUS_HIGH_LEVEL)
+ usb_charger_vbus_change(chgnum, 1);
+ else
+ CPRINTS("%s %d: Unexpected Vbus interrupt: 0x%02x",
+ CHARGER_NAME, chgnum, vbus_reg);
+ }
+}
+
+static const struct charger_info *sm5803_get_info(int chgnum)
+{
+ return &sm5803_charger_info;
+}
+
+static enum ec_error_list sm5803_get_status(int chgnum, int *status)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ /* Charger obeys smart battery requests - making it level 2 */
+ *status = CHARGER_LEVEL_2;
+
+ rv = chg_read8(chgnum, SM5803_REG_FLOW1, &reg);
+ if (rv)
+ return rv;
+
+ if (!(reg & SM5803_FLOW1_CHG_EN))
+ *status |= CHARGER_CHARGE_INHIBITED;
+
+ return EC_SUCCESS;
+}
+
+static enum ec_error_list sm5803_set_mode(int chgnum, int mode)
+{
+ enum ec_error_list rv;
+ int flow1_reg, flow2_reg;
+
+ rv = chg_read8(chgnum, SM5803_REG_FLOW1, &flow1_reg);
+ if (rv)
+ return rv;
+
+ rv = chg_read8(chgnum, SM5803_REG_FLOW2, &flow2_reg);
+ if (rv)
+ return rv;
+
+ if (mode & CHARGE_FLAG_INHIBIT_CHARGE) {
+ /* If already inhibited, don't bother re-inhibiting */
+ if (!(flow1_reg & SM5803_FLOW1_CHG_EN))
+ return EC_SUCCESS;
+
+ flow1_reg &= ~SM5803_FLOW1_CHG_EN;
+ flow2_reg &= ~SM5803_FLOW2_AUTO_ENABLED;
+ } else {
+ flow1_reg |= SM5803_FLOW1_CHG_EN;
+ flow2_reg |= SM5803_FLOW2_AUTO_ENABLED;
+ }
+
+ rv = chg_write8(chgnum, SM5803_REG_FLOW1, flow1_reg);
+ rv |= chg_write8(chgnum, SM5803_REG_FLOW2, flow2_reg);
+
+ return rv;
+}
+
+static enum ec_error_list sm5803_get_current(int chgnum, int *current)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = chg_read8(chgnum, SM5803_REG_FAST_CONF4, &reg);
+ if (rv)
+ return rv;
+
+ *current = SM5803_REG_TO_CURRENT(reg & SM5803_CONF4_ICHG_FAST);
+ return EC_SUCCESS;
+}
+
+static enum ec_error_list sm5803_set_current(int chgnum, int current)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = chg_read8(chgnum, SM5803_REG_FAST_CONF4, &reg);
+ if (rv)
+ return rv;
+
+ reg &= ~SM5803_CONF4_ICHG_FAST;
+ reg |= SM5803_CURRENT_TO_REG(current);
+
+ rv = chg_write8(chgnum, SM5803_REG_FAST_CONF4, reg);
+ return rv;
+}
+
+static enum ec_error_list sm5803_get_voltage(int chgnum, int *voltage)
+{
+ enum ec_error_list rv;
+ int reg;
+ int volt_bits;
+
+ /* Note: Vsys should match Vbat voltage */
+ rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_MSB, &reg);
+ if (rv)
+ return rv;
+
+ volt_bits = reg << 3;
+
+ rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_LSB, &reg);
+ if (rv)
+ return rv;
+
+ volt_bits |= (reg & 0x7);
+
+ *voltage = SM5803_REG_TO_VOLTAGE(volt_bits);
+ return EC_SUCCESS;
+}
+
+static enum ec_error_list sm5803_set_voltage(int chgnum, int voltage)
+{
+ enum ec_error_list rv;
+ int volt_bits;
+
+ volt_bits = SM5803_VOLTAGE_TO_REG(voltage);
+
+ /*
+ * Note: Set both voltages on both chargers. Vbat will only be used on
+ * primary, which enables charging.
+ */
+ rv = chg_write8(chgnum, SM5803_REG_VSYS_PREREG_MSB, (volt_bits >> 3));
+ rv |= chg_write8(chgnum, SM5803_REG_VSYS_PREREG_LSB, (volt_bits & 0x7));
+ rv |= chg_write8(chgnum, SM5803_REG_VBAT_FAST_MSB, (volt_bits >> 3));
+ rv |= chg_write8(chgnum, SM5803_REG_VBAT_FAST_LSB, (volt_bits & 0x7));
+
+ return rv;
+}
+
+static enum ec_error_list sm5803_get_vbus_voltage(int chgnum, int port,
+ int *voltage)
+{
+ enum ec_error_list rv;
+ int reg;
+ int volt_bits;
+
+ rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_MSB, &reg);
+ if (rv)
+ return rv;
+
+ volt_bits = reg << 2;
+
+ rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_LSB, &reg);
+
+ volt_bits |= reg & SM5803_VBUS_MEAS_LSB;
+
+ /* Vbus ADC is in 23.4 mV steps */
+ *voltage = (int)((float)volt_bits * 23.4f);
+ return rv;
+}
+
+static enum ec_error_list sm5803_set_input_current(int chgnum,
+ int input_current)
+{
+ int reg;
+
+ reg = SM5803_CURRENT_TO_REG(input_current) & SM5803_CHG_ILIM_RAW;
+
+ return chg_write8(chgnum, SM5803_REG_CHG_ILIM, reg);
+}
+
+static enum ec_error_list sm5803_get_input_current(int chgnum,
+ int *input_current)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ rv = chg_read8(chgnum, SM5803_REG_CHG_ILIM, &reg);
+ if (rv)
+ return rv;
+
+ *input_current = SM5803_REG_TO_CURRENT(reg & SM5803_CHG_ILIM_RAW);
+ return EC_SUCCESS;
+}
+
+static enum ec_error_list sm5803_get_option(int chgnum, int *option)
+{
+ enum ec_error_list rv;
+ uint32_t control;
+ int reg;
+
+ rv = chg_read8(chgnum, SM5803_REG_FLOW1, &reg);
+ control = reg;
+
+ rv |= chg_read8(chgnum, SM5803_REG_FLOW2, &reg);
+ control |= reg << 8;
+
+ rv |= chg_read8(chgnum, SM5803_REG_FLOW3, &reg);
+ control |= reg << 16;
+
+ return rv;
+}
+
+static enum ec_error_list sm5803_set_option(int chgnum, int option)
+{
+ enum ec_error_list rv;
+ int reg;
+
+ reg = option & 0xFF;
+ rv = chg_write8(chgnum, SM5803_REG_FLOW1, reg);
+ if (rv)
+ return rv;
+
+ reg = (option >> 8) & 0xFF;
+ rv = chg_write8(chgnum, SM5803_REG_FLOW2, reg);
+ if (rv)
+ return rv;
+
+ reg = (option >> 16) & 0xFF;
+ rv = chg_write8(chgnum, SM5803_REG_FLOW3, reg);
+
+ return rv;
+}
+
+const struct charger_drv sm5803_drv = {
+ .init = &sm5803_init,
+ .post_init = &sm5803_post_init,
+ .get_info = &sm5803_get_info,
+ .get_status = &sm5803_get_status,
+ .set_mode = &sm5803_set_mode,
+ .get_current = &sm5803_get_current,
+ .set_current = &sm5803_set_current,
+ .get_voltage = &sm5803_get_voltage,
+ .set_voltage = &sm5803_set_voltage,
+ .get_vbus_voltage = &sm5803_get_vbus_voltage,
+ .set_input_current = &sm5803_set_input_current,
+ .get_input_current = &sm5803_get_input_current,
+ .get_option = &sm5803_get_option,
+ .set_option = &sm5803_set_option,
+};
diff --git a/driver/charger/sm5803.h b/driver/charger/sm5803.h
new file mode 100644
index 0000000000..86e2fa43c2
--- /dev/null
+++ b/driver/charger/sm5803.h
@@ -0,0 +1,216 @@
+/* Copyright 2020 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.
+ *
+ * Silicon Mitus SM5803 Buck-Boost Charger
+ */
+
+#ifndef __CROS_EC_SM5803_H
+#define __CROS_EC_SM5803_H
+
+/* Note: configure charger struct with CHARGER_FLAGS */
+#define SM5803_ADDR_MAIN_FLAGS 0x30
+#define SM5803_ADDR_MEAS_FLAGS 0x31
+#define SM5803_ADDR_CHARGER_FLAGS 0x32
+
+/* Main registers (address 0x30) */
+
+#define SM5803_REG_STATUS1 0x01
+#define SM5803_STATUS1_VSYS_OK BIT(0)
+#define SM5803_STATUS1_VPWR_OK BIT(1)
+#define SM5803_STATUS1_VBUS_UVL BIT(3)
+#define SM5803_STATUS1_VBUS_SHORT BIT(4)
+#define SM5803_STATUS1_VBUS_OVH BIT(5)
+#define SM5803_STATUS1_CHG_DET BIT(6)
+#define SM5803_STATUS1_BAT_DET BIT(7)
+
+#define SM5803_REG_STATUS2 0x02
+#define SM5803_STATUS2_BAT_DET_FG BIT(1)
+#define SM5803_STATUS2_VBAT_SHORT BIT(0)
+
+#define SM5803_REG_INT1_REQ 0x05
+#define SM5803_REG_INT1_EN 0x0A
+#define SM5803_INT1_VBUS_PWR_HWSAFE_LIMIT BIT(0)
+#define SM5803_INT1_CHG BIT(2)
+#define SM5803_INT1_BAT BIT(3)
+#define SM5803_INT1_CLS_OC BIT(4)
+#define SM5803_INT1_SLV_DET BIT(5)
+#define SM5803_INT1_SWL_DISCH BIT(6)
+#define SM5803_INT1_PREREG BIT(7)
+
+#define SM5803_REG_INT2_REQ 0x06
+#define SM5803_REG_INT2_EN 0x0B
+#define SM5803_INT2_VBATSNSP BIT(0)
+#define SM5803_INT2_IBAT_DISCHG BIT(1)
+#define SM5803_INT2_IBAT_CHG BIT(2)
+#define SM5803_INT2_IBUS BIT(3)
+#define SM5803_INT2_VBUS BIT(4)
+#define SM5803_INT2_VCHGPWR BIT(5)
+#define SM5803_INT2_VSYS BIT(6)
+#define SM5803_INT2_TINT BIT(7)
+
+#define SM5803_REG_INT3_REQ 0x07
+#define SM5803_REG_INT3_EN 0x0C
+#define SM5803_INT3_GPADC0 BIT(0)
+#define SM5803_INT3_VBATC1 BIT(1)
+#define SM5803_INT3_VBATC2 BIT(2)
+#define SM5803_INT3_SPARE BIT(3)
+#define SM5803_INT3_VBUS_PWR_LIMIT BIT(4)
+#define SM5803_INT3_IBAT BIT(5)
+
+#define SM5803_REG_INT4_REQ 0x08
+#define SM5803_REG_INT4_EN 0x0D
+#define SM5803_INT4_CHG_FAIL BIT(0)
+#define SM5803_INT4_CHG_DONE BIT(1)
+#define SM5803_INT4_CHG_START BIT(2)
+#define SM5803_INT4_SLP_EXIT BIT(3)
+#define SM5803_INT4_OTG_FAIL BIT(4)
+#define SM5803_INT4_CHG_ILIM BIT(5)
+#define SM5803_INT4_IBAT_CC BIT(6)
+#define SM5803_INT4_CC BIT(7)
+
+#define SM5803_REG_MISC_CONFIG 0x15
+#define SM5803_MISC_INV_INT BIT(0)
+#define SM5803_INT_CLEAR_MODE BIT(1)
+#define SM5803_INT_MASK_MODE BIT(2)
+
+#define SM5803_REG_REFERENCE 0x20
+#define SM5803_REFERENCE_LDO3P3_PGOOD BIT(4)
+#define SM5803_REFERENCE_LDO5_PGOOD BIT(5)
+
+#define SM5803_REG_GPIO0_CTRL 0x30
+#define SM5803_GPIO0_VAL BIT(0)
+#define SM5803_GPIO0_MODE_MASK GENMASK(2, 1)
+#define SM5803_GPIO0_OPEN_DRAIN_EN BIT(6)
+#define SM5803_CHG_DET_OPEN_DRAIN_EN BIT(7)
+
+enum sm5803_gpio0_modes {
+ GPIO0_MODE_PROCHOT,
+ GPIO0_MODE_OUTPUT,
+ GPIO0_MODE_INPUT
+};
+
+#define SM5803_REG_PORTS_CTRL 0x40
+#define SM5803_PORTS_VBUS_DISCH BIT(0)
+#define SM5803_PORTS_VBUS_PULLDOWN BIT(1)
+#define SM5803_PORTS_VBUS_SNS_DISCH BIT(2)
+#define SM5803_PORTS_VBUS_SNS_PULLDOWN BIT(3)
+
+/* ADC Registers (address 0x31) */
+
+#define SM5803_REG_GPADC_CONFIG1 0x01
+#define SM5803_GPADCC1_VBATSNSP_EN BIT(0)
+#define SM5803_GPADCC1_IBAT_DIS_EN BIT(1)
+#define SM5803_GPADCC1_IBAT_CHG_EN BIT(2)
+#define SM5803_GPADCC1_IBUS_EN BIT(3)
+#define SM5803_GPADCC1_VBUS_EN BIT(4)
+#define SM5803_GPADCC1_VCHGPWR_EN BIT(5)
+#define SM5803_GPADCC1_VSYS_EN BIT(6)
+#define SM5803_GPADCC1_TINT_EN BIT(7)
+
+/* Note: Threshold registers all assume lower 2 bits are 0 */
+#define SM5803_REG_VBUS_LOW_TH 0x1B
+#define SM5803_REG_VBUS_HIGH_TH 0x2B
+#define SM5803_REG_TINT_HIGH_TH 0x2D
+
+/*
+ * Vbus levels increment in 23.4 mV, set thresholds to below 3.5V and above 4.0V
+ * to mirror what TCPCI uses for Vbus present indication
+ */
+#define SM5803_VBUS_LOW_LEVEL 0x25
+#define SM5803_VBUS_HIGH_LEVEL 0x2C
+
+#define SM5803_REG_VBUS_MEAS_MSB 0x48
+#define SM5803_REG_VBUS_MEAS_LSB 0x49
+#define SM5803_VBUS_MEAS_LSB GENMASK(1, 0)
+#define SM5803_VBUS_MEAS_BAT_DET BIT(2)
+#define SM5803_VBUS_MEAS_VBUS_SHORT BIT(4)
+#define SM5803_VBUS_MEAS_OV_TEMP BIT(5)
+#define SM5803_VBUS_MEAS_CHG_DET BIT(6)
+
+/* Charger registers (address 0x32) */
+
+#define SM5803_REG_FLOW1 0x1C
+#define SM5803_FLOW1_CHG_EN BIT(0)
+#define SM5803_FLOW1_VBUSIN_DISCHG_EN BIT(1)
+#define SM5803_FLOW1_DIRECTCHG_SRC_EN BIT(2)
+#define SM5803_FLOW1_USB_SUSP BIT(7)
+
+#define SM5803_REG_FLOW2 0x1D
+#define SM5803_FLOW2_AUTO_TRKL_EN BIT(0)
+#define SM5803_FLOW2_AUTO_PRECHG_EN BIT(1)
+#define SM5803_FLOW2_AUTO_FASTCHG_EN BIT(2)
+#define SM5803_FLOW2_AUTO_ENABLED GENMASK(2, 0)
+#define SM5803_FLOW2_FW_TRKL_CMD BIT(3)
+#define SM5803_FLOW2_FW_PRECHG_CMD BIT(4)
+#define SM5803_FLOW2_FW_FASTCHG_CMD BIT(5)
+#define SM5803_FLOW2_HOST_MODE_EN BIT(6)
+#define SM5803_FLOW2_AUTO_CHGEN_SET BIT(7)
+
+#define SM5803_REG_FLOW3 0x1E
+#define SM5803_FLOW3_SWITCH_BCK_BST BIT(0)
+#define SM5803_FLOW3_FW_SWITCH_RESUME BIT(1)
+#define SM5803_FLOW3_FW_SWITCH_PAUSE BIT(2)
+#define SM5803_FLOW3_SOFT_DISABLE_EN BIT(3)
+
+/*
+ * Input current limit is CHG_ILIM_RAW *100 mA
+ */
+#define SM5803_REG_CHG_ILIM 0x24
+#define SM5803_CHG_ILIM_RAW GENMASK(4, 0)
+#define SM5803_CURRENT_STEP 100
+#define SM5803_REG_TO_CURRENT(r) (r * SM5803_CURRENT_STEP)
+#define SM5803_CURRENT_TO_REG(c) (c / SM5803_CURRENT_STEP)
+
+/*
+ * Vsys is 11 bits, with the lower 3 bits in the LSB register.
+ * The pre-regulation value is 2.72 V + Vsys_prereg * 10 mV
+ * Lower saturation value is 3V, upper is 20V
+ */
+#define SM5803_REG_VSYS_PREREG_MSB 0x36
+#define SM5803_REG_VSYS_PREREG_LSB 0x37
+#define SM5803_VOLTAGE_STEP 10
+#define SM5803_VOLTAGE_SHIFT 2720
+#define SM5803_REG_TO_VOLTAGE(r) (SM5803_VOLTAGE_SHIFT + \
+ r * SM5803_VOLTAGE_STEP)
+#define SM5803_VOLTAGE_TO_REG(v) ((v - SM5803_VOLTAGE_SHIFT) \
+ / SM5803_VOLTAGE_STEP)
+
+/*
+ * Vbat for fast charge uses the same equation as Vsys
+ * Lower saturation value is 3V, upper is dependent on number of cells
+ */
+#define SM5803_REG_VBAT_FAST_MSB 0x3A
+#define SM5803_REG_VBAT_FAST_LSB 0x3B
+
+/*
+ * Fast charge current limit is ICHG_FAST * 100 mA
+ * Value read back may be adjusted if tempearture limits are exceeded
+ */
+#define SM5803_REG_FAST_CONF4 0x3C
+#define SM5803_CONF4_ICHG_FAST GENMASK(5, 0)
+
+#define CHARGER_NAME "sm5803"
+
+#define CHARGE_V_MAX 20000
+#define CHARGE_V_MIN SM5803_VOLTAGE_SHIFT
+#define CHARGE_V_STEP SM5803_VOLTAGE_STEP
+
+#define CHARGE_I_MAX 6300
+#define CHARGE_I_MIN 0
+#define CHARGE_I_STEP SM5803_CURRENT_STEP
+
+#define INPUT_I_MAX 3100
+#define INPUT_I_MIN 0
+#define INPUT_I_STEP SM5803_CURRENT_STEP
+
+/* Expose functions to control charger's GPIO */
+enum ec_error_list sm5803_configure_gpio0(int chgnum,
+ enum sm5803_gpio0_modes mode);
+enum ec_error_list sm5803_set_gpio0_level(int chgnum, int level);
+
+void sm5803_handle_interrupt(int chgnum);
+
+extern const struct charger_drv sm5803_drv;
+
+#endif