Skip to content

Commit da76adf

Browse files
James Courtier-DuttonJames Courtier-Dutton
authored andcommitted
Implement a more advanced multi-slot charging state that have lower, upper and discharge bounds.
Signed-off-by: James Courtier-Dutton <james@superbug.co.uk>
1 parent 5d95925 commit da76adf

3 files changed

Lines changed: 135 additions & 24 deletions

File tree

common/charge_state.c

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ static unsigned int user_current_limit = -1U;
8282
test_export_static timestamp_t shutdown_target_time;
8383
static timestamp_t precharge_start_time;
8484
static struct sustain_soc sustain_soc;
85+
static struct sustain_soc3 sustain_soc3[4];
86+
int sustain3_slot = 0;
8587
static struct current_limit {
8688
uint32_t value; /* Charge limit to apply, in mA */
8789
int soc; /* Minimum battery SoC at which the limit will be applied. */
@@ -224,6 +226,9 @@ int battery_sustainer_set(int8_t lower, int8_t upper)
224226
sustain_soc.lower = lower;
225227
sustain_soc.upper = upper;
226228
CPRINTS("Sustainer set: %d%% ~ %d%%", lower, upper);
229+
sustain_soc3[0].lower = lower;
230+
sustain_soc3[0].upper = upper;
231+
sustain_soc3[0].discharge = -1;
227232
return EC_SUCCESS;
228233
}
229234

@@ -334,6 +339,14 @@ static void dump_charge_state(void)
334339
ccprintf("Battery sustainer = %s (%d%% ~ %d%%)\n",
335340
battery_sustainer_enabled() ? "on" : "off", sustain_soc.lower,
336341
sustain_soc.upper);
342+
ccprintf("Sustainer slot = %d\n", sustain3_slot);
343+
for (int n = 0; n < 4; n++) {
344+
ccprintf("Sustainer slot[%d] (%d%% ~ %d%% - %d%%)\n",
345+
n,
346+
sustain_soc3[n].lower,
347+
sustain_soc3[n].upper,
348+
sustain_soc3[n].discharge);
349+
}
337350
#undef DUMP
338351
}
339352

@@ -917,11 +930,26 @@ int battery_outside_charging_temperature(void)
917930
return 0;
918931
}
919932

933+
int sustain3_is_slot_valid(int slot) {
934+
if (slot < 0 || slot >= 4) {
935+
return 0;
936+
}
937+
if ((sustain_soc3[slot].lower == -1) ||
938+
(sustain_soc3[slot].upper == -1)) {
939+
return 0;
940+
}
941+
if ((sustain_soc3[slot].lower == 0) ||
942+
(sustain_soc3[slot].upper == 0)) {
943+
return 0;
944+
}
945+
return 1;
946+
}
947+
920948
static enum ec_charge_control_mode
921949
sustain_switch_mode(enum ec_charge_control_mode mode)
922950
{
923951
enum ec_charge_control_mode new_mode = mode;
924-
int soc = charge_get_display_charge() / 10;
952+
int soc = (charge_get_display_charge() + 5) / 10;
925953

926954
/*
927955
* The sustain range is defined by 'lower' and 'upper' where the equal
@@ -946,54 +974,68 @@ sustain_switch_mode(enum ec_charge_control_mode mode)
946974
* makes the sustainer use DISCHARGE instead of IDLE. This is done by
947975
* setting lower != upper in V2, which doesn't support the flag.
948976
*/
977+
978+
/*
979+
* Slot 0 is the parameters set by the BIOS
980+
* Slot 1 is the parameters set by the user. e.g. with ectool
981+
* Slot 2 is the battery_extender stage 1
982+
* Slot 3 is the battery_extender stage 2
983+
*/
984+
int slot = sustain3_slot;
985+
if (slot < 0 || slot >= 4) {
986+
slot = 0;
987+
}
988+
// If the current slot is invalid, switch back to slot 0
989+
// If slot == 0, and slot 1 is valid, switch to slot 1
990+
if (!sustain3_is_slot_valid(slot)) {
991+
slot = 0;
992+
}
993+
if (slot == 0) {
994+
if (sustain3_is_slot_valid(1)) {
995+
slot = 1;
996+
} else {
997+
slot = 0;
998+
}
999+
}
1000+
sustain3_slot = slot;
1001+
int discharge = sustain_soc3[slot].discharge;
1002+
if (discharge <= sustain_soc3[slot].upper) discharge = 126;
1003+
// By default, don't change mode
1004+
new_mode = mode;
9491005
switch (mode) {
9501006
case CHARGE_CONTROL_NORMAL:
9511007
/* Currently charging */
952-
if (sustain_soc.upper < soc) {
1008+
if (soc >= discharge) {
1009+
new_mode = CHARGE_CONTROL_DISCHARGE;
1010+
} else if (soc >= sustain_soc3[slot].upper) {
9531011
/*
9541012
* We come here only if the soc is already above the
9551013
* upper limit at the time the sustainer started.
9561014
*/
957-
//new_mode = CHARGE_CONTROL_DISCHARGE;
9581015
new_mode = CHARGE_CONTROL_IDLE;
959-
} else if (sustain_soc.upper == soc) {
960-
/*
961-
* We've been charging and finally reached the upper.
962-
* Let's switch to IDLE to stay.
963-
*/
964-
//if (sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE)
965-
// new_mode = CHARGE_CONTROL_DISCHARGE;
966-
//else
967-
new_mode = CHARGE_CONTROL_IDLE;
9681016
}
9691017
break;
9701018
case CHARGE_CONTROL_IDLE:
971-
/* Discharging naturally */
972-
if (soc < sustain_soc.lower)
1019+
if (soc >= discharge) {
1020+
new_mode = CHARGE_CONTROL_DISCHARGE;
1021+
if (soc <= sustain_soc3[slot].lower)
9731022
/*
9741023
* Presumably, we stayed in the sustain range for a
9751024
* while but finally fell off the range. Let's charge to
9761025
* the upper.
9771026
*/
9781027
new_mode = CHARGE_CONTROL_NORMAL;
979-
else if (sustain_soc.upper < soc)
980-
/*
981-
* This can happen only if sustainer is restarted with
982-
* decreased upper limit. Let's discharge to the upper.
983-
*/
984-
//new_mode = CHARGE_CONTROL_DISCHARGE;
985-
new_mode = CHARGE_CONTROL_IDLE;
1028+
}
9861029
break;
9871030
case CHARGE_CONTROL_DISCHARGE:
9881031
/* Discharging actively. */
989-
if (soc <= sustain_soc.upper &&
990-
!(sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE))
1032+
if (soc <= sustain_soc3[slot].upper)
9911033
/*
9921034
* Normal case. We've been discharging and finally
9931035
* reached the upper. Let's switch to IDLE to stay.
9941036
*/
9951037
new_mode = CHARGE_CONTROL_IDLE;
996-
else if (soc < sustain_soc.lower)
1038+
else if (soc <= sustain_soc3[slot].lower)
9971039
/*
9981040
* This can happen only if sustainer is restarted with
9991041
* increase lower limit. Let's charge to the upper (then
@@ -2206,6 +2248,36 @@ charge_command_charge_control(struct host_cmd_handler_args *args)
22062248
DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL, charge_command_charge_control,
22072249
EC_VER_MASK(2) | EC_VER_MASK(3));
22082250

2251+
2252+
static enum ec_status
2253+
charge_command_charge_control3(struct host_cmd_handler_args *args)
2254+
{
2255+
const struct ec_params_charge_control3 *p = args->params;
2256+
struct ec_response_charge_control3 *r = args->response;
2257+
2258+
if (p->cmd == EC_CHARGE_CONTROL_CMD_SET) {
2259+
int slot = p->slot;
2260+
sustain_soc3[slot].lower = p->sustain_soc3.lower;
2261+
sustain_soc3[slot].upper = p->sustain_soc3.upper;
2262+
sustain_soc3[slot].discharge = p->sustain_soc3.discharge;
2263+
} else if (p->cmd == EC_CHARGE_CONTROL_CMD_GET) {
2264+
for (int n = 0; n < 4; n++) {
2265+
r->slot = sustain3_slot;
2266+
r->sustain_soc3[n].lower = sustain_soc3[n].lower;
2267+
r->sustain_soc3[n].upper = sustain_soc3[n].upper;
2268+
r->sustain_soc3[n].discharge = sustain_soc3[n].discharge;
2269+
}
2270+
args->response_size = sizeof(*r);
2271+
return EC_RES_SUCCESS;
2272+
} else {
2273+
return EC_RES_INVALID_PARAM;
2274+
}
2275+
2276+
return EC_RES_SUCCESS;
2277+
}
2278+
DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL3, charge_command_charge_control3,
2279+
EC_VER_MASK(3));
2280+
22092281
static enum ec_status
22102282
charge_command_current_limit(struct host_cmd_handler_args *args)
22112283
{

include/charge_state.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ struct sustain_soc {
119119
uint8_t flags; /* enum ec_charge_control_flag */
120120
};
121121

122+
struct sustain_soc3 {
123+
int8_t lower;
124+
int8_t upper;
125+
int8_t discharge;
126+
};
127+
122128
#define BAT_MAX_DISCHG_CURRENT 5000 /* mA */
123129
#define BAT_LOW_VOLTAGE_THRESH 3200 /* mV */
124130

include/ec_commands.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4485,6 +4485,39 @@ struct ec_response_charge_control {
44854485
uint8_t reserved;
44864486
} __ec_align4;
44874487

4488+
/*****************************************************************************/
4489+
/* Charge control3 commands */
4490+
4491+
#define EC_CMD_CHARGE_CONTROL3 0x3e96
4492+
#define EC_VER_CHARGE_CONTROL3 3
4493+
4494+
struct ec_params_charge_control3 {
4495+
uint32_t mode; /* enum charge_control_mode */
4496+
4497+
uint8_t cmd; /* enum ec_charge_control3_cmd. */
4498+
uint8_t slot; /* enum ec_charge_control_flag (v3+) */
4499+
/*
4500+
* Lower and upper thresholds for battery sustainer. This struct isn't
4501+
* named to avoid tainting foreign projects' name spaces.
4502+
*/
4503+
struct {
4504+
int8_t lower; /* Display SoC in percentage. */
4505+
int8_t upper; /* Display SoC in percentage. */
4506+
int8_t discharge;
4507+
} sustain_soc3;
4508+
} __ec_align4;
4509+
4510+
struct ec_response_charge_control3 {
4511+
uint8_t slot;
4512+
struct { /* Battery sustainer thresholds */
4513+
int8_t lower;
4514+
int8_t upper;
4515+
int8_t discharge;
4516+
} sustain_soc3[4];
4517+
uint8_t reserved1;
4518+
uint8_t reserved2;
4519+
} __ec_align4;
4520+
44884521
/*****************************************************************************/
44894522

44904523
/* Snapshot console output buffer for use by EC_CMD_CONSOLE_READ. */

0 commit comments

Comments
 (0)