diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-03-20 13:47:35 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-03-22 11:24:28 -0700 |
commit | 743c05f01f8f2b19dbf565bee645076fff75c42d (patch) | |
tree | cbad9ab036c32b3b4d47ad2ad4ded17f18fb02b6 /chip/stm32/keyboard_raw.c | |
parent | cdb08e12217367f0ac8c6ce0dc1df2e27f80563e (diff) | |
download | chrome-ec-743c05f01f8f2b19dbf565bee645076fff75c42d.tar.gz |
Add keyboard_raw interface
This is the low-level platform-dependent interface to drive keyboard
columns, read rows, and handle keyboard interrupts.
Both lm4 and stm32 had something like this before, but the interfaces
weren't fully explicit or compatible.
BUG=chrome-os-partner:18360
BRANCH=none
TEST=manual
- Build all platforms.
- Boot system and test typing on keyboard.
- Hold power+refresh+esc to test boot key detection; should go to recovery.
Change-Id: Ie3bcc1d066a4da5204f0e236daeb52c4064a6213
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/46156
Diffstat (limited to 'chip/stm32/keyboard_raw.c')
-rw-r--r-- | chip/stm32/keyboard_raw.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/chip/stm32/keyboard_raw.c b/chip/stm32/keyboard_raw.c new file mode 100644 index 0000000000..e6a3dc65eb --- /dev/null +++ b/chip/stm32/keyboard_raw.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. + * + * Raw keyboard I/O layer for STM32 + * + * To make this code portable, we rely heavily on looping over the keyboard + * input and output entries in the board's gpio_list[]. Each set of inputs or + * outputs must be listed in consecutive, increasing order so that scan loops + * can iterate beginning at KB_IN00 or KB_OUT00 for however many GPIOs are + * utilized (KB_INPUTS or KB_OUTPUTS). + */ + +#include "gpio.h" +#include "keyboard_raw.h" +#include "keyboard_scan.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +/* Mask of external interrupts on input lines */ +static unsigned int irq_mask; + +static const uint32_t kb_out_ports[] = { KB_OUT_PORT_LIST }; + +static void set_irq_mask(void) +{ + int i; + + for (i = GPIO_KB_IN00; i < GPIO_KB_IN00 + KB_INPUTS; i++) + irq_mask |= gpio_list[i].mask; +} + +void keyboard_raw_init(void) +{ + /* Determine EXTI_PR mask to use for the board */ + set_irq_mask(); + + /* Ensure interrupts are disabled in EXTI_PR */ + keyboard_raw_enable_interrupt(0); +} + +void keyboard_raw_task_start(void) +{ + /* Enable interrupts for keyboard matrix inputs */ + gpio_enable_interrupt(GPIO_KB_IN00); + gpio_enable_interrupt(GPIO_KB_IN01); + gpio_enable_interrupt(GPIO_KB_IN02); + gpio_enable_interrupt(GPIO_KB_IN03); + gpio_enable_interrupt(GPIO_KB_IN04); + gpio_enable_interrupt(GPIO_KB_IN05); + gpio_enable_interrupt(GPIO_KB_IN06); + gpio_enable_interrupt(GPIO_KB_IN07); +} + +void keyboard_raw_drive_column(int out) +{ + int i, done = 0; + + for (i = 0; i < ARRAY_SIZE(kb_out_ports); i++) { + uint32_t bsrr = 0; + int j; + + for (j = GPIO_KB_OUT00; j <= GPIO_KB_OUT12; j++) { + if (gpio_list[j].port != kb_out_ports[i]) + continue; + + if (out == KEYBOARD_COLUMN_ALL) { + /* drive low (clear bit) */ + bsrr |= gpio_list[j].mask << 16; + } else if (out == KEYBOARD_COLUMN_NONE) { + /* put output in hi-Z state (set bit) */ + bsrr |= gpio_list[j].mask; + } else if (j - GPIO_KB_OUT00 == out) { + /* + * Drive specified output low, others => hi-Z. + * + * To avoid conflict, tri-state all outputs + * first, then assert specified output. + */ + keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); + bsrr |= gpio_list[j].mask << 16; + done = 1; + break; + } + } + + if (bsrr) + STM32_GPIO_BSRR_OFF(kb_out_ports[i]) = bsrr; + + if (done) + break; + } +} + +int keyboard_raw_read_rows(void) +{ + int i; + unsigned int port, prev_port = 0; + int state = 0; + uint16_t port_val = 0; + + for (i = 0; i < KB_INPUTS; i++) { + port = gpio_list[GPIO_KB_IN00 + i].port; + if (port != prev_port) { + port_val = STM32_GPIO_IDR_OFF(port); + prev_port = port; + } + + if (port_val & gpio_list[GPIO_KB_IN00 + i].mask) + state |= 1 << i; + } + + /* Invert it so 0=not pressed, 1=pressed */ + return state ^ 0xff; +} + +void keyboard_raw_enable_interrupt(int enable) +{ + if (enable) { + /* + * Assert all outputs would trigger un-wanted interrupts. + * Clear them before enable interrupt. + */ + STM32_EXTI_PR |= irq_mask; + STM32_EXTI_IMR |= irq_mask; /* 1: unmask interrupt */ + } else { + STM32_EXTI_IMR &= ~irq_mask; /* 0: mask interrupts */ + } +} + +void keyboard_raw_gpio_interrupt(enum gpio_signal signal) +{ + task_wake(TASK_ID_KEYSCAN); +} |