diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2021-05-31 13:30:24 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-28 16:21:13 +0000 |
commit | b67eba19973a046ffdc87926d527f240bfee29d7 (patch) | |
tree | 4544bf9387a5ceeb0aabb0fdf66d06b4a17a7624 /common/charge_state_v2.c | |
parent | d1c28d2974d8f573e727abb41e783b855b52f99d (diff) | |
download | chrome-ec-b67eba19973a046ffdc87926d527f240bfee29d7.tar.gz |
chgstv2: Add battery sustainer
This patch adds the battery sustainer. Given a target SoC by the host,
the sustainer will try to keep the SoC stay close within the range
near the target.
The diagram below shows how the sustainer uses the charge mode to
charge or discharge the battery as the SoC moves near the target:
T-d% T%
----------|----------------------|-----------
charge normally charge normally/slowly
(mode=NORMAL)
... ----> +--------------------->
| |
<----------------------+ <----- ...
discharge naturally discharge normally
(mode=IDLE) (mode=DISCHARGE)
When AC is unplugged, the sustainer is disabled. Currently, the
sustainer requires CONFIG_CHARGER_DISCHARGE_ON_AC.
> chgstate
state_of_charge = 69%
chg_ctl_mode = NORMAL
manual_voltage = -1
manual_current = -1
Battery sustainer = off (-1% ~ -1%)
> chgstate sustain 70 72
state_of_charge = 69%
chg_ctl_mode = NORMAL
manual_voltage = -1
manual_current = -1
Battery sustainer = on (70% ~ 72%)
> battfake 71
> chgstate
state_of_charge = 71%
chg_ctl_mode = NORMAL
> battfake 73
> chgstate
state_of_charge = 73%
chg_ctl_mode = DISCHARGE
manual_voltage = -1
manual_current = -1
> battfake 71
> chgstate
state_of_charge = 71%
chg_ctl_mode = IDLE
manual_voltage = 0
manual_current = 0
Unplug AC and EC keeps running.
> chgstate
state_of_charge = 73%
chg_ctl_mode = DISCHARGE
manual_voltage = -1
manual_current = -1
Replug AC.
> chgstate
state_of_charge = 73%
chg_ctl_mode = DISCHARGE
manual_voltage = 0
manual_current = 0
BUG=b:188457962
BRANCH=None
TEST=Atlas. See the description above.
Change-Id: I62b4e8bc9517900a5a32d2f35369c645fa8a60c3
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2929347
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'common/charge_state_v2.c')
-rw-r--r-- | common/charge_state_v2.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c index 797dd55885..84f99cf23b 100644 --- a/common/charge_state_v2.c +++ b/common/charge_state_v2.c @@ -14,6 +14,7 @@ #include "chipset.h" #include "common.h" #include "console.h" +#include "ec_commands.h" #include "ec_ec_comm_client.h" #include "ec_ec_comm_server.h" #include "extpower.h" @@ -1122,6 +1123,9 @@ static const char * const batt_pres[] = { "NO", "YES", "NOT_SURE", }; +const char *mode_text[] = EC_CHARGE_MODE_TEXT; +BUILD_ASSERT(ARRAY_SIZE(mode_text) == CHARGE_CONTROL_COUNT); + static void dump_charge_state(void) { #define DUMP(FLD, FMT) ccprintf(#FLD " = " FMT "\n", curr.FLD) @@ -1182,7 +1186,9 @@ static void dump_charge_state(void) #ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT DUMP(input_voltage, "%dmV"); #endif - ccprintf("chg_ctl_mode = %d\n", chg_ctl_mode); + ccprintf("chg_ctl_mode = %s (%d)\n", + chg_ctl_mode < CHARGE_CONTROL_COUNT + ? mode_text[chg_ctl_mode] : "UNDEF", chg_ctl_mode); ccprintf("manual_voltage = %d\n", manual_voltage); ccprintf("manual_current = %d\n", manual_current); ccprintf("user_current_limit = %dmA\n", user_current_limit); @@ -1700,6 +1706,49 @@ static int battery_outside_charging_temperature(void) } #endif +static void sustain_battery_soc(void) +{ + enum ec_charge_control_mode mode = chg_ctl_mode; + int soc; + int rv; + + /* If either AC or battery is not present, nothing to do. */ + if (!curr.ac || curr.batt.is_present != BP_YES + || !battery_sustainer_enabled()) + return; + + soc = charge_get_display_charge() / 10; + + switch (chg_ctl_mode) { + case CHARGE_CONTROL_NORMAL: + /* Going up */ + if (sustain_soc.upper < soc) + mode = CHARGE_CONTROL_DISCHARGE; + break; + case CHARGE_CONTROL_IDLE: + /* discharging naturally */ + if (soc < sustain_soc.lower) + /* TODO: Charge slowly */ + mode = CHARGE_CONTROL_NORMAL; + break; + case CHARGE_CONTROL_DISCHARGE: + /* discharging rapidly (discharge_on_ac) */ + if (soc < sustain_soc.upper) + mode = CHARGE_CONTROL_IDLE; + break; + default: + return; + } + + if (mode == chg_ctl_mode) + return; + + rv = set_chg_ctrl_mode(mode); + CPRINTS("%s: %s control mode to %s", + __func__, rv == EC_SUCCESS ? "Switched" : "Failed to switch", + mode_text[mode]); +} + /*****************************************************************************/ /* Hooks */ void charger_init(void) @@ -1715,6 +1764,8 @@ void charger_init(void) * their tasks. Make them ready first. */ battery_get_params(&curr.batt); + + battery_sustainer_disable(); } DECLARE_HOOK(HOOK_INIT, charger_init, HOOK_PRIO_DEFAULT); @@ -1865,7 +1916,7 @@ void charger_task(void *u) prev_ac = curr.ac; } else { /* Some things are only meaningful on AC */ - chg_ctl_mode = CHARGE_CONTROL_NORMAL; + set_chg_ctrl_mode(CHARGE_CONTROL_NORMAL); battery_seems_to_be_dead = 0; prev_ac = curr.ac; @@ -2136,6 +2187,7 @@ wait_for_it: (is_full != prev_full) || (curr.state != prev_state) || (curr.batt.display_charge != prev_disp_charge)) { + sustain_battery_soc(); show_charging_progress(); prev_charge = curr.batt.state_of_charge; prev_disp_charge = curr.batt.display_charge; @@ -2920,6 +2972,7 @@ static int command_chgstate(int argc, char **argv) { int rv; int val; + char *e; if (argc > 1) { if (!strcasecmp(argv[1], "idle")) { @@ -2945,6 +2998,20 @@ static int command_chgstate(int argc, char **argv) return EC_ERROR_PARAM_COUNT; if (!parse_bool(argv[2], &debugging)) return EC_ERROR_PARAM2; + } else if (!strcasecmp(argv[1], "sustain")) { + int lower, upper; + + if (argc <= 3) + return EC_ERROR_PARAM_COUNT; + lower = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + upper = strtoi(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + rv = battery_sustainer_set(lower, upper); + if (rv) + return EC_ERROR_INVAL; } else { return EC_ERROR_PARAM1; } @@ -2954,7 +3021,8 @@ static int command_chgstate(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(chgstate, command_chgstate, - "[idle|discharge|debug on|off]", + "[idle|discharge|debug on|off]" + "\n[sustain <lower> <upper>]", "Get/set charge state machine status"); #ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT |