diff --git a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts index ddada360b99..2568a542b5e 100644 --- a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts +++ b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts @@ -17,6 +17,30 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; }; + + aliases { + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led0 { + gpios = <&gpio19 6 0>; + label = "led0"; + }; + led1: led1 { + gpios = <&gpio19 4 0>; + label = "led1"; + }; + led2: led2 { + gpios = <&gpio20 0 0>; + label = "led2"; + }; + led3: led3 { + gpios = <&gpio23 4 0>; + label = "led3"; + }; + }; }; diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 19c9d3e976c..0e94d78dba3 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -87,6 +87,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SEDI gpio_sedi.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_BCM2711 gpio_bcm2711.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RA gpio_ra.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_RZT2M gpio_rzt2m.c) if (CONFIG_GPIO_EMUL_SDL) zephyr_library_sources(gpio_emul_sdl.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 92d7b0587e9..7ae1a8d0d93 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -214,4 +214,6 @@ source "drivers/gpio/Kconfig.bcm2711" source "drivers/gpio/Kconfig.ra" +source "drivers/gpio/Kconfig.rzt2m" + endif # GPIO diff --git a/drivers/gpio/Kconfig.rzt2m b/drivers/gpio/Kconfig.rzt2m new file mode 100644 index 00000000000..d9cb6b1e867 --- /dev/null +++ b/drivers/gpio/Kconfig.rzt2m @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_RZT2M + bool "Renesas RZT2M GPIO" + default y + depends on DT_HAS_RENESAS_RZT2M_GPIO_ENABLED + help + Enable Renesas RZT2M GPIO driver. diff --git a/drivers/gpio/gpio_rzt2m.c b/drivers/gpio/gpio_rzt2m.c new file mode 100644 index 00000000000..c2bfd1a4acd --- /dev/null +++ b/drivers/gpio/gpio_rzt2m.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzt2m_gpio + +#include +#include +#include +#include +#include +#include +#include + +#define PMm_OFFSET 0x200 +#define PINm_OFFSET 0x800 +#define DRCTLm_OFFSET 0xa00 + +#define DRIVE_SHIFT 0 +#define SCHMITT_TRIGGER_SHIFT 4 +#define SLEW_RATE_SHIFT 5 + +#define PULL_SHIFT 2 +#define PULL_NONE (0 << PULL_SHIFT) +#define PULL_UP (1 << PULL_SHIFT) +#define PULL_DOWN (2 << PULL_SHIFT) + +struct rzt2m_gpio_config { + struct gpio_driver_config common; + uint8_t *port_nsr; + uint8_t *ptadr; + uint8_t port; +}; + +struct rzt2m_gpio_data { + struct gpio_driver_data common; +}; + +static void rzt2m_gpio_unlock(void) +{ + rzt2m_unlock_prcrn(PRCRN_PRC1); + rzt2m_unlock_prcrs(PRCRS_GPIO); +} + +static void rzt2m_gpio_lock(void) +{ + rzt2m_lock_prcrn(PRCRN_PRC1); + rzt2m_lock_prcrs(PRCRS_GPIO); +} + +/* Port m output data store */ +static volatile uint8_t *rzt2m_gpio_get_p_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->port_nsr + config->port); +} + +/* Port m input data store */ +static volatile uint8_t *rzt2m_gpio_get_pin_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->port_nsr + PINm_OFFSET + config->port); +} + +/* Port m mode register */ +static volatile uint16_t *rzt2m_gpio_get_pm_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint16_t *)(config->port_nsr + PMm_OFFSET + 0x2 * config->port); +} + +/* IO Buffer m function switching register */ +static volatile uint64_t *rzt2m_gpio_get_drctl_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint64_t *)(config->port_nsr + DRCTLm_OFFSET + 0x8 * config->port); +} + +/* Port m region select register */ +static volatile uint8_t *rzt2m_gpio_get_rselp_reg(const struct device *dev) +{ + const struct rzt2m_gpio_config *config = dev->config; + + return (volatile uint8_t *)(config->ptadr + config->port); +} + +static int rzt2m_gpio_init(const struct device *dev) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *rselp_reg = rzt2m_gpio_get_rselp_reg(dev); + *rselp_reg = 0xFF; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *pin_reg = rzt2m_gpio_get_pin_reg(dev); + *value = *pin_reg; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg = (*p_reg & ~mask) | (value & mask); + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg |= pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg &= ~pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_toggle(const struct device *dev, gpio_port_pins_t pins) +{ + rzt2m_gpio_unlock(); + + volatile uint8_t *p_reg = rzt2m_gpio_get_p_reg(dev); + *p_reg ^= pins; + + rzt2m_gpio_lock(); + + return 0; +} + +static int rzt2m_gpio_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + volatile uint16_t *pm_reg = rzt2m_gpio_get_pm_reg(dev); + volatile uint64_t *drctl_reg = rzt2m_gpio_get_drctl_reg(dev); + + rzt2m_gpio_unlock(); + + WRITE_BIT(*pm_reg, pin * 2, flags & GPIO_INPUT); + WRITE_BIT(*pm_reg, pin * 2 + 1, flags & GPIO_OUTPUT); + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_OUTPUT_INIT_LOW) { + rzt2m_port_clear_bits_raw(dev, 1 << pin); + } else if (flags & GPIO_OUTPUT_INIT_HIGH) { + rzt2m_port_set_bits_raw(dev, 1 << pin); + } + } + + if (flags & GPIO_PULL_UP && flags & GPIO_PULL_DOWN) { + rzt2m_gpio_lock(); + return -EINVAL; + } + + uint8_t drctl_pin_config = 0; + + if (flags & GPIO_PULL_UP) { + drctl_pin_config |= PULL_UP; + } else if (flags & GPIO_PULL_DOWN) { + drctl_pin_config |= PULL_DOWN; + } else { + drctl_pin_config |= PULL_NONE; + } + + drctl_pin_config |= + (flags & RZT2M_GPIO_DRIVE_MASK) >> (RZT2M_GPIO_DRIVE_OFFSET - DRIVE_SHIFT); + drctl_pin_config |= (flags & RZT2M_GPIO_SCHMITT_TRIGGER_MASK) >> + (RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET - SCHMITT_TRIGGER_SHIFT); + drctl_pin_config |= (flags & RZT2M_GPIO_SLEW_RATE_MASK) >> + (RZT2M_GPIO_SLEW_RATE_OFFSET - SLEW_RATE_SHIFT); + + uint64_t drctl_pin_value = *drctl_reg & ~(0xFFULL << (pin * 8)); + *drctl_reg = drctl_pin_value | ((uint64_t)drctl_pin_config << (pin * 8)); + + rzt2m_gpio_lock(); + + return 0; +} + +static const struct gpio_driver_api rzt2m_gpio_driver_api = { + .pin_configure = rzt2m_gpio_configure, + .port_get_raw = rzt2m_gpio_get_raw, + .port_set_masked_raw = rzt2m_port_set_masked_raw, + .port_set_bits_raw = rzt2m_port_set_bits_raw, + .port_clear_bits_raw = rzt2m_port_clear_bits_raw, + .port_toggle_bits = rzt2m_gpio_toggle}; + +#define RZT2M_GPIO_DEFINE(inst) \ + static struct rzt2m_gpio_data rzt2m_gpio_data##inst; \ + static struct rzt2m_gpio_config rzt2m_gpio_config##inst = { \ + .port_nsr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), port_nsr), \ + .ptadr = (uint8_t *)DT_REG_ADDR_BY_NAME(DT_INST_PARENT(inst), ptadr), \ + .port = DT_INST_REG_ADDR(inst), \ + .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst)}}; \ + DEVICE_DT_INST_DEFINE(inst, rzt2m_gpio_init, NULL, &rzt2m_gpio_data##inst, \ + &rzt2m_gpio_config##inst, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &rzt2m_gpio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RZT2M_GPIO_DEFINE) diff --git a/dts/arm/renesas/rzt2m.dtsi b/dts/arm/renesas/rzt2m.dtsi index dada6ea55c7..9c6c1688d63 100644 --- a/dts/arm/renesas/rzt2m.dtsi +++ b/dts/arm/renesas/rzt2m.dtsi @@ -117,6 +117,32 @@ compatible = "renesas,rzt2m-pinctrl"; reg = <0x800a0000 0x1000 0x81030c00 0x1000>; reg-names = "port_nsr", "ptadr"; + #address-cells = <1>; + #size-cells = <0>; + + gpio19: gpio@13 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x13>; + }; + + gpio20: gpio@14 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x14>; + }; + + gpio23: gpio@17 { + compatible = "renesas,rzt2m-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <8>; + reg = <0x17>; + }; }; }; }; diff --git a/dts/bindings/gpio/renesas,rzt2m-gpio.yaml b/dts/bindings/gpio/renesas,rzt2m-gpio.yaml new file mode 100644 index 00000000000..e099c81753e --- /dev/null +++ b/dts/bindings/gpio/renesas,rzt2m-gpio.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 +description: Renesas RZT2M GPIO + +compatible: "renesas,rzt2m-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h b/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h new file mode 100644 index 00000000000..8bd26d46434 --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/renesas-rzt2m-gpio.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ +#include + +#define RZT2M_GPIO_DRIVE_OFFSET 8 +#define RZT2M_GPIO_DRIVE_MASK GENMASK(RZT2M_GPIO_DRIVE_OFFSET + 2, RZT2M_GPIO_DRIVE_OFFSET) + +/** + * @brief Select GPIO pin drive strength + */ +#define RZT2M_GPIO_DRIVE_LOW (0U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_MIDDLE (1U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_HIGH (2U << RZT2M_GPIO_DRIVE_OFFSET) +#define RZT2M_GPIO_DRIVE_ULTRA_HIGH (3U << RZT2M_GPIO_DRIVE_OFFSET) + +#define RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET 10 +#define RZT2M_GPIO_SCHMITT_TRIGGER_MASK BIT(RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET) + +/** + * @brief Enable GPIO pin schmitt trigger + */ +#define RZT2M_GPIO_SCHMITT_TRIGGER BIT(RZT2M_GPIO_SCHMITT_TRIGGER_OFFSET) + +#define RZT2M_GPIO_SLEW_RATE_OFFSET 11 +#define RZT2M_GPIO_SLEW_RATE_MASK BIT(RZT2M_GPIO_SLEW_RATE_OFFSET) + +/** + * @brief Select GPIO pin slew rate + */ +#define RZT2M_GPIO_SLEW_RATE_SLOW 0U +#define RZT2M_GPIO_SLEW_RATE_FAST BIT(RZT2M_GPIO_SLEW_RATE_OFFSET) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RENESAS_RZT2M_H_ */