Skip to content

Commit 7d875de

Browse files
dnojirikiram9
authored andcommitted
Update EC_CMD_CHARGE_CONTROL to version 2
Version 2 of EC_CMD_CHARGE_CONTROL can control battery sustainer. It allows the host to set the upper and lower thresholds between which the EC tries to keep the battery state of charge. Version 2 of EC_CMD_CHARGE_CONTROL also supports 'GET' request. It allows the host to query the current charge control settings. localhost ~ # ectool chargecontrol Charge mode = NORMAL (0) Battery sustainer = off (-1% ~ -1%) localhost ~ # ectool chargecontrol normal 66 66 Charge state machine is in normal mode with sustainer enabled. localhost ~ # ectool chargecontrol Charge mode = NORMAL (0) Battery sustainer = on (66% ~ 66%) localhost ~ # ectool chargecontrol normal Charge state machine is in normal mode. BUG=b:188457962 BRANCH=none TEST=Atlas. See above. Change-Id: I81ec62172b4f159c46334fc0f940a2adae3f2b8a Signed-off-by: Daisuke Nojiri <[email protected]> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2929340 Reviewed-by: Vincent Palatin <[email protected]>
1 parent 3d68909 commit 7d875de

File tree

4 files changed

+184
-16
lines changed

4 files changed

+184
-16
lines changed

common/charge_state_v2.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,39 @@ static void problem(enum problem_type p, int v)
205205
}
206206

207207
#ifdef CONFIG_EC_EC_COMM_BATTERY_MASTER
208+
static int battery_sustainer_set(int8_t lower, int8_t upper)
209+
{
210+
if (lower == -1 || upper == -1) {
211+
CPRINTS("Sustain mode disabled");
212+
sustain_soc.lower = -1;
213+
sustain_soc.upper = -1;
214+
return EC_SUCCESS;
215+
}
216+
217+
if (lower <= upper && 0 <= lower && upper <= 100) {
218+
/* Currently sustainer requires discharge_on_ac. */
219+
if (!IS_ENABLED(CONFIG_CHARGER_DISCHARGE_ON_AC))
220+
return EC_RES_UNAVAILABLE;
221+
sustain_soc.lower = lower;
222+
sustain_soc.upper = upper;
223+
return EC_SUCCESS;
224+
}
225+
226+
CPRINTS("Invalid param: %s(%d, %d)", __func__, lower, upper);
227+
return EC_ERROR_INVAL;
228+
}
229+
230+
static void battery_sustainer_disable(void)
231+
{
232+
battery_sustainer_set(-1, -1);
233+
}
234+
235+
static bool battery_sustainer_enabled(void)
236+
{
237+
return sustain_soc.lower != -1 && sustain_soc.upper != -1;
238+
}
239+
240+
#ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT
208241
/*
209242
* Parameters for dual-battery policy.
210243
* TODO(b:71881017): This should be made configurable by AP in the future.
@@ -1156,7 +1189,8 @@ static void dump_charge_state(void)
11561189
battery_seems_to_be_disconnected);
11571190
ccprintf("battery_was_removed = %d\n", battery_was_removed);
11581191
ccprintf("debug output = %s\n", debugging ? "on" : "off");
1159-
ccprintf("sustain charge = %d%% ~ %d%%\n",
1192+
ccprintf("Battery sustainer = %s (%d%% ~ %d%%)\n",
1193+
battery_sustainer_enabled() ? "on" : "off",
11601194
sustain_soc.lower, sustain_soc.upper);
11611195
#undef DUMP
11621196
}
@@ -2658,8 +2692,33 @@ static enum ec_status
26582692
charge_command_charge_control(struct host_cmd_handler_args *args)
26592693
{
26602694
const struct ec_params_charge_control *p = args->params;
2695+
struct ec_response_charge_control *r = args->response;
26612696
int rv;
26622697

2698+
if (args->version >= 2) {
2699+
if (p->cmd == EC_CHARGE_CONTROL_CMD_SET) {
2700+
if (chg_ctl_mode == CHARGE_CONTROL_NORMAL) {
2701+
rv = battery_sustainer_set(
2702+
p->sustain_soc.lower,
2703+
p->sustain_soc.upper);
2704+
if (rv == EC_RES_UNAVAILABLE)
2705+
return EC_RES_UNAVAILABLE;
2706+
if (rv)
2707+
return EC_RES_INVALID_PARAM;
2708+
} else {
2709+
battery_sustainer_disable();
2710+
}
2711+
} else if (p->cmd == EC_CHARGE_CONTROL_CMD_GET) {
2712+
r->mode = chg_ctl_mode;
2713+
r->sustain_soc.lower = sustain_soc.lower;
2714+
r->sustain_soc.upper = sustain_soc.upper;
2715+
args->response_size = sizeof(*r);
2716+
return EC_RES_SUCCESS;
2717+
} else {
2718+
return EC_RES_INVALID_PARAM;
2719+
}
2720+
}
2721+
26632722
rv = set_chg_ctrl_mode(p->mode);
26642723
if (rv != EC_SUCCESS)
26652724
return EC_RES_ERROR;
@@ -2693,7 +2752,7 @@ charge_command_charge_control(struct host_cmd_handler_args *args)
26932752
return EC_RES_SUCCESS;
26942753
}
26952754
DECLARE_HOST_COMMAND(EC_CMD_CHARGE_CONTROL, charge_command_charge_control,
2696-
EC_VER_MASK(1));
2755+
EC_VER_MASK(1) | EC_VER_MASK(2));
26972756

26982757
static void reset_current_limit(void)
26992758
{

include/charge_state_v2.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ struct charge_state_data {
5252
};
5353

5454
struct sustain_soc {
55-
int16_t lower;
56-
int16_t upper;
55+
int8_t lower;
56+
int8_t upper;
5757
};
5858

5959
/**

include/ec_commands.h

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4167,21 +4167,53 @@ struct ec_params_i2c_write {
41674167
* discharge the battery.
41684168
*/
41694169
#define EC_CMD_CHARGE_CONTROL 0x0096
4170-
#define EC_VER_CHARGE_CONTROL 1
4170+
#define EC_VER_CHARGE_CONTROL 2
41714171

41724172
enum ec_charge_control_mode {
41734173
CHARGE_CONTROL_NORMAL = 0,
41744174
CHARGE_CONTROL_IDLE,
41754175
CHARGE_CONTROL_DISCHARGE,
41764176
};
41774177

4178+
#define EC_CHARGE_MODE_TEXT { \
4179+
[CHARGE_CONTROL_NORMAL] = "NORMAL", \
4180+
[CHARGE_CONTROL_IDLE] = "IDLE", \
4181+
[CHARGE_CONTROL_DISCHARGE] = "DISCHARGE", \
4182+
}
4183+
4184+
enum ec_charge_control_cmd {
4185+
EC_CHARGE_CONTROL_CMD_SET = 0,
4186+
EC_CHARGE_CONTROL_CMD_GET,
4187+
};
4188+
41784189
struct ec_params_charge_control {
41794190
uint32_t mode; /* enum charge_control_mode */
4180-
/* For sustain charge (v2). The struct doesn't need to be exported. */
4191+
4192+
/* Below are the fields added in V2. */
4193+
uint8_t cmd; /* enum ec_charge_control_cmd. */
4194+
uint8_t reserved;
4195+
/*
4196+
* Lower and upper thresholds for battery sustainer. This struct isn't
4197+
* named to avoid tainting foreign projects' name spaces.
4198+
*
4199+
* If charge mode is explicitly set (e.g. DISCHARGE), battery sustainer
4200+
* will be disabled. To disable battery sustainer, set mode=NORMAL,
4201+
* lower=-1, upper=-1.
4202+
*/
41814203
struct {
4182-
int16_t lower;
4183-
int16_t upper;
4184-
} sustain_charge;
4204+
int8_t lower; /* Display SoC in percentage. */
4205+
int8_t upper; /* Display SoC in percentage. */
4206+
} sustain_soc;
4207+
} __ec_align4;
4208+
4209+
/* Added in v2 */
4210+
struct ec_response_charge_control {
4211+
uint32_t mode; /* enum charge_control_mode */
4212+
struct { /* Battery sustainer thresholds */
4213+
int8_t lower;
4214+
int8_t upper;
4215+
} sustain_soc;
4216+
uint16_t reserved;
41854217
} __ec_align4;
41864218

41874219
/*****************************************************************************/

util/ectool.c

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7378,38 +7378,115 @@ int cmd_charge_current_limit(int argc, char *argv[])
73787378
return rv;
73797379
}
73807380

7381+
static void cmd_charge_control_help(const char *cmd, const char *msg)
7382+
{
7383+
if (msg)
7384+
fprintf(stderr, "ERROR: %s\n", msg);
7385+
7386+
fprintf(stderr,
7387+
"\n"
7388+
" Usage: %s\n"
7389+
" Get current settings.\n"
7390+
" Usage: %s normal|idle|discharge\n"
7391+
" Set charge mode (and disable battery sustainer).\n"
7392+
" Usage: %s normal <lower> <upper>\n"
7393+
" Enable battery sustainer. <lower> and <upper> are battery SoC\n"
7394+
" between which EC tries to keep the battery level.\n"
7395+
"\n",
7396+
cmd, cmd, cmd);
7397+
}
73817398

73827399
int cmd_charge_control(int argc, char *argv[])
73837400
{
73847401
struct ec_params_charge_control p;
7402+
struct ec_response_charge_control r;
7403+
int version = 2;
7404+
const char * const charge_mode_text[] = EC_CHARGE_MODE_TEXT;
7405+
char *e;
73857406
int rv;
73867407

7387-
if (argc != 2) {
7388-
fprintf(stderr, "Usage: %s <normal | idle | discharge>\n",
7389-
argv[0]);
7390-
return -1;
7408+
if (!ec_cmd_version_supported(EC_CMD_CHARGE_CONTROL, 2))
7409+
version = 1;
7410+
7411+
if (argc == 1) {
7412+
if (version < 2) {
7413+
cmd_charge_control_help(argv[0],
7414+
"Old EC doesn't support GET.");
7415+
return -1;
7416+
}
7417+
p.cmd = EC_CHARGE_CONTROL_CMD_GET;
7418+
rv = ec_command(EC_CMD_CHARGE_CONTROL, version,
7419+
&p, sizeof(p), &r, sizeof(r));
7420+
if (rv < 0) {
7421+
fprintf(stderr, "Command failed.\n");
7422+
return rv;
7423+
}
7424+
printf("Charge mode = %s (%d)\n",
7425+
r.mode < ARRAY_SIZE(charge_mode_text)
7426+
? charge_mode_text[r.mode] : "UNDEFINED",
7427+
r.mode);
7428+
printf("Battery sustainer = %s (%d%% ~ %d%%)\n",
7429+
(r.sustain_soc.lower != -1 && r.sustain_soc.upper != -1)
7430+
? "on" : "off",
7431+
r.sustain_soc.lower, r.sustain_soc.upper);
7432+
return 0;
73917433
}
73927434

73937435
if (!strcasecmp(argv[1], "normal")) {
73947436
p.mode = CHARGE_CONTROL_NORMAL;
7437+
if (argc == 2) {
7438+
p.sustain_soc.lower = -1;
7439+
p.sustain_soc.upper = -1;
7440+
} else if (argc == 4) {
7441+
if (version < 2) {
7442+
cmd_charge_control_help(argv[0],
7443+
"Old EC doesn't support sustainer.");
7444+
return -1;
7445+
}
7446+
p.sustain_soc.lower = strtol(argv[2], &e, 0);
7447+
if (e && *e) {
7448+
cmd_charge_control_help(argv[0],
7449+
"Bad character in <lower>");
7450+
return -1;
7451+
}
7452+
p.sustain_soc.upper = strtol(argv[3], &e, 0);
7453+
if (e && *e) {
7454+
cmd_charge_control_help(argv[0],
7455+
"Bad character in <upper>");
7456+
return -1;
7457+
}
7458+
} else {
7459+
cmd_charge_control_help(argv[0], "Bad arguments");
7460+
return -1;
7461+
}
73957462
} else if (!strcasecmp(argv[1], "idle")) {
7463+
if (argc != 2) {
7464+
cmd_charge_control_help(argv[0], "Bad arguments");
7465+
return -1;
7466+
}
73967467
p.mode = CHARGE_CONTROL_IDLE;
73977468
} else if (!strcasecmp(argv[1], "discharge")) {
7469+
if (argc != 2) {
7470+
cmd_charge_control_help(argv[0], "Bad arguments");
7471+
return -1;
7472+
}
73987473
p.mode = CHARGE_CONTROL_DISCHARGE;
73997474
} else {
7400-
fprintf(stderr, "Bad value.\n");
7475+
cmd_charge_control_help(argv[0], "Bad sub-command");
74017476
return -1;
74027477
}
74037478

7404-
rv = ec_command(EC_CMD_CHARGE_CONTROL, 1, &p, sizeof(p), NULL, 0);
7479+
rv = ec_command(EC_CMD_CHARGE_CONTROL, version, &p, sizeof(p), NULL, 0);
74057480
if (rv < 0) {
74067481
fprintf(stderr, "Is AC connected?\n");
74077482
return rv;
74087483
}
74097484

74107485
switch (p.mode) {
74117486
case CHARGE_CONTROL_NORMAL:
7412-
printf("Charge state machine normal mode.\n");
7487+
printf("Charge state machine is in normal mode%s.\n",
7488+
(p.sustain_soc.lower == -1 || p.sustain_soc.upper == -1)
7489+
? "" : " with sustainer enabled");
74137490
break;
74147491
case CHARGE_CONTROL_IDLE:
74157492
printf("Charge state machine force idle.\n");

0 commit comments

Comments
 (0)