diff options
author | Diana Z <dzigterman@chromium.org> | 2020-01-03 13:11:43 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-16 19:11:43 +0000 |
commit | bf3e265541b3596359ae3d579657e07598c02ae5 (patch) | |
tree | 27521d2ac9788cf746cb31d666bfaa1394b685c5 /driver | |
parent | d3f1c78324eff32285a7be3959508428471ad497 (diff) | |
download | chrome-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')
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/charger/sm5803.c | 408 | ||||
-rw-r--r-- | driver/charger/sm5803.h | 216 |
3 files changed, 625 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index fcc8c9334c..79bcd729b0 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -66,6 +66,7 @@ driver-$(CONFIG_CHARGER_RAA489000)+=charger/isl923x.o driver-$(CONFIG_CHARGER_RT9466)+=charger/rt946x.o driver-$(CONFIG_CHARGER_RT9467)+=charger/rt946x.o driver-$(CONFIG_CHARGER_SY21612)+=charger/sy21612.o +driver-$(CONFIG_CHARGER_SM5803)+=charger/sm5803.o # Fingerprint Sensors include $(_driver_cur_dir)fingerprint/build.mk 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + if (rv) + return rv; + + volt_bits = reg << 3; + + rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_LSB, ®); + 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, ®); + if (rv) + return rv; + + volt_bits = reg << 2; + + rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_LSB, ®); + + 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, ®); + 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, ®); + control = reg; + + rv |= chg_read8(chgnum, SM5803_REG_FLOW2, ®); + control |= reg << 8; + + rv |= chg_read8(chgnum, SM5803_REG_FLOW3, ®); + 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 |