mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
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
This commit is contained in:
committed by
ChromeBot
parent
cdb08e1221
commit
743c05f01f
@@ -10,7 +10,7 @@
|
||||
#include "gaia_power.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "pmu_tpschrome.h"
|
||||
#include "registers.h"
|
||||
#include "spi.h"
|
||||
@@ -44,21 +44,21 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"LID_OPEN", GPIO_C, (1<<13), GPIO_INT_RISING, gaia_lid_event},
|
||||
{"SUSPEND_L", GPIO_A, (1<<7), GPIO_INT_BOTH, gaia_suspend_event},
|
||||
{"KB_IN00", GPIO_C, (1<<8), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN01", GPIO_C, (1<<9), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN02", GPIO_C, (1<<10), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN03", GPIO_C, (1<<11), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN04", GPIO_C, (1<<12), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN05", GPIO_C, (1<<14), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN06", GPIO_C, (1<<15), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN07", GPIO_D, (1<<2), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
/* Other inputs */
|
||||
{"AC_PWRBTN_L", GPIO_A, (1<<0), GPIO_INT_BOTH, NULL},
|
||||
{"SPI1_NSS", GPIO_A, (1<<4), GPIO_PULL_UP, NULL},
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "i2c.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "registers.h"
|
||||
#include "spi.h"
|
||||
#include "task.h"
|
||||
@@ -30,21 +30,21 @@ static void kbd_power_on(enum gpio_signal signal);
|
||||
const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
/* Inputs with interrupt handlers are first for efficiency */
|
||||
{"KB_IN00", GPIO_B, (1<<8), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN01", GPIO_B, (1<<9), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN02", GPIO_B, (1<<10), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN03", GPIO_B, (1<<11), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN04", GPIO_B, (1<<12), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN05", GPIO_B, (1<<13), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN06", GPIO_B, (1<<14), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN07", GPIO_B, (1<<15), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KBD_PWR_BUTTON", GPIO_B, (1<<2), GPIO_INPUT, kbd_power_on},
|
||||
|
||||
{"OMZO_RDY_L", GPIO_A, (1<<0), GPIO_INPUT, NULL}, /* PA0_WKUP */
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "i2c.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "pmu_tpschrome.h"
|
||||
#include "power_led.h"
|
||||
#include "registers.h"
|
||||
@@ -41,21 +41,21 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"SUSPEND_L", GPIO_A, (1<<7), INT_BOTH_FLOATING, gaia_suspend_event},
|
||||
{"WP_L", GPIO_B, (1<<4), GPIO_INPUT, NULL},
|
||||
{"KB_IN00", GPIO_C, (1<<8), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN01", GPIO_C, (1<<9), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN02", GPIO_C, (1<<10), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN03", GPIO_C, (1<<11), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN04", GPIO_C, (1<<12), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN05", GPIO_C, (1<<14), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN06", GPIO_C, (1<<15), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN07", GPIO_D, (1<<2), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
/* Other inputs */
|
||||
{"AC_PWRBTN_L", GPIO_A, (1<<0), GPIO_INT_BOTH, NULL},
|
||||
{"SPI1_NSS", GPIO_A, (1<<4), GPIO_DEFAULT, spi_event},
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "i2c.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "pmu_tpschrome.h"
|
||||
#include "registers.h"
|
||||
#include "stm32_adc.h"
|
||||
@@ -43,21 +43,21 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"SUSPEND_L", GPIO_A, (1<<7), INT_BOTH_FLOATING, gaia_suspend_event},
|
||||
{"WP_L", GPIO_A, (1<<13), GPIO_INPUT, NULL},
|
||||
{"KB_IN00", GPIO_C, (1<<8), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN01", GPIO_C, (1<<9), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN02", GPIO_C, (1<<10), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN03", GPIO_C, (1<<11), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN04", GPIO_C, (1<<12), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN05", GPIO_C, (1<<14), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN06", GPIO_C, (1<<15), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"KB_IN07", GPIO_D, (1<<2), GPIO_KB_INPUT,
|
||||
keyboard_scan_interrupt},
|
||||
keyboard_raw_gpio_interrupt},
|
||||
{"USB_CHG_INT", GPIO_A, (1<<6), GPIO_INT_FALLING,
|
||||
usb_charge_interrupt},
|
||||
/* Other inputs */
|
||||
|
||||
@@ -22,6 +22,6 @@ chip-$(CONFIG_ONEWIRE)+=onewire.o
|
||||
chip-$(CONFIG_PECI)+=peci.o
|
||||
chip-$(CONFIG_PWM)+=pwm.o
|
||||
chip-$(CONFIG_SPI)+=spi.o
|
||||
chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o keyboard_scan_stub.o
|
||||
chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o keyboard_raw.o
|
||||
chip-$(CONFIG_TASK_SWITCH)+=switch.o
|
||||
chip-$(CONFIG_WATCHDOG)+=watchdog.o
|
||||
|
||||
112
chip/lm4/keyboard_raw.c
Normal file
112
chip/lm4/keyboard_raw.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Functions needed by keyboard scanner module for Chrome EC */
|
||||
|
||||
#include "common.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
|
||||
void keyboard_raw_init(void)
|
||||
{
|
||||
/* Ensure top-level interrupt is disabled */
|
||||
keyboard_raw_enable_interrupt(0);
|
||||
|
||||
/*
|
||||
* Set column outputs as open-drain; we either pull them low or let
|
||||
* them float high.
|
||||
*/
|
||||
LM4_GPIO_AFSEL(LM4_GPIO_P) = 0; /* KSO[7:0] */
|
||||
LM4_GPIO_AFSEL(LM4_GPIO_Q) &= ~0x1f; /* KSO[12:8] */
|
||||
LM4_GPIO_DEN(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_DEN(LM4_GPIO_Q) |= 0x1f;
|
||||
LM4_GPIO_DIR(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_DIR(LM4_GPIO_Q) |= 0x1f;
|
||||
LM4_GPIO_ODR(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_ODR(LM4_GPIO_Q) |= 0x1f;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Edge-sensitive on both edges. */
|
||||
LM4_GPIO_IS(KB_SCAN_ROW_GPIO) = 0;
|
||||
LM4_GPIO_IBE(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
|
||||
/*
|
||||
* Enable interrupts for the inputs. The top-level interrupt is still
|
||||
* masked off, so this won't trigger interrupts yet.
|
||||
*/
|
||||
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
}
|
||||
|
||||
void keyboard_raw_task_start(void)
|
||||
{
|
||||
task_enable_irq(KB_SCAN_ROW_IRQ);
|
||||
}
|
||||
|
||||
void keyboard_raw_drive_column(int col)
|
||||
{
|
||||
if (col == KEYBOARD_COLUMN_NONE) {
|
||||
/* Tri-state all outputs */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0xff;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0x1f;
|
||||
} else if (col == KEYBOARD_COLUMN_ALL) {
|
||||
/* Assert all outputs */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0;
|
||||
} else {
|
||||
/* Assert a single output */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0xff;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0x1f;
|
||||
if (col < 8)
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 1 << col) = 0;
|
||||
else
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 1 << (col - 8)) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int keyboard_raw_read_rows(void)
|
||||
{
|
||||
/* Bits are active-low, so invert returned levels */
|
||||
return LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff) ^ 0xff;
|
||||
}
|
||||
|
||||
void keyboard_raw_enable_interrupt(int enable)
|
||||
{
|
||||
if (enable) {
|
||||
/*
|
||||
* Clear pending interrupts before enabling them, because the
|
||||
* raw interrupt status may have been tripped by keyboard
|
||||
* scanning or, if a key is already pressed, by driving all the
|
||||
* outputs.
|
||||
*
|
||||
* We won't lose keyboard events because the scanning task will
|
||||
* explicitly check the raw row state before waiting for an
|
||||
* interrupt. If a key is pressed, the task won't wait.
|
||||
*/
|
||||
LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
} else {
|
||||
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt handler for the entire GPIO bank of keyboard rows.
|
||||
*/
|
||||
static void keyboard_raw_interrupt(void)
|
||||
{
|
||||
/* Clear all pending keyboard interrupts */
|
||||
LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
|
||||
/* Wake the scan task */
|
||||
task_wake(TASK_ID_KEYSCAN);
|
||||
}
|
||||
DECLARE_IRQ(KB_SCAN_ROW_IRQ, keyboard_raw_interrupt, 3);
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
/* 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.
|
||||
*/
|
||||
@@ -10,9 +10,8 @@
|
||||
#include "console.h"
|
||||
#include "host_command.h"
|
||||
#include "keyboard.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_scan_stub.h"
|
||||
#include "registers.h"
|
||||
#include "switch.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
@@ -83,29 +82,29 @@ static int print_state_changes;
|
||||
#define MASK_INDEX_KEY_H 6
|
||||
#define MASK_VALUE_KEY_H 0x02
|
||||
|
||||
static int enable_scanning = 1; /* Must init to 1 for scanning at boot */
|
||||
|
||||
static void enable_interrupt(void)
|
||||
{
|
||||
CPRINTF("[%T KB wait]\n");
|
||||
|
||||
/* Assert all outputs would trigger un-wanted interrupts.
|
||||
* Clear them before enable interrupt. */
|
||||
lm4_select_column(COLUMN_ASSERT_ALL);
|
||||
lm4_clear_matrix_interrupt_status();
|
||||
if (enable_scanning)
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_ALL);
|
||||
|
||||
lm4_enable_matrix_interrupt();
|
||||
keyboard_raw_enable_interrupt(1);
|
||||
}
|
||||
|
||||
static void enter_polling_mode(void)
|
||||
{
|
||||
CPRINTF("[%T KB poll]\n");
|
||||
lm4_disable_matrix_interrupt();
|
||||
lm4_select_column(COLUMN_TRI_STATE_ALL);
|
||||
keyboard_raw_enable_interrupt(0);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
}
|
||||
|
||||
static int is_scanning_enabled(void)
|
||||
{
|
||||
/* Scan only if enabled AND lid is open. */
|
||||
return lm4_get_scanning_enabled() && switch_get_lid_open();
|
||||
return enable_scanning && switch_get_lid_open();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,14 +124,16 @@ static int read_matrix(uint8_t *state)
|
||||
int pressed = 0;
|
||||
|
||||
for (c = 0; c < KB_COLS; c++) {
|
||||
/* Stop if scanning becomes disabled */
|
||||
if (!enable_scanning)
|
||||
break;
|
||||
|
||||
/* Select column, then wait a bit for it to settle */
|
||||
lm4_select_column(c);
|
||||
keyboard_raw_drive_column(c);
|
||||
udelay(COLUMN_CHARGE_US);
|
||||
|
||||
/* Read the row state */
|
||||
r = lm4_read_raw_row_state();
|
||||
/* Invert it so 0=not pressed, 1=pressed */
|
||||
r ^= 0xff;
|
||||
r = keyboard_raw_read_rows();
|
||||
/* Mask off keys that don't exist so they never show
|
||||
* as pressed */
|
||||
r &= actual_key_mask[c];
|
||||
@@ -141,7 +142,7 @@ static int read_matrix(uint8_t *state)
|
||||
pressed |= r;
|
||||
}
|
||||
|
||||
lm4_select_column(COLUMN_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
|
||||
return pressed ? 1 : 0;
|
||||
}
|
||||
@@ -413,10 +414,10 @@ enum boot_key keyboard_scan_get_boot_key(void)
|
||||
void keyboard_scan_init(void)
|
||||
{
|
||||
/* Configure GPIO */
|
||||
lm4_configure_keyboard_gpio();
|
||||
keyboard_raw_init();
|
||||
|
||||
/* Tri-state the columns */
|
||||
lm4_select_column(COLUMN_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
|
||||
/* Initialize raw state */
|
||||
read_matrix(debounced_state);
|
||||
@@ -436,8 +437,7 @@ void keyboard_scan_task(void)
|
||||
|
||||
print_state(debounced_state, "init state");
|
||||
|
||||
/* Enable interrupts */
|
||||
task_enable_irq(KB_SCAN_ROW_IRQ);
|
||||
keyboard_raw_task_start();
|
||||
|
||||
while (1) {
|
||||
/* Enable all outputs */
|
||||
@@ -451,8 +451,7 @@ void keyboard_scan_task(void)
|
||||
* user pressing a key and enable_interrupt()
|
||||
* starting to pay attention to edges.
|
||||
*/
|
||||
if ((lm4_read_raw_row_state() == 0xff) ||
|
||||
!is_scanning_enabled())
|
||||
if (!keyboard_raw_read_rows() || !is_scanning_enabled())
|
||||
task_wait_event(-1);
|
||||
} while (!is_scanning_enabled());
|
||||
|
||||
@@ -475,22 +474,10 @@ void keyboard_scan_task(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void matrix_interrupt(void)
|
||||
{
|
||||
uint32_t ris = lm4_clear_matrix_interrupt_status();
|
||||
|
||||
if (ris)
|
||||
task_wake(TASK_ID_KEYSCAN);
|
||||
}
|
||||
DECLARE_IRQ(KB_SCAN_ROW_IRQ, matrix_interrupt, 3);
|
||||
|
||||
/*
|
||||
* The actual implementation is controlling the enable_scanning variable, then
|
||||
* that controls whether lm4_select_column() can pull-down columns or not.
|
||||
*/
|
||||
void keyboard_enable_scanning(int enable)
|
||||
{
|
||||
lm4_set_scanning_enabled(enable);
|
||||
enable_scanning = enable;
|
||||
|
||||
if (enable) {
|
||||
/*
|
||||
* A power button press had tri-stated all columns (see the
|
||||
@@ -499,13 +486,13 @@ void keyboard_enable_scanning(int enable)
|
||||
*/
|
||||
task_wake(TASK_ID_KEYSCAN);
|
||||
} else {
|
||||
lm4_select_column(COLUMN_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
keyboard_clear_underlying_buffer();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console commands*/
|
||||
/* Console commands */
|
||||
|
||||
static int command_ksstate(int argc, char **argv)
|
||||
{
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Functions needed by keyboard scanner module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_scan_stub.h"
|
||||
#include "registers.h"
|
||||
|
||||
|
||||
/* Notes:
|
||||
*
|
||||
* Link proto0 board:
|
||||
*
|
||||
* Columns (outputs):
|
||||
* KSO0 - KSO7 = PP0:7
|
||||
* KSO8 - KSO12 = PQ0:4
|
||||
*
|
||||
* Rows (inputs):
|
||||
* KSI0 - KSI7 = PN0:7
|
||||
*
|
||||
* Other:
|
||||
* PWR_BTN# = PK7 (handled by gpio module)
|
||||
*/
|
||||
|
||||
|
||||
static int enable_scanning = 1; /* Must init to 1 for scanning at boot */
|
||||
|
||||
|
||||
void lm4_set_scanning_enabled(int enabled)
|
||||
{
|
||||
enable_scanning = enabled;
|
||||
}
|
||||
|
||||
|
||||
int lm4_get_scanning_enabled(void)
|
||||
{
|
||||
return enable_scanning;
|
||||
}
|
||||
|
||||
|
||||
void lm4_select_column(int col)
|
||||
{
|
||||
if (col == COLUMN_TRI_STATE_ALL || !enable_scanning) {
|
||||
/* Tri-state all outputs */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0xff;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0x1f;
|
||||
} else if (col == COLUMN_ASSERT_ALL) {
|
||||
/* Assert all outputs */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0;
|
||||
} else {
|
||||
/* Assert a single output */
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0xff;
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 0x1f) = 0x1f;
|
||||
if (col < 8)
|
||||
LM4_GPIO_DATA(LM4_GPIO_P, 1 << col) = 0;
|
||||
else
|
||||
LM4_GPIO_DATA(LM4_GPIO_Q, 1 << (col - 8)) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t lm4_clear_matrix_interrupt_status(void)
|
||||
{
|
||||
uint32_t ris = LM4_GPIO_RIS(KB_SCAN_ROW_GPIO);
|
||||
LM4_GPIO_ICR(KB_SCAN_ROW_GPIO) = ris;
|
||||
|
||||
return ris;
|
||||
}
|
||||
|
||||
|
||||
void lm4_enable_matrix_interrupt(void)
|
||||
{
|
||||
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0xff; /* 1: enable interrupt */
|
||||
}
|
||||
|
||||
|
||||
void lm4_disable_matrix_interrupt(void)
|
||||
{
|
||||
LM4_GPIO_IM(KB_SCAN_ROW_GPIO) = 0; /* 0: disable interrupt */
|
||||
}
|
||||
|
||||
|
||||
int lm4_read_raw_row_state(void)
|
||||
{
|
||||
return LM4_GPIO_DATA(KB_SCAN_ROW_GPIO, 0xff);
|
||||
}
|
||||
|
||||
|
||||
void lm4_configure_keyboard_gpio(void)
|
||||
{
|
||||
/* Set column outputs as open-drain; we either pull them low or let
|
||||
* them float high. */
|
||||
LM4_GPIO_AFSEL(LM4_GPIO_P) = 0; /* KSO[7:0] */
|
||||
LM4_GPIO_AFSEL(LM4_GPIO_Q) &= ~0x1f; /* KSO[12:8] */
|
||||
LM4_GPIO_DEN(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_DEN(LM4_GPIO_Q) |= 0x1f;
|
||||
LM4_GPIO_DIR(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_DIR(LM4_GPIO_Q) |= 0x1f;
|
||||
LM4_GPIO_ODR(LM4_GPIO_P) = 0xff;
|
||||
LM4_GPIO_ODR(LM4_GPIO_Q) |= 0x1f;
|
||||
|
||||
/* 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;
|
||||
/* Edge-sensitive on both edges. Don't enable interrupts yet. */
|
||||
LM4_GPIO_IS(KB_SCAN_ROW_GPIO) = 0;
|
||||
LM4_GPIO_IBE(KB_SCAN_ROW_GPIO) = 0xff;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/* 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.
|
||||
*
|
||||
* Funcitons needed by keyboard scanner module.
|
||||
* Abstracted from keyboard_scan.c for stub.
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_KEYBOARD_SCAN_STUB_H
|
||||
#define __CROS_EC_KEYBOARD_SCAN_STUB_H
|
||||
|
||||
/* used for select_column() */
|
||||
enum COLUMN_INDEX {
|
||||
COLUMN_ASSERT_ALL = -2,
|
||||
COLUMN_TRI_STATE_ALL = -1,
|
||||
/* 0 ~ 12 for the corresponding column */
|
||||
};
|
||||
|
||||
/* Set keyboard scanning to enabled/disabled */
|
||||
void lm4_set_scanning_enabled(int enabled);
|
||||
|
||||
/* Get keyboard scanning enabled/disabled */
|
||||
int lm4_get_scanning_enabled(void);
|
||||
|
||||
/* Drive the specified column low; other columns are tristated */
|
||||
void lm4_select_column(int col);
|
||||
|
||||
/* Clear current interrupt status */
|
||||
uint32_t lm4_clear_matrix_interrupt_status(void);
|
||||
|
||||
/* Enable interrupt from keyboard matrix */
|
||||
void lm4_enable_matrix_interrupt(void);
|
||||
|
||||
/* Disable interrupt from keyboard matrix */
|
||||
void lm4_disable_matrix_interrupt(void);
|
||||
|
||||
/* Read raw row state */
|
||||
int lm4_read_raw_row_state(void);
|
||||
|
||||
/* Configure keyboard matrix GPIO */
|
||||
void lm4_configure_keyboard_gpio(void);
|
||||
|
||||
#endif /* __CROS_EC_KEYBOARD_SCAN_STUB_H */
|
||||
@@ -1,14 +1,14 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Mock functions for keyboard scanner module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_scan_stub.h"
|
||||
#include "task.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
@@ -20,55 +20,7 @@ static int selected_column = -1;
|
||||
static int interrupt_enabled = 0;
|
||||
static uint8_t matrix_status[MOCK_COLUMN_COUNT];
|
||||
|
||||
|
||||
void lm4_set_scanning_enabled(int enabled)
|
||||
{
|
||||
enable_scanning = enabled;
|
||||
uart_printf("%s keyboard scanning\n", enabled ? "Enable" : "Disable");
|
||||
}
|
||||
|
||||
|
||||
int lm4_get_scanning_enabled(void)
|
||||
{
|
||||
return enable_scanning;
|
||||
}
|
||||
|
||||
|
||||
void lm4_select_column(int col)
|
||||
{
|
||||
selected_column = col;
|
||||
}
|
||||
|
||||
|
||||
uint32_t lm4_clear_matrix_interrupt_status(void)
|
||||
{
|
||||
/* Not implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void lm4_enable_matrix_interrupt(void)
|
||||
{
|
||||
interrupt_enabled = 1;
|
||||
}
|
||||
|
||||
|
||||
void lm4_disable_matrix_interrupt(void)
|
||||
{
|
||||
interrupt_enabled = 0;
|
||||
}
|
||||
|
||||
|
||||
int lm4_read_raw_row_state(void)
|
||||
{
|
||||
if (selected_column >= 0)
|
||||
return matrix_status[selected_column];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void lm4_configure_keyboard_gpio(void)
|
||||
void keyboard_raw_init(void)
|
||||
{
|
||||
/* Init matrix status to release all */
|
||||
int i;
|
||||
@@ -76,6 +28,27 @@ void lm4_configure_keyboard_gpio(void)
|
||||
matrix_status[i] = 0xff;
|
||||
}
|
||||
|
||||
void keyboard_raw_task_start(void)
|
||||
{
|
||||
}
|
||||
|
||||
void keyboard_raw_drive_column(int col)
|
||||
{
|
||||
selected_column = col;
|
||||
}
|
||||
|
||||
int keyboard_raw_read_rows(void)
|
||||
{
|
||||
if (selected_column >= 0)
|
||||
return matrix_status[selected_column] ^ 0xff;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void keyboard_raw_enable_interrupt(int enable)
|
||||
{
|
||||
interrupt_enabled = enable;
|
||||
}
|
||||
|
||||
static int command_mock_matrix(int argc, char **argv)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ chip-y+=jtag-$(CHIP_VARIANT).o clock-$(CHIP_VARIANT).o gpio-$(CHIP_VARIANT).o
|
||||
chip-$(CONFIG_SPI)+=spi.o
|
||||
chip-$(CONFIG_I2C)+=i2c.o
|
||||
chip-$(CONFIG_WATCHDOG)+=watchdog.o
|
||||
chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o
|
||||
chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o keyboard_raw.o
|
||||
chip-$(CONFIG_TASK_POWERLED)+=power_led.o
|
||||
chip-$(CONFIG_FLASH)+=flash-$(CHIP_VARIANT).o
|
||||
chip-$(CONFIG_ADC)+=adc.o
|
||||
|
||||
135
chip/stm32/keyboard_raw.c
Normal file
135
chip/stm32/keyboard_raw.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -1,16 +1,8 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Keyboard scanner module for Chrome EC
|
||||
*
|
||||
* 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).
|
||||
* Keyboard scanner module for Chrome EC STM32
|
||||
*/
|
||||
|
||||
#include "atomic.h"
|
||||
@@ -19,9 +11,9 @@
|
||||
#include "gpio.h"
|
||||
#include "host_command.h"
|
||||
#include "keyboard.h"
|
||||
#include "keyboard_raw.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "keyboard_test.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
@@ -31,16 +23,6 @@
|
||||
#define CPUTS(outstr) cputs(CC_KEYSCAN, outstr)
|
||||
#define CPRINTF(format, args...) cprintf(CC_KEYSCAN, format, ## args)
|
||||
|
||||
/* used for assert_output() */
|
||||
enum {
|
||||
OUTPUT_ASSERT_ALL = -2,
|
||||
OUTPUT_TRI_STATE_ALL = -1,
|
||||
/* 0 ~ 12 for the corresponding output */
|
||||
};
|
||||
|
||||
/* Mask of external interrupts on input lines */
|
||||
static unsigned int irq_mask;
|
||||
|
||||
#define SCAN_TIME_COUNT 32
|
||||
|
||||
static struct mutex scanning_enabled;
|
||||
@@ -69,7 +51,7 @@ static uint8_t scan_edge_index[KB_OUTPUTS][KB_INPUTS];
|
||||
#define MASK_INDEX_LEFT_ALT 10
|
||||
#define MASK_VALUE_LEFT_ALT 0x40
|
||||
|
||||
static const uint32_t kb_out_ports[] = { KB_OUT_PORT_LIST };
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Provide a default function in case the board doesn't have one */
|
||||
void __board_keyboard_suppress_noise(void)
|
||||
@@ -171,45 +153,6 @@ static int kb_fifo_remove(uint8_t *buffp)
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static void assert_output(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 == OUTPUT_ASSERT_ALL) {
|
||||
/* drive low (clear bit) */
|
||||
bsrr |= gpio_list[j].mask << 16;
|
||||
} else if (out == OUTPUT_TRI_STATE_ALL) {
|
||||
/* put output in hi-Z state (set bit) */
|
||||
bsrr |= gpio_list[j].mask;
|
||||
} else {
|
||||
/* drive specified output low, others => hi-Z */
|
||||
if (j - GPIO_KB_OUT00 == out) {
|
||||
/* to avoid conflict, tri-state all
|
||||
* outputs first, then assert output */
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
bsrr |= gpio_list[j].mask << 16;
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bsrr)
|
||||
STM32_GPIO_BSRR_OFF(kb_out_ports[i]) = bsrr;
|
||||
|
||||
if (done)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert host keyboard interrupt line.
|
||||
*/
|
||||
@@ -219,28 +162,6 @@ static void set_host_interrupt(int active)
|
||||
gpio_set_level(GPIO_EC_INT, !active);
|
||||
}
|
||||
|
||||
/* Set up outputs so that we will get an interrupt when any key changed */
|
||||
void setup_interrupts(void)
|
||||
{
|
||||
uint32_t pr_before, pr_after;
|
||||
|
||||
/* Assert all outputs would trigger un-wanted interrupts.
|
||||
* Clear them before enable interrupt. */
|
||||
pr_before = STM32_EXTI_PR;
|
||||
assert_output(OUTPUT_ASSERT_ALL);
|
||||
pr_after = STM32_EXTI_PR;
|
||||
STM32_EXTI_PR |= ((pr_after & ~pr_before) & irq_mask);
|
||||
|
||||
STM32_EXTI_IMR |= irq_mask; /* 1: unmask interrupt */
|
||||
}
|
||||
|
||||
|
||||
void enter_polling_mode(void)
|
||||
{
|
||||
STM32_EXTI_IMR &= ~irq_mask; /* 0: mask interrupts */
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check special runtime key combinations.
|
||||
*
|
||||
@@ -288,38 +209,6 @@ static void print_state(const uint8_t *state, const char *msg)
|
||||
CPUTS("]\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the raw input state for the currently selected output
|
||||
*
|
||||
* It is assumed that the output is already selected by the scanning
|
||||
* hardware. The output number is only used by test code.
|
||||
*
|
||||
* @return input state, one bit for each input
|
||||
*/
|
||||
static uint8_t read_raw_input_state(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int port, prev_port = 0;
|
||||
uint8_t 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 */
|
||||
state ^= 0xff;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the raw keyboard matrix state.
|
||||
*
|
||||
@@ -338,10 +227,10 @@ static int read_matrix(uint8_t *state)
|
||||
|
||||
for (c = 0; c < KB_OUTPUTS; c++) {
|
||||
/* Assert output, then wait a bit for it to settle */
|
||||
assert_output(c);
|
||||
keyboard_raw_drive_column(c);
|
||||
udelay(config.output_settle_us);
|
||||
|
||||
r = read_raw_input_state();
|
||||
r = keyboard_raw_read_rows();
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_TEST
|
||||
/* Use simulated keyscan sequence instead if testing active */
|
||||
@@ -357,7 +246,7 @@ static int read_matrix(uint8_t *state)
|
||||
state[c] = r;
|
||||
pressed |= r;
|
||||
}
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
|
||||
return pressed ? 1 : 0;
|
||||
}
|
||||
@@ -499,11 +388,12 @@ static int check_recovery_key(const uint8_t *state)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void keyboard_scan_init(void)
|
||||
{
|
||||
keyboard_raw_init();
|
||||
|
||||
/* Tri-state (put into Hi-Z) the outputs */
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
|
||||
/* Initialize raw state */
|
||||
read_matrix(debounced_state);
|
||||
@@ -520,7 +410,8 @@ static void scan_keyboard(void)
|
||||
int keys_changed = 1;
|
||||
|
||||
mutex_lock(&scanning_enabled);
|
||||
setup_interrupts();
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_ALL);
|
||||
keyboard_raw_enable_interrupt(1);
|
||||
mutex_unlock(&scanning_enabled);
|
||||
|
||||
/*
|
||||
@@ -528,7 +419,7 @@ static void scan_keyboard(void)
|
||||
* re-start immediatly polling instead of waiting
|
||||
* for the next interrupt.
|
||||
*/
|
||||
if (!read_raw_input_state()) {
|
||||
if (!keyboard_raw_read_rows()) {
|
||||
#ifdef CONFIG_KEYBOARD_TEST
|
||||
task_wait_event(keyscan_seq_next_event_delay());
|
||||
#else
|
||||
@@ -536,7 +427,8 @@ static void scan_keyboard(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
enter_polling_mode();
|
||||
keyboard_raw_enable_interrupt(0);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
|
||||
/* Busy polling keyboard state. */
|
||||
while (1) {
|
||||
@@ -566,47 +458,22 @@ static void scan_keyboard(void)
|
||||
}
|
||||
}
|
||||
|
||||
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_scan_task(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);
|
||||
|
||||
/* Determine EXTI_PR mask to use for the board */
|
||||
set_irq_mask();
|
||||
|
||||
print_state(debounced_state, "init state");
|
||||
|
||||
keyboard_raw_task_start();
|
||||
|
||||
while (1) {
|
||||
if (config.flags & EC_MKBP_FLAGS_ENABLE) {
|
||||
scan_keyboard();
|
||||
} else {
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
task_wait_event(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void keyboard_scan_interrupt(enum gpio_signal signal)
|
||||
{
|
||||
task_wake(TASK_ID_KEYSCAN);
|
||||
}
|
||||
|
||||
int keyboard_has_char(void)
|
||||
{
|
||||
/* TODO: needs to be implemented */
|
||||
@@ -660,8 +527,16 @@ void keyboard_enable_scanning(int enable)
|
||||
mutex_unlock(&scanning_enabled);
|
||||
task_wake(TASK_ID_KEYSCAN);
|
||||
} else {
|
||||
/*
|
||||
* TODO: using a mutex to control scanning isn't very
|
||||
* responsive. If we just started scanning the matrix, the
|
||||
* mutex will already be locked, and we'll finish the entire
|
||||
* matrix scan before we stop driving columns. We should
|
||||
* instead do something like link, where disabling scanning
|
||||
* immediately stops driving the columns.
|
||||
*/
|
||||
mutex_lock(&scanning_enabled);
|
||||
assert_output(OUTPUT_TRI_STATE_ALL);
|
||||
keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
74
include/keyboard_raw.h
Normal file
74
include/keyboard_raw.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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 access to keyboard GPIOs.
|
||||
*
|
||||
* The keyboard matrix is read by driving output signals on the column lines
|
||||
* and reading the row lines.
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_KEYBOARD_RAW_H
|
||||
#define __CROS_EC_KEYBOARD_RAW_H
|
||||
|
||||
#include "common.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/* used for select_column() */
|
||||
enum keyboard_column_index {
|
||||
KEYBOARD_COLUMN_ALL = -2, /* Drive all columns */
|
||||
KEYBOARD_COLUMN_NONE = -1, /* Drive no columns (tri-state all) */
|
||||
/* 0 ~ 12 for the corresponding column */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the raw keyboard interface.
|
||||
*
|
||||
* Must be called before any other functions in this interface.
|
||||
*/
|
||||
void keyboard_raw_init(void);
|
||||
|
||||
/**
|
||||
* Finish intitialization after task scheduling has started.
|
||||
*
|
||||
* Call from the keyboard scan task.
|
||||
*/
|
||||
void keyboard_raw_task_start(void);
|
||||
|
||||
/**
|
||||
* Drive the specified column low.
|
||||
*
|
||||
* Other columns are tristated. See enum keyboard_column_index for special
|
||||
* values for <col>.
|
||||
*/
|
||||
void keyboard_raw_drive_column(int col);
|
||||
|
||||
/**
|
||||
* Read raw row state.
|
||||
*
|
||||
* Bits are 1 if signal is present, 0 if not present.
|
||||
*/
|
||||
int keyboard_raw_read_rows(void);
|
||||
|
||||
/**
|
||||
* Enable or disable keyboard interrupts.
|
||||
*
|
||||
* Enabling interrupts will clear any pending interrupt bits. To avoid missing
|
||||
* any interrupts that occur between the end of scanning and then, you should
|
||||
* call keyboard_raw_read_rows() after this. If it returns non-zero, disable
|
||||
* interrupts and go back to polling mode instead of waiting for an interrupt.
|
||||
*/
|
||||
void keyboard_raw_enable_interrupt(int enable);
|
||||
|
||||
#ifdef CONFIG_TASK_KEYSCAN
|
||||
|
||||
/**
|
||||
* GPIO interrupt for raw keyboard input
|
||||
*/
|
||||
void keyboard_raw_gpio_interrupt(enum gpio_signal signal);
|
||||
|
||||
#else
|
||||
#define keyboard_raw_gpio_interrupt NULL
|
||||
#endif
|
||||
|
||||
#endif /* __CROS_EC_KEYBOARD_RAW_H */
|
||||
@@ -9,7 +9,6 @@
|
||||
#define __CROS_EC_KEYBOARD_SCAN_H
|
||||
|
||||
#include "common.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/**
|
||||
* Initializes the module.
|
||||
@@ -52,15 +51,4 @@ void keyboard_enable_scanning(int enable);
|
||||
*/
|
||||
void keyboard_send_battery_key(void);
|
||||
|
||||
#ifdef CONFIG_TASK_KEYSCAN
|
||||
|
||||
/**
|
||||
* Keyboard scan GPIO interrupt.
|
||||
*/
|
||||
void keyboard_scan_interrupt(enum gpio_signal signal);
|
||||
|
||||
#else
|
||||
#define keyboard_scan_interrupt NULL
|
||||
#endif
|
||||
|
||||
#endif /* __CROS_EC_KEYBOARD_SCAN_H */
|
||||
|
||||
Reference in New Issue
Block a user