Microchip: MEC172x: kscan driver

Update keyscan driver to support MEC172x device

Signed-off-by: Jay Vasanth <jay.vasanth@microchip.com>
This commit is contained in:
Jay Vasanth 2021-11-22 14:41:23 -05:00 committed by Anas Nashif
commit f6394e0d54
6 changed files with 250 additions and 96 deletions

View file

@ -148,3 +148,7 @@
lines = <4>;
chip-select = <0>;
};
&kscan0 {
status = "okay";
};

View file

@ -74,6 +74,36 @@ const struct pin_info espi_pin_table[] = {
#endif
};
/* kscan: KSCAN KSO & KSI */
const struct pin_info kscan_pin_table[] = {
#if defined(CONFIG_KSCAN_XEC) && DT_NODE_HAS_STATUS(DT_NODELABEL(kscan0), okay)
{ port_040_076, MCHP_GPIO_040, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_045, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_046, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_125, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_126, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_047, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_107, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_112, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_113, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_140_176, MCHP_GPIO_152, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_140_176, MCHP_GPIO_151, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_120, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_121, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_122, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_123, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_100_136, MCHP_GPIO_124, MCHP_GPIO_CTRL_MUX_F2 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_017, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_020, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_021, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_026, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_027, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_030, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_031, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
{ port_040_076, MCHP_GPIO_032, MCHP_GPIO_CTRL_MUX_F1 | MCHP_GPIO_CTRL_PUD_PU },
#endif
};
static void brd_init_pinmux_ports(struct pinmux_ports_t *pp)
{
ARG_UNUSED(pp);
@ -167,6 +197,7 @@ static int board_pinmux_init(const struct device *dev)
brd_init_pinmux_ports(&pp);
brd_pin_table_init(&pp, uart_pin_table, ARRAY_SIZE(uart_pin_table));
brd_pin_table_init(&pp, espi_pin_table, ARRAY_SIZE(espi_pin_table));
brd_pin_table_init(&pp, kscan_pin_table, ARRAY_SIZE(kscan_pin_table));
return 0;
}

View file

@ -3,9 +3,12 @@
# Copyright (c) 2019 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
DT_COMPAT_ST_KSCAN_XEC := microchip,xec-kscan
menuconfig KSCAN_XEC
bool "XEC Microchip KSCAN driver"
bool "Microchip XEC series KSCAN driver"
depends on SOC_FAMILY_MEC
default $(dt_compat_enabled,$(DT_COMPAT_ST_KSCAN_XEC))
select MULTITHREADING
help
Enable the Microchip XEC Kscan IO driver.
@ -13,33 +16,33 @@ menuconfig KSCAN_XEC
if KSCAN_XEC
config KSCAN_XEC_COLUMN_SIZE
int "KSCAN_XEC_COLUMN_SIZE"
int "Keyscan XEC Column Size"
default 16
help
Adjust the value to your keyboard columns. The maximum
column size for the Microchip XEC family is 18 (from 0 to 17).
config KSCAN_XEC_ROW_SIZE
int "KSCAN_XEC_ROW_SIZE"
int "Keyscan XEC Row Size"
default 8
help
Adjust the value to your keyboard rows. The maximum
column size for the Microchip XEC family is 8 (from 0 to 7).
config KSCAN_XEC_DEBOUNCE_DOWN
int "KSCAN_XEC_DEBOUNCE_DOWN"
int "Keyscan XEC Debounce Down"
default 10
help
Determines the time in msecs for debouncing a key press.
config KSCAN_XEC_DEBOUNCE_UP
int "KSCAN_XEC_DEBOUNCE_UP"
int "Keyscan XEC Debounce Up"
default 20
help
Determines the time in msecs for debouncing a key release.
config KSCAN_XEC_POLL_PERIOD
int "KSCAN_XEC_POLL_PERIOD"
int "Keyscan XEC Poll Period"
default 5
help
Defines the poll period in msecs between between matrix scans.

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* Copyright (c) 2022 Microchip Technology Inc.
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,11 +8,14 @@
#include <errno.h>
#include <device.h>
#include <drivers/clock_control/mchp_xec_clock_control.h>
#include <drivers/interrupt_controller/intc_mchp_xec_ecia.h>
#include <drivers/kscan.h>
#include <kernel.h>
#include <soc.h>
#include <sys/atomic.h>
#include <logging/log.h>
#include <arch/arm/aarch32/cortex_m/cmsis.h>
#define LOG_LEVEL CONFIG_KSCAN_LOG_LEVEL
LOG_MODULE_REGISTER(kscan_mchp_xec);
@ -33,6 +36,16 @@ LOG_MODULE_REGISTER(kscan_mchp_xec);
/* Thread stack size */
#define TASK_STACK_SIZE 1024
struct kscan_xec_config {
struct kscan_regs *regs;
uint8_t girq;
uint8_t girq_pos;
uint8_t irq_pri;
uint8_t pcr_idx;
uint8_t pcr_pos;
uint8_t rsvd[3];
};
struct kscan_xec_data {
/* variables in usec units */
uint32_t deb_time_press;
@ -57,31 +70,84 @@ struct kscan_xec_data {
K_KERNEL_STACK_MEMBER(thread_stack, TASK_STACK_SIZE);
};
static KSCAN_Type *base = (KSCAN_Type *)
(DT_INST_REG_ADDR(0));
static struct kscan_xec_data kbd_data;
static void drive_keyboard_column(int data)
#ifdef CONFIG_SOC_SERIES_MEC172X
static void kscan_clear_girq_status(const struct device *dev)
{
struct kscan_xec_config const *cfg = dev->config;
mchp_xec_ecia_girq_src_clr(cfg->girq, cfg->girq_pos);
}
static void kscan_configure_girq(const struct device *dev, bool enable)
{
struct kscan_xec_config const *cfg = dev->config;
if (enable) {
mchp_xec_ecia_enable(cfg->girq, cfg->girq_pos);
} else {
mchp_xec_ecia_disable(cfg->girq, cfg->girq_pos);
}
}
static void kscan_clr_slp_en(const struct device *dev)
{
struct kscan_xec_config const *cfg = dev->config;
z_mchp_xec_pcr_periph_sleep(cfg->pcr_idx, cfg->pcr_pos, 0);
}
#else
static void kscan_clear_girq_status(const struct device *dev)
{
ARG_UNUSED(dev);
MCHP_GIRQ_SRC(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
}
static void kscan_configure_girq(const struct device *dev, bool enable)
{
if (enable) {
MCHP_GIRQ_ENSET(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
} else {
MCHP_GIRQ_ENCLR(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
}
}
static void kscan_clr_slp_en(const struct device *dev)
{
ARG_UNUSED(dev);
mchp_pcr_periph_slp_ctrl(PCR_KEYSCAN, 0);
}
#endif
static void drive_keyboard_column(const struct device *dev, int data)
{
struct kscan_xec_config const *cfg = dev->config;
struct kscan_regs *regs = cfg->regs;
if (data == KEYBOARD_COLUMN_DRIVE_ALL) {
/* KSO output controlled by the KSO_SELECT field */
base->KSO_SEL = MCHP_KSCAN_KSO_ALL;
regs->KSO_SEL = MCHP_KSCAN_KSO_ALL;
} else if (data == KEYBOARD_COLUMN_DRIVE_NONE) {
/* Keyboard scan disabled. All KSO output buffers disabled */
base->KSO_SEL = MCHP_KSCAN_KSO_EN;
regs->KSO_SEL = MCHP_KSCAN_KSO_EN;
} else {
/* It is assumed, KEYBOARD_COLUMN_DRIVE_ALL was
* previously set
*/
base->KSO_SEL = data;
regs->KSO_SEL = data;
}
}
static uint8_t read_keyboard_row(void)
static uint8_t read_keyboard_row(const struct device *dev)
{
struct kscan_xec_config const *cfg = dev->config;
struct kscan_regs *regs = cfg->regs;
/* In this implementation a 1 means key pressed */
return ~(base->KSI_IN & 0xFF);
return ~(regs->KSI_IN & 0xFF);
}
static bool is_matrix_ghosting(const uint8_t *state)
@ -123,49 +189,51 @@ static bool is_matrix_ghosting(const uint8_t *state)
return false;
}
static bool read_keyboard_matrix(uint8_t *new_state)
static bool read_keyboard_matrix(const struct device *dev, uint8_t *new_state)
{
uint8_t row;
uint8_t key_event = 0U;
for (int col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
drive_keyboard_column(col);
drive_keyboard_column(dev, col);
/* Allow the matrix to stabilize before reading it */
k_busy_wait(50U);
row = read_keyboard_row();
row = read_keyboard_row(dev);
new_state[col] = row;
key_event |= row;
}
drive_keyboard_column(KEYBOARD_COLUMN_DRIVE_NONE);
drive_keyboard_column(dev, KEYBOARD_COLUMN_DRIVE_NONE);
return key_event != 0U ? true : false;
}
static void scan_matrix_xec_isr(const void *arg)
static void scan_matrix_xec_isr(const struct device *dev)
{
ARG_UNUSED(arg);
struct kscan_xec_data *const data = dev->data;
MCHP_GIRQ_SRC(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
kscan_clear_girq_status(dev);
irq_disable(DT_INST_IRQN(0));
k_sem_give(&kbd_data.poll_lock);
k_sem_give(&data->poll_lock);
LOG_DBG(" ");
}
static bool check_key_events(const struct device *dev)
{
struct kscan_xec_data *const data = dev->data;
uint8_t matrix_new_state[MAX_MATRIX_KEY_COLS] = {0U};
bool key_pressed = false;
uint32_t cycles_now = k_cycle_get_32();
if (++kbd_data.scan_cycles_idx >= SCAN_OCURRENCES)
kbd_data.scan_cycles_idx = 0U;
if (++data->scan_cycles_idx >= SCAN_OCURRENCES) {
data->scan_cycles_idx = 0U;
}
kbd_data.scan_clk_cycle[kbd_data.scan_cycles_idx] = cycles_now;
data->scan_clk_cycle[data->scan_cycles_idx] = cycles_now;
/* Scan the matrix */
key_pressed = read_keyboard_matrix(matrix_new_state);
key_pressed = read_keyboard_matrix(dev, matrix_new_state);
/* Abort if ghosting is detected */
if (is_matrix_ghosting(matrix_new_state)) {
@ -181,29 +249,32 @@ static bool check_key_events(const struct device *dev)
for (int c = 0; c < MAX_MATRIX_KEY_COLS; c++) {
/* Check if there was an update from the previous scan */
row_changed = matrix_new_state[c] ^
kbd_data.matrix_previous_state[c];
data->matrix_previous_state[c];
if (!row_changed)
if (!row_changed) {
continue;
}
for (int r = 0; r < MAX_MATRIX_KEY_ROWS; r++) {
/* Index all they keys that changed for each row
* in order to debounce each key in terms of it
*/
if (row_changed & BIT(r))
kbd_data.scan_cycle_idx[c][r] =
kbd_data.scan_cycles_idx;
if (row_changed & BIT(r)) {
data->scan_cycle_idx[c][r] =
data->scan_cycles_idx;
}
}
kbd_data.matrix_unstable_state[c] |= row_changed;
kbd_data.matrix_previous_state[c] = matrix_new_state[c];
data->matrix_unstable_state[c] |= row_changed;
data->matrix_previous_state[c] = matrix_new_state[c];
}
for (int c = 0; c < MAX_MATRIX_KEY_COLS; c++) {
deb_col = kbd_data.matrix_unstable_state[c];
deb_col = data->matrix_unstable_state[c];
if (!deb_col)
if (!deb_col) {
continue;
}
/* Debouncing for each row key occurs here */
for (int r = 0; r < MAX_MATRIX_KEY_ROWS; r++) {
@ -211,24 +282,25 @@ static bool check_key_events(const struct device *dev)
uint8_t row_bit = matrix_new_state[c] & mask;
/* Continue if we already debounce a key */
if (!(deb_col & mask))
if (!(deb_col & mask)) {
continue;
}
/* Convert the clock cycle differences to usec */
uint32_t debt = CLOCK_32K_HW_CYCLES_TO_US(cycles_now -
kbd_data.scan_clk_cycle[kbd_data.scan_cycle_idx[c][r]]);
data->scan_clk_cycle[data->scan_cycle_idx[c][r]]);
/* Does the key requires more time to be debounced? */
if (debt < (row_bit ? kbd_data.deb_time_press :
kbd_data.deb_time_rel)) {
if (debt < (row_bit ? data->deb_time_press :
data->deb_time_rel)) {
/* Need more time to debounce */
continue;
}
kbd_data.matrix_unstable_state[c] &= ~row_bit;
data->matrix_unstable_state[c] &= ~row_bit;
/* Check if there was a change in the stable state */
if ((kbd_data.matrix_stable_state[c] & mask)
if ((data->matrix_stable_state[c] & mask)
== row_bit) {
/* Key state did not change */
continue;
@ -239,9 +311,9 @@ static bool check_key_events(const struct device *dev)
* the stable state. Then, proceed to notify the
* application about the keys pressed.
*/
kbd_data.matrix_stable_state[c] ^= mask;
if (atomic_get(&kbd_data.enable_scan) == 1U) {
kbd_data.callback(dev, r, c,
data->matrix_stable_state[c] ^= mask;
if (atomic_get(&data->enable_scan) == 1U) {
data->callback(dev, r, c,
row_bit ? true : false);
}
}
@ -267,34 +339,38 @@ static bool poll_expired(uint32_t start_cycles, int64_t *timeout)
}
void polling_task(void *dummy1, void *dummy2, void *dummy3)
void polling_task(const struct device *dev, void *dummy2, void *dummy3)
{
struct kscan_xec_config const *cfg = dev->config;
struct kscan_xec_data *const data = dev->data;
struct kscan_regs *regs = cfg->regs;
uint32_t current_cycles;
uint32_t cycles_diff;
uint32_t wait_period;
int64_t local_poll_timeout = kbd_data.poll_timeout;
int64_t local_poll_timeout = data->poll_timeout;
ARG_UNUSED(dummy1);
ARG_UNUSED(dummy2);
ARG_UNUSED(dummy3);
while (true) {
base->KSI_STS = MCHP_KSCAN_KSO_SEL_REG_MASK;
regs->KSI_STS = MCHP_KSCAN_KSO_SEL_REG_MASK;
/* Ignore isr when releasing a key as we are polling */
MCHP_GIRQ_SRC(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
NVIC_ClearPendingIRQ(MCHP_KSAN_NVIC);
irq_enable(MCHP_KSAN_NVIC);
drive_keyboard_column(KEYBOARD_COLUMN_DRIVE_ALL);
k_sem_take(&kbd_data.poll_lock, K_FOREVER);
kscan_clear_girq_status(dev);
NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
irq_enable(DT_INST_IRQN(0));
drive_keyboard_column(dev, KEYBOARD_COLUMN_DRIVE_ALL);
k_sem_take(&data->poll_lock, K_FOREVER);
uint32_t start_poll_cycles = k_cycle_get_32();
while (atomic_get(&kbd_data.enable_scan) == 1U) {
while (atomic_get(&data->enable_scan) == 1U) {
uint32_t start_period_cycles = k_cycle_get_32();
if (check_key_events(DEVICE_DT_INST_GET(0))) {
local_poll_timeout = kbd_data.poll_timeout;
local_poll_timeout = data->poll_timeout;
start_poll_cycles = k_cycle_get_32();
} else if (!poll_expired(start_poll_cycles,
&local_poll_timeout)) {
@ -307,21 +383,22 @@ void polling_task(void *dummy1, void *dummy2, void *dummy3)
*/
current_cycles = k_cycle_get_32();
cycles_diff = current_cycles - start_period_cycles;
wait_period = kbd_data.poll_period -
wait_period = data->poll_period -
CLOCK_32K_HW_CYCLES_TO_US(cycles_diff);
/* Override wait_period in case it is less than 1 ms */
if (wait_period < MSEC_PER_MS)
if (wait_period < MSEC_PER_MS) {
wait_period = MSEC_PER_MS;
}
/* wait period results in a larger number when
* current cycles counter wrap. In this case, the
* whole poll period is used
*/
if (wait_period > kbd_data.poll_period) {
if (wait_period > data->poll_period) {
LOG_DBG("wait_period : %u", wait_period);
wait_period = kbd_data.poll_period;
wait_period = data->poll_period;
}
/* Allow other threads to run while we sleep */
@ -333,33 +410,34 @@ void polling_task(void *dummy1, void *dummy2, void *dummy3)
static int kscan_xec_configure(const struct device *dev,
kscan_callback_t callback)
{
ARG_UNUSED(dev);
struct kscan_xec_data *const data = dev->data;
if (!callback) {
return -EINVAL;
}
kbd_data.callback = callback;
data->callback = callback;
MCHP_GIRQ_ENSET(MCHP_KSCAN_GIRQ) = BIT(MCHP_KSCAN_GIRQ_POS);
kscan_clear_girq_status(dev);
kscan_configure_girq(dev, 1);
return 0;
}
static int kscan_xec_inhibit_interface(const struct device *dev)
{
ARG_UNUSED(dev);
struct kscan_xec_data *const data = dev->data;
atomic_set(&kbd_data.enable_scan, 0);
atomic_set(&data->enable_scan, 0);
return 0;
}
static int kscan_xec_enable_interface(const struct device *dev)
{
ARG_UNUSED(dev);
struct kscan_xec_data *const data = dev->data;
atomic_set(&kbd_data.enable_scan, 1);
atomic_set(&data->enable_scan, 1);
return 0;
}
@ -370,45 +448,63 @@ static const struct kscan_driver_api kscan_xec_driver_api = {
.enable_callback = kscan_xec_enable_interface,
};
static int kscan_xec_init(const struct device *dev);
DEVICE_DT_INST_DEFINE(0,
&kscan_xec_init,
NULL,
NULL, NULL,
POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY,
&kscan_xec_driver_api);
static int kscan_xec_init(const struct device *dev)
{
ARG_UNUSED(dev);
struct kscan_xec_config const *cfg = dev->config;
struct kscan_xec_data *const data = dev->data;
struct kscan_regs *regs = cfg->regs;
kscan_clr_slp_en(dev);
/* Enable predrive */
base->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS);
base->EXT_CTRL = MCHP_KSCAN_EXT_CTRL_PREDRV_EN;
base->KSO_SEL &= ~BIT(MCHP_KSCAN_KSO_EN_POS);
base->KSI_IEN = MCHP_KSCAN_KSI_IEN_REG_MASK;
regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS);
regs->EXT_CTRL = MCHP_KSCAN_EXT_CTRL_PREDRV_EN;
regs->KSO_SEL &= ~BIT(MCHP_KSCAN_KSO_EN_POS);
regs->KSI_IEN = MCHP_KSCAN_KSI_IEN_REG_MASK;
/* Time figures are transformed from msec to usec */
kbd_data.deb_time_press = (uint32_t)
data->deb_time_press = (uint32_t)
(CONFIG_KSCAN_XEC_DEBOUNCE_DOWN * MSEC_PER_MS);
kbd_data.deb_time_rel = (uint32_t)
data->deb_time_rel = (uint32_t)
(CONFIG_KSCAN_XEC_DEBOUNCE_UP * MSEC_PER_MS);
kbd_data.poll_period = (uint32_t)
data->poll_period = (uint32_t)
(CONFIG_KSCAN_XEC_POLL_PERIOD * MSEC_PER_MS);
kbd_data.poll_timeout = 100 * MSEC_PER_MS;
data->poll_timeout = 100 * MSEC_PER_MS;
k_sem_init(&kbd_data.poll_lock, 0, 1);
atomic_set(&kbd_data.enable_scan, 1);
k_sem_init(&data->poll_lock, 0, 1);
atomic_set(&data->enable_scan, 1);
k_thread_create(&kbd_data.thread, kbd_data.thread_stack,
k_thread_create(&data->thread, data->thread_stack,
TASK_STACK_SIZE,
polling_task, NULL, NULL, NULL,
(void (*)(void *, void *, void *))polling_task,
(void *)dev, NULL, NULL,
K_PRIO_COOP(4), 0, K_NO_WAIT);
/* Interrupts are enabled in the thread function */
IRQ_CONNECT(MCHP_KSAN_NVIC, 0, scan_matrix_xec_isr, NULL, 0);
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
scan_matrix_xec_isr, DEVICE_DT_INST_GET(0), 0);
return 0;
}
static struct kscan_xec_data kbd_data;
static struct kscan_xec_config kscan_xec_cfg_0 = {
.regs = (struct kscan_regs *)(DT_INST_REG_ADDR(0)),
#ifdef CONFIG_SOC_SERIES_MEC172X
.girq = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 0)),
.girq_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 1)),
.pcr_idx = (uint8_t)(DT_INST_PROP_BY_IDX(0, pcrs, 0)),
.pcr_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, pcrs, 1)),
#else
.girq = MCHP_KSCAN_GIRQ,
.girq_pos = MCHP_KSCAN_GIRQ_POS,
.pcr_idx = 3u,
.pcr_pos = MCHP_PCR3_KEYSCAN_POS,
#endif
};
DEVICE_DT_INST_DEFINE(0, kscan_xec_init,
NULL, &kbd_data, &kscan_xec_cfg_0,
POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY,
&kscan_xec_driver_api);

View file

@ -736,6 +736,7 @@
#io-channel-cells = <1>;
};
kscan0: kscan@40009c00 {
compatible = "microchip,xec-kscan";
reg = <0x40009c00 0x18>;
interrupts = <135 0>;
girqs = <21 25>;

View file

@ -1,11 +1,12 @@
# Copyright (c) 2019, Intel Corporation
# Copyright (c) 2021, Microchip Technology Inc.
# SPDX-License-Identifier: Apache-2.0
description: Microchip XEC keyboard matrix controller
compatible: "microchip,xec-kscan"
include: kscan.yaml
include: [kscan.yaml]
properties:
"#address-cells":
@ -19,3 +20,21 @@ properties:
interrupts:
required: true
girqs:
type: array
required: false
description: Array of pairs of GIRQ number and bit position
pcrs:
type: array
required: false
description: ADC PCR register index and bit position
girq-cells:
- girqnum
- bitpos
pcr-cells:
- regidx
- bitpos