drivers: gpio: Add support for RZ/G3S
This adds GPIO driver for Renesas RZ/G3S. Signed-off-by: Quang Le <quang.le.eb@bp.renesas.com> Signed-off-by: Nhut Nguyen <nhut.nguyen.kc@renesas.com> Signed-off-by: Binh Nguyen <binh.nguyen.xw@renesas.com>
This commit is contained in:
parent
c1fb75b616
commit
cd495936cf
13 changed files with 911 additions and 0 deletions
|
|
@ -75,6 +75,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_PSOC6 gpio_psoc6.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_GPIO_RA_IOPORT gpio_renesas_ra_ioport.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RCAR gpio_rcar.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RENESAS_RA gpio_renesas_ra.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RENESAS_RZ gpio_renesas_rz.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RP1 gpio_rp1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RPI_PICO gpio_rpi_pico.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_RT1718S gpio_rt1718s.c)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ source "drivers/gpio/Kconfig.psoc6"
|
|||
source "drivers/gpio/Kconfig.rcar"
|
||||
source "drivers/gpio/Kconfig.renesas_ra"
|
||||
source "drivers/gpio/Kconfig.renesas_ra_ioport"
|
||||
source "drivers/gpio/Kconfig.renesas_rz"
|
||||
source "drivers/gpio/Kconfig.rp1"
|
||||
source "drivers/gpio/Kconfig.rpi_pico"
|
||||
source "drivers/gpio/Kconfig.rt1718s"
|
||||
|
|
|
|||
10
drivers/gpio/Kconfig.renesas_rz
Normal file
10
drivers/gpio/Kconfig.renesas_rz
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config GPIO_RENESAS_RZ
|
||||
bool "Renesas RZ series gpio driver"
|
||||
default y
|
||||
depends on DT_HAS_RENESAS_RZ_GPIO_ENABLED
|
||||
select USE_RZ_FSP_IOPORT
|
||||
help
|
||||
Enable Renesas RZ series gpio driver.
|
||||
502
drivers/gpio/gpio_renesas_rz.c
Normal file
502
drivers/gpio/gpio_renesas_rz.c
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT renesas_rz_gpio
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/irq.h>
|
||||
#include "r_ioport.h"
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
#include "gpio_renesas_rz.h"
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(rz_gpio, CONFIG_GPIO_LOG_LEVEL);
|
||||
|
||||
#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__)
|
||||
#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:" #format, (dev)->name, ##__VA_ARGS__)
|
||||
|
||||
struct gpio_rz_config {
|
||||
struct gpio_driver_config common;
|
||||
uint8_t ngpios;
|
||||
uint8_t port_num;
|
||||
bsp_io_port_t fsp_port;
|
||||
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];
|
||||
};
|
||||
|
||||
struct gpio_rz_data {
|
||||
struct gpio_driver_data common;
|
||||
sys_slist_t cb;
|
||||
ioport_instance_ctrl_t *fsp_ctrl;
|
||||
struct k_spinlock lock;
|
||||
};
|
||||
|
||||
struct gpio_rz_tint_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];
|
||||
uint32_t irq_set_edge;
|
||||
};
|
||||
|
||||
struct gpio_rz_tint_config {
|
||||
void (*gpio_int_init)(void);
|
||||
};
|
||||
|
||||
static int gpio_rz_pin_config_get_raw(bsp_io_port_pin_t port_pin, uint32_t *flags);
|
||||
|
||||
#ifdef CONFIG_GPIO_GET_CONFIG
|
||||
static int gpio_rz_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *flags)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
bsp_io_port_pin_t port_pin = config->fsp_port | pin;
|
||||
|
||||
gpio_rz_pin_config_get_raw(port_pin, flags);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get previous pin's configuration, used by pin_configure/pin_interrupt_configure api */
|
||||
static int gpio_rz_pin_config_get_raw(bsp_io_port_pin_t port_pin, uint32_t *flags)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (p_value) {
|
||||
*flags |= GPIO_OUTPUT_INIT_HIGH;
|
||||
} else {
|
||||
*flags |= GPIO_OUTPUT_INIT_LOW;
|
||||
}
|
||||
|
||||
*flags |= ((pm_value << 16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
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;
|
||||
uint32_t ioport_config_data = 0;
|
||||
gpio_flags_t pre_flags;
|
||||
fsp_err_t err;
|
||||
|
||||
gpio_rz_pin_config_get_raw(port_pin, &pre_flags);
|
||||
|
||||
if (!flags) {
|
||||
/* Disconnect mode */
|
||||
ioport_config_data = 0;
|
||||
} else if (!(flags & GPIO_OPEN_DRAIN)) {
|
||||
/* PM register */
|
||||
ioport_config_data &= GPIO_RZ_PIN_CONFIGURE_INPUT_OUTPUT_RESET;
|
||||
if (flags & GPIO_INPUT) {
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
ioport_config_data |= IOPORT_CFG_PORT_DIRECTION_OUTPUT_INPUT;
|
||||
} else {
|
||||
ioport_config_data |= IOPORT_CFG_PORT_DIRECTION_INPUT;
|
||||
}
|
||||
} else if (flags & GPIO_OUTPUT) {
|
||||
ioport_config_data &= GPIO_RZ_PIN_CONFIGURE_INPUT_OUTPUT_RESET;
|
||||
ioport_config_data |= IOPORT_CFG_PORT_DIRECTION_OUTPUT;
|
||||
}
|
||||
/* P register */
|
||||
if (!(flags & (GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOW))) {
|
||||
flags |= pre_flags & (GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOW);
|
||||
}
|
||||
|
||||
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||
ioport_config_data |= IOPORT_CFG_PORT_OUTPUT_HIGH;
|
||||
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||
ioport_config_data &= ~(IOPORT_CFG_PORT_OUTPUT_HIGH);
|
||||
}
|
||||
/* PUPD register */
|
||||
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;
|
||||
}
|
||||
|
||||
/* ISEL register */
|
||||
if (flags & GPIO_INT_ENABLE) {
|
||||
ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_INT_ENABLE;
|
||||
} else if (flags & GPIO_INT_DISABLE) {
|
||||
ioport_config_data &= GPIO_RZ_PIN_CONFIGURE_INT_DISABLE;
|
||||
}
|
||||
|
||||
/* Drive Ability register */
|
||||
ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_GET_DRIVE_ABILITY(flags);
|
||||
|
||||
/* Filter register, see in renesas-rz-gpio-ioport.h */
|
||||
ioport_config_data |= GPIO_RZ_PIN_CONFIGURE_GET_FILTER(flags);
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
err = config->fsp_api->pinCfg(data->fsp_ctrl, port_pin, ioport_config_data);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_port_get_raw(const struct device *dev, gpio_port_value_t *value)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
fsp_err_t err;
|
||||
ioport_size_t port_value;
|
||||
|
||||
err = config->fsp_api->portRead(data->fsp_ctrl, config->fsp_port, &port_value);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
*value = (gpio_port_value_t)port_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
|
||||
gpio_port_value_t value)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
ioport_size_t port_mask = (ioport_size_t)mask;
|
||||
ioport_size_t port_value = (ioport_size_t)value;
|
||||
fsp_err_t err;
|
||||
|
||||
err = config->fsp_api->portWrite(data->fsp_ctrl, config->fsp_port, port_value, port_mask);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
ioport_size_t mask = (ioport_size_t)pins;
|
||||
ioport_size_t value = (ioport_size_t)pins;
|
||||
fsp_err_t err;
|
||||
|
||||
err = config->fsp_api->portWrite(data->fsp_ctrl, config->fsp_port, value, mask);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
ioport_size_t mask = (ioport_size_t)pins;
|
||||
ioport_size_t value = 0x00;
|
||||
fsp_err_t err;
|
||||
|
||||
err = config->fsp_api->portWrite(data->fsp_ctrl, config->fsp_port, value, mask);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_rz_config *config = dev->config;
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
bsp_io_port_pin_t port_pin;
|
||||
gpio_flags_t pre_flags;
|
||||
ioport_size_t value = 0;
|
||||
fsp_err_t err;
|
||||
|
||||
for (uint8_t idx = 0; idx < config->ngpios; idx++) {
|
||||
if (pins & (1U << idx)) {
|
||||
port_pin = config->fsp_port | idx;
|
||||
gpio_rz_pin_config_get_raw(port_pin, &pre_flags);
|
||||
if (pre_flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||
value &= (1U << idx);
|
||||
} else if (pre_flags & GPIO_OUTPUT_INIT_LOW) {
|
||||
value |= (1U << idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
err = config->fsp_api->portWrite(data->fsp_ctrl, config->fsp_port, value,
|
||||
(ioport_size_t)pins);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GPIO_RZ_HAS_INTERRUPT DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_gpio_int)
|
||||
|
||||
#if GPIO_RZ_HAS_INTERRUPT
|
||||
static int gpio_rz_int_disable(const struct device *dev, uint8_t tint_num)
|
||||
{
|
||||
struct gpio_rz_tint_data *data = dev->data;
|
||||
volatile uint32_t *tssr = &R_INTC_IM33->TSSR0;
|
||||
volatile uint32_t *titsr = &R_INTC_IM33->TITSR0;
|
||||
volatile uint32_t *tscr = &R_INTC_IM33->TSCR;
|
||||
|
||||
/* Get register offset base on interrupt number. */
|
||||
tssr = &tssr[tint_num / 4];
|
||||
titsr = &titsr[tint_num / 16];
|
||||
|
||||
irq_disable(GPIO_RZ_TINT_IRQ_GET(tint_num));
|
||||
/* Disable interrupt and clear interrupt source. */
|
||||
*tssr &= ~(0xFF << GPIO_RZ_TSSR_OFFSET(tint_num));
|
||||
/* Reset interrupt dectect type to default. */
|
||||
*titsr &= ~(0x3 << GPIO_RZ_TITSR_OFFSET(tint_num));
|
||||
|
||||
/* Clear interrupt detection status. */
|
||||
if (data->irq_set_edge & BIT(tint_num)) {
|
||||
*tscr &= ~BIT(tint_num);
|
||||
data->irq_set_edge &= ~BIT(tint_num);
|
||||
}
|
||||
data->tint_data[tint_num].gpio_dev = NULL;
|
||||
data->tint_data[tint_num].pin = UINT8_MAX;
|
||||
|
||||
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)
|
||||
{
|
||||
struct gpio_rz_tint_data *int_data = int_dev->data;
|
||||
const struct gpio_rz_config *gpio_config = gpio_dev->config;
|
||||
volatile uint32_t *tssr = &R_INTC_IM33->TSSR0;
|
||||
volatile uint32_t *titsr = &R_INTC_IM33->TITSR0;
|
||||
|
||||
tssr = &tssr[tint_num / 4];
|
||||
titsr = &titsr[tint_num / 16];
|
||||
/* Select interrupt detect type. */
|
||||
*titsr |= (irq_type << GPIO_RZ_TITSR_OFFSET(tint_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);
|
||||
|
||||
if (irq_type == GPIO_RZ_TINT_EDGE_RISING || irq_type == GPIO_RZ_TINT_EDGE_FALLING) {
|
||||
int_data->irq_set_edge |= BIT(tint_num);
|
||||
/* Clear interrupt status. */
|
||||
R_INTC_IM33->TSCR &= ~BIT(tint_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));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
|
||||
enum gpio_int_mode mode, enum gpio_int_trig trig)
|
||||
{
|
||||
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 irq_type = 0;
|
||||
gpio_flags_t pre_flags = 0;
|
||||
k_spinlock_key_t key;
|
||||
|
||||
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 (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);
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
irq_type = GPIO_RZ_TINT_LEVEL_HIGH;
|
||||
if (trig == GPIO_INT_TRIG_LOW) {
|
||||
irq_type = GPIO_RZ_TINT_LEVEL_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
exit_unlock:
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_rz_manage_callback(const struct device *dev, struct gpio_callback *callback,
|
||||
bool set)
|
||||
{
|
||||
struct gpio_rz_data *data = dev->data;
|
||||
|
||||
return gpio_manage_callback(&data->cb, callback, set);
|
||||
}
|
||||
|
||||
static void gpio_rz_isr(const struct device *dev, uint8_t pin)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->irq_set_edge & BIT(tint_num)) {
|
||||
*tscr &= ~BIT(tint_num);
|
||||
}
|
||||
|
||||
gpio_rz_isr(data->tint_data[tint_num].gpio_dev, data->tint_data[tint_num].pin);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
static const struct gpio_driver_api gpio_rz_driver_api = {
|
||||
.pin_configure = gpio_rz_pin_configure,
|
||||
#ifdef CONFIG_GPIO_GET_CONFIG
|
||||
.pin_get_config = gpio_rz_pin_get_config,
|
||||
#endif
|
||||
.port_get_raw = gpio_rz_port_get_raw,
|
||||
.port_set_masked_raw = gpio_rz_port_set_masked_raw,
|
||||
.port_set_bits_raw = gpio_rz_port_set_bits_raw,
|
||||
.port_clear_bits_raw = gpio_rz_port_clear_bits_raw,
|
||||
.port_toggle_bits = gpio_rz_port_toggle_bits,
|
||||
#if GPIO_RZ_HAS_INTERRUPT
|
||||
.pin_interrupt_configure = gpio_rz_pin_interrupt_configure,
|
||||
.manage_callback = gpio_rz_manage_callback,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*Initialize GPIO interrupt device*/
|
||||
#define GPIO_RZ_TINT_ISR_DECLARE(irq_num, node_id) \
|
||||
static void rz_gpio_isr_##irq_num(void *param) \
|
||||
{ \
|
||||
gpio_rz_tint_isr(DT_IRQ_BY_IDX(node_id, irq_num, irq), param); \
|
||||
}
|
||||
|
||||
#define GPIO_RZ_TINT_ISR_INIT(node_id, irq_num) LISTIFY(irq_num, \
|
||||
GPIO_RZ_TINT_ISR_DECLARE, (), node_id)
|
||||
|
||||
#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, \
|
||||
DEVICE_DT_GET(node_id), 0);
|
||||
|
||||
#define GPIO_RZ_TINT_CONNECT_FUNC(node_id) \
|
||||
static void rz_gpio_tint_connect_func##node_id(void) \
|
||||
{ \
|
||||
LISTIFY(DT_NUM_IRQS(node_id), \
|
||||
GPIO_RZ_TINT_CONNECT, (;), \
|
||||
node_id) \
|
||||
}
|
||||
/* Initialize GPIO device*/
|
||||
#define GPIO_RZ_INT_INIT(node_id) \
|
||||
GPIO_RZ_TINT_ISR_INIT(node_id, 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 = {}; \
|
||||
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)
|
||||
|
||||
#define VALUE_2X(i, _) UTIL_X2(i)
|
||||
#define PIN_IRQ_GET(idx, inst) \
|
||||
COND_CODE_1(DT_INST_PROP_HAS_IDX(inst, irqs, idx), \
|
||||
([DT_INST_PROP_BY_IDX(inst, irqs, idx)] = \
|
||||
DT_INST_PROP_BY_IDX(inst, irqs, UTIL_INC(idx)),), \
|
||||
())
|
||||
|
||||
#define PIN_IRQS_GET(inst) \
|
||||
FOR_EACH_FIXED_ARG(PIN_IRQ_GET, (), inst, \
|
||||
LISTIFY(DT_INST_PROP_LEN_OR(inst, irqs, 0), VALUE_2X, (,)))
|
||||
|
||||
#define RZG_GPIO_PORT_INIT(inst) \
|
||||
static ioport_cfg_t g_ioport_##inst##_cfg = { \
|
||||
.number_of_pins = 0, \
|
||||
.p_pin_cfg_data = NULL, \
|
||||
.p_extend = NULL, \
|
||||
}; \
|
||||
static const struct gpio_rz_config gpio_rz_##inst##_config = { \
|
||||
.common = \
|
||||
{ \
|
||||
.port_pin_mask = \
|
||||
(gpio_port_pins_t)GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
|
||||
}, \
|
||||
.fsp_port = (uint32_t)DT_INST_REG_ADDR(inst), \
|
||||
.port_num = (uint8_t)DT_NODE_CHILD_IDX(DT_DRV_INST(inst)), \
|
||||
.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)}, \
|
||||
}; \
|
||||
static ioport_instance_ctrl_t g_ioport_##inst##_ctrl; \
|
||||
static struct gpio_rz_data gpio_rz_##inst##_data = { \
|
||||
.fsp_ctrl = &g_ioport_##inst##_ctrl, \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &gpio_rz_##inst##_data, &gpio_rz_##inst##_config, \
|
||||
POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, &gpio_rz_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(RZG_GPIO_PORT_INIT)
|
||||
46
drivers/gpio/gpio_renesas_rz.h
Normal file
46
drivers/gpio/gpio_renesas_rz.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#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_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_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_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_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_INT_ENABLE IOPORT_CFG_TINT_ENABLE
|
||||
#define GPIO_RZ_PIN_CONFIGURE_INT_DISABLE (~(IOPORT_CFG_TINT_ENABLE))
|
||||
#define GPIO_RZ_PIN_CONFIGURE_INPUT_OUTPUT_RESET (~(0x3 << 2))
|
||||
|
||||
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};
|
||||
#endif /* ZEPHYR_DRIVERS_GPIO_RENESAS_RZ_H_ */
|
||||
|
|
@ -36,6 +36,193 @@
|
|||
compatible = "renesas,rzg-pinctrl";
|
||||
reg = <0x41030000 DT_SIZE_K(64)>;
|
||||
reg-names = "pinctrl";
|
||||
|
||||
gpio: gpio-common {
|
||||
compatible = "renesas,rz-gpio-int";
|
||||
interrupts =
|
||||
<429 10>, <430 10>, <431 10>, <432 10>,
|
||||
<433 10>, <434 10>, <435 10>, <436 10>,
|
||||
<437 10>, <438 10>, <439 10>, <440 10>,
|
||||
<441 10>, <442 10>, <443 10>, <444 10>,
|
||||
<445 10>, <446 10>, <447 10>, <448 10>,
|
||||
<449 10>, <450 10>, <451 10>, <452 10>,
|
||||
<453 10>, <454 10>, <455 10>, <456 10>,
|
||||
<457 10>, <458 10>, <459 10>, <460 10>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
gpio0: gpio@0 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio1: gpio@1000 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x1000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio2: gpio@1100 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x1100>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio3: gpio@1200 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x1200>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio4: gpio@1300 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <6>;
|
||||
reg = <0x1300>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio5: gpio@100 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x100>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio6: gpio@200 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x200>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio7: gpio@1400 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x1400>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio8: gpio@1500 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x1500>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio9: gpio@1600 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x1600>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio10: gpio@1700 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x1700>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio11: gpio@300 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x300>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio12: gpio@400 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <2>;
|
||||
reg = <0x400>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio13: gpio@500 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <5>;
|
||||
reg = <0x500>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio14: gpio@600 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <3>;
|
||||
reg = <0x600>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio15: gpio@700 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x700>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio16: gpio@800 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <2>;
|
||||
reg = <0x800>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio17: gpio@900 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells= <2>;
|
||||
ngpios = <4>;
|
||||
reg = <0x900>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio18: gpio@A00 {
|
||||
compatible = "renesas,rz-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells=<2>;
|
||||
ngpios = <6>;
|
||||
reg = <0xA00>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
scif0: serial@4004b800 {
|
||||
|
|
|
|||
18
dts/bindings/gpio/renesas,rz-gpio-int.yaml
Normal file
18
dts/bindings/gpio/renesas,rz-gpio-int.yaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas RZ GPIO Interrupt
|
||||
|
||||
compatible: "renesas,rz-gpio-int"
|
||||
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
43
dts/bindings/gpio/renesas,rz-gpio.yaml
Normal file
43
dts/bindings/gpio/renesas,rz-gpio.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Reneses RZ GPIO controller node.
|
||||
Sample of usage:
|
||||
gpio-consumer{
|
||||
out-gpio = <&gpio8 2 (GPIO_PULL_UP);
|
||||
};
|
||||
&gpio8{
|
||||
irq = <2 10>, <9 1>;
|
||||
status = "okay";
|
||||
};
|
||||
Example above will configure pin 2 port 8:
|
||||
- Using interrupt TINT10
|
||||
- Set Pullup
|
||||
|
||||
|
||||
compatible: "renesas,rz-gpio"
|
||||
|
||||
include:
|
||||
- name: base.yaml
|
||||
property-allowlist:
|
||||
- status
|
||||
- reg
|
||||
- label
|
||||
- name: gpio-controller.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
description: GPIO port number
|
||||
|
||||
irqs:
|
||||
type: array
|
||||
description: pin-irq pairs
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
||||
43
include/zephyr/dt-bindings/gpio/renesas-rz-gpio.h
Normal file
43
include/zephyr/dt-bindings/gpio/renesas-rz-gpio.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZ_GPIO_H_
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZ_GPIO_H_
|
||||
|
||||
/*********************************RZG3S*****************************************/
|
||||
|
||||
/**
|
||||
* @brief RZ G3S 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: Pin driving ability value
|
||||
* - Bit 11..10: Digital Noise Filter Clock Selection value
|
||||
* - Bit 13..12: Digital Noise Filter Number value
|
||||
* - Bit 14: Digital Noise Filter ON/OFF
|
||||
* example:
|
||||
* gpio-consumer {
|
||||
* out-gpios = <&port8 2 (GPIO_PULL_UP | RZG3S_GPIO_FILTER_SET(1, 3, 3))>;
|
||||
* };
|
||||
* gpio-consumer {
|
||||
* out-gpios = <&port8 2 (GPIO_PULL_UP | RZG3S_GPIO_IOLH_SET(2))>;
|
||||
* };
|
||||
*/
|
||||
|
||||
/* GPIO drive IOLH */
|
||||
#define RZG3S_GPIO_IOLH_SHIFT 7U
|
||||
#define RZG3S_GPIO_IOLH_SET(iolh_val) (iolh_val << RZG3S_GPIO_IOLH_SHIFT)
|
||||
|
||||
/* GPIO filter */
|
||||
#define RZG3S_GPIO_FILTER_SHIFT 9U
|
||||
#define RZG3S_GPIO_FILNUM_SHIFT 1U
|
||||
#define RZG3S_GPIO_FILCLKSEL_SHIFT 3U
|
||||
#define RZG3S_GPIO_FILTER_SET(fillonoff, filnum, filclksel) \
|
||||
(((fillonoff) | ((filnum) << RZG3S_GPIO_FILNUM_SHIFT) | \
|
||||
((filclksel) << RZG3S_GPIO_FILCLKSEL_SHIFT)) \
|
||||
<< RZG3S_GPIO_FILTER_SHIFT)
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZ_GPIO_H_ */
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&gpio{
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio18{
|
||||
irqs = <0 16>;
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
led0 = &led_0;
|
||||
};
|
||||
|
||||
gpio-led {
|
||||
compatible = "gpio-leds";
|
||||
led_0: led_0 {
|
||||
gpios = <&gpio13 1 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gpio{
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio13 {
|
||||
irqs = <1 1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
CONFIG_SKIP_PULL_TEST=y
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
resources {
|
||||
compatible = "test-gpio-basic-api";
|
||||
out-gpios = <&gpio8 2 GPIO_ACTIVE_HIGH>;
|
||||
in-gpios = <&gpio8 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio{
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio8{
|
||||
irqs = <3 20>;
|
||||
status = "okay";
|
||||
};
|
||||
Loading…
Reference in a new issue