input: convert kscan_mchp_xec.c driver to input

Convert the XEC keyboard scanning driver from kscan to input, add the
corresponding kscan compatibility node to the current board, build test
only.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
This commit is contained in:
Fabio Baltieri 2023-11-14 11:05:12 +00:00 committed by Anas Nashif
parent 3b50237699
commit ddd2cf1fdc
17 changed files with 146 additions and 158 deletions

View file

@ -3,6 +3,9 @@
if BOARD_MEC1501MODULAR_ASSY6885 if BOARD_MEC1501MODULAR_ASSY6885
config INPUT
default y if KSCAN
#PS/2 driver is compiled in terms of this flag. #PS/2 driver is compiled in terms of this flag.
config ESPI_PERIPHERAL_8042_KBC config ESPI_PERIPHERAL_8042_KBC
default y default y

View file

@ -17,7 +17,7 @@
zephyr,sram = &sram0; zephyr,sram = &sram0;
zephyr,console = &uart1; zephyr,console = &uart1;
zephyr,flash = &flash0; zephyr,flash = &flash0;
zephyr,keyboard-scan = &kscan0; zephyr,keyboard-scan = &kscan_input;
}; };
aliases { aliases {
@ -26,7 +26,7 @@
i2c0 = &i2c_smb_0; i2c0 = &i2c_smb_0;
i2c1 = &i2c_smb_1; i2c1 = &i2c_smb_1;
kscan0 = &kscan0; kscan0 = &kscan_input;
watchdog0 = &wdog; watchdog0 = &wdog;
}; };
}; };
@ -100,7 +100,7 @@
pinctrl-names = "default"; pinctrl-names = "default";
}; };
&kscan0 { &kbd0 {
status = "okay"; status = "okay";
pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125 pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125
@ -118,6 +118,10 @@
&ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep &ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep
&ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >; &ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >;
pinctrl-names = "default", "sleep"; pinctrl-names = "default", "sleep";
kscan_input: kscan-input {
compatible = "zephyr,kscan-input";
};
}; };
&peci0 { &peci0 {

View file

@ -3,6 +3,9 @@
if BOARD_MEC15XXEVB_ASSY6853 if BOARD_MEC15XXEVB_ASSY6853
config INPUT
default y if KSCAN
config ESPI_XEC config ESPI_XEC
default y default y
depends on ESPI depends on ESPI

View file

@ -16,7 +16,7 @@
zephyr,sram = &sram0; zephyr,sram = &sram0;
zephyr,console = &uart2; zephyr,console = &uart2;
zephyr,flash = &flash0; zephyr,flash = &flash0;
zephyr,keyboard-scan = &kscan0; zephyr,keyboard-scan = &kscan_input;
}; };
aliases { aliases {
@ -29,7 +29,7 @@
i2c-0 = &i2c_smb_0; i2c-0 = &i2c_smb_0;
i2c1 = &i2c_smb_1; i2c1 = &i2c_smb_1;
i2c7 = &i2c_smb_2; i2c7 = &i2c_smb_2;
kscan0 = &kscan0; kscan0 = &kscan_input;
watchdog0 = &wdog; watchdog0 = &wdog;
}; };
@ -157,7 +157,7 @@
pinctrl-names = "default"; pinctrl-names = "default";
}; };
&kscan0 { &kbd0 {
status = "okay"; status = "okay";
pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125 pinctrl-0 = < &kso00_gpio040 &kso01_gpio045 &kso02_gpio046 &kso12_gpio125
@ -175,6 +175,10 @@
&ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep &ksi2_gpio021_sleep &ksi3_gpio026_sleep &ksi4_gpio027_sleep
&ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >; &ksi5_gpio030_sleep &ksi6_gpio031_sleep &ksi7_gpio032_sleep >;
pinctrl-names = "default", "sleep"; pinctrl-names = "default", "sleep";
kscan_input: kscan-input {
compatible = "zephyr,kscan-input";
};
}; };
&peci0 { &peci0 {

View file

@ -3,6 +3,9 @@
if BOARD_MEC172XEVB_ASSY6906 if BOARD_MEC172XEVB_ASSY6906
config INPUT
default y if KSCAN
if RTOS_TIMER if RTOS_TIMER
# XEC RTOS timer HW frequency is fixed at 32768 Hz. # XEC RTOS timer HW frequency is fixed at 32768 Hz.

View file

@ -213,7 +213,7 @@
pinctrl-names = "default"; pinctrl-names = "default";
}; };
&kscan0 { &kbd0 {
status = "okay"; status = "okay";
pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026
@ -231,6 +231,10 @@
&kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep &kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep
&kso13_gpio126_sleep >; &kso13_gpio126_sleep >;
pinctrl-names = "default", "sleep"; pinctrl-names = "default", "sleep";
kscan_input: kscan-input {
compatible = "zephyr,kscan-input";
};
}; };
&ksi0_gpio017 { &ksi0_gpio017 {

View file

@ -3,6 +3,9 @@
if BOARD_MEC172XMODULAR_ASSY6930 if BOARD_MEC172XMODULAR_ASSY6930
config INPUT
default y if KSCAN
if RTOS_TIMER if RTOS_TIMER
# XEC RTOS timer HW frequency is fixed at 32768 Hz. # XEC RTOS timer HW frequency is fixed at 32768 Hz.

View file

@ -191,7 +191,7 @@
pinctrl-names = "default"; pinctrl-names = "default";
}; };
&kscan0 { &kbd0 {
status = "okay"; status = "okay";
pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026 pinctrl-0 = < &ksi0_gpio017 &ksi1_gpio020 &ksi2_gpio021 &ksi3_gpio026
@ -209,6 +209,10 @@
&kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep &kso10_gpio123_sleep &kso11_gpio124_sleep &kso12_gpio125_sleep
&kso13_gpio126_sleep >; &kso13_gpio126_sleep >;
pinctrl-names = "default", "sleep"; pinctrl-names = "default", "sleep";
kscan_input: kscan-input {
compatible = "zephyr,kscan-input";
};
}; };
&ksi0_gpio017 { &ksi0_gpio017 {

View file

@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_NPCX_KBD input_npcx_kbd.c)
zephyr_library_sources_ifdef(CONFIG_INPUT_PAT912X input_pat912x.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PAT912X input_pat912x.c)
zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c)
zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c) zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c)
zephyr_library_sources_ifdef(CONFIG_INPUT_XEC_KBD input_xec_kbd.c)
zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c)
# zephyr-keep-sorted-stop # zephyr-keep-sorted-stop

View file

@ -24,6 +24,7 @@ source "drivers/input/Kconfig.pat912x"
source "drivers/input/Kconfig.pmw3610" source "drivers/input/Kconfig.pmw3610"
source "drivers/input/Kconfig.sdl" source "drivers/input/Kconfig.sdl"
source "drivers/input/Kconfig.stmpe811" source "drivers/input/Kconfig.stmpe811"
source "drivers/input/Kconfig.xec"
source "drivers/input/Kconfig.xpt2046" source "drivers/input/Kconfig.xpt2046"
# zephyr-keep-sorted-stop # zephyr-keep-sorted-stop

View file

@ -3,47 +3,47 @@
# Copyright (c) 2019 Intel Corporation # Copyright (c) 2019 Intel Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
menuconfig KSCAN_XEC menuconfig INPUT_XEC_KBD
bool "Microchip XEC series KSCAN driver" bool "Microchip XEC series keyboard matrix driver"
default y default y
depends on DT_HAS_MICROCHIP_XEC_KSCAN_ENABLED depends on DT_HAS_MICROCHIP_XEC_KBD_ENABLED
select MULTITHREADING select MULTITHREADING
select PINCTRL select PINCTRL
help help
Enable the Microchip XEC Kscan IO driver. Enable the Microchip XEC Kscan IO driver.
if KSCAN_XEC if INPUT_XEC_KBD
config KSCAN_XEC_COLUMN_SIZE config INPUT_XEC_COLUMN_SIZE
int "Keyscan XEC Column Size" int "Keyscan XEC Column Size"
default 16 default 16
help help
Adjust the value to your keyboard columns. The maximum Adjust the value to your keyboard columns. The maximum
column size for the Microchip XEC family is 18 (from 0 to 17). column size for the Microchip XEC family is 18 (from 0 to 17).
config KSCAN_XEC_ROW_SIZE config INPUT_XEC_ROW_SIZE
int "Keyscan XEC Row Size" int "Keyscan XEC Row Size"
default 8 default 8
help help
Adjust the value to your keyboard rows. The maximum Adjust the value to your keyboard rows. The maximum
column size for the Microchip XEC family is 8 (from 0 to 7). column size for the Microchip XEC family is 8 (from 0 to 7).
config KSCAN_XEC_DEBOUNCE_DOWN config INPUT_XEC_DEBOUNCE_DOWN
int "Keyscan XEC Debounce Down" int "Keyscan XEC Debounce Down"
default 10 default 10
help help
Determines the time in msecs for debouncing a key press. Determines the time in msecs for debouncing a key press.
config KSCAN_XEC_DEBOUNCE_UP config INPUT_XEC_DEBOUNCE_UP
int "Keyscan XEC Debounce Up" int "Keyscan XEC Debounce Up"
default 20 default 20
help help
Determines the time in msecs for debouncing a key release. Determines the time in msecs for debouncing a key release.
config KSCAN_XEC_POLL_PERIOD config INPUT_XEC_POLL_PERIOD
int "Keyscan XEC Poll Period" int "Keyscan XEC Poll Period"
default 5 default 5
help help
Defines the poll period in msecs between between matrix scans. Defines the poll period in msecs between between matrix scans.
endif # KSCAN_XEC endif # INPUT_XEC

View file

@ -4,30 +4,28 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define DT_DRV_COMPAT microchip_xec_kscan #define DT_DRV_COMPAT microchip_xec_kbd
#include <cmsis_core.h> #include <cmsis_core.h>
#include <errno.h> #include <errno.h>
#include <soc.h>
#include <zephyr/device.h> #include <zephyr/device.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/input/input.h>
#include <zephyr/irq.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#ifdef CONFIG_SOC_SERIES_MEC172X #ifdef CONFIG_SOC_SERIES_MEC172X
#include <zephyr/drivers/clock_control/mchp_xec_clock_control.h> #include <zephyr/drivers/clock_control/mchp_xec_clock_control.h>
#include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h> #include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h>
#endif #endif
#include <zephyr/drivers/kscan.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/kernel.h>
#include <soc.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/policy.h>
#define LOG_LEVEL CONFIG_KSCAN_LOG_LEVEL LOG_MODULE_REGISTER(input_xec_kbd, CONFIG_INPUT_LOG_LEVEL);
LOG_MODULE_REGISTER(kscan_mchp_xec);
#define MAX_MATRIX_KEY_COLS CONFIG_KSCAN_XEC_COLUMN_SIZE #define MAX_MATRIX_KEY_COLS CONFIG_INPUT_XEC_COLUMN_SIZE
#define MAX_MATRIX_KEY_ROWS CONFIG_KSCAN_XEC_ROW_SIZE #define MAX_MATRIX_KEY_ROWS CONFIG_INPUT_XEC_ROW_SIZE
#define KEYBOARD_COLUMN_DRIVE_ALL -2 #define KEYBOARD_COLUMN_DRIVE_ALL -2
#define KEYBOARD_COLUMN_DRIVE_NONE -1 #define KEYBOARD_COLUMN_DRIVE_NONE -1
@ -42,7 +40,7 @@ LOG_MODULE_REGISTER(kscan_mchp_xec);
/* Thread stack size */ /* Thread stack size */
#define TASK_STACK_SIZE 1024 #define TASK_STACK_SIZE 1024
struct kscan_xec_config { struct xec_kbd_config {
struct kscan_regs *regs; struct kscan_regs *regs;
const struct pinctrl_dev_config *pcfg; const struct pinctrl_dev_config *pcfg;
uint8_t rsvd[3]; uint8_t rsvd[3];
@ -54,7 +52,7 @@ struct kscan_xec_config {
bool wakeup_source; bool wakeup_source;
}; };
struct kscan_xec_data { struct xec_kbd_data {
/* variables in usec units */ /* variables in usec units */
uint32_t deb_time_press; uint32_t deb_time_press;
uint32_t deb_time_rel; uint32_t deb_time_rel;
@ -71,24 +69,22 @@ struct kscan_xec_data {
uint8_t scan_clk_cycle[SCAN_OCURRENCES]; uint8_t scan_clk_cycle[SCAN_OCURRENCES];
struct k_sem poll_lock; struct k_sem poll_lock;
uint8_t scan_cycles_idx; uint8_t scan_cycles_idx;
kscan_callback_t callback;
struct k_thread thread; struct k_thread thread;
atomic_t enable_scan;
K_KERNEL_STACK_MEMBER(thread_stack, TASK_STACK_SIZE); K_KERNEL_STACK_MEMBER(thread_stack, TASK_STACK_SIZE);
}; };
#ifdef CONFIG_SOC_SERIES_MEC172X #ifdef CONFIG_SOC_SERIES_MEC172X
static void kscan_clear_girq_status(const struct device *dev) static void xec_kbd_clear_girq_status(const struct device *dev)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
mchp_xec_ecia_girq_src_clr(cfg->girq, cfg->girq_pos); mchp_xec_ecia_girq_src_clr(cfg->girq, cfg->girq_pos);
} }
static void kscan_configure_girq(const struct device *dev, bool enable) static void xec_kbd_configure_girq(const struct device *dev, bool enable)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
if (enable) { if (enable) {
mchp_xec_ecia_enable(cfg->girq, cfg->girq_pos); mchp_xec_ecia_enable(cfg->girq, cfg->girq_pos);
@ -97,24 +93,24 @@ static void kscan_configure_girq(const struct device *dev, bool enable)
} }
} }
static void kscan_clr_slp_en(const struct device *dev) static void xec_kbd_clr_slp_en(const struct device *dev)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
z_mchp_xec_pcr_periph_sleep(cfg->pcr_idx, cfg->pcr_pos, 0); z_mchp_xec_pcr_periph_sleep(cfg->pcr_idx, cfg->pcr_pos, 0);
} }
#else #else
static void kscan_clear_girq_status(const struct device *dev) static void xec_kbd_clear_girq_status(const struct device *dev)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
MCHP_GIRQ_SRC(cfg->girq) = BIT(cfg->girq_pos); MCHP_GIRQ_SRC(cfg->girq) = BIT(cfg->girq_pos);
} }
static void kscan_configure_girq(const struct device *dev, bool enable) static void xec_kbd_configure_girq(const struct device *dev, bool enable)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
if (enable) { if (enable) {
MCHP_GIRQ_ENSET(cfg->girq) = BIT(cfg->girq_pos); MCHP_GIRQ_ENSET(cfg->girq) = BIT(cfg->girq_pos);
@ -123,7 +119,7 @@ static void kscan_configure_girq(const struct device *dev, bool enable)
} }
} }
static void kscan_clr_slp_en(const struct device *dev) static void xec_kbd_clr_slp_en(const struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
@ -131,10 +127,9 @@ static void kscan_clr_slp_en(const struct device *dev)
} }
#endif #endif
static void drive_keyboard_column(const struct device *dev, int data) static void drive_keyboard_column(const struct device *dev, int data)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
struct kscan_regs *regs = cfg->regs; struct kscan_regs *regs = cfg->regs;
if (data == KEYBOARD_COLUMN_DRIVE_ALL) { if (data == KEYBOARD_COLUMN_DRIVE_ALL) {
@ -153,7 +148,7 @@ static void drive_keyboard_column(const struct device *dev, int data)
static uint8_t read_keyboard_row(const struct device *dev) static uint8_t read_keyboard_row(const struct device *dev)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
struct kscan_regs *regs = cfg->regs; struct kscan_regs *regs = cfg->regs;
/* In this implementation a 1 means key pressed */ /* In this implementation a 1 means key pressed */
@ -221,17 +216,17 @@ static bool read_keyboard_matrix(const struct device *dev, uint8_t *new_state)
static void scan_matrix_xec_isr(const struct device *dev) static void scan_matrix_xec_isr(const struct device *dev)
{ {
struct kscan_xec_data *const data = dev->data; struct xec_kbd_data *const data = dev->data;
kscan_clear_girq_status(dev); xec_kbd_clear_girq_status(dev);
irq_disable(DT_INST_IRQN(0)); irq_disable(DT_INST_IRQN(0));
k_sem_give(&data->poll_lock); k_sem_give(&data->poll_lock);
LOG_DBG(" "); LOG_DBG("");
} }
static bool check_key_events(const struct device *dev) static bool check_key_events(const struct device *dev)
{ {
struct kscan_xec_data *const data = dev->data; struct xec_kbd_data *const data = dev->data;
uint8_t matrix_new_state[MAX_MATRIX_KEY_COLS] = {0U}; uint8_t matrix_new_state[MAX_MATRIX_KEY_COLS] = {0U};
bool key_pressed = false; bool key_pressed = false;
uint32_t cycles_now = k_cycle_get_32(); uint32_t cycles_now = k_cycle_get_32();
@ -322,10 +317,10 @@ static bool check_key_events(const struct device *dev)
* application about the keys pressed. * application about the keys pressed.
*/ */
data->matrix_stable_state[c] ^= mask; data->matrix_stable_state[c] ^= mask;
if (atomic_get(&data->enable_scan) == 1U) {
data->callback(dev, r, c, input_report_abs(dev, INPUT_ABS_X, c, false, K_FOREVER);
row_bit ? true : false); input_report_abs(dev, INPUT_ABS_Y, r, false, K_FOREVER);
} input_report_key(dev, INPUT_BTN_TOUCH, row_bit, true, K_FOREVER);
} }
} }
@ -351,8 +346,8 @@ static bool poll_expired(uint32_t start_cycles, int64_t *timeout)
void polling_task(const struct device *dev, void *dummy2, void *dummy3) void polling_task(const struct device *dev, void *dummy2, void *dummy3)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
struct kscan_xec_data *const data = dev->data; struct xec_kbd_data *const data = dev->data;
struct kscan_regs *regs = cfg->regs; struct kscan_regs *regs = cfg->regs;
uint32_t current_cycles; uint32_t current_cycles;
uint32_t cycles_diff; uint32_t cycles_diff;
@ -366,7 +361,7 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3)
regs->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 */ /* Ignore isr when releasing a key as we are polling */
kscan_clear_girq_status(dev); xec_kbd_clear_girq_status(dev);
NVIC_ClearPendingIRQ(DT_INST_IRQN(0)); NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
irq_enable(DT_INST_IRQN(0)); irq_enable(DT_INST_IRQN(0));
@ -377,7 +372,7 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3)
uint32_t start_poll_cycles = k_cycle_get_32(); uint32_t start_poll_cycles = k_cycle_get_32();
while (atomic_get(&data->enable_scan) == 1U) { while (true) {
uint32_t start_period_cycles = k_cycle_get_32(); uint32_t start_period_cycles = k_cycle_get_32();
if (check_key_events(DEVICE_DT_INST_GET(0))) { if (check_key_events(DEVICE_DT_INST_GET(0))) {
@ -407,7 +402,7 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3)
* whole poll period is used * whole poll period is used
*/ */
if (wait_period > data->poll_period) { if (wait_period > data->poll_period) {
LOG_DBG("wait_period : %u", wait_period); LOG_DBG("wait_period: %u", wait_period);
wait_period = data->poll_period; wait_period = data->poll_period;
} }
@ -420,99 +415,63 @@ void polling_task(const struct device *dev, void *dummy2, void *dummy3)
} }
} }
static int kscan_xec_configure(const struct device *dev,
kscan_callback_t callback)
{
struct kscan_xec_data *const data = dev->data;
if (!callback) {
return -EINVAL;
}
data->callback = callback;
kscan_clear_girq_status(dev);
kscan_configure_girq(dev, 1);
return 0;
}
static int kscan_xec_inhibit_interface(const struct device *dev)
{
struct kscan_xec_data *const data = dev->data;
atomic_set(&data->enable_scan, 0);
return 0;
}
static int kscan_xec_enable_interface(const struct device *dev)
{
struct kscan_xec_data *const data = dev->data;
atomic_set(&data->enable_scan, 1);
return 0;
}
#ifdef CONFIG_PM_DEVICE #ifdef CONFIG_PM_DEVICE
static int kscan_xec_pm_action(const struct device *dev, enum pm_device_action action) static int xec_kbd_pm_action(const struct device *dev, enum pm_device_action action)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
struct kscan_regs *regs = cfg->regs; struct kscan_regs *regs = cfg->regs;
int ret = 0; int ret;
if (cfg->wakeup_source) {
return 0;
}
switch (action) { switch (action) {
case PM_DEVICE_ACTION_RESUME: case PM_DEVICE_ACTION_RESUME:
if (!(cfg->wakeup_source)) { ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (ret != 0) {
if (ret != 0) { LOG_ERR("XEC KSCAN pinctrl init failed (%d)", ret);
LOG_ERR("XEC KSCAN pinctrl init failed (%d)", ret); return ret;
return ret;
}
regs->KSO_SEL &= ~BIT(MCHP_KSCAN_KSO_EN_POS);
/* Clea Status register */
regs->KSI_STS = MCHP_KSCAN_KSO_SEL_REG_MASK;
regs->KSI_IEN = MCHP_KSCAN_KSI_IEN_REG_MASK;
} }
break;
regs->KSO_SEL &= ~BIT(MCHP_KSCAN_KSO_EN_POS);
/* Clear status register */
regs->KSI_STS = MCHP_KSCAN_KSO_SEL_REG_MASK;
regs->KSI_IEN = MCHP_KSCAN_KSI_IEN_REG_MASK;
break;
case PM_DEVICE_ACTION_SUSPEND: case PM_DEVICE_ACTION_SUSPEND:
if (!(cfg->wakeup_source)) { regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS);
regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS); regs->KSI_IEN = (~MCHP_KSCAN_KSI_IEN_REG_MASK);
regs->KSI_IEN = (~MCHP_KSCAN_KSI_IEN_REG_MASK); ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP);
ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); if (ret != -ENOENT) {
if (ret == -ENOENT) { /* pinctrl-1 does not exist. */ /* pinctrl-1 does not exist */
ret = 0; return ret;
}
} }
break; break;
default: default:
ret = -ENOTSUP; return -ENOTSUP;
} }
return ret;
return 0;
} }
#endif /* CONFIG_PM_DEVICE */ #endif /* CONFIG_PM_DEVICE */
static const struct kscan_driver_api kscan_xec_driver_api = { static int xec_kbd_init(const struct device *dev)
.config = kscan_xec_configure,
.disable_callback = kscan_xec_inhibit_interface,
.enable_callback = kscan_xec_enable_interface,
};
static int kscan_xec_init(const struct device *dev)
{ {
struct kscan_xec_config const *cfg = dev->config; struct xec_kbd_config const *cfg = dev->config;
struct kscan_xec_data *const data = dev->data; struct xec_kbd_data *const data = dev->data;
struct kscan_regs *regs = cfg->regs; struct kscan_regs *regs = cfg->regs;
int ret;
int ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
if (ret != 0) { if (ret != 0) {
LOG_ERR("XEC KSCAN pinctrl init failed (%d)", ret); LOG_ERR("XEC KSCAN pinctrl init failed (%d)", ret);
return ret; return ret;
} }
kscan_clr_slp_en(dev); xec_kbd_clr_slp_en(dev);
/* Enable predrive */ /* Enable predrive */
regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS); regs->KSO_SEL |= BIT(MCHP_KSCAN_KSO_EN_POS);
@ -522,15 +481,14 @@ static int kscan_xec_init(const struct device *dev)
/* Time figures are transformed from msec to usec */ /* Time figures are transformed from msec to usec */
data->deb_time_press = (uint32_t) data->deb_time_press = (uint32_t)
(CONFIG_KSCAN_XEC_DEBOUNCE_DOWN * MSEC_PER_MS); (CONFIG_INPUT_XEC_DEBOUNCE_DOWN * MSEC_PER_MS);
data->deb_time_rel = (uint32_t) data->deb_time_rel = (uint32_t)
(CONFIG_KSCAN_XEC_DEBOUNCE_UP * MSEC_PER_MS); (CONFIG_INPUT_XEC_DEBOUNCE_UP * MSEC_PER_MS);
data->poll_period = (uint32_t) data->poll_period = (uint32_t)
(CONFIG_KSCAN_XEC_POLL_PERIOD * MSEC_PER_MS); (CONFIG_INPUT_XEC_POLL_PERIOD * MSEC_PER_MS);
data->poll_timeout = 100 * MSEC_PER_MS; data->poll_timeout = 100 * MSEC_PER_MS;
k_sem_init(&data->poll_lock, 0, 1); k_sem_init(&data->poll_lock, 0, 1);
atomic_set(&data->enable_scan, 1);
k_thread_create(&data->thread, data->thread_stack, k_thread_create(&data->thread, data->thread_stack,
TASK_STACK_SIZE, TASK_STACK_SIZE,
@ -542,20 +500,20 @@ static int kscan_xec_init(const struct device *dev)
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
scan_matrix_xec_isr, DEVICE_DT_INST_GET(0), 0); scan_matrix_xec_isr, DEVICE_DT_INST_GET(0), 0);
xec_kbd_clear_girq_status(dev);
xec_kbd_configure_girq(dev, true);
return 0; return 0;
} }
static struct kscan_xec_data kbd_data; static struct xec_kbd_data kbd_data;
PINCTRL_DT_INST_DEFINE(0); PINCTRL_DT_INST_DEFINE(0);
/* To enable wakeup on the KSCAN, the DTS needs to have entries defined /* To enable wakeup, set the "wakeup-source" on the keyboard scanning device
* in the KSCAN node in the DTS specifying it as a wake source; * node.
* Example as below
*
* wakeup-source;
*/ */
static struct kscan_xec_config kscan_xec_cfg_0 = { static struct xec_kbd_config xec_kbd_cfg_0 = {
.regs = (struct kscan_regs *)(DT_INST_REG_ADDR(0)), .regs = (struct kscan_regs *)(DT_INST_REG_ADDR(0)),
.girq = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 0)), .girq = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 0)),
.girq_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 1)), .girq_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 1)),
@ -565,9 +523,9 @@ static struct kscan_xec_config kscan_xec_cfg_0 = {
.wakeup_source = DT_INST_PROP(0, wakeup_source) .wakeup_source = DT_INST_PROP(0, wakeup_source)
}; };
PM_DEVICE_DT_INST_DEFINE(0, kscan_xec_pm_action); PM_DEVICE_DT_INST_DEFINE(0, xec_kbd_pm_action);
DEVICE_DT_INST_DEFINE(0, kscan_xec_init, DEVICE_DT_INST_DEFINE(0, xec_kbd_init,
PM_DEVICE_DT_INST_GET(0), &kbd_data, &kscan_xec_cfg_0, PM_DEVICE_DT_INST_GET(0), &kbd_data, &xec_kbd_cfg_0,
POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY,
&kscan_xec_driver_api); NULL);

View file

@ -4,7 +4,6 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/kscan.h)
zephyr_library() zephyr_library()
zephyr_library_sources_ifdef(CONFIG_KSCAN_XEC kscan_mchp_xec.c)
zephyr_library_sources_ifdef(CONFIG_KSCAN_HT16K33 kscan_ht16k33.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_HT16K33 kscan_ht16k33.c)
zephyr_library_sources_ifdef(CONFIG_KSCAN_INPUT kscan_input.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_INPUT kscan_input.c)

View file

@ -10,7 +10,6 @@ menuconfig KSCAN
if KSCAN if KSCAN
source "drivers/kscan/Kconfig.xec"
source "drivers/kscan/Kconfig.ht16k33" source "drivers/kscan/Kconfig.ht16k33"
source "drivers/kscan/Kconfig.input" source "drivers/kscan/Kconfig.input"

View file

@ -443,8 +443,8 @@
#io-channel-cells = <1>; #io-channel-cells = <1>;
clktime = <32>; clktime = <32>;
}; };
kscan0: kscan@40009c00 { kbd0: kbd@40009c00 {
compatible = "microchip,xec-kscan"; compatible = "microchip,xec-kbd";
reg = <0x40009c00 0x18>; reg = <0x40009c00 0x18>;
interrupts = <135 0>; interrupts = <135 0>;
girqs = <21 25>; girqs = <21 25>;

View file

@ -651,8 +651,8 @@ adc0: adc@40007c00 {
#io-channel-cells = <1>; #io-channel-cells = <1>;
clktime = <32>; clktime = <32>;
}; };
kscan0: kscan@40009c00 { kbd0: kbd@40009c00 {
compatible = "microchip,xec-kscan"; compatible = "microchip,xec-kbd";
reg = <0x40009c00 0x18>; reg = <0x40009c00 0x18>;
interrupts = <135 0>; interrupts = <135 0>;
girqs = <21 25>; girqs = <21 25>;

View file

@ -4,17 +4,19 @@
description: Microchip XEC keyboard matrix controller description: Microchip XEC keyboard matrix controller
compatible: "microchip,xec-kscan" compatible: "microchip,xec-kbd"
include: [kscan.yaml, pinctrl-device.yaml] include: [base.yaml, pinctrl-device.yaml]
properties: properties:
"#address-cells": "#address-cells":
required: true required: true
const: 1 const: 1
"#size-cells": "#size-cells":
type: int type: int
const: 0 const: 0
reg: reg:
required: true required: true