summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parker <dparker@google.com>2014-06-12 20:31:26 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-06-15 01:45:21 +0000
commitefd3a8925eecce4559d8c81175258d5974140db6 (patch)
tree091fee596c1c03a2cd3ea248e3f5cc199557240a
parenta0119238c7e398135c2b8e4fbb06ba81d4a6a494 (diff)
downloadchrome-ec-efd3a8925eecce4559d8c81175258d5974140db6.tar.gz
Add 'at-shutdown' option to batterycutoff host command
If at-shutdown is specified, the battery is cut off 1 seconds after the host has shutdown. BUG=chrome-os-partner:29292,chrome-os-partner:28887 BRANCH=tot,nyan TEST=Run batterycutoff ectool command and cutoff console command with and without 'at-shutdown' option. Verify the battery is cut off immediately without the option specified and 1 seconds after shutdown with. View the console log to see the deferred cutoff occur. The following tests are verified on big. console: cutoff, AC on: system is off after removing AC. cutoff, AC off: system is off immediately. at-shutdown, AC on: system is off after "power off" and removing AC. at-shutdown, AC off: system is off after "power off". ectool: batterycutoff, AC on: system is off after removing AC. batterycutoff, AC off: system is off immediately. at-shutdown, AC on: battery is cut off after 1s of shutdown. system is off right after removing AC power. at-shutdown, AC off: system is off after 1s of shutdown. [84.058416 power state 3 = S0, in 0x0000] [84.058803 power lost input; wanted 0x0001, got 0x0000] [84.059120 power off 3] [84.072148 Cutting off battery in 1 second(s)] [84.123896 power shutdown complete] [84.128790 power state 7 = S0->S3, in 0x0002] [84.139694 power state 2 = S3, in 0x0002] [84.150857 power state 8 = S3->S5, in 0x0002] [84.166975 power state 1 = S5, in 0x0002] [84.177972 power state 1 = S5, in 0x0002] [85.080012 Battery cut off succeeded.] Change-Id: Id4bacf79ad3add885260655f80cb8127bafe1ad6 Signed-off-by: Dave Parker <dparker@google.com> Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/203694 Reviewed-by: Vic Yang <victoryang@chromium.org>
-rw-r--r--common/battery.c98
-rw-r--r--include/battery.h6
-rw-r--r--include/config.h6
-rw-r--r--include/ec_commands.h14
-rw-r--r--util/ectool.c27
5 files changed, 125 insertions, 26 deletions
diff --git a/common/battery.c b/common/battery.c
index 323f3d2790..408ae92c46 100644
--- a/common/battery.c
+++ b/common/battery.c
@@ -17,8 +17,18 @@
#include "util.h"
#include "watchdog.h"
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args)
+
#ifdef CONFIG_BATTERY_CUT_OFF
-static int is_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
@@ -261,41 +271,95 @@ DECLARE_CONSOLE_COMMAND(battery, command_battery,
"Print battery info",
NULL);
-
#ifdef CONFIG_BATTERY_CUT_OFF
int battery_is_cut_off(void)
{
- return is_cut_off;
+ return (battery_cutoff_state == BATTERY_CUTOFF_STATE_CUT_OFF);
}
-static void clean_cut_off(void)
+static void pending_cutoff_deferred(void)
{
- if (extpower_is_present())
- is_cut_off = 0;
+ int rv;
+
+ 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(pending_cutoff_deferred);
+
+static void clear_pending_cutoff(void)
+{
+ if (extpower_is_present()) {
+ battery_cutoff_state = BATTERY_CUTOFF_STATE_NORMAL;
+ hook_call_deferred(pending_cutoff_deferred, -1);
+ }
}
-DECLARE_HOOK(HOOK_AC_CHANGE, clean_cut_off, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_AC_CHANGE, clear_pending_cutoff, HOOK_PRIO_DEFAULT);
-static int battery_command_cut_off(struct host_cmd_handler_args *args)
+static int battery_command_cutoff(struct host_cmd_handler_args *args)
{
- int rv = board_cut_off_battery();
- if (!rv)
- is_cut_off = 1;
+ 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;
+ CPRINTS("Battery cut off at-shutdown is scheduled");
+ return EC_RES_SUCCESS;
+ }
+ }
+
+ rv = board_cut_off_battery();
+ if (!rv) {
+ CPRINTS("Battery cut off is successful.");
+ battery_cutoff_state = BATTERY_CUTOFF_STATE_CUT_OFF;
+ } else {
+ CPRINTS("Battery cut off has failed.");
+ }
return rv;
}
-DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_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 void check_pending_cutoff(void)
+{
+ 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);
static int command_cutoff(int argc, char **argv)
{
- int rv = board_cut_off_battery();
- if (!rv)
- is_cut_off = 1;
+ int rv;
+
+ if (argc > 1) {
+ if (!strcasecmp(argv[1], "at-shutdown")) {
+ battery_cutoff_state = BATTERY_CUTOFF_STATE_PENDING;
+ return EC_SUCCESS;
+ } else {
+ return EC_ERROR_INVAL;
+ }
+ }
+
+ 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
diff --git a/include/battery.h b/include/battery.h
index b61da1833c..898e3da403 100644
--- a/include/battery.h
+++ b/include/battery.h
@@ -43,6 +43,12 @@ enum battery_present {
BP_NOT_SURE,
};
+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 */
diff --git a/include/config.h b/include/config.h
index 2b5e8afadc..8c77772c7c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -137,6 +137,12 @@
#undef CONFIG_BATTERY_CUT_OFF
/*
+ * The default delay is 1 second. Define this if a board prefers
+ * different delay.
+ */
+#undef CONFIG_BATTERY_CUTOFF_DELAY_US
+
+/*
* The board-specific battery.c implements get and set functions to read and
* write arbirary vendor-specific parameters stored in the battery.
* See include/battery.h for prototypes.
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 5edd754df3..54f0ed2aa7 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1967,12 +1967,20 @@ struct ec_params_charge_control {
/*****************************************************************************/
/*
- * 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_VER_BATTERY_CUT_OFF 1
+
+#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 13062afcbf..17a5ad011a 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -34,7 +34,7 @@ const char help_str[] =
" Enable/disable LCD backlight\n"
" battery\n"
" Prints battery info\n"
- " batterycutoff\n"
+ " batterycutoff [at-shutdown]\n"
" Cut off battery output power\n"
" batteryparam\n"
" Read or write board-specific battery parameter\n"
@@ -3653,9 +3653,21 @@ cmd_error:
int cmd_battery_cut_off(int argc, char *argv[])
{
+ struct ec_params_battery_cutoff p;
int rv;
- rv = ec_command(EC_CMD_BATTERY_CUT_OFF, 0, NULL, 0, NULL, 0);
+ memset(&p, 0, sizeof(p));
+ 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;
+ }
+ }
+
+ rv = ec_command(EC_CMD_BATTERY_CUT_OFF, EC_VER_BATTERY_CUT_OFF,
+ &p, sizeof(p), NULL, 0);
rv = (rv < 0 ? rv : 0);
if (rv < 0) {
@@ -3666,11 +3678,14 @@ 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 (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;
}