summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/lm4/keyboard_scan.c205
-rw-r--r--common/main.c4
-rw-r--r--include/keyboard_scan.h5
3 files changed, 145 insertions, 69 deletions
diff --git a/chip/lm4/keyboard_scan.c b/chip/lm4/keyboard_scan.c
index 4056f7a21e..08456f2333 100644
--- a/chip/lm4/keyboard_scan.c
+++ b/chip/lm4/keyboard_scan.c
@@ -53,10 +53,12 @@ enum COLUMN_INDEX {
#define POLLING_MODE_TIMEOUT 1000000 /* 1 sec */
#define SCAN_LOOP_DELAY 10000 /* 10 ms */
+#define COLUMN_CHARGE_US 40 /* Column charge time in usec */
#define KB_COLS 13
static uint8_t raw_state[KB_COLS];
+static int recovery_key_pressed;
/* Mask with 1 bits only for keys that actually exist */
static const uint8_t *actual_key_mask;
@@ -72,6 +74,18 @@ static const uint8_t actual_key_masks[4][KB_COLS] = {
{0},
};
+/* Key mask for the recovery key (reload) */
+static const uint8_t recovery_key_mask[KB_COLS] = {
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+/* Key mask for keys allowed to be pressed at the same time as the recovery
+ * key. If more keys than this are pressed, the recovery key will be ignored;
+ * this protects against accidentally triggering recovery when a cat sits on
+ * your keyboard. (reload, ESC are ok) */
+static const uint8_t recovery_allowed_mask[KB_COLS] = {
+ 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
/* Drives the specified column low; other columns are tri-stated */
static void select_column(int col)
{
@@ -132,59 +146,6 @@ static void select_column(int col)
#endif
}
-int keyboard_scan_init(void)
-{
- volatile uint32_t scratch __attribute__((unused));
- int i;
-
- /* Enable GPIOs */
-#ifdef BOARD_link
- /* Enable clock to GPIO modules N,P,Q */
- LM4_SYSTEM_RCGCGPIO |= 0x7000;
-#else
- /* Enable clock to GPIO modules C,H,K,N,Q */
- LM4_SYSTEM_RCGCGPIO |= 0x5284;
-#endif
- scratch = LM4_SYSTEM_RCGCGPIO;
-
- /* Clear GPIOAFSEL and enable digital function for rows */
-#ifdef BOARD_link
- LM4_GPIO_AFSEL(LM4_GPIO_P) = 0; /* KSO[7:0] */
- LM4_GPIO_DEN(LM4_GPIO_P) = 0xff;
- LM4_GPIO_AFSEL(LM4_GPIO_Q) &= ~0x1f; /* KSO[12:8] */
- LM4_GPIO_DEN(LM4_GPIO_Q) |= 0x1f;
-#else
- LM4_GPIO_AFSEL(LM4_GPIO_K) &= ~0x0f;
- LM4_GPIO_DEN(LM4_GPIO_K) |= 0x0f;
- LM4_GPIO_AFSEL(LM4_GPIO_N) &= ~0x04;
- LM4_GPIO_DEN(LM4_GPIO_N) |= 0x04;
- LM4_GPIO_AFSEL(LM4_GPIO_Q) = 0;
- LM4_GPIO_DEN(LM4_GPIO_Q) = 0xff;
-#endif
-
- /* Set row inputs with pull-up */
- LM4_GPIO_AFSEL(KB_SCAN_ROW_GPIO) &= 0xff;
- LM4_GPIO_DEN(KB_SCAN_ROW_GPIO) |= 0xff;
- LM4_GPIO_DIR(KB_SCAN_ROW_GPIO) = 0;
- LM4_GPIO_PUR(KB_SCAN_ROW_GPIO) = 0xff;
-
- /* Tri-state the columns */
- select_column(COLUMN_TRI_STATE_ALL);
-
- /* Initialize raw state */
- for (i = 0; i < KB_COLS; i++)
- raw_state[i] = 0;
-
- /* TODO: method to set which keyboard we have, so we set the actual
- * key mask properly */
- actual_key_mask = actual_key_masks[0];
-
- /* Enable interrupts, now that we're set up */
- task_enable_irq(KB_SCAN_ROW_IRQ);
-
- return EC_SUCCESS;
-}
-
static uint32_t clear_matrix_interrupt_status(void) {
uint32_t ris = LM4_GPIO_RIS(KB_SCAN_ROW_GPIO);
@@ -194,7 +155,7 @@ static uint32_t clear_matrix_interrupt_status(void) {
}
-void wait_for_interrupt(void)
+static void wait_for_interrupt(void)
{
uart_printf("[kbscan %s()]\n", __func__);
@@ -209,7 +170,7 @@ void wait_for_interrupt(void)
}
-void enter_polling_mode(void)
+static void enter_polling_mode(void)
{
uart_printf("[kbscan %s()]\n", __func__);
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0; /* 0: disable interrupt */
@@ -217,6 +178,46 @@ void enter_polling_mode(void)
}
+/* Update the raw key state without sending messages. Used in pre-init, so
+ * must not make task-switching-dependent calls like usleep(); udelay() is ok
+ * because it's a spin-loop. */
+static void update_key_state(void)
+{
+ int c;
+ uint8_t r;
+
+ for (c = 0; c < KB_COLS; c++) {
+ /* Select column, then wait a bit for it to settle */
+ select_column(c);
+ udelay(COLUMN_CHARGE_US);
+ /* Read the row state */
+ r = LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff);
+ /* Invert it so 0=not pressed, 1=pressed */
+ r ^= 0xff;
+ /* Mask off keys that don't exist so they never show
+ * as pressed */
+ raw_state[c] = r & actual_key_mask[c];
+ }
+ select_column(COLUMN_TRI_STATE_ALL);
+}
+
+
+/* Print the raw keyboard state */
+static void print_raw_state(const char *msg)
+{
+ int c;
+
+ uart_printf("[%s:", msg);
+ for (c = 0; c < KB_COLS; c++) {
+ if (raw_state[c])
+ uart_printf(" %02x", raw_state[c]);
+ else
+ uart_puts(" --");
+ }
+ uart_puts("]\n");
+}
+
+
/* Returns 1 if any key is still pressed. 0 if no key is pressed. */
static int check_keys_changed(void)
{
@@ -228,7 +229,7 @@ static int check_keys_changed(void)
for (c = 0; c < KB_COLS; c++) {
/* Select column, then wait a bit for it to settle */
select_column(c);
- usleep(20);
+ udelay(COLUMN_CHARGE_US);
/* Read the row state */
r = LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff);
/* Invert it so 0=not pressed, 1=pressed */
@@ -259,17 +260,8 @@ static int check_keys_changed(void)
}
select_column(COLUMN_TRI_STATE_ALL);
- if (change) {
- uart_puts("[Keyboard state:");
- for (c = 0; c < KB_COLS; c++) {
- if (raw_state[c]) {
- uart_printf(" %02x", raw_state[c]);
- } else {
- uart_puts(" --");
- }
- }
- uart_puts("]\n");
- }
+ if (change)
+ print_raw_state("KB raw state");
/* Count number of key pressed */
for (c = 0; c < KB_COLS; c++) {
@@ -280,11 +272,88 @@ static int check_keys_changed(void)
}
+/* Returns non-zero if the recovery key is pressed, and only other allowed keys
+ * are pressed. */
+static int check_recovery_key(void) {
+ int c;
+
+ for (c = 0; c < KB_COLS; c++) {
+ if ((raw_state[c] & recovery_key_mask[c])
+ != recovery_key_mask[c])
+ return 0; /* Missing required key */
+ if (raw_state[c] & ~recovery_allowed_mask[c])
+ return 0; /* Additional disallowed key pressed */
+ }
+ return 1;
+}
+
+
+int keyboard_scan_recovery_pressed(void)
+{
+ return recovery_key_pressed;
+}
+
+
+int keyboard_scan_init(void)
+{
+ volatile uint32_t scratch __attribute__((unused));
+
+ /* Enable GPIOs */
+#ifdef BOARD_link
+ /* Enable clock to GPIO modules N,P,Q */
+ LM4_SYSTEM_RCGCGPIO |= 0x7000;
+#else
+ /* Enable clock to GPIO modules C,H,K,N,Q */
+ LM4_SYSTEM_RCGCGPIO |= 0x5284;
+#endif
+ scratch = LM4_SYSTEM_RCGCGPIO;
+
+ /* Clear GPIOAFSEL and enable digital function for rows */
+#ifdef BOARD_link
+ LM4_GPIO_AFSEL(LM4_GPIO_P) = 0; /* KSO[7:0] */
+ LM4_GPIO_DEN(LM4_GPIO_P) = 0xff;
+ LM4_GPIO_AFSEL(LM4_GPIO_Q) &= ~0x1f; /* KSO[12:8] */
+ LM4_GPIO_DEN(LM4_GPIO_Q) |= 0x1f;
+#else
+ LM4_GPIO_AFSEL(LM4_GPIO_K) &= ~0x0f;
+ LM4_GPIO_DEN(LM4_GPIO_K) |= 0x0f;
+ LM4_GPIO_AFSEL(LM4_GPIO_N) &= ~0x04;
+ LM4_GPIO_DEN(LM4_GPIO_N) |= 0x04;
+ LM4_GPIO_AFSEL(LM4_GPIO_Q) = 0;
+ LM4_GPIO_DEN(LM4_GPIO_Q) = 0xff;
+#endif
+
+ /* Set row inputs with pull-up */
+ LM4_GPIO_AFSEL(KB_SCAN_ROW_GPIO) &= 0xff;
+ LM4_GPIO_DEN(KB_SCAN_ROW_GPIO) |= 0xff;
+ LM4_GPIO_DIR(KB_SCAN_ROW_GPIO) = 0;
+ LM4_GPIO_PUR(KB_SCAN_ROW_GPIO) = 0xff;
+
+ /* Tri-state the columns */
+ select_column(COLUMN_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 and check if the recovery key is pressed. */
+ update_key_state();
+ recovery_key_pressed = check_recovery_key();
+
+ /* Enable interrupts, now that we're set up */
+ task_enable_irq(KB_SCAN_ROW_IRQ);
+
+ return EC_SUCCESS;
+}
+
+
void keyboard_scan_task(void)
{
int key_press_timer = 0;
- keyboard_scan_init();
+ print_raw_state("KB init state");
+ if (recovery_key_pressed)
+ uart_puts("[KB recovery key pressed at init!]\n");
while (1) {
wait_for_interrupt();
diff --git a/common/main.c b/common/main.c
index 70b2178d74..36c913cabb 100644
--- a/common/main.c
+++ b/common/main.c
@@ -18,6 +18,7 @@
#include "i2c.h"
#include "jtag.h"
#include "keyboard.h"
+#include "keyboard_scan.h"
#include "lpc.h"
#include "memory_commands.h"
#include "peci.h"
@@ -63,6 +64,9 @@ int main(void)
timer_init();
uart_init();
system_init();
+#ifdef CONFIG_TASK_KEYSCAN
+ keyboard_scan_init();
+#endif
#ifdef CONFIG_FLASH
flash_init();
#endif
diff --git a/include/keyboard_scan.h b/include/keyboard_scan.h
index 8bc10c2c17..31341333c5 100644
--- a/include/keyboard_scan.h
+++ b/include/keyboard_scan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* Copyright (c) 2012 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.
*/
@@ -13,4 +13,7 @@
/* Initializes the module. */
int keyboard_scan_init(void);
+/* Returns non-zero if recovery key was pressed at boot. */
+int keyboard_scan_recovery_pressed(void);
+
#endif /* __CROS_KEYBOARD_SCAN_H */