summaryrefslogtreecommitdiff
path: root/driver/charger
diff options
context:
space:
mode:
Diffstat (limited to 'driver/charger')
-rw-r--r--driver/charger/sm5803.c137
-rw-r--r--driver/charger/sm5803.h32
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, &reg);
+ rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_MEAS_MSB, &reg);
+ if (rv)
+ return rv;
+ curr = reg << 2;
+
+ rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_MEAS_LSB, &reg);
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, &reg);
+ rv = meas_read8(chgnum, SM5803_REG_VSYS_MEAS_MSB, &reg);
if (rv)
return rv;
+ volt_bits = reg << 2;
- volt_bits = reg << 3;
-
- rv = chg_read8(chgnum, SM5803_REG_VSYS_PREREG_LSB, &reg);
+ rv = meas_read8(chgnum, SM5803_REG_VSYS_MEAS_LSB, &reg);
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, &reg);
+ if (rv)
+ return rv;
+ curr = reg << 2;
- rv = chg_read8(chgnum, SM5803_REG_CHG_ILIM, &reg);
+ rv = meas_read8(chgnum, SM5803_REG_IBUS_CHG_MEAS_LSB, &reg);
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, &reg);
+ 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, &reg);
+ 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, &reg);
+ 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, &regval);
+ 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, &regval);
+ 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, &regval);
+ 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, &regval);
+ 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"