From 75ff886b073bede08cbe64b935fc6e042f0d12ab Mon Sep 17 00:00:00 2001 From: Aseda Aboagye Date: Mon, 3 Aug 2020 17:13:39 -0700 Subject: sm5803: Add support for OCPC This commit updates the SM5803 driver to add the required functionality for supporting OCPC. As this part does not have the ability to measure ISYS, one needs to make sure that flag is set in the OCPC chg_flags bitfield. Currently, sourcing out the mainboard port while charging through an auxiliary charger is not working. BUG=b:155224387 BRANCH=None TEST=Enable on waddledee, flash, verify DUT can charge thru the sub board port. Signed-off-by: Aseda Aboagye Change-Id: I7b60dec51e503c83a24799d523eb75408f91ce86 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2336175 Tested-by: Aseda Aboagye Reviewed-by: Justin TerAvest Reviewed-by: Diana Z Commit-Queue: Justin TerAvest Auto-Submit: Aseda Aboagye --- driver/charger/sm5803.c | 137 ++++++++++++++++++++++++++++++++++++++++++++---- driver/charger/sm5803.h | 32 +++++++++++ 2 files changed, 158 insertions(+), 11 deletions(-) (limited to 'driver/charger') diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c index 3899b95887..5b53abcc9c 100644 --- a/driver/charger/sm5803.c +++ b/driver/charger/sm5803.c @@ -7,6 +7,7 @@ #include "atomic.h" #include "battery.h" #include "battery_smart.h" +#include "charge_state_v2.h" #include "charger.h" #include "gpio.h" #include "hooks.h" @@ -665,12 +666,20 @@ static enum ec_error_list sm5803_get_current(int chgnum, int *current) { enum ec_error_list rv; int reg; + int curr; - rv = chg_read8(chgnum, SM5803_REG_FAST_CONF4, ®); + rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_MEAS_MSB, ®); + if (rv) + return rv; + curr = reg << 2; + + rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_MEAS_LSB, ®); if (rv) return rv; + curr |= reg & SM5803_IBAT_CHG_MEAS_LSB; - *current = SM5803_REG_TO_CURRENT(reg & SM5803_CONF4_ICHG_FAST); + /* The LSB is 7.32mA */ + *current = curr * 732 / 100; return EC_SUCCESS; } @@ -696,20 +705,19 @@ static enum ec_error_list sm5803_get_voltage(int chgnum, int *voltage) int reg; int volt_bits; - /* Note: Vsys should match Vbat voltage */ - rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_MSB, ®); + rv = meas_read8(chgnum, SM5803_REG_VSYS_MEAS_MSB, ®); if (rv) return rv; + volt_bits = reg << 2; - volt_bits = reg << 3; - - rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_LSB, ®); + rv = meas_read8(chgnum, SM5803_REG_VSYS_MEAS_LSB, ®); if (rv) return rv; + volt_bits |= reg & 0x3; - volt_bits |= (reg & 0x7); + /* The LSB is 23.4mV */ + *voltage = volt_bits * 234 / 10; - *voltage = SM5803_REG_TO_VOLTAGE(volt_bits); return EC_SUCCESS; } @@ -769,12 +777,20 @@ static enum ec_error_list sm5803_get_input_current(int chgnum, { enum ec_error_list rv; int reg; + int curr; + + rv = meas_read8(chgnum, SM5803_REG_IBUS_CHG_MEAS_MSB, ®); + if (rv) + return rv; + curr = reg << 2; - rv = chg_read8(chgnum, SM5803_REG_CHG_ILIM, ®); + rv = meas_read8(chgnum, SM5803_REG_IBUS_CHG_MEAS_LSB, ®); if (rv) return rv; + curr |= reg & 0x3; - *input_current = SM5803_REG_TO_CURRENT(reg & SM5803_CHG_ILIM_RAW); + /* The LSB is 7.32mA */ + *input_current = curr * 732 / 100; return EC_SUCCESS; } @@ -857,6 +873,37 @@ static enum ec_error_list sm5803_enable_otg_power(int chgnum, int enabled) rv = chg_write8(chgnum, SM5803_REG_ANA_EN1, reg); } + if (IS_ENABLED(CONFIG_OCPC) && + (chgnum == CHARGER_PRIMARY) && + (charge_get_active_chg_chip() != -1)) { + /* In linear mode, the sequence is a little different. */ + if (enabled) { + rv = chg_read8(chgnum, SM5803_REG_FLOW3, ®); + if (rv) + return rv; + reg &= ~SM5803_FLOW3_SWITCH_BCK_BST; + rv = chg_write8(chgnum, SM5803_REG_FLOW3, reg); + if (rv) + return rv; + + rv = chg_read8(chgnum, SM5803_REG_SWITCHER_CONF, ®); + if (rv) + return rv; + reg &= ~SM5803_SW_BCK_BST_CONF_AUTO; + rv = chg_write8(chgnum, SM5803_REG_SWITCHER_CONF, reg); + if (rv) + return rv; + } else { + rv = chg_read8(chgnum, SM5803_REG_SWITCHER_CONF, ®); + if (rv) + return rv; + reg |= SM5803_SW_BCK_BST_CONF_AUTO; + rv = chg_write8(chgnum, SM5803_REG_SWITCHER_CONF, reg); + if (rv) + return rv; + } + } + /* * Enable: CHG_EN - turns on buck-boost * VBUSIN_DISCH_EN - enable discharge on Vbus @@ -897,6 +944,73 @@ static int sm5803_is_sourcing_otg_power(int chgnum, int port) return reg == CHARGER_MODE_SOURCE; } +static enum ec_error_list sm5803_set_vsys_compensation(int chgnum, + struct ocpc_data *ocpc, + int current_ma, + int voltage_mv) +{ + + int rv; + int regval; + const struct battery_info *batt_info; + int ibat_eoc_ma; + int r; + + /* + * Enable linear, pre-charge, and linear fast charge for primary + * charger. + * + * TODO(b/163511546): Move this into a sink enable function. + */ + rv = chg_read8(CHARGER_PRIMARY, SM5803_REG_FLOW3, ®val); + regval |= BIT(6) | BIT(5) | BIT(4); + rv |= chg_write8(CHARGER_PRIMARY, SM5803_REG_FLOW3, regval); + + /* Set end of fast charge threshold */ + batt_info = battery_get_info(); + ibat_eoc_ma = batt_info->precharge_current - 50; + ibat_eoc_ma /= 100; + ibat_eoc_ma = CLAMP(ibat_eoc_ma, 0, SM5803_CONF5_IBAT_EOC_TH); + rv |= chg_read8(CHARGER_PRIMARY, SM5803_REG_FAST_CONF5, ®val); + regval &= ~SM5803_CONF5_IBAT_EOC_TH; + regval |= ibat_eoc_ma; + rv |= chg_write8(CHARGER_PRIMARY, SM5803_REG_FAST_CONF5, regval); + + /* Enable test address and do some magic.*/ + rv |= main_write8(CHARGER_PRIMARY, 0x1F, 0x1); + rv |= test_write8(CHARGER_PRIMARY, 0x44, 0x20); + rv |= test_write8(CHARGER_PRIMARY, 0x48, 0x4); + rv |= main_write8(CHARGER_PRIMARY, 0x1F, 0x0); + + /* Enable linear mode on the primary charger IC */ + rv |= sm5803_flow1_update(CHARGER_PRIMARY, MASK_SET, + SM5803_FLOW1_LINEAR_CHARGE_EN); + + /* Start pre-regulation on auxiliary charger. */ + rv |= chg_write8(chgnum, SM5803_REG_FLOW1, CHARGER_MODE_SINK); + + /* Enable the IBAT_CHG adc in order to calculate system resistance. */ + rv |= meas_read8(chgnum, SM5803_REG_GPADC_CONFIG1, ®val); + regval |= SM5803_GPADCC1_IBAT_CHG_EN; + rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG1, regval); + + /* Set IR drop compensation */ + r = ocpc->combined_rsys_rbatt_mo * 100 / 167; /* 1.67mOhm steps */ + r = MAX(0, r); + rv |= chg_write8(chgnum, SM5803_REG_IR_COMP2, r & 0x7F); + rv |= chg_read8(chgnum, SM5803_REG_IR_COMP1, ®val); + regval &= ~SM5803_IR_COMP_RES_SET_MSB; + r = r >> 8; /* Bits 9:8 */ + regval |= (r & 0x3) << SM5803_IR_COMP_RES_SET_MSB_SHIFT; + regval |= SM5803_IR_COMP_EN; + rv |= chg_write8(chgnum, SM5803_REG_IR_COMP1, regval); + + if (rv) + return EC_ERROR_UNKNOWN; + + return EC_ERROR_UNIMPLEMENTED; +} + #ifdef CONFIG_CMD_CHARGER_DUMP static int command_sm5803_dump(int argc, char **argv) { @@ -965,4 +1079,5 @@ const struct charger_drv sm5803_drv = { .set_otg_current_voltage = &sm5803_set_otg_current_voltage, .enable_otg_power = &sm5803_enable_otg_power, .is_sourcing_otg_power = &sm5803_is_sourcing_otg_power, + .set_vsys_compensation = &sm5803_set_vsys_compensation, }; diff --git a/driver/charger/sm5803.h b/driver/charger/sm5803.h index 9fc04de0f4..d16f000323 100644 --- a/driver/charger/sm5803.h +++ b/driver/charger/sm5803.h @@ -138,6 +138,16 @@ enum sm5803_gpio0_modes { #define SM5803_TINT_LOW_LEVEL 0xBF #define SM5803_TINT_HIGH_LEVEL 0xD1 +/* IBAT levels - The IBAT levels increment in 7.32mA */ +#define SM5803_REG_IBAT_CHG_MEAS_MSB 0x44 +#define SM5803_REG_IBAT_CHG_MEAS_LSB 0x45 +#define SM5803_IBAT_CHG_MEAS_LSB GENMASK(1, 0) + +/* IBUS levels - The IBUS levels increment in 7.32mA */ +#define SM5803_REG_IBUS_CHG_MEAS_MSB 0x46 +#define SM5803_REG_IBUS_CHG_MEAS_LSB 0x47 +#define SM5803_IBUS_CHG_MEAS_LSB GENMASK(1, 0) + #define SM5803_REG_VBUS_MEAS_MSB 0x48 #define SM5803_REG_VBUS_MEAS_LSB 0x49 #define SM5803_VBUS_MEAS_LSB GENMASK(1, 0) @@ -148,6 +158,11 @@ enum sm5803_gpio0_modes { #define SM5803_REG_TINT_MEAS_MSB 0x4E +/* VSYS levels - The VSYS levels increment in 23.4mV steps. */ +#define SM5803_REG_VSYS_MEAS_MSB 0x4C +#define SM5803_REG_VSYS_MEAS_LSB 0x4D +#define SM5803_VSYS_MEAS_LSB GENMASK(1, 0) + /* Charger registers (address 0x32) */ #define SM5803_REG_FLOW1 0x1C @@ -180,6 +195,9 @@ enum sm5803_charger_modes { #define SM5803_FLOW3_FW_SWITCH_PAUSE BIT(2) #define SM5803_FLOW3_SOFT_DISABLE_EN BIT(3) +#define SM5803_REG_SWITCHER_CONF 0x1F +#define SM5803_SW_BCK_BST_CONF_AUTO BIT(0) + #define SM5803_REG_ANA_EN1 0x21 #define SM5803_ANA_EN1_CLS_DISABLE BIT(7) @@ -249,12 +267,26 @@ enum sm5803_charger_modes { #define SM5803_REG_PRECHG 0x41 #define SM5803_PRECHG_ICHG_PRE_SET GENMASK(5, 0) +/* Fast charge Termination */ +#define SM5803_REG_FAST_CONF5 0x3D +#define SM5803_CONF5_IBAT_EOC_TH GENMASK(3, 0) + +/* IR drop compensation */ +#define SM5803_REG_IR_COMP1 0x3F +#define SM5803_IR_COMP_RES_SET_MSB GENMASK(7, 6) +#define SM5803_IR_COMP_RES_SET_MSB_SHIFT 6 +#define SM5803_IR_COMP_EN BIT(5) + +/* LSB is in 1.67mOhm steps. */ +#define SM5803_REG_IR_COMP2 0x40 + #define SM5803_REG_PHOT1 0x72 #define SM5803_PHOT1_IBAT_PHOT_COMP_EN BIT(0) #define SM5803_PHOT1_IBUS_PHOT_COMP_EN BIT(1) #define SM5803_PHOT1_VSYS_MON_EN BIT(2) #define SM5803_PHOT1_VBUS_MON_EN BIT(3) #define SM5803_PHOT1_DURATION GENMASK(6, 4) +#define SM5803_PHOT1_DURATION_SHIFT 4 #define SM5803_PHOT1_IRQ_MODE BIT(7) #define CHARGER_NAME "sm5803" -- cgit v1.2.1