diff options
-rw-r--r-- | driver/charger/bd99955.c | 113 | ||||
-rw-r--r-- | driver/charger/bd99955.h | 6 |
2 files changed, 109 insertions, 10 deletions
diff --git a/driver/charger/bd99955.c b/driver/charger/bd99955.c index 11217428e5..260eba8945 100644 --- a/driver/charger/bd99955.c +++ b/driver/charger/bd99955.c @@ -553,19 +553,113 @@ int charger_get_status(int *status) return EC_SUCCESS; } -int charger_set_mode(int mode) +/* + * Track charging state and update VSYS / charge enable when needed. + * VSYS must be set to FASTCHARGE_VSYSREG when charging in fastcharge mode, + * and PRECHARGE_DISCHARGE_VSYSREG otherwise. + */ +enum bd99955_charge_update { + BD99955_UPDATE_STOP_CHARGING, + BD99955_UPDATE_START_CHARGING, + BD99955_UPDATE_BAT_VOLTAGE, +}; + +enum bd99955_charge_state { + BD99955_CHARGE_STATE_UNINITIALIZED, + BD99955_CHARGE_STATE_NOT_CHARGING, + BD99955_CHARGE_STATE_PRECHARGE, + BD99955_CHARGE_STATE_FASTCHARGE, +}; + +/* + * Update battery charge state of bd99955 based upon parameter which indicates + * type of change. + */ +static int bd99955_update_charge_state(enum bd99955_charge_update update) { + static enum bd99955_charge_state charge_state = + BD99955_CHARGE_STATE_UNINITIALIZED; + enum bd99955_charge_state new_state; int rv; + int bat_voltage = 0; + + switch (update) { + case BD99955_UPDATE_STOP_CHARGING: + /* Transition directly to not charging state if asked */ + new_state = BD99955_CHARGE_STATE_NOT_CHARGING; + break; + case BD99955_UPDATE_BAT_VOLTAGE: + /* Battery voltage change is irrelevant if we're not charging */ + if (charge_state == BD99955_CHARGE_STATE_NOT_CHARGING) { + new_state = BD99955_CHARGE_STATE_NOT_CHARGING; + break; + } + /* Fall through */ + case BD99955_UPDATE_START_CHARGING: + /* Transition to fast or precharge upon battery */ + rv = ch_raw_read16(BD99955_CMD_VBAT_VAL, &bat_voltage, + BD99955_EXTENDED_COMMAND); + + /* Assume we're in precharge range on read error */ + if (rv) + bat_voltage = 0; + new_state = bat_voltage > FASTCHARGE_VSYSREG ? + BD99955_CHARGE_STATE_FASTCHARGE : + BD99955_CHARGE_STATE_PRECHARGE; + break; + default: + panic("Invalid update param"); + } + + if (new_state == charge_state) + return 0; - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) { - rv = bd99955_set_vsysreg(DISCHARGE_VSYSREG); - msleep(50); + CPRINTS("New bd99955 state: %d (%d mV)", new_state, bat_voltage); + + switch (new_state) { + case BD99955_CHARGE_STATE_NOT_CHARGING: + /* Bring up vsys if necessary, then disable charging */ + if (charge_state != BD99955_CHARGE_STATE_PRECHARGE) { + rv = bd99955_set_vsysreg(PRECHARGE_DISCHARGE_VSYSREG); + msleep(50); + } rv |= bd99955_charger_enable(0); - } else { - rv = bd99955_charger_enable(1); - msleep(1); - rv |= bd99955_set_vsysreg(CHARGE_VSYSREG); + break; + + case BD99955_CHARGE_STATE_PRECHARGE: + case BD99955_CHARGE_STATE_FASTCHARGE: + /* + * Enable charging if necessary, then bring down vsys if + * fastcharging. + */ + if (charge_state != BD99955_CHARGE_STATE_PRECHARGE && + charge_state != BD99955_CHARGE_STATE_FASTCHARGE) { + rv = bd99955_charger_enable(1); + msleep(1); + } + rv |= bd99955_set_vsysreg( + new_state == BD99955_CHARGE_STATE_PRECHARGE ? + PRECHARGE_DISCHARGE_VSYSREG : + FASTCHARGE_VSYSREG); + break; + + default: + panic("Invalid bd99955 state"); } + + charge_state = new_state; + return rv; +} + +int charger_set_mode(int mode) +{ + int rv; + + if (mode & CHARGE_FLAG_INHIBIT_CHARGE) + rv = bd99955_update_charge_state(BD99955_UPDATE_STOP_CHARGING); + else + rv = bd99955_update_charge_state(BD99955_UPDATE_START_CHARGING); + if (rv) return rv; @@ -594,6 +688,9 @@ int charger_set_current(int current) { int rv; + /* Switch between precharge and fastcharge if required */ + bd99955_update_charge_state(BD99955_UPDATE_BAT_VOLTAGE); + /* Charge current step 64 mA */ current &= ~0x3F; diff --git a/driver/charger/bd99955.h b/driver/charger/bd99955.h index 214a20fd7b..a2b53bbbae 100644 --- a/driver/charger/bd99955.h +++ b/driver/charger/bd99955.h @@ -43,8 +43,10 @@ enum bd99955_charge_port { #define BD99955_NO_BATTERY_CHARGE_I_MIN 512 /* VSYSREG settings */ -#define DISCHARGE_VSYSREG 8960 -#define CHARGE_VSYSREG 6144 +/* Setting for precharge charging and discharge */ +#define PRECHARGE_DISCHARGE_VSYSREG 8960 +/* Setting for fastcharge charging */ +#define FASTCHARGE_VSYSREG 6144 /* Battery Charger Commands */ #define BD99955_CMD_CHG_CURRENT 0x14 |