diff options
Diffstat (limited to 'driver/charger')
-rw-r--r-- | driver/charger/sm5803.c | 137 | ||||
-rw-r--r-- | driver/charger/sm5803.h | 32 |
2 files changed, 158 insertions, 11 deletions
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" |