summaryrefslogtreecommitdiff
path: root/common
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
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')
-rw-r--r--common/build.mk1
-rw-r--r--common/hooks.c1
-rw-r--r--common/keyboard_8042.c62
-rw-r--r--common/lid_switch.c1
-rw-r--r--common/power_button.c135
5 files changed, 172 insertions, 28 deletions
diff --git a/common/build.mk b/common/build.mk
index 3eb16d01a9..9b3297c7bf 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -30,6 +30,7 @@ common-$(CONFIG_LID_SWITCH)+=lid_switch.o
common-$(CONFIG_LP5562)+=lp5562.o lp5562_battery_led.o
common-$(CONFIG_LPC)+=port80.o
common-$(CONFIG_ONEWIRE_LED)+=onewire_led.o
+common-$(CONFIG_POWER_BUTTON)+=power_button.o
common-$(CONFIG_PSTORE)+=pstore_commands.o
common-$(CONFIG_SMART_BATTERY)+=smart_battery.o smart_battery_stub.o
common-$(HAS_TASK_CHIPSET)+=chipset.o
diff --git a/common/hooks.c b/common/hooks.c
index 3597a77ea8..d239e3abc2 100644
--- a/common/hooks.c
+++ b/common/hooks.c
@@ -42,6 +42,7 @@ static const struct hook_ptrs hook_list[] = {
{__hooks_chipset_shutdown, __hooks_chipset_shutdown_end},
{__hooks_ac_change, __hooks_ac_change_end},
{__hooks_lid_change, __hooks_lid_change_end},
+ {__hooks_pwrbtn_change, __hooks_pwrbtn_change_end},
{__hooks_tick, __hooks_tick_end},
{__hooks_second, __hooks_second_end},
};
diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c
index a65c935558..8e2646cb4a 100644
--- a/common/keyboard_8042.c
+++ b/common/keyboard_8042.c
@@ -15,6 +15,7 @@
#include "keyboard_protocol.h"
#include "lightbar.h"
#include "lpc.h"
+#include "power_button.h"
#include "queue.h"
#include "registers.h"
#include "shared_mem.h"
@@ -831,34 +832,6 @@ static void keyboard_special(uint16_t k)
}
}
-
-void keyboard_set_power_button(int pressed)
-{
- enum scancode_set_list code_set;
- uint8_t code[2][2][3] = {
- { /* set 1 */
- {0xe0, 0xde}, /* break */
- {0xe0, 0x5e}, /* make */
- }, { /* set 2 */
- {0xe0, 0xf0, 0x37}, /* break */
- {0xe0, 0x37}, /* make */
- }
- };
-
- power_button_pressed = pressed;
-
- /* Only send the scan code if main chipset is fully awake */
- if (!chipset_in_state(CHIPSET_STATE_ON))
- return;
-
- code_set = acting_code_set(scancode_set);
- if (keystroke_enabled) {
- i8042_send_to_host(
- (code_set == SCANCODE_SET_2 && !pressed) ? 3 : 2,
- code[code_set - SCANCODE_SET_1][pressed]);
- }
-}
-
void keyboard_protocol_task(void)
{
int wait = -1;
@@ -1097,3 +1070,36 @@ static void keyboard_restore_state(void)
}
}
DECLARE_HOOK(HOOK_INIT, keyboard_restore_state, HOOK_PRIO_DEFAULT);
+
+/**
+ * Handle power button changing state.
+ */
+static void keyboard_power_button(void)
+{
+ enum scancode_set_list code_set;
+ uint8_t code[2][2][3] = {
+ { /* set 1 */
+ {0xe0, 0xde}, /* break */
+ {0xe0, 0x5e}, /* make */
+ }, { /* set 2 */
+ {0xe0, 0xf0, 0x37}, /* break */
+ {0xe0, 0x37}, /* make */
+ }
+ };
+
+ power_button_pressed = power_button_is_pressed();
+
+ /*
+ * Only send the scan code if main chipset is fully awake and
+ * keystrokes are enabled.
+ */
+ if (!chipset_in_state(CHIPSET_STATE_ON) || !keystroke_enabled)
+ return;
+
+ code_set = acting_code_set(scancode_set);
+ i8042_send_to_host(
+ (code_set == SCANCODE_SET_2 && !power_button_pressed) ? 3 : 2,
+ code[code_set - SCANCODE_SET_1][power_button_pressed]);
+}
+DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button,
+ HOOK_PRIO_DEFAULT);
diff --git a/common/lid_switch.c b/common/lid_switch.c
index 0f83f7c318..8e1e1bf082 100644
--- a/common/lid_switch.c
+++ b/common/lid_switch.c
@@ -10,6 +10,7 @@
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
+#include "lid_switch.h"
#include "timer.h"
#include "util.h"
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);
+