summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2021-05-31 13:30:24 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-09-13 17:32:52 +0000
commitb92a150243dc4ad7ff69d7bb865da79841f3e0cb (patch)
treea8abaa9751a4be0bdd74888577495680a4b1c010
parent846d01788513e375b64fb73205cd58d51525451e (diff)
downloadchrome-ec-b92a150243dc4ad7ff69d7bb865da79841f3e0cb.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> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3869323 Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--common/charge_state_v2.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c
index 31cef7b255..31f526f6ef 100644
--- a/common/charge_state_v2.c
+++ b/common/charge_state_v2.c
@@ -16,6 +16,7 @@
#include "console.h"
#include "ec_ec_comm_master.h"
#include "ec_ec_comm_slave.h"
+#include "ec_commands.h"
#include "extpower.h"
#include "gpio.h"
#include "hooks.h"
@@ -1057,6 +1058,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)
@@ -1094,7 +1098,9 @@ static void dump_charge_state(void)
#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER
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);
@@ -1508,6 +1514,49 @@ const struct batt_params *charger_current_battery_params(void)
return &curr.batt;
}
+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)
@@ -1523,6 +1572,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);
@@ -1646,7 +1697,7 @@ void charger_task(void *u)
}
} 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;
}
@@ -1885,6 +1936,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;
@@ -2510,6 +2562,7 @@ static int command_chgstate(int argc, char **argv)
{
int rv;
int val;
+ char *e;
if (argc > 1) {
if (!strcasecmp(argv[1], "idle")) {
@@ -2535,6 +2588,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;
}
@@ -2544,7 +2611,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_MASTER