Browse Source

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>
pull/87098/head
Quang Le 5 months ago committed by Benjamin Cabé
parent
commit
b7f99ffbdd
  1. 268
      drivers/gpio/gpio_renesas_rz.c
  2. 64
      drivers/gpio/gpio_renesas_rz.h
  3. 237
      dts/arm/renesas/rz/rzn/r9a07g084.dtsi
  4. 38
      include/zephyr/dt-bindings/gpio/renesas-rztn-gpio.h
  5. 33
      tests/drivers/gpio/gpio_basic_api/boards/rzn2l_rsk.overlay

268
drivers/gpio/gpio_renesas_rz.c

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 @@ struct gpio_rz_config { @@ -28,7 +32,12 @@ struct gpio_rz_config {
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 @@ struct gpio_rz_data { @@ -36,15 +45,18 @@ struct gpio_rz_data {
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 @@ static int gpio_rz_pin_config_get_raw(bsp_io_port_pin_t port_pin, uint32_t *flag @@ -70,18 +82,12 @@ static int gpio_rz_pin_config_get_raw(bsp_io_port_pin_t port_pin, uint32_t *flag
{
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 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ @@ -108,7 +114,11 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_
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 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ @@ -136,7 +146,7 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_
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 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_ @@ -147,10 +157,14 @@ static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_
}
/* 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 @@ static int gpio_rz_port_toggle_bits(const struct device *dev, gpio_port_pins_t p @@ -251,60 +265,92 @@ static int gpio_rz_port_toggle_bits(const struct device *dev, gpio_port_pins_t p
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 @@ static int gpio_rz_pin_interrupt_configure(const struct device *dev, gpio_pin_t @@ -315,54 +361,56 @@ static int gpio_rz_pin_interrupt_configure(const struct device *dev, gpio_pin_t
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 @@ static int gpio_rz_manage_callback(const struct device *dev, struct gpio_callbac @@ -373,41 +421,37 @@ static int gpio_rz_manage_callback(const struct device *dev, struct gpio_callbac
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;
static int gpio_rz_int_init(const struct device *dev)
{
const struct gpio_rz_tint_config *config = dev->config;
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];
config->gpio_int_init();
return 0;
gpio_fire_callbacks(&gpio_data->cb, gpio_dev, BIT(pin));
#endif /* CONFIG_SOC_SERIES_* */
}
#endif
#endif /* GPIO_RZ_HAS_INTERRUPT */
static DEVICE_API(gpio, gpio_rz_driver_api) = {
.pin_configure = gpio_rz_pin_configure,
@ -426,18 +470,29 @@ static DEVICE_API(gpio, gpio_rz_driver_api) = { @@ -426,18 +470,29 @@ static DEVICE_API(gpio, gpio_rz_driver_api) = {
};
/*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 @@ static DEVICE_API(gpio, gpio_rz_driver_api) = { @@ -449,18 +504,42 @@ static DEVICE_API(gpio, gpio_rz_driver_api) = {
}
/* 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 @@ DT_FOREACH_STATUS_OKAY(renesas_rz_gpio_int, GPIO_RZ_INT_INIT) @@ -489,9 +568,8 @@ DT_FOREACH_STATUS_OKAY(renesas_rz_gpio_int, GPIO_RZ_INT_INIT)
.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, \

64
drivers/gpio/gpio_renesas_rz.h

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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 @@ @@ -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_ */

237
dts/arm/renesas/rz/rzn/r9a07g084.dtsi

@ -242,6 +242,243 @@ @@ -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 {

38
include/zephyr/dt-bindings/gpio/renesas-rztn-gpio.h

@ -0,0 +1,38 @@ @@ -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_ */

33
tests/drivers/gpio/gpio_basic_api/boards/rzn2l_rsk.overlay

@ -0,0 +1,33 @@ @@ -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";
};
Loading…
Cancel
Save