From 37062dd4377eb35d2261015729ef867e936833ea Mon Sep 17 00:00:00 2001 From: Dave Parker Date: Mon, 21 Apr 2014 16:09:58 -0700 Subject: Move battery cutoff to a shared command with config option Boards can define the config option and implement a battery_cut_off() function to put their battery into "ship mode." Works with the existing "batterycutoff" host command. When using the host command, the battery is cut off 5 seconds after the system is shut down to minimize filessystem corruption issues. Also includes a "battcutoff" console command that requires AC power be removed. Cut off is immediate in this case. BUG=chrome-os-partner:28190 BRANCH=ToT TEST=Run 'ectool batterycutoff' and the console 'battcutoff' commands on a board using the CONFIG_BATTERY_CUT_OFF option. Verify the battery is cut off by pressing the power button >5 seconds after shutting down. Change-Id: I4d99a2e5aec53906416677ea44b41123b2957815 Signed-off-by: Dave Parker Reviewed-on: https://chromium-review.googlesource.com/196133 Reviewed-by: Randall Spangler Reviewed-by: Vic Yang --- common/battery.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/battery.h | 10 ++++++++ include/config.h | 7 +++++ 3 files changed, 93 insertions(+) diff --git a/common/battery.c b/common/battery.c index 7f318646a3..5f556b7762 100644 --- a/common/battery.c +++ b/common/battery.c @@ -8,11 +8,17 @@ #include "battery.h" #include "common.h" #include "console.h" +#include "extpower.h" #include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "system.h" #include "timer.h" #include "util.h" #include "watchdog.h" +#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) + #ifdef CONFIG_BATTERY_PRESENT_GPIO #ifdef CONFIG_BATTERY_PRESENT_CUSTOM #error "Don't define both CONFIG_BATTERY_PRESENT_CUSTOM and" \ @@ -27,6 +33,13 @@ 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) @@ -236,3 +249,66 @@ DECLARE_CONSOLE_COMMAND(battery, command_battery, " ", "Print battery info", NULL); + +#ifdef CONFIG_BATTERY_CUT_OFF +static void cut_off_wrapper(void) +{ + int rv; + + rv = battery_cut_off(); /* In board/$board/battery.c */ + + if (rv == EC_SUCCESS) + CPRINTF("[%T Battery cut off succeeded.]\n"); + else + CPRINTF("[%T Battery cut off failed!]\n"); +} +DECLARE_DEFERRED(cut_off_wrapper); + +static void check_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); + } +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, check_pending_cutoff, HOOK_PRIO_LAST); + +int host_command_battery_cut_off(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; +} +DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, host_command_battery_cut_off, + EC_VER_MASK(0)); + +static int console_command_battcutoff(int argc, char **argv) +{ + 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 (extpower_is_present()) + return EC_ERROR_UNKNOWN; + + ccprintf("Cutting off battery.\n"); + + return battery_cut_off(); +} +DECLARE_CONSOLE_COMMAND(battcutoff, console_command_battcutoff, NULL, + "Cut off the battery", NULL); +#endif /* CONFIG_BATTERY_CUT_OFF */ diff --git a/include/battery.h b/include/battery.h index 8ede38641b..d8229a0fad 100644 --- a/include/battery.h +++ b/include/battery.h @@ -252,4 +252,14 @@ 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 + * + * @return non-zero if error + */ +int battery_cut_off(void); +#endif + #endif /* __CROS_EC_BATTERY_H */ diff --git a/include/config.h b/include/config.h index af842f957b..341b9d78ac 100644 --- a/include/config.h +++ b/include/config.h @@ -91,6 +91,13 @@ #undef CONFIG_BATTERY_BQ27541 /* BQ27541 battery */ #undef CONFIG_BATTERY_LINK /* Battery used on Link */ +/* + * The board's battery.c implements a battery_cut_off() function to command the + * battery to enter "shipping mode" from the factory. This config option adds + * a host and console command to call this function. + */ +#undef CONFIG_BATTERY_CUT_OFF + /* Compile mock battery support; used by tests. */ #undef CONFIG_BATTERY_MOCK -- cgit v1.2.1