diff options
author | Dave Parker <dparker@chromium.org> | 2014-07-14 18:55:36 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-07-15 17:53:14 +0000 |
commit | 0f3858a3d1734e6433b74c2ac2657957d08aa6e1 (patch) | |
tree | 836c4686452f756db88050f1470ea3671abf3d72 | |
parent | 6a4725e803a72873b1d3392f27a26ca3ab27a02e (diff) | |
download | chrome-ec-0f3858a3d1734e6433b74c2ac2657957d08aa6e1.tar.gz |
BayTrail: Add support for battery cutoff at-shutdown
This change brings over support from ToT for the
'at-shutdown' option to "ectool batterycutoff"
A board wishing to use the common command should define:
CONFIG_BATTERY_CUT_OFF in its board.h,
implement "int board_cut_off_battery(void)"
and remove any other EC_CMD_BATTERY_CUT_OFF command handlers.
BUG=chrome-os-partner:28190
BRANCH=None
TEST=Run the following commands and verify on the serial
console that the battery is cut off at the appropriate time.
Console:
cutoff
cutoff at-shutdown
ectool (from both ToT and Rambi branch)
ectool batterycutoff
ectool batterycutoff at-shutdown
Change-Id: I9071b0250181af5a31ff2eea71f9a142df0470d3
Signed-off-by: Dave Parker <dparker@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/207982
Reviewed-by: Vic Yang <victoryang@chromium.org>
-rw-r--r-- | common/battery.c | 130 | ||||
-rw-r--r-- | include/battery.h | 20 | ||||
-rw-r--r-- | include/ec_commands.h | 14 | ||||
-rw-r--r-- | util/ectool.c | 42 |
4 files changed, 146 insertions, 60 deletions
diff --git a/common/battery.c b/common/battery.c index c9589607a0..90676596c1 100644 --- a/common/battery.c +++ b/common/battery.c @@ -19,6 +19,17 @@ #define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) +#ifdef CONFIG_BATTERY_CUT_OFF + +#ifndef CONFIG_BATTERY_CUTOFF_DELAY_US +#define CONFIG_BATTERY_CUTOFF_DELAY_US (1 * SECOND) +#endif + +static enum battery_cutoff_states battery_cutoff_state = + BATTERY_CUTOFF_STATE_NORMAL; + +#endif + #ifdef CONFIG_BATTERY_PRESENT_GPIO #ifdef CONFIG_BATTERY_PRESENT_CUSTOM #error "Don't define both CONFIG_BATTERY_PRESENT_CUSTOM and" \ @@ -33,13 +44,6 @@ int battery_is_present(void) } #endif -#ifdef CONFIG_BATTERY_CUT_OFF -#define BATTERY_CUTOFF_DELAY_US (5 * SECOND) -#define BATTERY_CUTOFF_CONSOLE_TRIES 5 - -static int pending_cutoff; /* If a battery cut-off has been requested */ -#endif - static const char *get_error_text(int rv) { if (rv == EC_ERROR_UNIMPLEMENTED) @@ -251,67 +255,103 @@ DECLARE_CONSOLE_COMMAND(battery, command_battery, NULL); #ifdef CONFIG_BATTERY_CUT_OFF -static void cut_off_wrapper(void) +int battery_is_cut_off(void) +{ + return (battery_cutoff_state == BATTERY_CUTOFF_STATE_CUT_OFF); +} + +static void pending_cutoff_deferred(void) { int rv; - rv = battery_cut_off(); /* In board/$board/battery.c */ + rv = board_cut_off_battery(); if (rv == EC_SUCCESS) CPRINTF("[%T Battery cut off succeeded.]\n"); else CPRINTF("[%T Battery cut off failed!]\n"); } -DECLARE_DEFERRED(cut_off_wrapper); +DECLARE_DEFERRED(pending_cutoff_deferred); -static void check_pending_cutoff(void) +static void clear_pending_cutoff(void) { - if (pending_cutoff) { - CPRINTF("[%T Cutting off battery in %d second(s)]\n", - BATTERY_CUTOFF_DELAY_US / SECOND); - hook_call_deferred(cut_off_wrapper, BATTERY_CUTOFF_DELAY_US); + if (extpower_is_present()) { + battery_cutoff_state = BATTERY_CUTOFF_STATE_NORMAL; + hook_call_deferred(pending_cutoff_deferred, -1); } } -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, check_pending_cutoff, HOOK_PRIO_LAST); +DECLARE_HOOK(HOOK_AC_CHANGE, clear_pending_cutoff, HOOK_PRIO_DEFAULT); -int host_command_battery_cut_off(struct host_cmd_handler_args *args) +static int battery_command_cutoff(struct host_cmd_handler_args *args) { - pending_cutoff = 1; - - /* - * When cutting off the battery, the AP is off and AC is not present. - * This makes serial console unresponsive and hard to verify battery - * cut-off. Let's disable sleep here so one can check cut-off status - * if needed. This shouldn't matter because we are about to cut off - * the battery. - */ - disable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP); - - return EC_RES_SUCCESS; + const struct ec_params_battery_cutoff *p; + int rv; + + if (args->version == 1) { + p = args->params; + if (p->flags & EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN) { + battery_cutoff_state = BATTERY_CUTOFF_STATE_PENDING; + CPRINTF("[%T Battery cut off at-shutdown"); + CPRINTF(" is scheduled]\n"); + return EC_RES_SUCCESS; + } + } + + rv = board_cut_off_battery(); + if (!rv) { + CPRINTF("[%T Battery cut off is successful.]\n"); + battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF; + } else { + CPRINTF("[%T Battery cut off has failed.]\n"); + } + + return rv; } -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, host_command_battery_cut_off, - EC_VER_MASK(0)); +DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cutoff, + EC_VER_MASK(0) | EC_VER_MASK(1)); -static int console_command_battcutoff(int argc, char **argv) +static void check_pending_cutoff(void) { - int tries = BATTERY_CUTOFF_CONSOLE_TRIES; - - while (extpower_is_present() && tries > 0) { - ccprintf("Remove AC power within %d seconds...\n", tries); - tries--; - usleep(SECOND); + if (battery_cutoff_state == BATTERY_CUTOFF_STATE_PENDING) { + CPRINTF("[%T Cutting off battery in %d second(s)]\n", + CONFIG_BATTERY_CUTOFF_DELAY_US / SECOND); + hook_call_deferred(pending_cutoff_deferred, + CONFIG_BATTERY_CUTOFF_DELAY_US); } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, check_pending_cutoff, HOOK_PRIO_LAST); - if (extpower_is_present()) - return EC_ERROR_UNKNOWN; +static int command_cutoff(int argc, char **argv) +{ + int rv; - ccprintf("Cutting off battery.\n"); + if (argc > 1) { + if (!strcasecmp(argv[1], "at-shutdown")) { + battery_cutoff_state = BATTERY_CUTOFF_STATE_PENDING; + return EC_SUCCESS; + } else { + return EC_ERROR_INVAL; + } + } - return battery_cut_off(); + rv = board_cut_off_battery(); + if (!rv) { + ccprintf("[%T Battery cut off]\n"); + battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF; + } + + return rv; +} +DECLARE_CONSOLE_COMMAND(cutoff, command_cutoff, + "[at-shutdown]", + "Cut off the battery output", + NULL); +#else +int battery_is_cut_off(void) +{ + return 0; /* Always return NOT cut off */ } -DECLARE_CONSOLE_COMMAND(battcutoff, console_command_battcutoff, NULL, - "Cut off the battery", NULL); -#endif /* CONFIG_BATTERY_CUT_OFF */ +#endif /* CONFIG_BATTERY_CUT_OFF */ #ifdef CONFIG_BATTERY_VENDOR_PARAM static int console_command_battery_vendor_param(int argc, char **argv) diff --git a/include/battery.h b/include/battery.h index 540a143653..b9934f9817 100644 --- a/include/battery.h +++ b/include/battery.h @@ -41,6 +41,12 @@ #define CONFIG_BATTERY_LEVEL_SHUTDOWN 3 #endif +enum battery_cutoff_states { + BATTERY_CUTOFF_STATE_NORMAL = 0, + BATTERY_CUTOFF_STATE_CUT_OFF, + BATTERY_CUTOFF_STATE_PENDING, +}; + /* Battery parameters */ struct batt_params { int temperature; /* Temperature in 0.1 K */ @@ -260,15 +266,17 @@ int battery_device_chemistry(char *dest, int size); */ int battery_manufacturer_date(int *year, int *month, int *day); -#ifdef CONFIG_BATTERY_CUT_OFF /** - * Cut off battery power. - * Optional, vendor-specific implementation in board/$board/battery.c + * Call board-specific cut-off function. * - * @return non-zero if error + * @return EC_RES_INVALID_COMMAND if the battery doesn't support. */ -int battery_cut_off(void); -#endif +int board_cut_off_battery(void); + +/** + * Return if the battery has been cut off. + */ +int battery_is_cut_off(void); /** * Read battery vendor parameter. diff --git a/include/ec_commands.h b/include/ec_commands.h index 9a5c4ec68b..35361c325d 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1818,15 +1818,21 @@ struct ec_params_charge_control { #define EC_CMD_CONSOLE_READ 0x98 /*****************************************************************************/ - /* - * Cut off battery power output if the battery supports. + * Cut off battery power immediately or after the host has shut down. * - * For unsupported battery, just don't implement this command and lets EC - * return EC_RES_INVALID_COMMAND. + * return EC_RES_INVALID_COMMAND if unsupported by a board/battery. + * EC_RES_SUCCESS if the command was successful. + * EC_RES_ERROR if the cut off command failed. */ #define EC_CMD_BATTERY_CUT_OFF 0x99 +#define EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN (1 << 0) + +struct ec_params_battery_cutoff { + uint8_t flags; +} __packed; + /*****************************************************************************/ /* USB port mux control. */ diff --git a/util/ectool.c b/util/ectool.c index 4539d62e7c..1e23137a12 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -3174,9 +3174,37 @@ cmd_error: int cmd_battery_cut_off(int argc, char *argv[]) { + struct ec_params_battery_cutoff p; + int cmd_version; int rv; - rv = ec_command(EC_CMD_BATTERY_CUT_OFF, 0, NULL, 0, NULL, 0); + memset(&p, 0, sizeof(p)); + if (ec_cmd_version_supported(EC_CMD_BATTERY_CUT_OFF, 1)) { + cmd_version = 1; + if (argc > 1) { + if (!strcasecmp(argv[1], "at-shutdown")) { + p.flags = EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN; + } else { + fprintf(stderr, "Bad parameter: %s\n", argv[1]); + return -1; + } + } + } else { + /* Fall back to version 0 command */ + cmd_version = 0; + if (argc > 1) { + if (!strcasecmp(argv[1], "at-shutdown")) { + fprintf(stderr, "Explicit 'at-shutdown' "); + fprintf(stderr, "parameter not supported.\n"); + } else { + fprintf(stderr, "Bad parameter: %s\n", argv[1]); + } + return -1; + } + } + + rv = ec_command(EC_CMD_BATTERY_CUT_OFF, cmd_version, &p, sizeof(p), + NULL, 0); rv = (rv < 0 ? rv : 0); if (rv < 0) { @@ -3187,11 +3215,15 @@ int cmd_battery_cut_off(int argc, char *argv[]) EC_RES_INVALID_COMMAND); } else { printf("\n"); - printf("SUCCESS. The battery has arranged a cut-off and\n"); - printf("the system should be shutdown immediately.\n"); + printf("SUCCESS. The battery has arranged a cut-off.\n"); + + if (cmd_version == 1 && + (p.flags & EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN)) + printf("The battery will be cut off after shutdown.\n"); + else + printf("The system should be shutdown immediately.\n"); + printf("\n"); - printf("If the system is still alive, you could remove\n"); - printf("the AC power and try again.\n"); } return rv; } |