samples: boards: renesas: Add sample for CTSU input driver

Add sample for CTSU input driver using QE config files on
RSK-RX130-512KB

Signed-off-by: Minh Tang <minh.tang.ue@bp.renesas.com>
diff --git a/samples/boards/renesas/ctsu_input/CMakeLists.txt b/samples/boards/renesas/ctsu_input/CMakeLists.txt
new file mode 100644
index 0000000..48994f4
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/CMakeLists.txt
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: Apache-2.0
+
+cmake_minimum_required(VERSION 3.20.0)
+find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
+
+project(renesas_ctsu)
+
+target_sources(app PRIVATE src/main.c)
+
+if(CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG)
+  zephyr_include_directories(src/qe_generated_files)
+  zephyr_sources(src/qe_generated_files/qe_touch_config.c)
+endif()
diff --git a/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay b/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay
new file mode 100644
index 0000000..ee4811e
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+&ctsu {
+	status = "okay";
+};
+
+&onboard_slider {
+	zephyr,code = <1>;
+};
+
+&onboard_button_1 {
+	zephyr,code = <10>;
+};
+
+&onboard_button_2 {
+	zephyr,code = <11>;
+};
+
+/ {
+	leds {
+		testled0: testled0 {
+			gpios = <&ioportd 3 GPIO_ACTIVE_LOW>;
+			label = "LED0";
+		};
+
+		testled1: testled1 {
+			gpios = <&ioportd 4 GPIO_ACTIVE_LOW>;
+			label = "LED1";
+		};
+
+		testled2: testled2 {
+			gpios = <&ioporte 6 GPIO_ACTIVE_LOW>;
+			label = "LED2";
+		};
+
+		testled3: testled3 {
+			gpios = <&ioporte 7 GPIO_ACTIVE_LOW>;
+			label = "LED3";
+		};
+	};
+};
diff --git a/samples/boards/renesas/ctsu_input/prj.conf b/samples/boards/renesas/ctsu_input/prj.conf
new file mode 100644
index 0000000..f691746
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/prj.conf
@@ -0,0 +1,4 @@
+CONFIG_GPIO=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MODE_SYNCHRONOUS=y
+CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG=y
diff --git a/samples/boards/renesas/ctsu_input/src/main.c b/samples/boards/renesas/ctsu_input/src/main.c
new file mode 100644
index 0000000..5912c5e
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/main.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/sys/util.h>
+#include <zephyr/device.h>
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/kernel.h>
+#include <zephyr/input/input.h>
+#include <zephyr/input/input_renesas_rx_ctsu.h>
+
+#ifdef CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG
+#include "qe_touch_config.h"
+#endif /* CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG */
+
+static const struct device *const test_touch_dev = DEVICE_DT_GET(DT_NODELABEL(ctsu));
+#define BUTTON_1_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_button_1))
+#define BUTTON_2_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_button_2))
+#define SLIDER_IDX   DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_slider))
+
+#define STACKSIZE    1024
+#define PRIORITY     7
+#define LED0_NODE    DT_NODELABEL(testled0)
+#define LED1_NODE    DT_NODELABEL(testled1)
+#define LED2_NODE    DT_NODELABEL(testled2)
+#define LED3_NODE    DT_NODELABEL(testled3)
+#define NUM_TEST_LED 4
+
+#define LED_ON  1
+#define LED_OFF 0
+
+enum {
+	TOUCH_BUTTON_1 = 10,
+	TOUCH_BUTTON_2 = 11,
+	TOUCH_SLIDER = 1,
+};
+
+static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
+static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
+static const struct gpio_dt_spec led2 = GPIO_DT_SPEC_GET(LED2_NODE, gpios);
+static const struct gpio_dt_spec led3 = GPIO_DT_SPEC_GET(LED3_NODE, gpios);
+static const struct gpio_dt_spec *leds[] = {&led0, &led1, &led2, &led3};
+static volatile int led_state;
+static volatile int leds_on_off[NUM_TEST_LED] = {0};
+static volatile int current_main_led;
+
+static volatile int event_count[DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(ctsu))] = {0};
+static uint16_t last_code;
+static volatile int32_t last_val[DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(ctsu))];
+static struct k_sem btn1_sem;
+static struct k_sem btn2_sem;
+static struct k_sem sldr_sem;
+static struct k_sem render_sem;
+
+static void sample_setup(void)
+{
+	gpio_pin_configure_dt(&led0, GPIO_OUTPUT_INACTIVE);
+	gpio_pin_configure_dt(&led1, GPIO_OUTPUT_INACTIVE);
+	gpio_pin_configure_dt(&led2, GPIO_OUTPUT_INACTIVE);
+	gpio_pin_configure_dt(&led3, GPIO_OUTPUT_INACTIVE);
+
+	k_sem_init(&btn1_sem, 0, 1);
+	k_sem_init(&btn2_sem, 0, 1);
+	k_sem_init(&sldr_sem, 0, 1);
+	k_sem_init(&render_sem, 0, 1);
+
+#ifdef CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG
+	int ret = renesas_rx_ctsu_group_configure(
+		test_touch_dev, (struct renesas_rx_ctsu_touch_cfg *)&g_qe_touch_instance_config01);
+
+	if (ret < 0) {
+		printk("Failed to configure QE Touch: %d\n", ret);
+		return;
+	}
+#endif /* CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG */
+}
+
+static void button1_task(void)
+{
+	while (1) {
+		k_sem_take(&btn1_sem, K_FOREVER);
+		if (led_state == 0) {
+			/** Current leds are OFF, do nothing */
+		} else {
+			if (led_state >= 15) {
+				led_state = 1;
+			} else {
+				led_state++;
+			}
+		}
+		k_sem_give(&render_sem);
+	}
+}
+
+static void button2_task(void)
+{
+	int prev_state = 0;
+
+	while (1) {
+		k_sem_take(&btn2_sem, K_FOREVER);
+		if (led_state == 0) {
+			/** Current led state is OFF */
+			if (prev_state == 0) {
+				/** First time power on */
+				led_state = 1;
+			} else {
+				/** Restore prev_state */
+				led_state = prev_state;
+			}
+		} else {
+			prev_state = led_state;
+			led_state = 0;
+		}
+		k_sem_give(&render_sem);
+	}
+}
+
+static void slider_task(void)
+{
+	while (1) {
+		k_sem_take(&sldr_sem, K_FOREVER);
+		if (led_state == 0) {
+			continue;
+		}
+		int curr_val = last_val[SLIDER_IDX];
+
+		if (curr_val != TOUCH_OFF_VALUE) {
+			if (curr_val == 100) {
+				curr_val = 99;
+			}
+			current_main_led = 3 - (curr_val / 25);
+		}
+		k_sem_give(&render_sem);
+	}
+}
+
+static void render_task(void)
+{
+	while (1) {
+		k_sem_take(&render_sem, K_FOREVER);
+		for (int i = 0; i < NUM_TEST_LED; i++) {
+			if (led_state & BIT(i)) {
+				gpio_pin_set_dt(leds[(current_main_led + i) % 4], LED_ON);
+			} else {
+				gpio_pin_set_dt(leds[(current_main_led + i) % 4], LED_OFF);
+			}
+		}
+	}
+}
+
+static void test_touch_keys_cb_handler(struct input_event *evt, void *user_data)
+{
+	switch (evt->code) {
+	case TOUCH_BUTTON_1:
+		if (evt->value == 0) {
+			printk("Button 1 released\n");
+			if (last_val[BUTTON_1_IDX] != 0) {
+				k_sem_give(&btn1_sem);
+			}
+		} else {
+			event_count[BUTTON_1_IDX]++;
+			printk("Button 1 pressed %d time(s)\n", event_count[BUTTON_1_IDX]);
+		}
+		last_val[BUTTON_1_IDX] = evt->value;
+		break;
+
+	case TOUCH_BUTTON_2:
+		if (evt->value == 0) {
+			printk("Button 2 released\n");
+			if (last_val[BUTTON_2_IDX] != 0) {
+				k_sem_give(&btn2_sem);
+			}
+		} else {
+			event_count[BUTTON_2_IDX]++;
+			printk("Button 2 pressed %d time(s)\n", event_count[BUTTON_2_IDX]);
+		}
+		last_val[BUTTON_2_IDX] = evt->value;
+		break;
+
+	case TOUCH_SLIDER:
+		if (evt->value == TOUCH_OFF_VALUE) {
+			printk("Slider released\n");
+			if (last_val[SLIDER_IDX] != TOUCH_OFF_VALUE) {
+			}
+		} else {
+			if (last_val[SLIDER_IDX] == TOUCH_OFF_VALUE) {
+				event_count[SLIDER_IDX]++;
+				printk("Slider pressed\n");
+			}
+			printk("Position: %d\n", evt->value);
+		}
+		k_sem_give(&sldr_sem);
+		last_val[SLIDER_IDX] = evt->value;
+		break;
+
+	default:
+		break;
+	}
+	last_code = evt->code;
+}
+INPUT_CALLBACK_DEFINE(test_touch_dev, test_touch_keys_cb_handler, NULL);
+
+K_THREAD_DEFINE(button1_id, STACKSIZE, button1_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(button2_id, STACKSIZE, button2_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(slider_id, STACKSIZE, slider_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(render_id, STACKSIZE, render_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+
+int main(void)
+{
+	sample_setup();
+	printk("On board CTSU components sample started!\n");
+	printk("Press on touch nodes for sample\n");
+	return 0;
+}
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c
new file mode 100644
index 0000000..afd30b7
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "qe_touch_config.h"
+
+volatile uint8_t g_qe_touch_flag;
+volatile ctsu_event_t g_qe_ctsu_event;
+
+void qe_touch_callback(touch_callback_args_t *p_args)
+{
+	g_qe_touch_flag = 1;
+	g_qe_ctsu_event = p_args->event;
+}
+
+/* CTSU Related Information for [CONFIG01] configuration. */
+
+const ctsu_element_cfg_t g_qe_ctsu_element_cfg_config01[] = {
+	{.ssdiv = CTSU_SSDIV_2000, .so = 0x045, .snum = 0x03, .sdpa = 0x07},
+	{.ssdiv = CTSU_SSDIV_2000, .so = 0x055, .snum = 0x03, .sdpa = 0x07},
+	{.ssdiv = CTSU_SSDIV_2000, .so = 0x04D, .snum = 0x03, .sdpa = 0x07},
+	{.ssdiv = CTSU_SSDIV_2000, .so = 0x042, .snum = 0x03, .sdpa = 0x07},
+	{.ssdiv = CTSU_SSDIV_4000, .so = 0x0D0, .snum = 0x07, .sdpa = 0x03},
+	{.ssdiv = CTSU_SSDIV_4000, .so = 0x0C9, .snum = 0x07, .sdpa = 0x03},
+};
+
+const ctsu_cfg_t g_qe_ctsu_cfg_config01 = {
+	.cap = CTSU_CAP_SOFTWARE,
+
+	.txvsel = CTSU_TXVSEL_VCC,
+
+	.atune1 = CTSU_ATUNE1_NORMAL,
+
+	.md = CTSU_MODE_SELF_MULTI_SCAN,
+
+	.ctsuchac0 = 0x80,  /* ch0-ch7 enable mask */
+	.ctsuchac1 = 0x1F,  /* ch8-ch15 enable mask */
+	.ctsuchac2 = 0x00,  /* ch16-ch23 enable mask */
+	.ctsuchac3 = 0x00,  /* ch24-ch31 enable mask */
+	.ctsuchac4 = 0x00,  /* ch32-ch39 enable mask */
+	.ctsuchtrc0 = 0x00, /* ch0-ch7 mutual tx mask */
+	.ctsuchtrc1 = 0x00, /* ch8-ch15 mutual tx mask */
+	.ctsuchtrc2 = 0x00, /* ch16-ch23 mutual tx mask */
+	.ctsuchtrc3 = 0x00, /* ch24-ch31 mutual tx mask */
+	.ctsuchtrc4 = 0x00, /* ch32-ch39 mutual tx mask */
+	.num_rx = 6,
+	.num_tx = 0,
+	.p_elements = g_qe_ctsu_element_cfg_config01,
+
+#if (CTSU_TARGET_VALUE_CONFIG_SUPPORT == 1)
+	.tuning_self_target_value = 15360,
+	.tuning_mutual_target_value = 10240,
+#endif
+
+	.num_moving_average = 4,
+	.tuning_enable = true,
+	.p_callback = &qe_touch_callback,
+
+};
+
+ctsu_instance_ctrl_t g_qe_ctsu_ctrl_config01;
+
+const ctsu_instance_t g_qe_ctsu_instance_config01 = {
+	.p_ctrl = &g_qe_ctsu_ctrl_config01,
+	.p_cfg = &g_qe_ctsu_cfg_config01,
+	.p_api = &g_ctsu_on_ctsu,
+};
+
+/* Touch Related Information for [CONFIG01] configuration. */
+
+#define QE_TOUCH_CONFIG01_NUM_BUTTONS (2)
+#define QE_TOUCH_CONFIG01_NUM_SLIDERS (1)
+#define QE_TOUCH_CONFIG01_NUM_WHEELS  (0)
+
+/* Button configurations */
+#if (QE_TOUCH_CONFIG01_NUM_BUTTONS != 0)
+const touch_button_cfg_t g_qe_touch_button_cfg_config01[] = {
+
+	/* button1 */
+	{
+		.elem_index = 4,
+		.threshold = 2056,
+		.hysteresis = 102,
+	},
+	/* button02 */
+	{
+		.elem_index = 5,
+		.threshold = 2865,
+		.hysteresis = 143,
+	},
+};
+#endif
+
+/* Slider configurations */
+const uint8_t g_qe_touch_elem_slider_config01_slider01[] = {3, 2, 1, 0};
+
+#if (QE_TOUCH_CONFIG01_NUM_SLIDERS != 0)
+const touch_slider_cfg_t g_qe_touch_slider_cfg_config01[] = {
+	/* slider01 */
+	{
+		.p_elem_index = g_qe_touch_elem_slider_config01_slider01,
+		.num_elements = 4,
+		.threshold = 1157,
+	},
+};
+#endif
+
+/* Wheel configurations */
+#if (QE_TOUCH_CONFIG01_NUM_WHEELS != 0)
+const touch_wheel_cfg_t g_qe_touch_wheel_cfg_config01[] = {NULL};
+#endif
+
+/* Touch configurations */
+const touch_cfg_t g_qe_touch_cfg_config01 = {
+	.p_buttons = g_qe_touch_button_cfg_config01,
+	.p_sliders = g_qe_touch_slider_cfg_config01,
+	.p_wheels = NULL,
+	.num_buttons = QE_TOUCH_CONFIG01_NUM_BUTTONS,
+	.num_sliders = QE_TOUCH_CONFIG01_NUM_SLIDERS,
+	.num_wheels = QE_TOUCH_CONFIG01_NUM_WHEELS,
+
+	.number = 0,
+
+	.on_freq = 3,
+	.off_freq = 3,
+	.drift_freq = 255,
+	.cancel_freq = 0,
+
+	.p_ctsu_instance = &g_qe_ctsu_instance_config01,
+};
+
+touch_instance_ctrl_t g_qe_touch_ctrl_config01;
+
+const touch_instance_t g_qe_touch_instance_config01 = {
+	.p_ctrl = &g_qe_touch_ctrl_config01,
+	.p_cfg = &g_qe_touch_cfg_config01,
+	.p_api = &g_touch_on_ctsu,
+};
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h
new file mode 100644
index 0000000..fbf8f27
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef QE_TOUCH_CONFIG_H
+#define QE_TOUCH_CONFIG_H
+
+#include "r_ctsu_qe.h"
+#include "rm_touch_qe.h"
+#include "qe_touch_define.h"
+
+/* Exported global variables */
+extern const ctsu_instance_t g_qe_ctsu_instance_config01;
+extern const touch_instance_t g_qe_touch_instance_config01;
+
+extern volatile uint8_t g_qe_touch_flag;
+extern volatile ctsu_event_t g_qe_ctsu_event;
+
+/* Exported global functions (to be accessed by other files) */
+extern void qe_touch_callback(touch_callback_args_t *p_args);
+
+#endif /* QE_TOUCH_CONFIG_H */
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h
new file mode 100644
index 0000000..d57c453
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef QE_TOUCH_DEFINE_H
+#define QE_TOUCH_DEFINE_H
+
+/* Macro definitions */
+#define QE_TOUCH_VERSION 0x0420
+
+#define CTSU_CFG_NUM_SELF_ELEMENTS 6
+
+#define CTSU_CFG_NUM_MUTUAL_ELEMENTS 0
+
+#define TOUCH_CFG_MONITOR_ENABLE 1
+#define TOUCH_CFG_NUM_BUTTONS    2
+#define TOUCH_CFG_NUM_SLIDERS    1
+#define TOUCH_CFG_NUM_WHEELS     0
+#define TOUCH_CFG_PAD_ENABLE     0
+
+#define QE_TOUCH_MACRO_CTSU_IP_KIND 1
+
+#define CTSU_CFG_VCC_MV           3300
+#define CTSU_CFG_LOW_VOLTAGE_MODE 0
+
+#define CTSU_CFG_PCLK_DIVISION 0
+
+#define CTSU_CFG_TSCAP_PORT 0x0C04
+
+#define CTSU_CFG_NUM_SUMULTI 1
+
+#define CTSU_CFG_TARGET_VALUE_QE_SUPPORT 1
+
+#define CTSU_CFG_NUM_AUTOJUDGE_SELF_ELEMENTS   0
+#define CTSU_CFG_NUM_AUTOJUDGE_MUTUAL_ELEMENTS 0
+
+/* Button State Mask for each configuration. */
+#define CONFIG01_INDEX_BUTTON1  0
+#define CONFIG01_MASK_BUTTON1   (1ULL << CONFIG01_INDEX_BUTTON1)
+#define CONFIG01_INDEX_BUTTON02 1
+#define CONFIG01_MASK_BUTTON02  (1ULL << CONFIG01_INDEX_BUTTON02)
+
+#endif /* QE_TOUCH_DEFINE_H */