Commit b7f99ffb authored by Quang Le's avatar Quang Le Committed by Benjamin Cabé
Browse files

drivers: gpio: Add support for RZ/N2L



Add GPIO driver for RZ/N2L

Signed-off-by: default avatarQuang Le <quang.le.eb@bp.renesas.com>
Signed-off-by: default avatarNhut Nguyen <nhut.nguyen.kc@renesas.com>
parent 020a0d31
Loading
Loading
Loading
Loading
+173 −95
Original line number Diff line number Diff line
/*
 * 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 @@ 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 {
	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
{
	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_

	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_
		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_
		}

		/* 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
	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);
	}
	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);
	}
	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));
#endif /* CONFIG_SOC_SERIES_* */

	return 0;
}
@@ -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 */
	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);
	gpio_rz_int_enable(config->int_dev, dev, tint_num, irq_type, pin);
	}

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
	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) = {
};

/*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) = {
	}
/* 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)
		.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,                                               \
+54 −10
Original line number Diff line number Diff line
/*
 * 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_ */
+237 −0

File changed.

Preview size limit exceeded, changes collapsed.

+38 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
/*
 * 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";
};