summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/keyboard_scan.c86
-rw-r--r--common/gaia_power.c14
-rw-r--r--include/ec_commands.h1
3 files changed, 79 insertions, 22 deletions
diff --git a/chip/stm32/keyboard_scan.c b/chip/stm32/keyboard_scan.c
index b8051539d5..2b7b894dd6 100644
--- a/chip/stm32/keyboard_scan.c
+++ b/chip/stm32/keyboard_scan.c
@@ -17,6 +17,7 @@
#include "keyboard.h"
#include "keyboard_scan.h"
#include "registers.h"
+#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -41,6 +42,9 @@ enum COL_INDEX {
/* The keyboard state from the last read */
static uint8_t raw_state[KB_OUTPUTS];
+/* status of keyboard related switches */
+static uint8_t switches;
+
/* Mask with 1 bits only for keys that actually exist */
static const uint8_t *actual_key_mask;
@@ -55,6 +59,12 @@ static const uint8_t actual_key_masks[4][KB_OUTPUTS] = {
{0},
};
+/* Key masks for special boot keys */
+#define MASK_INDEX_ESC 1
+#define MASK_VALUE_ESC 0x02
+#define MASK_INDEX_REFRESH 2
+#define MASK_VALUE_REFRESH 0x04
+
struct kbc_gpio {
int num; /* logical row or column number */
uint32_t port;
@@ -187,26 +197,6 @@ static void select_column(int col)
}
-int keyboard_scan_init(void)
-{
- int i;
-
- /* Tri-state (put into Hi-Z) the outputs */
- select_column(COL_TRI_STATE_ALL);
-
- /* initialize raw state since host may request it before
- * a key has been pressed (e.g. during keyboard driver init) */
- for (i = 0; i < ARRAY_SIZE(raw_state); i++)
- raw_state[i] = 0x00;
-
- /* TODO: method to set which keyboard we have, so we set the actual
- * key mask properly */
- actual_key_mask = actual_key_masks[0];
-
- return EC_SUCCESS;
-}
-
-
void wait_for_interrupt(void)
{
uint32_t pr_before, pr_after;
@@ -316,6 +306,58 @@ static int check_keys_changed(void)
}
+/* Returns non-zero if the user has triggered a recovery reset by pushing
+ * Power + Refresh + ESC. */
+static int check_recovery_key(void)
+{
+ int c;
+
+ /* check the recovery key only if we're booting due to a
+ * reset-pin-caused reset. */
+ if (system_get_reset_cause() != SYSTEM_RESET_RESET_PIN)
+ return 0;
+
+ /* cold boot : Power + Refresh were pressed,
+ * check if ESC is also pressed for recovery. */
+ if (!(raw_state[MASK_INDEX_ESC] & MASK_VALUE_ESC))
+ return 0;
+
+ /* Make sure only other allowed keys are pressed. This protects
+ * against accidentally triggering the special key when a cat sits on
+ * your keyboard. Currently, only the requested key and ESC are
+ * allowed. */
+ for (c = 0; c < KB_OUTPUTS; c++) {
+ if (raw_state[c] &&
+ (c != MASK_INDEX_ESC || raw_state[c] != MASK_VALUE_ESC) &&
+ (c != MASK_INDEX_REFRESH || raw_state[c] != MASK_VALUE_REFRESH))
+ return 0; /* Additional disallowed key pressed */
+ }
+
+ CPRINTF("Keyboard RECOVERY detected !\n");
+ return 1;
+}
+
+
+int keyboard_scan_init(void)
+{
+ /* Tri-state (put into Hi-Z) the outputs */
+ select_column(COL_TRI_STATE_ALL);
+
+ /* TODO: method to set which keyboard we have, so we set the actual
+ * key mask properly */
+ actual_key_mask = actual_key_masks[0];
+
+ /* Initialize raw state */
+ check_keys_changed();
+
+ /* is recovery key pressed on cold startup ? */
+ switches |= check_recovery_key() ?
+ EC_SWITCH_KEYBOARD_RECOVERY : 0;
+
+ return EC_SUCCESS;
+}
+
+
void keyboard_scan_task(void)
{
int key_press_timer = 0;
@@ -376,8 +418,7 @@ void keyboard_put_char(uint8_t chr, int send_irq)
int keyboard_scan_recovery_pressed(void)
{
- /* TODO: (crosbug.com/p/8573) needs to be implemented */
- return 0;
+ return switches & EC_SWITCH_KEYBOARD_RECOVERY;
}
static int keyboard_get_scan(uint8_t *data, int *resp_size)
@@ -397,6 +438,7 @@ static int keyboard_get_info(uint8_t *data, int *resp_size)
r->rows = 8;
r->cols = KB_OUTPUTS;
+ r->switches = switches;
*resp_size = sizeof(struct ec_response_mkbp_info);
return EC_RES_SUCCESS;
diff --git a/common/gaia_power.c b/common/gaia_power.c
index 519099d0eb..841135fc48 100644
--- a/common/gaia_power.c
+++ b/common/gaia_power.c
@@ -27,6 +27,7 @@
#include "chipset.h" /* This module implements chipset functions too */
#include "console.h"
#include "gpio.h"
+#include "keyboard_scan.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -96,6 +97,9 @@ static int pwron_released;
/* time where we will release GPIO_PMIC_PWRON_L */
static timestamp_t pwron_deadline;
+/* force AP power on (used for recovery keypress) */
+static int auto_power_on;
+
/*
* Wait for GPIO "signal" to reach level "value".
* Returns EC_ERROR_TIMEOUT if timeout before reaching the desired state.
@@ -189,6 +193,10 @@ int gaia_power_init(void)
gpio_enable_interrupt(GPIO_PP1800_LDO2);
gpio_enable_interrupt(GPIO_SOC1V8_XPSHOLD);
+ /* auto power on if the recovery combination was pressed */
+ if (keyboard_scan_recovery_pressed())
+ auto_power_on = 1;
+
return EC_SUCCESS;
}
@@ -233,6 +241,12 @@ static int check_for_power_on_event(void)
if (gpio_get_level(GPIO_EN_PP3300))
return 1;
+ /* power on requested at EC startup for recovery */
+ if (auto_power_on) {
+ auto_power_on = 0;
+ return 1;
+ }
+
/* wait for Power button press */
wait_in_signal(GPIO_KB_PWR_ON_L, 0, -1);
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 4599cf4475..805398e1fb 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -533,6 +533,7 @@ struct ec_response_mkbp_state {
struct ec_response_mkbp_info {
uint32_t rows;
uint32_t cols;
+ uint8_t switches;
} __attribute__ ((packed));
/* Simulate key press */