summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parker <dparker@chromium.org>2014-07-14 18:55:36 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-07-15 17:53:14 +0000
commit0f3858a3d1734e6433b74c2ac2657957d08aa6e1 (patch)
tree836c4686452f756db88050f1470ea3671abf3d72
parent6a4725e803a72873b1d3392f27a26ca3ab27a02e (diff)
downloadchrome-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.c130
-rw-r--r--include/battery.h20
-rw-r--r--include/ec_commands.h14
-rw-r--r--util/ectool.c42
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;
}