drivers: gpio: Add support for RZ/N2L
Add GPIO driver for RZ/N2L
Signed-off-by: Quang Le <quang.le.eb@bp.renesas.com>
Signed-off-by: Nhut Nguyen <nhut.nguyen.kc@renesas.com>
diff --git a/drivers/gpio/gpio_renesas_rz.c b/drivers/gpio/gpio_renesas_rz.c
index 386bae1..8692a64 100644
--- a/drivers/gpio/gpio_renesas_rz.c
+++ b/drivers/gpio/gpio_renesas_rz.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Renesas Electronics Corporation
+ * Copyright (c) 2024-2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -15,6 +15,10 @@
#include <zephyr/drivers/gpio/gpio_utils.h>
#include "gpio_renesas_rz.h"
#include <zephyr/logging/log.h>
+#if defined(CONFIG_SOC_SERIES_RZN2L)
+#include "r_icu.h"
+#include <zephyr/drivers/interrupt_controller/intc_rz_ext_irq.h>
+#endif
LOG_MODULE_REGISTER(rz_gpio, CONFIG_GPIO_LOG_LEVEL);
#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__)
@@ -28,7 +32,12 @@
const ioport_cfg_t *fsp_cfg;
const ioport_api_t *fsp_api;
const struct device *int_dev;
- uint8_t tint_num[GPIO_RZ_MAX_TINT_NUM];
+ uint8_t int_num[GPIO_RZ_MAX_INT_NUM];
+#if defined(CONFIG_SOC_SERIES_RZN2L)
+ const struct device *eirq_dev[GPIO_RZ_MAX_INT_NUM];
+
+ void (*cb_list[GPIO_RZ_MAX_INT_NUM])(void *arg);
+#endif
};
struct gpio_rz_data {
@@ -36,15 +45,18 @@
sys_slist_t cb;
ioport_instance_ctrl_t *fsp_ctrl;
struct k_spinlock lock;
+#if defined(CONFIG_SOC_SERIES_RZN2L)
+ uint8_t pin[GPIO_RZ_MAX_INT_NUM];
+#endif
};
-struct gpio_rz_tint_isr_data {
+struct gpio_rz_isr_data {
const struct device *gpio_dev;
gpio_pin_t pin;
};
-struct gpio_rz_tint_data {
- struct gpio_rz_tint_isr_data tint_data[GPIO_RZ_MAX_TINT_NUM];
+struct gpio_rz_int_data {
+ struct gpio_rz_isr_data gpio_mapping[GPIO_RZ_MAX_INT_NUM];
uint32_t irq_set_edge;
};
@@ -70,18 +82,12 @@
{
bsp_io_port_t port = (port_pin >> 8U) & 0xFF;
gpio_pin_t pin = port_pin & 0xFF;
- volatile uint8_t *p_p = GPIO_RZ_IOPORT_P_REG_BASE_GET;
- volatile uint16_t *p_pm = GPIO_RZ_IOPORT_PM_REG_BASE_GET;
+ volatile uint8_t *p_p = GPIO_RZ_IOPORT_P_REG_GET(port, pin);
+ volatile uint16_t *p_pm = GPIO_RZ_IOPORT_PM_REG_GET(port, pin);
- uint8_t adr_offset;
uint8_t p_value;
uint16_t pm_value;
- adr_offset = (uint8_t)GPIO_RZ_REG_OFFSET(port, pin);
-
- p_p = &p_p[adr_offset];
- p_pm = &p_pm[adr_offset];
-
p_value = GPIO_RZ_P_VALUE_GET(*p_p, pin);
pm_value = GPIO_RZ_PM_VALUE_GET(*p_pm, pin);
@@ -108,7 +114,11 @@
if (!flags) {
/* Disconnect mode */
+#if defined(CONFIG_SOC_SERIES_RZN2L)
+ GPIO_RZ_PIN_DISCONNECT(config->fsp_port, pin);
+#elif defined(CONFIG_SOC_SERIES_RZG3S)
ioport_config_data = 0;
+#endif /* CONFIG_SOC_SERIES_* */
} else if (!(flags & GPIO_OPEN_DRAIN)) {
/* PM register */
ioport_config_data &= GPIO_RZ_PIN_CONFIGURE_INPUT_OUTPUT_RESET;
@@ -136,7 +146,7 @@
if (flags & GPIO_PULL_UP) {
ioport_config_data |= IOPORT_CFG_PULLUP_ENABLE;
} else if (flags & GPIO_PULL_DOWN) {
- ioport_config_data |= IOPORT_CFG_PULLUP_ENABLE;
+ ioport_config_data |= IOPORT_CFG_PULLDOWN_ENABLE;
}
/* ISEL register */
@@ -147,10 +157,14 @@
}
/* Drive Ability register */
- ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_GET_DRIVE_ABILITY(flags);
-
+ ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_GET(flags);
+#if defined(CONFIG_SOC_SERIES_RZG3S)
/* Filter register, see in renesas-rz-gpio-ioport.h */
ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_GET_FILTER(flags);
+#elif defined(CONFIG_SOC_SERIES_RZN2L)
+ /* RSEL reg */
+ ioport_config_data |= IOPORT_CFG_REGION_NSAFETY;
+#endif /* CONFIG_SOC_SERIES_* */
} else {
return -ENOTSUP;
}
@@ -251,60 +265,92 @@
return 0;
}
-#define GPIO_RZ_HAS_INTERRUPT DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_gpio_int)
+#define GPIO_RZ_HAS_INTERRUPT \
+ DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_gpio_int) | \
+ DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_ext_irq)
#if GPIO_RZ_HAS_INTERRUPT
-static int gpio_rz_int_disable(const struct device *dev, uint8_t tint_num)
+static int gpio_rz_int_disable(const struct device *dev, const struct device *gpio_dev,
+ uint8_t int_num, gpio_pin_t pin)
{
- struct gpio_rz_tint_data *data = dev->data;
+#if defined(CONFIG_SOC_SERIES_RZG3S)
volatile uint32_t *tssr = &R_INTC_IM33->TSSR0;
volatile uint32_t *titsr = &R_INTC_IM33->TITSR0;
volatile uint32_t *tscr = &R_INTC_IM33->TSCR;
+ struct gpio_rz_int_data *data = dev->data;
/* Get register offset base on interrupt number. */
- tssr = &tssr[tint_num / 4];
- titsr = &titsr[tint_num / 16];
+ tssr = &tssr[int_num / 4];
+ titsr = &titsr[int_num / 16];
- irq_disable(GPIO_RZ_TINT_IRQ_GET(tint_num));
+ irq_disable(GPIO_RZ_TINT_IRQ_GET(int_num));
/* Disable interrupt and clear interrupt source. */
- *tssr &= ~(0xFF << GPIO_RZ_TSSR_OFFSET(tint_num));
+ *tssr &= ~(0xFF << GPIO_RZ_TSSR_OFFSET(int_num));
/* Reset interrupt dectect type to default. */
- *titsr &= ~(0x3 << GPIO_RZ_TITSR_OFFSET(tint_num));
+ *titsr &= ~(0x3 << GPIO_RZ_TITSR_OFFSET(int_num));
/* Clear interrupt detection status. */
- if (data->irq_set_edge & BIT(tint_num)) {
- *tscr &= ~BIT(tint_num);
- data->irq_set_edge &= ~BIT(tint_num);
+ if (data->irq_set_edge & BIT(int_num)) {
+ *tscr &= ~BIT(int_num);
+ data->irq_set_edge &= ~BIT(int_num);
}
- data->tint_data[tint_num].gpio_dev = NULL;
- data->tint_data[tint_num].pin = UINT8_MAX;
+
+ data->gpio_mapping[int_num].gpio_dev = NULL;
+ data->gpio_mapping[int_num].pin = UINT8_MAX;
+#elif defined(CONFIG_SOC_SERIES_RZN2L)
+ const struct gpio_rz_config *gpio_config = gpio_dev->config;
+ const struct device *eirq_dev = gpio_config->eirq_dev[pin];
+
+ if (device_is_ready(eirq_dev)) {
+ intc_rz_ext_irq_disable(eirq_dev);
+ }
+#endif /* CONFIG_SOC_SERIES_* */
return 0;
}
static int gpio_rz_int_enable(const struct device *int_dev, const struct device *gpio_dev,
- uint8_t tint_num, uint8_t irq_type, gpio_pin_t pin)
+ uint8_t int_num, uint8_t irq_type, gpio_pin_t pin)
{
- struct gpio_rz_tint_data *int_data = int_dev->data;
+ if (irq_type == GPIO_RZ_INT_UNSUPPORTED) {
+ return -ENOTSUP;
+ }
+
const struct gpio_rz_config *gpio_config = gpio_dev->config;
+
+#if defined(CONFIG_SOC_SERIES_RZG3S)
volatile uint32_t *tssr = &R_INTC_IM33->TSSR0;
volatile uint32_t *titsr = &R_INTC_IM33->TITSR0;
+ struct gpio_rz_int_data *int_data = int_dev->data;
- tssr = &tssr[tint_num / 4];
- titsr = &titsr[tint_num / 16];
+ tssr = &tssr[int_num / 4];
+ titsr = &titsr[int_num / 16];
/* Select interrupt detect type. */
- *titsr |= (irq_type << GPIO_RZ_TITSR_OFFSET(tint_num));
+ *titsr &= ~(3U << GPIO_RZ_TITSR_OFFSET(int_num));
+ *titsr |= (irq_type << GPIO_RZ_TITSR_OFFSET(int_num));
/* Select interrupt source base on port and pin number.*/
- *tssr |= (GPIO_RZ_TSSR_VAL(gpio_config->port_num, pin)) << GPIO_RZ_TSSR_OFFSET(tint_num);
+ *tssr |= (GPIO_RZ_TSSR_VAL(gpio_config->port_num, pin)) << GPIO_RZ_TSSR_OFFSET(int_num);
- if (irq_type == GPIO_RZ_TINT_EDGE_RISING || irq_type == GPIO_RZ_TINT_EDGE_FALLING) {
- int_data->irq_set_edge |= BIT(tint_num);
+ if (irq_type == GPIO_RZ_INT_EDGE_RISING || irq_type == GPIO_RZ_INT_EDGE_FALLING) {
+ int_data->irq_set_edge |= BIT(int_num);
/* Clear interrupt status. */
- R_INTC_IM33->TSCR &= ~BIT(tint_num);
+ R_INTC_IM33->TSCR &= ~BIT(int_num);
}
- int_data->tint_data[tint_num].gpio_dev = gpio_dev;
- int_data->tint_data[tint_num].pin = pin;
- irq_enable(GPIO_RZ_TINT_IRQ_GET(tint_num));
+ irq_enable(GPIO_RZ_TINT_IRQ_GET(int_num));
+ int_data->gpio_mapping[int_num].gpio_dev = gpio_dev;
+ int_data->gpio_mapping[int_num].pin = pin;
+#elif defined(CONFIG_SOC_SERIES_RZN2L)
+ const struct device *eirq_dev = gpio_config->eirq_dev[pin];
+ struct gpio_rz_data *gpio_data = gpio_dev->data;
+
+ gpio_data->pin[int_num] = pin;
+ if (device_is_ready(eirq_dev)) {
+ intc_rz_ext_irq_set_type(eirq_dev, irq_type);
+ intc_rz_ext_irq_enable(eirq_dev);
+ intc_rz_ext_irq_set_callback(eirq_dev, gpio_config->cb_list[int_num],
+ (void *)gpio_dev);
+ }
+#endif /* CONFIG_SOC_SERIES_* */
return 0;
}
@@ -315,54 +361,56 @@
const struct gpio_rz_config *config = dev->config;
struct gpio_rz_data *data = dev->data;
bsp_io_port_pin_t port_pin = config->fsp_port | pin;
- uint8_t tint_num = config->tint_num[pin];
+ uint8_t int_num = config->int_num[pin];
uint8_t irq_type = 0;
gpio_flags_t pre_flags = 0;
k_spinlock_key_t key;
+ int ret = 0;
- if (tint_num >= GPIO_RZ_MAX_TINT_NUM) {
- LOG_DEV_ERR(dev, "Invalid TINT interrupt:%d >= %d", tint_num, GPIO_RZ_MAX_TINT_NUM);
+ if (int_num >= GPIO_RZ_MAX_INT_NUM) {
+ LOG_DEV_ERR(dev, "Invalid interrupt:%d >= %d", int_num, GPIO_RZ_MAX_INT_NUM);
}
if (pin > config->ngpios) {
return -EINVAL;
}
- if (trig == GPIO_INT_TRIG_BOTH) {
- return -ENOTSUP;
- }
-
key = k_spin_lock(&data->lock);
if (mode == GPIO_INT_MODE_DISABLED) {
gpio_rz_pin_config_get_raw(port_pin, &pre_flags);
pre_flags |= GPIO_INT_DISABLE;
gpio_rz_pin_configure(dev, pin, pre_flags);
- gpio_rz_int_disable(config->int_dev, tint_num);
+ gpio_rz_int_disable(config->int_dev, dev, int_num, pin);
goto exit_unlock;
}
if (mode == GPIO_INT_MODE_EDGE) {
- irq_type = GPIO_RZ_TINT_EDGE_RISING;
if (trig == GPIO_INT_TRIG_LOW) {
- irq_type = GPIO_RZ_TINT_EDGE_FALLING;
+ irq_type = GPIO_RZ_INT_EDGE_FALLING;
+ } else if (trig == GPIO_INT_TRIG_HIGH) {
+ irq_type = GPIO_RZ_INT_EDGE_RISING;
+ } else if (trig == GPIO_INT_TRIG_BOTH) {
+ irq_type = GPIO_RZ_INT_BOTH_EDGE;
}
} else {
- irq_type = GPIO_RZ_TINT_LEVEL_HIGH;
if (trig == GPIO_INT_TRIG_LOW) {
- irq_type = GPIO_RZ_TINT_LEVEL_LOW;
+ irq_type = GPIO_RZ_INT_LEVEL_LOW;
+ } else if (trig == GPIO_INT_TRIG_HIGH) {
+ irq_type = GPIO_RZ_INT_LEVEL_HIGH;
}
}
- /* Set register ISEL */
- gpio_rz_pin_config_get_raw(port_pin, &pre_flags);
- pre_flags |= GPIO_INT_ENABLE;
- gpio_rz_pin_configure(dev, pin, pre_flags);
- gpio_rz_int_enable(config->int_dev, dev, tint_num, irq_type, pin);
+ ret = gpio_rz_int_enable(config->int_dev, dev, int_num, irq_type, pin);
+ if (ret == 0) {
+ gpio_rz_pin_config_get_raw(port_pin, &pre_flags);
+ pre_flags |= GPIO_INT_ENABLE;
+ gpio_rz_pin_configure(dev, pin, pre_flags);
+ }
exit_unlock:
k_spin_unlock(&data->lock, key);
- return 0;
+ return ret;
}
static int gpio_rz_manage_callback(const struct device *dev, struct gpio_callback *callback,
@@ -373,41 +421,37 @@
return gpio_manage_callback(&data->cb, callback, set);
}
-static void gpio_rz_isr(const struct device *dev, uint8_t pin)
+static void gpio_rz_isr(uint16_t irq, void *param)
{
- struct gpio_rz_data *data = dev->data;
-
- gpio_fire_callbacks(&data->cb, dev, BIT(pin));
-}
-
-static void gpio_rz_tint_isr(uint16_t irq, const struct device *dev)
-{
- struct gpio_rz_tint_data *data = dev->data;
+#if defined(CONFIG_SOC_SERIES_RZG3S)
+ const struct device *dev = param;
+ struct gpio_rz_int_data *int_data = dev->data;
volatile uint32_t *tscr = &R_INTC_IM33->TSCR;
- uint8_t tint_num;
- tint_num = irq - GPIO_RZ_TINT_IRQ_OFFSET;
-
- if (!(*tscr & BIT(tint_num))) {
- LOG_DEV_DBG(dev, "tint:%u spurious irq, status 0", tint_num);
+ if (!(*tscr & BIT(irq))) {
+ LOG_DEV_DBG(dev, "tint:%u spurious irq, status 0", irq);
return;
}
- if (data->irq_set_edge & BIT(tint_num)) {
- *tscr &= ~BIT(tint_num);
+ if (int_data->irq_set_edge & BIT(irq)) {
+ *tscr &= ~BIT(irq);
}
- gpio_rz_isr(data->tint_data[tint_num].gpio_dev, data->tint_data[tint_num].pin);
+ uint8_t pin = int_data->gpio_mapping[irq].pin;
+ const struct device *gpio_dev = int_data->gpio_mapping[irq].gpio_dev;
+ struct gpio_rz_data *gpio_data = gpio_dev->data;
+
+ gpio_fire_callbacks(&gpio_data->cb, gpio_dev, BIT(pin));
+#elif defined(CONFIG_SOC_SERIES_RZN2L)
+ const struct device *gpio_dev = (const struct device *)param;
+ struct gpio_rz_data *gpio_data = gpio_dev->data;
+ uint8_t pin = gpio_data->pin[irq];
+
+ gpio_fire_callbacks(&gpio_data->cb, gpio_dev, BIT(pin));
+#endif /* CONFIG_SOC_SERIES_* */
}
-static int gpio_rz_int_init(const struct device *dev)
-{
- const struct gpio_rz_tint_config *config = dev->config;
-
- config->gpio_int_init();
- return 0;
-}
-#endif
+#endif /* GPIO_RZ_HAS_INTERRUPT */
static DEVICE_API(gpio, gpio_rz_driver_api) = {
.pin_configure = gpio_rz_pin_configure,
@@ -426,18 +470,29 @@
};
/*Initialize GPIO interrupt device*/
-#define GPIO_RZ_TINT_ISR_DECLARE(irq_num, node_id) \
- static void rz_gpio_isr_##irq_num(void *param) \
+#define GPIO_RZ_ISR_DEFINE(irq_num, _) \
+ static void rz_gpio_isr##irq_num(void *param) \
{ \
- gpio_rz_tint_isr(DT_IRQ_BY_IDX(node_id, irq_num, irq), param); \
+ gpio_rz_isr(irq_num, param); \
}
-#define GPIO_RZ_TINT_ISR_INIT(node_id, irq_num) LISTIFY(irq_num, \
- GPIO_RZ_TINT_ISR_DECLARE, (), node_id)
+#define GPIO_RZ_ALL_ISR_DEFINE(irq_num) LISTIFY(irq_num, GPIO_RZ_ISR_DEFINE, ())
+
+#if defined(CONFIG_SOC_SERIES_RZG3S)
+
+#define GPIO_RZ_INT_DEFINE(inst) .int_dev = DEVICE_DT_GET_OR_NULL(DT_INST(0, renesas_rz_gpio_int))
+
+static int gpio_rz_int_init(const struct device *dev)
+{
+ const struct gpio_rz_tint_config *config = dev->config;
+
+ config->gpio_int_init();
+ return 0;
+}
#define GPIO_RZ_TINT_CONNECT(irq_num, node_id) \
IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, irq_num, irq), \
- DT_IRQ_BY_IDX(node_id, irq_num, priority), rz_gpio_isr_##irq_num, \
+ DT_IRQ_BY_IDX(node_id, irq_num, priority), rz_gpio_isr##irq_num, \
DEVICE_DT_GET(node_id), 0);
#define GPIO_RZ_TINT_CONNECT_FUNC(node_id) \
@@ -449,18 +504,42 @@
}
/* Initialize GPIO device*/
#define GPIO_RZ_INT_INIT(node_id) \
- GPIO_RZ_TINT_ISR_INIT(node_id, DT_NUM_IRQS(node_id)) \
+ GPIO_RZ_ALL_ISR_DEFINE(DT_NUM_IRQS(node_id)) \
GPIO_RZ_TINT_CONNECT_FUNC(node_id) \
static const struct gpio_rz_tint_config rz_gpio_tint_cfg_##node_id = { \
.gpio_int_init = rz_gpio_tint_connect_func##node_id, \
}; \
- static struct gpio_rz_tint_data rz_gpio_tint_data_##node_id = {}; \
+ static struct gpio_rz_int_data rz_gpio_tint_data_##node_id = {}; \
DEVICE_DT_DEFINE(node_id, gpio_rz_int_init, NULL, &rz_gpio_tint_data_##node_id, \
&rz_gpio_tint_cfg_##node_id, POST_KERNEL, \
UTIL_DEC(CONFIG_GPIO_INIT_PRIORITY), NULL);
-
DT_FOREACH_STATUS_OKAY(renesas_rz_gpio_int, GPIO_RZ_INT_INIT)
+#elif defined(CONFIG_SOC_SERIES_RZN2L) && GPIO_RZ_HAS_INTERRUPT
+
+GPIO_RZ_ALL_ISR_DEFINE(GPIO_RZ_MAX_INT_NUM)
+
+#define EIRQ_CB_GET(eirq_line, _) [eirq_line] = rz_gpio_isr##eirq_line
+
+#define EIRQ_DEV_LABEL_GET(inst, idx) CONCAT(irq, DT_INST_PROP_BY_IDX(inst, irqs, UTIL_INC(idx)))
+
+#define EIRQ_DEV_GET(idx, inst) \
+ COND_CODE_1(DT_INST_PROP_HAS_IDX(inst, irqs, idx), \
+ ([DT_INST_PROP_BY_IDX(inst, irqs, idx)] = \
+ DEVICE_DT_GET_OR_NULL(DT_NODELABEL(EIRQ_DEV_LABEL_GET(inst, idx))),), \
+ ())
+
+#define ALL_EIRQ_DEV_GET(inst) \
+ FOR_EACH_FIXED_ARG(EIRQ_DEV_GET, (), inst, \
+ LISTIFY(DT_INST_PROP_LEN_OR(inst, irqs, 0), VALUE_2X, (,)))
+
+#define GPIO_RZ_INT_DEFINE(inst) \
+ .eirq_dev = {ALL_EIRQ_DEV_GET(inst)}, \
+ .cb_list = {LISTIFY(GPIO_RZ_MAX_INT_NUM, EIRQ_CB_GET, (,))}
+#else
+#define GPIO_RZ_INT_DEFINE(inst)
+#endif /* CONFIG_SOC_SERIES_* */
+
#define VALUE_2X(i, _) UTIL_X2(i)
#define PIN_IRQ_GET(idx, inst) \
COND_CODE_1(DT_INST_PROP_HAS_IDX(inst, irqs, idx), \
@@ -489,9 +568,8 @@
.ngpios = (uint8_t)DT_INST_PROP(inst, ngpios), \
.fsp_cfg = &g_ioport_##inst##_cfg, \
.fsp_api = &g_ioport_on_ioport, \
- .int_dev = DEVICE_DT_GET_OR_NULL(DT_INST(0, renesas_rz_gpio_int)), \
- .tint_num = {PIN_IRQS_GET(inst)}, \
- }; \
+ .int_num = {PIN_IRQS_GET(inst)}, \
+ GPIO_RZ_INT_DEFINE(inst)}; \
static ioport_instance_ctrl_t g_ioport_##inst##_ctrl; \
static struct gpio_rz_data gpio_rz_##inst##_data = { \
.fsp_ctrl = &g_ioport_##inst##_ctrl, \
diff --git a/drivers/gpio/gpio_renesas_rz.h b/drivers/gpio/gpio_renesas_rz.h
index 6980450..e3ab3b8 100644
--- a/drivers/gpio/gpio_renesas_rz.h
+++ b/drivers/gpio/gpio_renesas_rz.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 Renesas Electronics Corporation
+ * Copyright (c) 2024-2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,35 +7,40 @@
#ifndef ZEPHYR_DRIVERS_GPIO_RENESAS_RZ_H_
#define ZEPHYR_DRIVERS_GPIO_RENESAS_RZ_H_
-#include <zephyr/dt-bindings/gpio/renesas-rz-gpio.h>
#include "r_ioport.h"
+#define GPIO_RZ_INT_UNSUPPORTED 0xF
+
+#if defined(CONFIG_SOC_SERIES_RZG3S)
+#include <zephyr/dt-bindings/gpio/renesas-rz-gpio.h>
+
#define GPIO_RZ_IOPORT_P_REG_BASE_GET (&R_GPIO->P_20)
#define GPIO_RZ_IOPORT_PM_REG_BASE_GET (&R_GPIO->PM_20)
-#define GPIO_RZ_REG_OFFSET(port, pin) (port + (pin / 4))
+#define GPIO_RZ_IOPORT_P_REG_GET(port, pin) (&GPIO_RZ_IOPORT_P_REG_BASE_GET[port + (pin / 4)])
+#define GPIO_RZ_IOPORT_PM_REG_GET(port, pin) (&GPIO_RZ_IOPORT_PM_REG_BASE_GET[port + (pin / 4)])
#define GPIO_RZ_P_VALUE_GET(value, pin) ((value >> pin) & 1U)
#define GPIO_RZ_PM_VALUE_GET(value, pin) ((value >> (pin * 2)) & 3U)
#define GPIO_RZ_MAX_PORT_NUM 19
-#define GPIO_RZ_MAX_TINT_NUM 32
+#define GPIO_RZ_MAX_INT_NUM 32
#define GPIO_RZ_TINT_IRQ_OFFSET 429
#define GPIO_RZ_TINT_IRQ_GET(tint_num) (tint_num + GPIO_RZ_TINT_IRQ_OFFSET)
-#define GPIO_RZ_TINT_EDGE_RISING 0x0
-#define GPIO_RZ_TINT_EDGE_FALLING 0x1
-#define GPIO_RZ_TINT_LEVEL_HIGH 0x2
-#define GPIO_RZ_TINT_LEVEL_LOW 0x3
+#define GPIO_RZ_INT_EDGE_RISING 0x0
+#define GPIO_RZ_INT_EDGE_FALLING 0x1
+#define GPIO_RZ_INT_LEVEL_HIGH 0x2
+#define GPIO_RZ_INT_LEVEL_LOW 0x3
+#define GPIO_RZ_INT_BOTH_EDGE GPIO_RZ_INT_UNSUPPORTED
#define GPIO_RZ_TSSR_VAL(port, pin) (0x80 | (gpio_rz_int[port] + pin))
#define GPIO_RZ_TSSR_OFFSET(irq) ((irq % 4) * 8)
#define GPIO_RZ_TITSR_OFFSET(irq) ((irq % 16) * 2)
#define GPIO_RZ_PIN_CONFIGURE_GET_FILTER(flag) (((flags >> RZG3S_GPIO_FILTER_SHIFT) & 0x1F) << 19U)
-#define GPIO_RZ_PIN_CONFIGURE_GET_DRIVE_ABILITY(flag) \
- (((flag >> RZG3S_GPIO_IOLH_SHIFT) & 0x3) << 10U)
+#define GPIO_RZ_PIN_CONFIGURE_GET(flag) (((flag >> RZG3S_GPIO_IOLH_SHIFT) & 0x3) << 10U)
#define GPIO_RZ_PIN_CONFIGURE_INT_ENABLE IOPORT_CFG_TINT_ENABLE
#define GPIO_RZ_PIN_CONFIGURE_INT_DISABLE (~(IOPORT_CFG_TINT_ENABLE))
@@ -43,4 +48,43 @@
static const uint8_t gpio_rz_int[GPIO_RZ_MAX_PORT_NUM] = {0, 4, 9, 13, 17, 23, 28, 33, 38, 43,
47, 52, 56, 58, 63, 66, 70, 72, 76};
+
+#elif defined(CONFIG_SOC_SERIES_RZN2L)
+#include <zephyr/dt-bindings/gpio/renesas-rztn-gpio.h>
+#define GPIO_RZ_IOPORT_P_REG_REGION_GET(p) (R_BSP_IoRegionGet(p) == BSP_IO_REGION_NOT_SAFE ? 1 : 0)
+#define GPIO_RZ_IOPORT_PM_REG_REGION_GET(p) (R_BSP_IoRegionGet(p) == BSP_IO_REGION_NOT_SAFE ? 1 : 0)
+
+#define GPIO_RZ_IOPORT_P_REG_BASE_GET(port, pin) \
+ (GPIO_RZ_IOPORT_P_REG_REGION_GET((port << 8U) | pin) == 1 ? &R_PORT_NSR->P[port] \
+ : &R_PORT_SR->P[port])
+
+#define GPIO_RZ_IOPORT_PM_REG_BASE_GET(port, pin) \
+ (GPIO_RZ_IOPORT_PM_REG_REGION_GET((port << 8U) | pin) == 1 ? &R_PORT_NSR->PM[port] \
+ : &R_PORT_SR->PM[port])
+
+#define GPIO_RZ_IOPORT_P_REG_GET(port, pin) (GPIO_RZ_IOPORT_P_REG_BASE_GET(port, pin))
+#define GPIO_RZ_IOPORT_PM_REG_GET(port, pin) (GPIO_RZ_IOPORT_PM_REG_BASE_GET(port, pin))
+
+#define GPIO_RZ_P_VALUE_GET(value, pin) ((value >> pin) & 1U)
+#define GPIO_RZ_PM_VALUE_GET(value, pin) ((value >> (pin * 2)) & 3U)
+
+#define GPIO_RZ_PIN_DISCONNECT(port, pin) \
+ *GPIO_RZ_IOPORT_PM_REG_GET((port >> 8U), pin) &= ~(3U << (pin * 2))
+
+#define GPIO_RZ_MAX_INT_NUM 16
+
+#define GPIO_RZ_INT_EDGE_FALLING 0x0
+#define GPIO_RZ_INT_EDGE_RISING 0x1
+#define GPIO_RZ_INT_BOTH_EDGE 0x2
+#define GPIO_RZ_INT_LEVEL_LOW 0x3
+#define GPIO_RZ_INT_LEVEL_HIGH GPIO_RZ_INT_UNSUPPORTED
+
+#define GPIO_RZ_PIN_CONFIGURE_GET(flag) (((flag >> RZTN_GPIO_DRCTL_SHIFT) & 0x33) << 8U)
+
+#define GPIO_RZ_PIN_CONFIGURE_INT_ENABLE (1U << 3)
+#define GPIO_RZ_PIN_CONFIGURE_INT_DISABLE (~(1U << 3))
+#define GPIO_RZ_PIN_CONFIGURE_INPUT_OUTPUT_RESET (~(0x3 << 2))
+
+#endif /* CONFIG_SOC_* */
+
#endif /* ZEPHYR_DRIVERS_GPIO_RENESAS_RZ_H_ */
diff --git a/dts/arm/renesas/rz/rzn/r9a07g084.dtsi b/dts/arm/renesas/rz/rzn/r9a07g084.dtsi
index b7d6ba7..9133045 100644
--- a/dts/arm/renesas/rz/rzn/r9a07g084.dtsi
+++ b/dts/arm/renesas/rz/rzn/r9a07g084.dtsi
@@ -242,6 +242,243 @@
pinctrl: pinctrl@800a0000 {
compatible = "renesas,rzn-pinctrl";
reg = <0x800a0000 0x1000 0x81030c00 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio0: gpio@0 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <8>;
+ reg = <0x0>;
+ status = "disabled";
+ };
+
+ gpio1: gpio@100 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0100>;
+ status = "disabled";
+ };
+
+ gpio2: gpio@200 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0200>;
+ status = "disabled";
+ };
+
+ gpio3: gpio@300 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <1 4>;
+ reg = <0x0300>;
+ status = "disabled";
+ };
+
+ gpio4: gpio@400 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <2 2>;
+ reg = <0x0400>;
+ status = "disabled";
+ };
+
+ gpio5: gpio@500 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0500>;
+ status = "disabled";
+ };
+
+ gpio6: gpio@600 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0600>;
+ status = "disabled";
+ };
+
+ gpio7: gpio@700 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <5>;
+ reg = <0x0700>;
+ status = "disabled";
+ };
+
+ gpio8: gpio@800 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <0 4>;
+ reg = <0x0800>;
+ status = "disabled";
+ };
+
+ gpio9: gpio@900 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0900>;
+ status = "disabled";
+ };
+
+ gpio10: gpio@a00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <5>;
+ reg = <0x0a00>;
+ status = "disabled";
+ };
+
+ gpio11: gpio@b00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <0>;
+ reg = <0x0b00>;
+ status = "disabled";
+ };
+
+ gpio12: gpio@c00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <5>;
+ gpio-reserved-ranges = <0 4>;
+ reg = <0x0c00>;
+ status = "disabled";
+ };
+
+ gpio13: gpio@d00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <0 2>;
+ reg = <0x0d00>;
+ status = "disabled";
+ };
+
+ gpio14: gpio@e00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0e00>;
+ status = "disabled";
+ };
+
+ gpio15: gpio@f00 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ reg = <0x0f00>;
+ status = "disabled";
+ };
+
+ gpio16: gpio@1000 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <4 1>;
+ reg = <0x1000>;
+ status = "disabled";
+ };
+
+ gpio17: gpio@1100 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <1 2>;
+ reg = <0x1100>;
+ status = "disabled";
+ };
+
+ gpio18: gpio@1200 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <7>;
+ reg = <0x1200>;
+ status = "disabled";
+ };
+
+ gpio19: gpio@1300 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <1>;
+ reg = <0x1300>;
+ status = "disabled";
+ };
+
+ gpio20: gpio@1400 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <5>;
+ gpio-reserved-ranges = <0 1>;
+ reg = <0x1400>;
+ status = "disabled";
+ };
+
+ gpio21: gpio@1500 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <0 1>;
+ reg = <0x1500>;
+ status = "disabled";
+ };
+
+ gpio22: gpio@1600 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <4>;
+ reg = <0x1600>;
+ status = "disabled";
+ };
+
+ gpio23: gpio@1700 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <8>;
+ gpio-reserved-ranges = <0 7>;
+ reg = <0x1700>;
+ status = "disabled";
+ };
+
+ gpio24: gpio@1800 {
+ compatible = "renesas,rz-gpio";
+ gpio-controller;
+ #gpio-cells= <2>;
+ ngpios = <3>;
+ reg = <0x1800>;
+ status = "disabled";
+ };
};
sci0: sci0@80001000 {
diff --git a/include/zephyr/dt-bindings/gpio/renesas-rztn-gpio.h b/include/zephyr/dt-bindings/gpio/renesas-rztn-gpio.h
new file mode 100644
index 0000000..22d4d3e
--- /dev/null
+++ b/include/zephyr/dt-bindings/gpio/renesas-rztn-gpio.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZTN_GPIO_H_
+#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZTN_GPIO_H_
+
+/*********************************RZTN*****************************************/
+
+/**
+ * @brief RZTN specific GPIO Flags
+ * The pin driving ability flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as
+ * follows:
+ * - Bit 9..8: Driving ability control
+ * - Bit 12: Schmitt trigger control
+ * - Bit 13: Slew rate control
+ * Example:
+ * Driving ability control: Middle
+ * Schmitt trigger control: Enabled
+ * Slew rate control: Slow
+ * gpio-consumer {
+ * out-gpios = <&port8 2 (GPIO_PULL_UP | RZTN_GPIO_CFG_SET(1, 1, 0))>;
+ * };
+ */
+
+/* GPIO DRCTL register */
+#define RZTN_GPIO_DRCTL_SHIFT 8U
+#define RZTN_GPIO_SCHMITT_TRIG_SHIFT 4U
+#define RZTN_GPIO_SLEW_RATE_SHIFT 5U
+#define RZTN_GPIO_DRCTL_SET(drive_ability, schmitt_trig, slew_rate) \
+ (((drive_ability) | ((schmitt_trig) << RZTN_GPIO_SCHMITT_TRIG_SHIFT) | \
+ ((slew_rate) << RZTN_GPIO_SLEW_RATE_SHIFT)) \
+ << RZTN_GPIO_DRCTL_SHIFT)
+
+/*******************************************************************************/
+
+#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZTN_GPIO_H_ */
diff --git a/tests/drivers/gpio/gpio_basic_api/boards/rzn2l_rsk.overlay b/tests/drivers/gpio/gpio_basic_api/boards/rzn2l_rsk.overlay
new file mode 100644
index 0000000..85624d2
--- /dev/null
+++ b/tests/drivers/gpio/gpio_basic_api/boards/rzn2l_rsk.overlay
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/ {
+ resources {
+ compatible = "test-gpio-basic-api";
+ out-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+ in-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&pinctrl {
+ input_test: input_test {
+ group1 {
+ pinmux = <RZN_PINMUX(PORT_02, 0, 0)>;
+ input-enable;
+ };
+ };
+};
+
+&irq4 {
+ trigger-type = "falling";
+ pinctrl-0 = <&input_test>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&gpio2 {
+ irqs = <0 4>;
+ status = "okay";
+};