drivers: input: initial support for renesas,ra-ctsu
First commit to add support for Renesas RA Capasitive Sensing Unit Signed-off-by: The Nguyen <the.nguyen.yf@renesas.com>
This commit is contained in:
parent
a5176adc41
commit
9ae5b7efd9
@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_PAW32XX input_paw32xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_PINNACLE input_pinnacle.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_REALTEK_RTS5912_KBD input_realtek_rts5912_kbd.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_RENESAS_RA_CTSU input_renesas_ra_ctsu.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_SBUS input_sbus.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_STM32_TSC_KEYS input_tsc_keys.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c)
|
||||
|
||||
@ -33,6 +33,7 @@ source "drivers/input/Kconfig.pat912x"
|
||||
source "drivers/input/Kconfig.paw32xx"
|
||||
source "drivers/input/Kconfig.pinnacle"
|
||||
source "drivers/input/Kconfig.pmw3610"
|
||||
source "drivers/input/Kconfig.renesas_ra"
|
||||
source "drivers/input/Kconfig.rts5912"
|
||||
source "drivers/input/Kconfig.sbus"
|
||||
source "drivers/input/Kconfig.sdl"
|
||||
|
||||
96
drivers/input/Kconfig.renesas_ra
Normal file
96
drivers/input/Kconfig.renesas_ra
Normal file
@ -0,0 +1,96 @@
|
||||
# Copyright (c) 2025 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU
|
||||
bool "Renesas RA Capacitive Touch driver"
|
||||
default y
|
||||
depends on DT_HAS_RENESAS_RA_CTSU_ENABLED
|
||||
select USE_RA_FSP_CTSU
|
||||
select USE_RA_FSP_TOUCH
|
||||
select SYS_MEM_BLOCKS
|
||||
select GPIO
|
||||
select PINCTRL
|
||||
help
|
||||
Enable Renesas RA Touch Sensing driver.
|
||||
|
||||
if INPUT_RENESAS_RA_CTSU
|
||||
|
||||
config INPUT_RENESAS_RA_DEVICE_VCC
|
||||
int "SoC VCC input in minivolt"
|
||||
default 3300
|
||||
help
|
||||
SoC VCC input in milivolt.
|
||||
|
||||
config INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
bool "Using QE Touch Workflow to config this driver"
|
||||
help
|
||||
If this config was enabled, setting for CTSU and Cap
|
||||
Touch driver will be reflected the setting that generated
|
||||
from QE Touch Workflow.
|
||||
Please add the generated C source files into the app CMakeLists
|
||||
to make the driver can using it.
|
||||
|
||||
if !INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_NUM_SELF_ELEMENTS
|
||||
int "Number of self-capacitance elements"
|
||||
default 0
|
||||
help
|
||||
Number of self-capacitance elements in the CTSU.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_NUM_MUTUAL_ELEMENTS
|
||||
int "Number of mutual-capacitance elements"
|
||||
default 0
|
||||
help
|
||||
Number of mutual-capacitance elements in the CTSU.
|
||||
|
||||
choice INPUT_RENESAS_RA_CTSU_CHATTERING_SUPPRESSION_TYPE
|
||||
prompt "Type of chattering suppression"
|
||||
default INPUT_RENESAS_RA_CTSU_CHATTERING_SUPPRESSION_TYPE_A
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_CHATTERING_SUPPRESSION_TYPE_A
|
||||
bool "Counter of exceed threshold is hold within hysteresis range"
|
||||
help
|
||||
Counter of exceed threshold is hold within hysteresis range.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_CHATTERING_SUPPRESSION_TYPE_B
|
||||
bool "Counter of exceed threshold is reset within hysteresis range"
|
||||
help
|
||||
Counter of exceed threshold is reset within hysteresis range.
|
||||
|
||||
endchoice # INPUT_RENESAS_RA_CTSU_CHATTERING_SUPPRESSION_TYPE
|
||||
|
||||
endif # !INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_POLLING_INTERVAL_MS
|
||||
int "CTSU debounce interval time"
|
||||
range 20 500
|
||||
default 100
|
||||
help
|
||||
Debouncing interval time in milliseconds.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_STABILIZATION_TIME_US
|
||||
int "CTSU stabilization time"
|
||||
default 20
|
||||
help
|
||||
Stabilization time required to wait between 2 scans in microseconds.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_DRV_STACK_SIZE
|
||||
int "CTSU internal thread stack size"
|
||||
default 512
|
||||
help
|
||||
CTSU driver internal thread stack size.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_DRV_PRIORITY
|
||||
int "CTSU internal thread priority"
|
||||
default 8
|
||||
help
|
||||
CTSU driver internal thread priority.
|
||||
|
||||
config INPUT_RENESAS_RA_CTSU_MSG_MEM_BLOCK_SIZE
|
||||
int "CTSU internal sys_mem_blocks allocator size"
|
||||
default 10
|
||||
help
|
||||
CTSU driver internal sys_mem_blocks allocator maximum num blocks.
|
||||
|
||||
endif # INPUT_RENESAS_RA_CTSU
|
||||
705
drivers/input/input_renesas_ra_ctsu.c
Normal file
705
drivers/input/input_renesas_ra_ctsu.c
Normal file
@ -0,0 +1,705 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Renesas Electronics Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include <zephyr/input/input.h>
|
||||
#include <zephyr/sys/math_extras.h>
|
||||
#include <zephyr/sys/mem_blocks.h>
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr/drivers/clock_control/renesas_ra_cgc.h>
|
||||
#include <zephyr/input/input_renesas_ra_ctsu.h>
|
||||
#include <rm_touch.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(renesas_ra_touch, CONFIG_INPUT_LOG_LEVEL);
|
||||
|
||||
struct renesas_ra_ctsu_cfg {
|
||||
const struct gpio_dt_spec tscap_pin;
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
const struct device *clock;
|
||||
const struct clock_control_ra_subsys_cfg clock_subsys;
|
||||
void (*irq_config)(void);
|
||||
};
|
||||
|
||||
struct renesas_ra_ctsu_data {
|
||||
struct k_sem scanning;
|
||||
struct k_queue scan_q;
|
||||
struct k_thread thread_data;
|
||||
|
||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_RENESAS_RA_CTSU_DRV_STACK_SIZE);
|
||||
};
|
||||
|
||||
struct renesas_ra_ctsu_group_cfg {
|
||||
const struct device *ctsu_dev;
|
||||
size_t num_button;
|
||||
size_t num_slider;
|
||||
size_t num_wheel;
|
||||
};
|
||||
|
||||
struct renesas_ra_ctsu_device_cb {
|
||||
const struct device *dev;
|
||||
void (*device_cb)(const struct device *dev, void *data);
|
||||
};
|
||||
|
||||
struct renesas_ra_ctsu_group_data {
|
||||
const struct device *dev;
|
||||
/* FSP Touch data */
|
||||
struct st_touch_instance touch_instance;
|
||||
#ifndef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
struct st_touch_instance_ctrl touch_ctrl;
|
||||
struct st_touch_cfg touch_cfg;
|
||||
/* FSP CTSU data */
|
||||
struct st_ctsu_instance ctsu_instance;
|
||||
struct st_ctsu_instance_ctrl ctsu_ctrl;
|
||||
struct st_ctsu_cfg ctsu_cfg;
|
||||
#endif /* CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG */
|
||||
/* Touch driver private data */
|
||||
struct k_work reading_work;
|
||||
struct k_timer sampling_timer;
|
||||
/* Touch driver sample result */
|
||||
uint64_t *p_button_status;
|
||||
uint16_t *p_slider_position;
|
||||
uint16_t *p_wheel_position;
|
||||
/* Touch device callback data */
|
||||
struct renesas_ra_ctsu_device_cb *p_button_cb;
|
||||
struct renesas_ra_ctsu_device_cb *p_slider_cb;
|
||||
struct renesas_ra_ctsu_device_cb *p_wheel_cb;
|
||||
};
|
||||
|
||||
extern void ctsu_write_isr(void);
|
||||
extern void ctsu_read_isr(void);
|
||||
extern void ctsu_end_isr(void);
|
||||
|
||||
struct ctsu_device_cfg {
|
||||
const struct device *group_dev;
|
||||
uint16_t event_code;
|
||||
};
|
||||
|
||||
struct ctsu_scan_msg {
|
||||
void *reserved; /* first word of queue data item reserved for the kernel */
|
||||
struct st_touch_instance *p_instance;
|
||||
};
|
||||
|
||||
SYS_MEM_BLOCKS_DEFINE_STATIC(scan_msg_allocator, sizeof(struct ctsu_scan_msg),
|
||||
CONFIG_INPUT_RENESAS_RA_CTSU_MSG_MEM_BLOCK_SIZE, sizeof(uint32_t));
|
||||
|
||||
static void renesas_ra_callback_adapter(touch_callback_args_t *p_args)
|
||||
{
|
||||
const struct device *dev = p_args->p_context;
|
||||
const struct renesas_ra_ctsu_group_cfg *cfg = dev->config;
|
||||
const struct device *ctsu_dev = cfg->ctsu_dev;
|
||||
struct renesas_ra_ctsu_data *ctsu_data = ctsu_dev->data;
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
|
||||
if (p_args->event == CTSU_EVENT_SCAN_COMPLETE) {
|
||||
k_work_submit(&data->reading_work);
|
||||
}
|
||||
|
||||
k_sem_give(&ctsu_data->scanning);
|
||||
}
|
||||
|
||||
#define POLLING_INTERVAL_MS K_MSEC(CONFIG_INPUT_RENESAS_RA_CTSU_POLLING_INTERVAL_MS)
|
||||
#define STABILIZATION_US K_USEC(CONFIG_INPUT_RENESAS_RA_CTSU_STABILIZATION_TIME_US)
|
||||
|
||||
static void renesas_ra_ctsu_drv_handler(void *arg0, void *arg1, void *arg2)
|
||||
{
|
||||
ARG_UNUSED(arg1);
|
||||
ARG_UNUSED(arg2);
|
||||
const struct device *ctsu_dev = arg0;
|
||||
struct renesas_ra_ctsu_data *ctsu_data = ctsu_dev->data;
|
||||
|
||||
while (true) {
|
||||
struct ctsu_scan_msg *msg = k_queue_get(&ctsu_data->scan_q, K_FOREVER);
|
||||
struct st_touch_instance *p_instance = msg->p_instance;
|
||||
fsp_err_t err;
|
||||
|
||||
k_sem_reset(&ctsu_data->scanning);
|
||||
err = p_instance->p_api->scanStart(p_instance->p_ctrl);
|
||||
if (err == FSP_SUCCESS) {
|
||||
k_sem_take(&ctsu_data->scanning, K_FOREVER);
|
||||
}
|
||||
|
||||
sys_mem_blocks_free(&scan_msg_allocator, 1, (void **)&msg);
|
||||
|
||||
k_sleep(STABILIZATION_US);
|
||||
}
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_group_sampling_handler(struct k_timer *timer)
|
||||
{
|
||||
struct renesas_ra_ctsu_group_data *data =
|
||||
CONTAINER_OF(timer, struct renesas_ra_ctsu_group_data, sampling_timer);
|
||||
const struct device *ctsu_dev = k_timer_user_data_get(timer);
|
||||
struct renesas_ra_ctsu_data *ctsu_data = ctsu_dev->data;
|
||||
struct ctsu_scan_msg *msg;
|
||||
|
||||
if (sys_mem_blocks_alloc(&scan_msg_allocator, 1, (void **)&msg) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg->p_instance = (void *)&data->touch_instance;
|
||||
k_queue_append(&ctsu_data->scan_q, msg);
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_group_buttons_read(const struct device *dev)
|
||||
{
|
||||
#if !DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_button)
|
||||
ARG_UNUSED(dev);
|
||||
#else
|
||||
const struct renesas_ra_ctsu_group_cfg *cfg = dev->config;
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
|
||||
if (cfg->num_button == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*data->p_button_status != 0) {
|
||||
uint64_t tmp_status = *data->p_button_status;
|
||||
|
||||
while (tmp_status != 0) {
|
||||
int num = u64_count_trailing_zeros(tmp_status);
|
||||
struct renesas_ra_ctsu_device_cb *p_button_cb = &data->p_button_cb[num];
|
||||
|
||||
p_button_cb->device_cb(p_button_cb->dev, NULL);
|
||||
WRITE_BIT(tmp_status, num, 0);
|
||||
}
|
||||
}
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_button) */
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_group_sliders_read(const struct device *dev)
|
||||
{
|
||||
#if !DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_slider)
|
||||
ARG_UNUSED(dev);
|
||||
#else
|
||||
const struct renesas_ra_ctsu_group_cfg *cfg = dev->config;
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
|
||||
if (cfg->num_slider == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cfg->num_slider; i++) {
|
||||
uint16_t slider_position = data->p_slider_position[i];
|
||||
|
||||
if (slider_position != UINT16_MAX) {
|
||||
struct renesas_ra_ctsu_device_cb *p_slider_cb = &data->p_slider_cb[i];
|
||||
|
||||
p_slider_cb->device_cb(p_slider_cb->dev, &slider_position);
|
||||
}
|
||||
}
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_slider) */
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_group_wheels_read(const struct device *dev)
|
||||
{
|
||||
#if !DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_wheel)
|
||||
ARG_UNUSED(dev);
|
||||
#else
|
||||
const struct renesas_ra_ctsu_group_cfg *cfg = dev->config;
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
|
||||
if (cfg->num_wheel == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cfg->num_wheel; i++) {
|
||||
uint16_t wheel_position = data->p_wheel_position[i];
|
||||
|
||||
if (wheel_position != UINT16_MAX) {
|
||||
struct renesas_ra_ctsu_device_cb *p_wheel_cb = &data->p_wheel_cb[i];
|
||||
|
||||
p_wheel_cb->device_cb(p_wheel_cb->dev, &wheel_position);
|
||||
}
|
||||
}
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ctsu_wheel) */
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_group_reading_handler(struct k_work *work)
|
||||
{
|
||||
struct renesas_ra_ctsu_group_data *data =
|
||||
CONTAINER_OF(work, struct renesas_ra_ctsu_group_data, reading_work);
|
||||
const struct device *dev = data->dev;
|
||||
const struct st_touch_instance *p_instance = &data->touch_instance;
|
||||
fsp_err_t err;
|
||||
|
||||
err = p_instance->p_api->dataGet(p_instance->p_ctrl, data->p_button_status,
|
||||
data->p_slider_position, data->p_wheel_position);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
renesas_ra_ctsu_group_buttons_read(dev);
|
||||
renesas_ra_ctsu_group_sliders_read(dev);
|
||||
renesas_ra_ctsu_group_wheels_read(dev);
|
||||
}
|
||||
|
||||
static int input_renesas_ra_ctsu_group_configure(const struct device *dev,
|
||||
const struct renesas_ra_ctsu_touch_cfg *cfg)
|
||||
{
|
||||
const struct st_touch_instance *p_instance = &cfg->touch_instance;
|
||||
const struct renesas_ra_ctsu_group_cfg *config = dev->config;
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
fsp_err_t err;
|
||||
|
||||
err = p_instance->p_api->open(p_instance->p_ctrl, p_instance->p_cfg);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = p_instance->p_api->callbackSet(p_instance->p_ctrl, renesas_ra_callback_adapter,
|
||||
(void *)dev, NULL);
|
||||
if (err != FSP_SUCCESS) {
|
||||
p_instance->p_api->close(p_instance->p_ctrl);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
data->touch_instance = *p_instance;
|
||||
#endif /* CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG */
|
||||
|
||||
k_work_init(&data->reading_work, renesas_ra_ctsu_group_reading_handler);
|
||||
k_timer_init(&data->sampling_timer, renesas_ra_ctsu_group_sampling_handler, NULL);
|
||||
k_timer_user_data_set(&data->sampling_timer, (void *)config->ctsu_dev);
|
||||
k_timer_start(&data->sampling_timer, POLLING_INTERVAL_MS, POLLING_INTERVAL_MS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int z_impl_renesas_ra_ctsu_group_configure(const struct device *dev,
|
||||
const struct renesas_ra_ctsu_touch_cfg *cfg)
|
||||
{
|
||||
#ifndef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(cfg);
|
||||
return -ENOSYS;
|
||||
#else
|
||||
return input_renesas_ra_ctsu_group_configure(dev, cfg);
|
||||
#endif /* CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG */
|
||||
}
|
||||
|
||||
static int renesas_ra_ctsu_group_init(const struct device *dev)
|
||||
{
|
||||
const struct renesas_ra_ctsu_group_cfg *cfg = dev->config;
|
||||
#ifndef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
struct renesas_ra_ctsu_group_data *data = dev->data;
|
||||
const struct renesas_ra_ctsu_touch_cfg *touch_cfg =
|
||||
(const struct renesas_ra_ctsu_touch_cfg *)&data->touch_instance;
|
||||
#endif /* CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG */
|
||||
|
||||
if (!device_is_ready(cfg->ctsu_dev)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
return input_renesas_ra_ctsu_group_configure(dev, touch_cfg);
|
||||
#else
|
||||
return 0;
|
||||
#endif /* CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG */
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_write_isr(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
ctsu_write_isr();
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_read_isr(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
ctsu_read_isr();
|
||||
}
|
||||
|
||||
static void renesas_ra_ctsu_end_isr(void *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
ctsu_end_isr();
|
||||
}
|
||||
|
||||
__maybe_unused static void ctsu_renesas_ra_button_cb(const struct device *dev, void *data)
|
||||
{
|
||||
ARG_UNUSED(data);
|
||||
const struct ctsu_device_cfg *cfg = dev->config;
|
||||
|
||||
input_report_key(dev, cfg->event_code, 0, false, K_NO_WAIT);
|
||||
}
|
||||
|
||||
__maybe_unused static void ctsu_renesas_ra_slider_cb(const struct device *dev, void *data)
|
||||
{
|
||||
const struct ctsu_device_cfg *cfg = dev->config;
|
||||
uint16_t *p_data = data;
|
||||
|
||||
if (p_data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
input_report_abs(dev, cfg->event_code, *p_data, false, K_NO_WAIT);
|
||||
}
|
||||
|
||||
#define ctsu_renesas_ra_wheel_cb ctsu_renesas_ra_slider_cb
|
||||
|
||||
#define FOREACH_CHILD_CB(node_id, fn, compat) \
|
||||
IF_ENABLED(DT_NODE_HAS_COMPAT(node_id, compat), (fn(node_id)))
|
||||
|
||||
#define FOREACH_CHILD(node_id, fn, compat) \
|
||||
DT_FOREACH_CHILD_STATUS_OKAY_VARGS(node_id, FOREACH_CHILD_CB, fn, compat)
|
||||
|
||||
/* CTSU instance define */
|
||||
#define DT_DRV_COMPAT renesas_ra_ctsu
|
||||
|
||||
/* CTSU group instance define */
|
||||
#define CTSU_ELEMENT_CFG_GET_BY_IDX(idx, id) \
|
||||
{ \
|
||||
.ssdiv = DT_ENUM_IDX_BY_IDX(id, ssdiv, idx), \
|
||||
.so = DT_PROP_BY_IDX(id, so, idx), \
|
||||
.snum = DT_PROP_BY_IDX(id, snum, idx), \
|
||||
.sdpa = DT_PROP_BY_IDX(id, sdpa, idx), \
|
||||
}
|
||||
|
||||
#define RENESAS_RA_CTSU_ELEM_GET(idx, node_id) DT_PROP_BY_IDX(node_id, elements, idx)
|
||||
|
||||
#define CTSU_ELEM_IDX_DEFINE(node_id) \
|
||||
static uint8_t CONCAT(DT_NODE_FULL_NAME_TOKEN(node_id), _elem_index)[] = { \
|
||||
LISTIFY(DT_PROP_LEN(node_id, elements), RENESAS_RA_CTSU_ELEM_GET, (,), node_id)};
|
||||
|
||||
#define CTSU_DEVICE_BUTTON_CALLBACK_DEFINE(node_id) \
|
||||
{ \
|
||||
.dev = DEVICE_DT_GET(node_id), \
|
||||
.device_cb = ctsu_renesas_ra_button_cb, \
|
||||
},
|
||||
|
||||
#define CTSU_DEVICE_SLIDER_CALLBACK_DEFINE(node_id) \
|
||||
{ \
|
||||
.dev = DEVICE_DT_GET(node_id), \
|
||||
.device_cb = ctsu_renesas_ra_slider_cb, \
|
||||
},
|
||||
|
||||
#define CTSU_DEVICE_WHEEL_CALLBACK_DEFINE(node_id) \
|
||||
{ \
|
||||
.dev = DEVICE_DT_GET(node_id), \
|
||||
.device_cb = ctsu_renesas_ra_wheel_cb, \
|
||||
},
|
||||
|
||||
#define CTSU_BUTTON_DT_SPEC_GET(node_id) \
|
||||
{ \
|
||||
.elem_index = DT_PROP(node_id, elements), \
|
||||
.threshold = DT_PROP(node_id, threshold), \
|
||||
.hysteresis = DT_PROP(node_id, hysteresis), \
|
||||
},
|
||||
|
||||
#define CTSU_SLIDER_DT_SPEC_GET(node_id) \
|
||||
{ \
|
||||
.p_elem_index = CONCAT(DT_NODE_FULL_NAME_TOKEN(node_id), _elem_index), \
|
||||
.num_elements = ARRAY_SIZE(CONCAT(DT_NODE_FULL_NAME_TOKEN(node_id), _elem_index)), \
|
||||
.threshold = DT_PROP(node_id, threshold), \
|
||||
},
|
||||
|
||||
#define CTSU_WHEEL_DT_SPEC_GET(node_id) CTSU_SLIDER_DT_SPEC_GET(node_id)
|
||||
|
||||
#define CTSU_GROUP_VAR_NAME(node_id, surfix) \
|
||||
CONCAT(renesas_ra_ctsu_, DT_NODE_FULL_NAME_TOKEN(node_id), surfix)
|
||||
|
||||
#define CTSU_ELEMENTS_DEFINE(node_id) \
|
||||
{LISTIFY(DT_PROP_LEN(node_id, ssdiv), CTSU_ELEMENT_CFG_GET_BY_IDX, (,), node_id)}
|
||||
|
||||
#ifndef CONFIG_INPUT_RENESAS_RA_QE_TOUCH_CFG
|
||||
#define RENESAS_RA_CTSU_GROUP_DEFINE(id) \
|
||||
static const ctsu_element_cfg_t CTSU_GROUP_VAR_NAME(id, _elements_cfg)[] = \
|
||||
CTSU_ELEMENTS_DEFINE(id); \
|
||||
\
|
||||
FOREACH_CHILD(id, CTSU_ELEM_IDX_DEFINE, renesas_ra_ctsu_slider); \
|
||||
FOREACH_CHILD(id, CTSU_ELEM_IDX_DEFINE, renesas_ra_ctsu_wheel); \
|
||||
\
|
||||
static touch_button_cfg_t CTSU_GROUP_VAR_NAME(id, _button_cfg)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_BUTTON_DT_SPEC_GET, renesas_ra_ctsu_button)}; \
|
||||
\
|
||||
static touch_slider_cfg_t CTSU_GROUP_VAR_NAME(id, _slider_cfg)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_SLIDER_DT_SPEC_GET, renesas_ra_ctsu_slider)}; \
|
||||
\
|
||||
static touch_wheel_cfg_t CTSU_GROUP_VAR_NAME(id, _wheel_cfg)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_WHEEL_DT_SPEC_GET, renesas_ra_ctsu_wheel)}; \
|
||||
\
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _button_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_BUTTON_CALLBACK_DEFINE, renesas_ra_ctsu_button)}; \
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _slider_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_SLIDER_CALLBACK_DEFINE, renesas_ra_ctsu_slider)}; \
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _wheel_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_WHEEL_CALLBACK_DEFINE, renesas_ra_ctsu_wheel)}; \
|
||||
\
|
||||
struct renesas_ra_ctsu_group_cfg CONCAT(renesas_ra_ctsu_, DT_NODE_FULL_NAME_TOKEN(id), \
|
||||
_cfg) = { \
|
||||
.ctsu_dev = DEVICE_DT_GET(DT_PARENT(id)), \
|
||||
.num_button = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _button_cfg)), \
|
||||
.num_slider = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _slider_cfg)), \
|
||||
.num_wheel = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _wheel_cfg)), \
|
||||
}; \
|
||||
\
|
||||
static uint64_t CTSU_GROUP_VAR_NAME(id, _button_data); \
|
||||
static uint16_t CTSU_GROUP_VAR_NAME( \
|
||||
id, _slider_data)[ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _slider_cfg))]; \
|
||||
static uint16_t CTSU_GROUP_VAR_NAME( \
|
||||
id, _wheel_data)[ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _wheel_cfg))]; \
|
||||
\
|
||||
static struct renesas_ra_ctsu_group_data CTSU_GROUP_VAR_NAME(id, _data) = { \
|
||||
.dev = DEVICE_DT_GET(id), \
|
||||
.touch_instance = \
|
||||
{ \
|
||||
.p_ctrl = &CTSU_GROUP_VAR_NAME(id, _data).touch_ctrl, \
|
||||
.p_cfg = &CTSU_GROUP_VAR_NAME(id, _data).touch_cfg, \
|
||||
.p_api = &g_touch_on_ctsu, \
|
||||
}, \
|
||||
.ctsu_instance = \
|
||||
{ \
|
||||
.p_ctrl = &CTSU_GROUP_VAR_NAME(id, _data).ctsu_ctrl, \
|
||||
.p_cfg = &CTSU_GROUP_VAR_NAME(id, _data).ctsu_cfg, \
|
||||
.p_api = &g_ctsu_on_ctsu, \
|
||||
}, \
|
||||
.touch_cfg = \
|
||||
{ \
|
||||
.on_freq = DT_PROP(id, on_freq), \
|
||||
.off_freq = DT_PROP(id, off_freq), \
|
||||
.drift_freq = DT_PROP(id, drift_freq), \
|
||||
.cancel_freq = DT_PROP(id, cancel_freq), \
|
||||
.p_ctsu_instance = &CTSU_GROUP_VAR_NAME(id, _data).ctsu_instance, \
|
||||
.p_buttons = CTSU_GROUP_VAR_NAME(id, _button_cfg), \
|
||||
.p_sliders = CTSU_GROUP_VAR_NAME(id, _slider_cfg), \
|
||||
.p_wheels = CTSU_GROUP_VAR_NAME(id, _wheel_cfg), \
|
||||
.num_sliders = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _slider_cfg)), \
|
||||
.num_wheels = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _wheel_cfg)), \
|
||||
.num_buttons = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _button_cfg)), \
|
||||
}, \
|
||||
.ctsu_cfg = \
|
||||
{ \
|
||||
.cap = CTSU_CAP_SOFTWARE, \
|
||||
.txvsel = DT_ENUM_IDX(DT_PARENT(id), pwr_supply_sel), \
|
||||
.txvsel2 = DT_ENUM_IDX(DT_PARENT(id), pwr_supply_sel2), \
|
||||
.atune1 = DT_ENUM_IDX(DT_PARENT(id), atune1), \
|
||||
.atune12 = DT_ENUM_IDX(DT_PARENT(id), atune12), \
|
||||
.md = CONCAT(CTSU_MODE_, \
|
||||
DT_STRING_UPPER_TOKEN(DT_PARENT(id), measure_mode)), \
|
||||
.posel = DT_ENUM_IDX(DT_PARENT(id), po_sel), \
|
||||
.ctsuchac0 = DT_PROP_BY_IDX(id, ctsuchac, 0), \
|
||||
.ctsuchac1 = DT_PROP_BY_IDX(id, ctsuchac, 1), \
|
||||
.ctsuchac2 = DT_PROP_BY_IDX(id, ctsuchac, 2), \
|
||||
.ctsuchac3 = DT_PROP_BY_IDX(id, ctsuchac, 3), \
|
||||
.ctsuchac4 = DT_PROP_BY_IDX(id, ctsuchac, 4), \
|
||||
.ctsuchtrc0 = DT_PROP_BY_IDX(id, ctsuchtrc, 0), \
|
||||
.ctsuchtrc1 = DT_PROP_BY_IDX(id, ctsuchtrc, 1), \
|
||||
.ctsuchtrc2 = DT_PROP_BY_IDX(id, ctsuchtrc, 2), \
|
||||
.ctsuchtrc3 = DT_PROP_BY_IDX(id, ctsuchtrc, 3), \
|
||||
.ctsuchtrc4 = DT_PROP_BY_IDX(id, ctsuchtrc, 4), \
|
||||
.num_rx = DT_PROP(id, rx_count), \
|
||||
.num_tx = DT_PROP(id, tx_count), \
|
||||
.num_moving_average = DT_PROP(id, num_moving_avg), \
|
||||
.p_elements = CTSU_GROUP_VAR_NAME(id, _elements_cfg), \
|
||||
.write_irq = DT_IRQ_BY_NAME(DT_PARENT(id), ctsuwr, irq), \
|
||||
.read_irq = DT_IRQ_BY_NAME(DT_PARENT(id), ctsurd, irq), \
|
||||
.end_irq = DT_IRQ_BY_NAME(DT_PARENT(id), ctsufn, irq), \
|
||||
}, \
|
||||
.p_button_status = &CTSU_GROUP_VAR_NAME(id, _button_data), \
|
||||
.p_slider_position = CTSU_GROUP_VAR_NAME(id, _slider_data), \
|
||||
.p_wheel_position = CTSU_GROUP_VAR_NAME(id, _wheel_data), \
|
||||
.p_button_cb = CTSU_GROUP_VAR_NAME(id, _button_cb), \
|
||||
.p_slider_cb = CTSU_GROUP_VAR_NAME(id, _slider_cb), \
|
||||
.p_wheel_cb = CTSU_GROUP_VAR_NAME(id, _wheel_cb), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_DEFINE(id, renesas_ra_ctsu_group_init, NULL, &CTSU_GROUP_VAR_NAME(id, _data), \
|
||||
&CTSU_GROUP_VAR_NAME(id, _cfg), POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \
|
||||
NULL);
|
||||
#else
|
||||
#define RENESAS_RA_CTSU_GROUP_DEFINE(id) \
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _button_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_BUTTON_CALLBACK_DEFINE, renesas_ra_ctsu_button)}; \
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _slider_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_SLIDER_CALLBACK_DEFINE, renesas_ra_ctsu_slider)}; \
|
||||
struct renesas_ra_ctsu_device_cb CTSU_GROUP_VAR_NAME(id, _wheel_cb)[] = { \
|
||||
FOREACH_CHILD(id, CTSU_DEVICE_WHEEL_CALLBACK_DEFINE, renesas_ra_ctsu_wheel)}; \
|
||||
\
|
||||
struct renesas_ra_ctsu_group_cfg CTSU_GROUP_VAR_NAME(id, _cfg) = { \
|
||||
.ctsu_dev = DEVICE_DT_GET(DT_PARENT(id)), \
|
||||
.num_button = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _button_cb)), \
|
||||
.num_slider = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _slider_cb)), \
|
||||
.num_wheel = ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _wheel_cb)), \
|
||||
}; \
|
||||
\
|
||||
static uint64_t CTSU_GROUP_VAR_NAME(id, _button_data); \
|
||||
static uint16_t CTSU_GROUP_VAR_NAME( \
|
||||
id, _slider_data)[ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _slider_cb))]; \
|
||||
static uint16_t CTSU_GROUP_VAR_NAME( \
|
||||
id, _wheel_data)[ARRAY_SIZE(CTSU_GROUP_VAR_NAME(id, _wheel_cb))]; \
|
||||
\
|
||||
static struct renesas_ra_ctsu_group_data CTSU_GROUP_VAR_NAME(id, _data) = { \
|
||||
.dev = DEVICE_DT_GET(id), \
|
||||
.p_button_status = &CTSU_GROUP_VAR_NAME(id, _button_data), \
|
||||
.p_slider_position = CTSU_GROUP_VAR_NAME(id, _slider_data), \
|
||||
.p_wheel_position = CTSU_GROUP_VAR_NAME(id, _wheel_data), \
|
||||
.p_button_cb = CTSU_GROUP_VAR_NAME(id, _button_cb), \
|
||||
.p_slider_cb = CTSU_GROUP_VAR_NAME(id, _slider_cb), \
|
||||
.p_wheel_cb = CTSU_GROUP_VAR_NAME(id, _wheel_cb), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_DEFINE(id, renesas_ra_ctsu_group_init, NULL, &CTSU_GROUP_VAR_NAME(id, _data), \
|
||||
&CTSU_GROUP_VAR_NAME(id, _cfg), POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
static int renesas_ra_ctsu_init(const struct device *dev)
|
||||
{
|
||||
const struct renesas_ra_ctsu_cfg *ctsu_cfg = dev->config;
|
||||
struct renesas_ra_ctsu_data *data = dev->data;
|
||||
k_tid_t tid;
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(ctsu_cfg->clock)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Perform discharge process for the TSCAP pin */
|
||||
ret = gpio_pin_configure_dt(&ctsu_cfg->tscap_pin, GPIO_OUTPUT_LOW);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait 10 usec for discharge to complete before switching to the CTSU pin function */
|
||||
k_busy_wait(10);
|
||||
|
||||
ret = pinctrl_apply_state(ctsu_cfg->pcfg, PINCTRL_STATE_DEFAULT);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clock_control_on(ctsu_cfg->clock, (clock_control_subsys_t)&ctsu_cfg->clock_subsys);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
k_sem_init(&data->scanning, 0, 1);
|
||||
k_queue_init(&data->scan_q);
|
||||
|
||||
tid = k_thread_create(
|
||||
&data->thread_data, data->thread_stack, K_THREAD_STACK_SIZEOF(data->thread_stack),
|
||||
renesas_ra_ctsu_drv_handler, (void *)dev, NULL, NULL,
|
||||
K_PRIO_COOP(CONFIG_INPUT_RENESAS_RA_CTSU_DRV_PRIORITY), K_ESSENTIAL, K_NO_WAIT);
|
||||
if (tid == NULL) {
|
||||
LOG_ERR("thread creation failed");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
k_thread_name_set(&data->thread_data, dev->name);
|
||||
|
||||
ctsu_cfg->irq_config();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RENESAS_RA_CTSU_DEFINE(inst) \
|
||||
PINCTRL_DT_INST_DEFINE(inst); \
|
||||
\
|
||||
static void renesas_ra_ctsu_irq_config##inst(void) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, ctsuwr, irq), \
|
||||
DT_INST_IRQ_BY_NAME(inst, ctsuwr, priority), \
|
||||
renesas_ra_ctsu_write_isr, NULL, 0); \
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, ctsurd, irq), \
|
||||
DT_INST_IRQ_BY_NAME(inst, ctsurd, priority), renesas_ra_ctsu_read_isr, \
|
||||
NULL, 0); \
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, ctsufn, irq), \
|
||||
DT_INST_IRQ_BY_NAME(inst, ctsufn, priority), renesas_ra_ctsu_end_isr, \
|
||||
NULL, 0); \
|
||||
\
|
||||
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(inst, ctsuwr, irq)] = \
|
||||
BSP_PRV_IELS_ENUM(EVENT_CTSU_WRITE); \
|
||||
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(inst, ctsurd, irq)] = \
|
||||
BSP_PRV_IELS_ENUM(EVENT_CTSU_READ); \
|
||||
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(inst, ctsufn, irq)] = \
|
||||
BSP_PRV_IELS_ENUM(EVENT_CTSU_END); \
|
||||
\
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(inst, ctsuwr, irq)); \
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(inst, ctsurd, irq)); \
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(inst, ctsufn, irq)); \
|
||||
} \
|
||||
\
|
||||
static const struct renesas_ra_ctsu_cfg renesas_ra_ctsu_cfg##inst = { \
|
||||
.tscap_pin = GPIO_DT_SPEC_INST_GET(inst, tscap_gpios), \
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
||||
.clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \
|
||||
.clock_subsys = \
|
||||
{ \
|
||||
.mstp = DT_INST_CLOCKS_CELL(inst, mstp), \
|
||||
.stop_bit = DT_INST_CLOCKS_CELL(inst, stop_bit), \
|
||||
}, \
|
||||
.irq_config = renesas_ra_ctsu_irq_config##inst, \
|
||||
}; \
|
||||
\
|
||||
static struct renesas_ra_ctsu_data renesas_ra_ctsu_data##inst; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, renesas_ra_ctsu_init, NULL, &renesas_ra_ctsu_data##inst, \
|
||||
&renesas_ra_ctsu_cfg##inst, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \
|
||||
NULL); \
|
||||
\
|
||||
DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, RENESAS_RA_CTSU_GROUP_DEFINE)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RENESAS_RA_CTSU_DEFINE)
|
||||
|
||||
static int ctsu_device_init(const struct device *dev)
|
||||
{
|
||||
const struct ctsu_device_cfg *cfg = dev->config;
|
||||
|
||||
return device_is_ready(cfg->group_dev) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
#undef DT_DRV_COMPAT
|
||||
#define DT_DRV_COMPAT renesas_ra_ctsu_button
|
||||
|
||||
#define RENESAS_RA_CTSU_BUTTON_DEFINE(inst) \
|
||||
IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(DT_INST_PARENT(inst)), ( \
|
||||
const struct ctsu_device_cfg ctsu_button_cfg##inst = { \
|
||||
.group_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||
.event_code = DT_INST_PROP(inst, event_code), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, ctsu_device_init, NULL, NULL, &ctsu_button_cfg##inst, \
|
||||
POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); \
|
||||
))
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RENESAS_RA_CTSU_BUTTON_DEFINE)
|
||||
|
||||
#undef DT_DRV_COMPAT
|
||||
#define DT_DRV_COMPAT renesas_ra_ctsu_slider
|
||||
|
||||
#define RENESAS_RA_CTSU_SLIDER_DEFINE(inst) \
|
||||
IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(DT_INST_PARENT(inst)), ( \
|
||||
const struct ctsu_device_cfg ctsu_slider_cfg##inst = { \
|
||||
.group_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||
.event_code = DT_INST_PROP(inst, event_code), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, ctsu_device_init, NULL, NULL, &ctsu_slider_cfg##inst, \
|
||||
POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); \
|
||||
))
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RENESAS_RA_CTSU_SLIDER_DEFINE)
|
||||
|
||||
#undef DT_DRV_COMPAT
|
||||
#define DT_DRV_COMPAT renesas_ra_ctsu_wheel
|
||||
|
||||
#define RENESAS_RA_CTSU_WHEEL_DEFINE(inst) \
|
||||
IF_ENABLED(DT_NODE_HAS_STATUS_OKAY(DT_INST_PARENT(inst)), ( \
|
||||
const struct ctsu_device_cfg ctsu_wheel_cfg##inst = { \
|
||||
.group_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||
.event_code = DT_INST_PROP(inst, event_code), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, ctsu_device_init, NULL, NULL, &ctsu_wheel_cfg##inst, \
|
||||
POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); \
|
||||
))
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RENESAS_RA_CTSU_WHEEL_DEFINE)
|
||||
69
dts/bindings/input/renesas,ra-ctsu-button.yaml
Normal file
69
dts/bindings/input/renesas,ra-ctsu-button.yaml
Normal file
@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2025 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Renesas RA Capacitive Touch Button instance.
|
||||
|
||||
This node is a renesas,ra-ctsu grandchild node and applies filters and calculations
|
||||
to detect an input event on a group which is the child of renesas,ra-ctsu.
|
||||
For more information see input/renesas,ra-ctsu.yaml
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/input/input-event-codes.h>
|
||||
|
||||
&ctsu {
|
||||
compatible = "renesas,ra-ctsu";
|
||||
|
||||
group1 {
|
||||
...
|
||||
button1 {
|
||||
compatible = "renesas,ra-ctsu-button";
|
||||
elements = <0>;
|
||||
threshold = <769>;
|
||||
hysteresis = <38>;
|
||||
event-code = <INPUT_KEY_0>;
|
||||
};
|
||||
|
||||
button2 {
|
||||
compatible = "renesas,ra-ctsu-button";
|
||||
elements = <1>;
|
||||
threshold = <769>;
|
||||
hysteresis = <38>;
|
||||
event-code = <INPUT_KEY_1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Notes: The order of the CTSU button nodes in the same group must follow these elements index.
|
||||
|
||||
compatible: "renesas,ra-ctsu-button"
|
||||
|
||||
include: [base.yaml]
|
||||
|
||||
properties:
|
||||
event-code:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
The key code for the device. This is used to identify the device in the
|
||||
input subsystem. It should be one of the values defined in
|
||||
include/input-event-codes.h.
|
||||
|
||||
elements:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Element number from CTSU group that this button located on.
|
||||
|
||||
threshold:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Touch/non-touch judgement threshold for automatic judgement.
|
||||
|
||||
hysteresis:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Threshold hysteresis for chattering prevention for automatic judgement.
|
||||
52
dts/bindings/input/renesas,ra-ctsu-slider.yaml
Normal file
52
dts/bindings/input/renesas,ra-ctsu-slider.yaml
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2025 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Renesas RA Capacitive Touch Slider instance.
|
||||
|
||||
This node is a renesas,ra-ctsu grandchild node and applies filters and calculations
|
||||
to detect an input event on a group which is the child of renesas,ra-ctsu.
|
||||
For more information see input/renesas,ra-ctsu.yaml
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/input/input-event-codes.h>
|
||||
|
||||
&ctsu {
|
||||
compatible = "renesas,ra-ctsu";
|
||||
|
||||
group1 {
|
||||
...
|
||||
slider {
|
||||
compatible = "renesas,ra-ctsu-slider";
|
||||
elements = <1>, <0>, <2>, <4>, <3>;
|
||||
threshold = <573>;
|
||||
event-code = <INPUT_ABS_THROTTLE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
compatible: "renesas,ra-ctsu-slider"
|
||||
|
||||
include: [base.yaml]
|
||||
|
||||
properties:
|
||||
event-code:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
The key code for the device. This is used to identify the device in the
|
||||
input subsystem. It should be one of the values defined in
|
||||
include/input-event-codes.h.
|
||||
|
||||
elements:
|
||||
type: array
|
||||
description: |
|
||||
Element number array from CTSU group that used by this node. It should have the same
|
||||
order with electrode located on the Capacitive Pad.
|
||||
|
||||
threshold:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Touch/non-touch judgement threshold for automatic judgement.
|
||||
52
dts/bindings/input/renesas,ra-ctsu-wheel.yaml
Normal file
52
dts/bindings/input/renesas,ra-ctsu-wheel.yaml
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (c) 2025 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Renesas RA Capacitive Touch Wheel
|
||||
|
||||
This node is a renesas,ra-ctsu grandchild node and applies filters and calculations
|
||||
to detect an input event on a group which is the child of renesas,ra-ctsu.
|
||||
For more information see input/renesas,ra-ctsu.yaml
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/input/input-event-codes.h>
|
||||
|
||||
&ctsu {
|
||||
compatible = "renesas,ra-ctsu";
|
||||
|
||||
group1 {
|
||||
...
|
||||
wheel {
|
||||
compatible = "renesas,ra-ctsu-wheel";
|
||||
elements = <0>, <3>, <2>, <1>;
|
||||
threshold = <711>;
|
||||
event-code = <INPUT_ABS_WHEEL>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
compatible: "renesas,ra-ctsu-wheel"
|
||||
|
||||
include: [base.yaml]
|
||||
|
||||
properties:
|
||||
event-code:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
The key code for the device. This is used to identify the device in the
|
||||
input subsystem. It should be one of the values defined in
|
||||
include/input-event-codes.h.
|
||||
|
||||
elements:
|
||||
type: array
|
||||
description: |
|
||||
Element number array from CTSU group that used by this node. It should have the same
|
||||
order with electrode located on the Capacitive Pad.
|
||||
|
||||
threshold:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Touch/non-touch judgement threshold for automatic judgement.
|
||||
199
dts/bindings/input/renesas,ra-ctsu.yaml
Normal file
199
dts/bindings/input/renesas,ra-ctsu.yaml
Normal file
@ -0,0 +1,199 @@
|
||||
# Copyright (c) 2025 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas RA Capacitive Sensing Unit
|
||||
|
||||
compatible: "renesas,ra-ctsu"
|
||||
|
||||
include: [base.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
pinctrl-0:
|
||||
required: true
|
||||
|
||||
clocks:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
||||
description: IRQ number and priority to use for CTSU.
|
||||
|
||||
interrupt-names:
|
||||
required: true
|
||||
description: |
|
||||
Interrupts must be given corresponding names so that the shim driver can recognize them.
|
||||
- "ctsuwr": write interrupt
|
||||
- "ctsurd": read interrupt
|
||||
- "ctsufn": end interrupt
|
||||
|
||||
variant:
|
||||
required: true
|
||||
type: string
|
||||
enum: ["ctsua", "ctsu2"]
|
||||
description: Determine which ctsu device is in use
|
||||
|
||||
clock-div:
|
||||
type: int
|
||||
enum: [1, 2, 4, 8]
|
||||
default: 1
|
||||
description: Select divider value for operating input clock. Default as div by 1.
|
||||
|
||||
pwr-supply-sel:
|
||||
type: string
|
||||
enum: ["vcc", "internal-power"]
|
||||
default: "internal-power"
|
||||
description: CTSU Transmission Power Supply Select (for both CTSUa and CTSU2).
|
||||
|
||||
pwr-supply-sel2:
|
||||
type: string
|
||||
enum: ["pwr-supply-sel", "vcc-private"]
|
||||
default: "pwr-supply-sel"
|
||||
description: CTSU Transmission Power Supply Select 2 (CTSU2 Only)
|
||||
|
||||
atune1:
|
||||
type: string
|
||||
enum: ["normal", "high"]
|
||||
default: "normal"
|
||||
description: |
|
||||
CTSU Power Supply Capacity Adjustment (CTSUa Only):
|
||||
- "normal": 40uA
|
||||
- "high": 80uA
|
||||
|
||||
atune12:
|
||||
type: int
|
||||
enum: [80, 40, 20, 160]
|
||||
default: 40
|
||||
description: |
|
||||
CTSU Power Supply Capacity Adjustment in uA (CTSU2 Only)
|
||||
|
||||
measure-mode:
|
||||
type: string
|
||||
enum:
|
||||
- "self-multi-scan"
|
||||
- "mutual-full-scan"
|
||||
- "mutual-cfc-scan"
|
||||
- "current-scan"
|
||||
- "correction-scan"
|
||||
- "diagnosis-scan"
|
||||
default: "self-multi-scan"
|
||||
description: CTSU Measurement Mode Select
|
||||
|
||||
po-sel:
|
||||
type: string
|
||||
enum:
|
||||
- "low-gpio"
|
||||
- "hi-z"
|
||||
- "low"
|
||||
- "same-pulse"
|
||||
default: "same-pulse"
|
||||
description: CTSU Non-Measured Channel Output Select (CTSU2 Only)
|
||||
|
||||
tscap-gpios:
|
||||
type: phandle-array
|
||||
required: true
|
||||
description: |
|
||||
CTSU TSCAP Pin. This pin is used to discharge the capacitior by
|
||||
control to output low, before switching to CTSU function.
|
||||
|
||||
child-binding:
|
||||
description: Renesas RA CTSU touch configuration
|
||||
properties:
|
||||
ctsuchac:
|
||||
type: array
|
||||
default: [0, 0, 0, 0, 0]
|
||||
description: |
|
||||
TSCAP pin enable mask. Expected fields, in order, are:
|
||||
- ctsuchac0: TS00-TS07 enable mask
|
||||
- ctsuchac1: TS08-TS15 enable mask
|
||||
- ctsuchac2: TS16-TS23 enable mask
|
||||
- ctsuchac3: TS24-TS31 enable mask
|
||||
- ctsuchac4: TS32-TS39 enable mask
|
||||
|
||||
ctsuchtrc:
|
||||
type: array
|
||||
default: [0, 0, 0, 0, 0]
|
||||
description: |
|
||||
TSCAP pin mutual-tx mask. Expected fields, in order, are:
|
||||
- ctsuchtrc0: TS00-TS07 mutual-tx mask
|
||||
- ctsuchtrc1: TS08-TS15 mutual-tx mask
|
||||
- ctsuchtrc2: TS16-TS23 mutual-tx mask
|
||||
- ctsuchtrc3: TS24-TS31 mutual-tx mask
|
||||
- ctsuchtrc4: TS32-TS39 mutual-tx mask
|
||||
|
||||
rx-count:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
The number of RX channels to be used. This should be set to the number of
|
||||
channels that are enabled in the ctsuchac0-4 properties.
|
||||
|
||||
tx-count:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
The number of TX channels to be used. This should be set to the number of
|
||||
channels that are enabled in the ctsuchtrc0-4 properties.
|
||||
|
||||
ssdiv:
|
||||
type: string-array
|
||||
default: ["4.00"]
|
||||
enum:
|
||||
- "4.00"
|
||||
- "2.00"
|
||||
- "1.33"
|
||||
- "1.00"
|
||||
- "0.80"
|
||||
- "0.67"
|
||||
- "0.57"
|
||||
- "0.50"
|
||||
- "0.44"
|
||||
- "0.40"
|
||||
- "0.36"
|
||||
- "0.33"
|
||||
- "0.31"
|
||||
- "0.29"
|
||||
- "0.27"
|
||||
- "0.00"
|
||||
description: CTSU Spectrum Diffusion Frequency Division Setting (CTSUa Only)
|
||||
|
||||
so:
|
||||
type: array
|
||||
default: [0]
|
||||
description: CTSU Sensor Offset Adjustment
|
||||
|
||||
snum:
|
||||
type: array
|
||||
default: [0]
|
||||
description: CTSU Measurement Count Setting
|
||||
|
||||
sdpa:
|
||||
type: array
|
||||
default: [0]
|
||||
description: CTSU Base Clock Setting
|
||||
|
||||
on-freq:
|
||||
type: int
|
||||
default: 0
|
||||
description: The cumulative number of determinations of ON.
|
||||
|
||||
off-freq:
|
||||
type: int
|
||||
default: 0
|
||||
description: The cumulative number of determinations of OFF.
|
||||
|
||||
drift-freq:
|
||||
type: int
|
||||
default: 0
|
||||
description: Base value drift frequency (0 mean no use).
|
||||
|
||||
cancel-freq:
|
||||
type: int
|
||||
default: 0
|
||||
description: Maximum continuous ON (0 mean no use).
|
||||
|
||||
num-moving-avg:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
The number of samples to use for moving average. If set to 0, no moving average is applied.
|
||||
This is useful for smoothing the sensor readings.
|
||||
40
include/zephyr/input/input_renesas_ra_ctsu.h
Normal file
40
include/zephyr/input/input_renesas_ra_ctsu.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Renesas Electronics Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ZEPHYR_INPUT_INPUT_RENESAS_RA_CTSU_H_
|
||||
#define ZEPHYR_INCLUDE_ZEPHYR_INPUT_INPUT_RENESAS_RA_CTSU_H_
|
||||
|
||||
#include <rm_touch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct renesas_ra_ctsu_touch_cfg {
|
||||
struct st_touch_instance touch_instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configure CTSU group device with a Renesas QE for Capacitive Touch Workflow generated
|
||||
* configuration
|
||||
*
|
||||
* @param dev Pointer to the input device instance
|
||||
* @param cfg Pointer to the configuration data for the device
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENOSYS in case INPUT_RENESAS_RA_QE_TOUCH_CFG was not enabled
|
||||
* @retval -errno on failure
|
||||
*/
|
||||
__syscall int renesas_ra_ctsu_group_configure(const struct device *dev,
|
||||
const struct renesas_ra_ctsu_touch_cfg *cfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <zephyr/syscalls/input_renesas_ra_ctsu.h>
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ZEPHYR_INPUT_INPUT_RENESAS_RA_CTSU_H_ */
|
||||
@ -201,6 +201,23 @@ config USE_RA_FSP_SSI
|
||||
help
|
||||
Enable RA FSP I2S SSI driver
|
||||
|
||||
config USE_RA_FSP_IOPORT
|
||||
bool
|
||||
help
|
||||
Enable RA FSP IOPORT driver
|
||||
|
||||
config USE_RA_FSP_CTSU
|
||||
bool
|
||||
select USE_RA_FSP_IOPORT
|
||||
help
|
||||
Enable RA FSP CTSU driver
|
||||
|
||||
config USE_RA_FSP_TOUCH
|
||||
bool
|
||||
depends on USE_RA_FSP_CTSU
|
||||
help
|
||||
Enable RA FSP TOUCH library
|
||||
|
||||
endif # HAS_RENESAS_RA_FSP
|
||||
|
||||
if HAS_RENESAS_RZ_FSP
|
||||
|
||||
Loading…
Reference in New Issue
Block a user