diff options
author | Myles Watson <mylesgw@chromium.org> | 2014-12-04 17:08:25 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2014-12-31 00:01:36 +0000 |
commit | ce9a8a2dad8945ce225ab1387bec0fdb261be482 (patch) | |
tree | 3fbaecb09fdbd076db916dcf209278da49814f99 /chip/nrf51/keyboard_raw.c | |
parent | 215399af25bfd489997ed86e7d17e8253cbfe517 (diff) | |
download | chrome-ec-ce9a8a2dad8945ce225ab1387bec0fdb261be482.tar.gz |
nrf51: Copy the keyboard_raw.c implementation from stm32.
BUG=chrome-os-partner:34477
BRANCH=none
TEST=make buildall -j
Signed-off-by: Myles Watson <mylesgw@chromium.org>
Change-Id: I2ad095a499e960e4b2929792708a563e5b1e1922
Reviewed-on: https://chromium-review.googlesource.com/234393
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Tested-by: Myles Watson <mylesgw@chromium.org>
Commit-Queue: Myles Watson <mylesgw@chromium.org>
Diffstat (limited to 'chip/nrf51/keyboard_raw.c')
-rw-r--r-- | chip/nrf51/keyboard_raw.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/chip/nrf51/keyboard_raw.c b/chip/nrf51/keyboard_raw.c new file mode 100644 index 0000000000..4ac7f2dcb2 --- /dev/null +++ b/chip/nrf51/keyboard_raw.c @@ -0,0 +1,143 @@ +/* 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 (KEYBOARD_ROWS or KEYBOARD_COLS). + */ + +#include "gpio.h" +#include "keyboard_config.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 + KEYBOARD_ROWS; 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); +} + +test_mockable 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; + } + } + + #ifdef CONFIG_KEYBOARD_COL2_INVERTED + if (bsrr & (gpio_list[GPIO_KB_OUT02].mask << 16 | + gpio_list[GPIO_KB_OUT02].mask)) + bsrr ^= (gpio_list[GPIO_KB_OUT02].mask << 16 | + gpio_list[GPIO_KB_OUT02].mask); + #endif + + if (bsrr) + STM32_GPIO_BSRR(kb_out_ports[i]) = bsrr; + + if (done) + break; + } +} + +test_mockable 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 < KEYBOARD_ROWS; i++) { + port = gpio_list[GPIO_KB_IN00 + i].port; + if (port != prev_port) { + port_val = STM32_GPIO_IDR(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); +} |