diff options
-rw-r--r-- | chip/lm4/keyboard_scan.c | 205 | ||||
-rw-r--r-- | common/main.c | 4 | ||||
-rw-r--r-- | include/keyboard_scan.h | 5 |
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 */ |