summaryrefslogtreecommitdiff
path: root/common/power_button.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-04-23 17:02:07 -0700
committerChromeBot <chrome-bot@google.com>2013-04-25 17:03:18 -0700
commit45bc5c1a2135eaae05978d371cff17fb810b9951 (patch)
tree38d71db1f356c86e37bbadedd384d000a329dfaf /common/power_button.c
parentb4b2c6ae7026569b21749dab563114f95d4c7396 (diff)
downloadchrome-ec-45bc5c1a2135eaae05978d371cff17fb810b9951.tar.gz
Split out power button code from switch.c
The power button code is platform-independent. This change splits the code out of the LM4 switch.c module so that a subseqent change to STM32 platforms can start using it. BUG=chrome-os-partner:18945 BRANCH=none TEST=manual 1. Power+refresh+esc goes to recovery mode, 2. Press power button at recovery screen turns off. 3. With system off, power button turns system on. 4. Press power button for a second; screen locks. 5. Press power button while typing; blocks keystrokes while it's pressed. 6. Hold power button down for 8 sec; system forced to shutdown. 7. From EC console, with system on: hostevent clear hostevent -> event 0x04 is clear press power button hostevent -> event 0x04 is set 8. From EC console, with system off: powerbtn -> system turns on powerbtn 5000 -> system turns off, just like power button was held for 5 sec Change-Id: If2a9b02514a201e1d03c857d128e2ccab51a16ef Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49217 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'common/power_button.c')
-rw-r--r--common/power_button.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/common/power_button.c b/common/power_button.c
new file mode 100644
index 0000000000..c26fb8d5d4
--- /dev/null
+++ b/common/power_button.c
@@ -0,0 +1,135 @@
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Power button module for Chrome EC */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "keyboard_scan.h"
+#include "lid_switch.h"
+#include "power_button.h"
+#include "timer.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_SWITCH, outstr)
+#define CPRINTF(format, args...) cprintf(CC_SWITCH, format, ## args)
+
+#define PWRBTN_DEBOUNCE_US (30 * MSEC) /* Debounce time for power button */
+
+static int debounced_power_pressed; /* Debounced power button state */
+static int simulate_power_pressed;
+
+/**
+ * Get raw power button signal state.
+ *
+ * @return 1 if power button is pressed, 0 if not pressed.
+ */
+static int raw_power_button_pressed(void)
+{
+ if (simulate_power_pressed)
+ return 1;
+
+ /* Ignore power button if lid is closed */
+ if (!lid_is_open())
+ return 0;
+
+ return gpio_get_level(GPIO_POWER_BUTTON_L) ? 0 : 1;
+}
+
+int power_button_is_pressed(void)
+{
+ return debounced_power_pressed;
+}
+
+/**
+ * Handle power button initialization.
+ */
+static void power_button_init(void)
+{
+ if (raw_power_button_pressed())
+ debounced_power_pressed = 1;
+
+ /* Enable interrupts, now that we've initialized */
+ gpio_enable_interrupt(GPIO_POWER_BUTTON_L);
+}
+DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_INIT_POWER_BUTTON);
+
+/**
+ * Handle debounced power button changing state.
+ */
+static void power_button_change_deferred(void)
+{
+ const int new_pressed = raw_power_button_pressed();
+
+ /* If power button hasn't changed state, nothing to do */
+ if (new_pressed == debounced_power_pressed)
+ return;
+
+ debounced_power_pressed = new_pressed;
+
+ CPRINTF("[%T power button %s]\n", new_pressed ? "pressed" : "released");
+
+ /* Re-enable keyboard scanning if power button is no longer pressed */
+ if (!new_pressed)
+ keyboard_scan_enable(1);
+
+ /* Call hooks */
+ hook_notify(HOOK_POWER_BUTTON_CHANGE);
+
+ /* Notify host if power button has been pressed */
+ if (new_pressed)
+ host_set_single_event(EC_HOST_EVENT_POWER_BUTTON);
+}
+DECLARE_DEFERRED(power_button_change_deferred);
+
+void power_button_interrupt(enum gpio_signal signal)
+{
+ /*
+ * If power button is pressed, disable the matrix scan as soon as
+ * possible to reduce the risk of false-reboot triggered by those keys
+ * on the same column with refresh key.
+ */
+ if (raw_power_button_pressed())
+ keyboard_scan_enable(0);
+
+ /* Reset power button debounce time */
+ hook_call_deferred(power_button_change_deferred, PWRBTN_DEBOUNCE_US);
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+static int command_powerbtn(int argc, char **argv)
+{
+ int ms = 200; /* Press duration in ms */
+ char *e;
+
+ if (argc > 1) {
+ ms = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM1;
+ }
+
+ ccprintf("Simulating %d ms power button press.\n", ms);
+ simulate_power_pressed = 1;
+ hook_call_deferred(power_button_change_deferred, 0);
+
+ msleep(ms);
+
+ ccprintf("Simulating power button release.\n");
+ simulate_power_pressed = 0;
+ hook_call_deferred(power_button_change_deferred, 0);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn,
+ "[msec]",
+ "Simulate power button press",
+ NULL);
+