From 9e44f59e9a27f44d0ac9dd428536914e00b82ad4 Mon Sep 17 00:00:00 2001 From: Wojciech Sipak Date: Wed, 4 Oct 2023 15:38:30 +0200 Subject: [PATCH] drivers: pinctrl: add RZT2M driver This adds a new driver for Renesas RZ/T2M. The driver allows configuration of pin direction, pull up/down resistors, drive strength and slew rate, and selection of function for a pin. Signed-off-by: Wojciech Sipak --- .../rzt2m_starterkit/rzt2m_starter_kit.dts | 27 ++++++ drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.rzt2m | 9 ++ drivers/pinctrl/pinctrl_rzt2m.c | 63 +++++++++++++ drivers/serial/Kconfig.rzt2m | 1 + drivers/serial/uart_rzt2m.c | 13 ++- dts/arm/renesas/rzt2m.dtsi | 5 + .../pinctrl/renesas,rzt2m-pinctrl.yaml | 93 +++++++++++++++++++ .../pinctrl/renesas-rzt2m-pinctrl.h | 18 ++++ soc/arm/renesas_rzt2m/pinctrl_soc.h | 57 ++++++++++++ 11 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/Kconfig.rzt2m create mode 100644 drivers/pinctrl/pinctrl_rzt2m.c create mode 100644 dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml create mode 100644 include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h create mode 100644 soc/arm/renesas_rzt2m/pinctrl_soc.h diff --git a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts index a9cb6bcf65a..ddada360b99 100644 --- a/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts +++ b/boards/arm/rzt2m_starterkit/rzt2m_starter_kit.dts @@ -5,6 +5,7 @@ */ /dts-v1/; +#include #include / { @@ -18,10 +19,36 @@ }; }; + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + uart3_default: uart3_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; + &uart0 { status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; }; &uart3 { status = "okay"; + pinctrl-0 = <&uart3_default>; + pinctrl-names = "default"; }; diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index ba49a637689..9455b6e7c78 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -37,3 +37,4 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_RA pinctrl_ra.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_RZT2M pinctrl_rzt2m.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index b7dc6c2fa69..8a165725e4d 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -65,5 +65,6 @@ source "drivers/pinctrl/Kconfig.ti_cc32xx" source "drivers/pinctrl/Kconfig.numaker" source "drivers/pinctrl/Kconfig.eos_s3" source "drivers/pinctrl/Kconfig.ra" +source "drivers/pinctrl/Kconfig.rzt2m" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.rzt2m b/drivers/pinctrl/Kconfig.rzt2m new file mode 100644 index 00000000000..236afdcf55e --- /dev/null +++ b/drivers/pinctrl/Kconfig.rzt2m @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_RZT2M + bool "Renesas RZ/T2M pin controller driver" + default y + depends on DT_HAS_RENESAS_RZT2M_PINCTRL_ENABLED + help + Renesas RZ/T2M pinctrl driver diff --git a/drivers/pinctrl/pinctrl_rzt2m.c b/drivers/pinctrl/pinctrl_rzt2m.c new file mode 100644 index 00000000000..0dff4461903 --- /dev/null +++ b/drivers/pinctrl/pinctrl_rzt2m.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzt2m_pinctrl + +#include +#include +#include + +#define PORT_NSR DT_INST_REG_ADDR_BY_NAME(0, port_nsr) +#define PTADR DT_INST_REG_ADDR_BY_NAME(0, ptadr) + +/* Port m mode control register */ +#define PMC(port) (PORT_NSR + 0x400 + port) +/* Port m function control register */ +#define PFC(port) (PORT_NSR + 0x600 + (0x4 * port)) +/* IO Buffer m function switching register */ +#define DRCTL(port, pin) (PORT_NSR + 0xa00 + (0x8 * port) + pin) +/* Port m region select register */ +#define RSELP(port) (PTADR + port) + +#define DRCTL_DRIVE_STRENGTH(val) (val & 0x3) +#define DRCTL_PULL_UP_DOWN(val) ((val & 0x3) << 2) +#define DRCTL_SCHMITT(val) ((val & 0x1) << 4) +#define DRCTL_SLEW_RATE(val) ((val & 0x1) << 5) +#define DRCTL_CONFIG(drive, pull, schmitt, slew) \ + (DRCTL_DRIVE_STRENGTH(drive) | DRCTL_PULL_UP_DOWN(pull) | DRCTL_SCHMITT(schmitt) | \ + DRCTL_SLEW_RATE(slew)) +#define PFC_FUNC_MASK(pin) (0xf << (pin * 4)) + +static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin) +{ + uint8_t rselp = sys_read8(RSELP(pin->port)); + uint32_t pfc = sys_read32(PFC(pin->port)) & ~(PFC_FUNC_MASK(pin->pin)); + uint8_t pmc = sys_read8(PMC(pin->port)); + + /* Set proper bit in the RSELP register to use as non-safety domain. */ + sys_write8(rselp | BIT(pin->pin), RSELP(pin->port)); + sys_write8(DRCTL_CONFIG( + pin->drive_strength, (pin->pull_up == 1 ? 1U : (pin->pull_down == 1 ? 2U : 0)), + pin->schmitt_enable, pin->slew_rate), + DRCTL(pin->port, pin->pin)); + + /* Select function for the pin. */ + sys_write32(pfc | pin->func << (pin->pin * 4), PFC(pin->port)); + + /* Set proper bit in the PMC register to use the pin as a peripheral IO. */ + sys_write8(pmc | BIT(pin->pin), PMC(pin->port)); +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + pinctrl_configure_pin(pins++); + } + + return 0; +} diff --git a/drivers/serial/Kconfig.rzt2m b/drivers/serial/Kconfig.rzt2m index bda26d628ad..2561499a5b5 100644 --- a/drivers/serial/Kconfig.rzt2m +++ b/drivers/serial/Kconfig.rzt2m @@ -7,5 +7,6 @@ config UART_RZT2M depends on DT_HAS_RENESAS_RZT2M_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT + select PINCTRL help Enable Renesas RZ/T2M UART Driver. diff --git a/drivers/serial/uart_rzt2m.c b/drivers/serial/uart_rzt2m.c index afd012d5a8b..e4ebe251f21 100644 --- a/drivers/serial/uart_rzt2m.c +++ b/drivers/serial/uart_rzt2m.c @@ -8,6 +8,7 @@ #include "zephyr/spinlock.h" #include "zephyr/sys/printk.h" #include +#include #include #include #include @@ -20,6 +21,7 @@ LOG_MODULE_REGISTER(uart_renesas_rzt2m, CONFIG_UART_LOG_LEVEL); struct rzt2m_device_config { mm_reg_t base; + const struct pinctrl_dev_config *pin_config; uart_irq_config_func_t irq_config_func; }; @@ -297,6 +299,12 @@ static int rzt2m_uart_init(const struct device *dev) *CCR3(config->base) = CCR3_DEFAULT_VALUE; *CCR4(config->base) = CCR4_DEFAULT_VALUE; + /* Configure pinmuxes */ + ret = pinctrl_apply_state(config->pin_config, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + *CFCLR(config->base) = CFCLR_ALL_FLAG_CLEAR; *FFCLR(config->base) = FFCLR_MASK_DRC; @@ -414,6 +422,7 @@ static void uart_rzt2m_isr(const struct device *dev) } #define UART_RZT2M_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ static struct rzt2m_device_data rzt2m_uart_##n##data = { \ .uart_cfg = \ { \ @@ -427,7 +436,9 @@ static void uart_rzt2m_isr(const struct device *dev) }; \ UART_RZT2M_CONFIG_FUNC(n); \ static const struct rzt2m_device_config rzt2m_uart_##n##_config = { \ - .base = DT_INST_REG_ADDR(n), .irq_config_func = uart##n##_rzt2m_irq_config}; \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = uart##n##_rzt2m_irq_config, \ + .pin_config = PINCTRL_DT_INST_DEV_CONFIG_GET(n)}; \ DEVICE_DT_INST_DEFINE(n, &rzt2m_uart_init, NULL, &rzt2m_uart_##n##data, \ &rzt2m_uart_##n##_config, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ &rzt2m_uart_api); diff --git a/dts/arm/renesas/rzt2m.dtsi b/dts/arm/renesas/rzt2m.dtsi index 7ac60cdf99c..dada6ea55c7 100644 --- a/dts/arm/renesas/rzt2m.dtsi +++ b/dts/arm/renesas/rzt2m.dtsi @@ -113,5 +113,10 @@ status = "disabled"; }; + pinctrl: pinctrl@800a0000 { + compatible = "renesas,rzt2m-pinctrl"; + reg = <0x800a0000 0x1000 0x81030c00 0x1000>; + reg-names = "port_nsr", "ptadr"; + }; }; }; diff --git a/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml b/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml new file mode 100644 index 00000000000..82016017201 --- /dev/null +++ b/dts/bindings/pinctrl/renesas,rzt2m-pinctrl.yaml @@ -0,0 +1,93 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: | + The Renesas RZ/T2M pin controller is a node responsible for controlling + pin function selection and pin properties, such as routing the TX and RX of UART0 + to pin 5 and pin 6 of port 16. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /* include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'input-enable' property in group 2. + +compatible: "renesas,rzt2m-pinctrl" + +include: base.yaml + +child-binding: + description: | + Definitions for a pinctrl state. + child-binding: + + include: + - name: pincfg-node.yaml + property-allowlist: + - input-enable + - bias-pull-up + - bias-pull-down + - bias-high-impedance + - input-schmitt-enable + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. Each + element of the array is an integer constructed from the + pin number and the alternative function of the pin. + drive-strength: + type: string + enum: + - "low" + - "middle" + - "high" + - "ultrahigh" + default: "low" + description: | + The drive strength of a pin, relative to full-driver strength. + The default value is "low", which is the reset value. + slew-rate: + type: string + enum: + - "slow" + - "fast" + default: "slow" + description: | + Select slew rate for a pin. The default is slow, which is the reset value. diff --git a/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h new file mode 100644 index 00000000000..ed1cbf7ee96 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas-rzt2m-pinctrl.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RENESAS_RZT2M_PINCTRL_H__ +#define __RENESAS_RZT2M_PINCTRL_H__ + +#define RZT2M_PINMUX(port, pin, func) ((port << 16) | (pin << 8) | func) + +#define UART0TX_P16_5 RZT2M_PINMUX(16, 5, 1) +#define UART0RX_P16_6 RZT2M_PINMUX(16, 6, 2) + +#define UART3TX_P18_0 RZT2M_PINMUX(18, 0, 4) +#define UART3RX_P17_7 RZT2M_PINMUX(17, 7, 4) + +#endif /* __RENESAS_RZT2M_PINCTRL_H__ */ diff --git a/soc/arm/renesas_rzt2m/pinctrl_soc.h b/soc/arm/renesas_rzt2m/pinctrl_soc.h new file mode 100644 index 00000000000..d740d6c115e --- /dev/null +++ b/soc/arm/renesas_rzt2m/pinctrl_soc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ +#define ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pinctrl_soc_pin_t { + uint32_t port; + uint32_t pin; + uint32_t func; + uint32_t input_enable: 1; + uint32_t output_enable: 1; + uint32_t pull_up: 1; + uint32_t pull_down: 1; + uint32_t high_impedance: 1; + uint32_t slew_rate: 2; + uint8_t drive_strength; + uint32_t schmitt_enable: 1; +} pinctrl_soc_pin_t; + +#define RZT2M_GET_PORT(pinctrl) ((pinctrl >> 16) & 0xff) +#define RZT2M_GET_PIN(pinctrl) ((pinctrl >> 8) & 0xff) +#define RZT2M_GET_FUNC(pinctrl) (pinctrl & 0xff) + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + .port = RZT2M_GET_PORT(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .pin = RZT2M_GET_PIN(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .func = RZT2M_GET_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \ + .input_enable = DT_PROP(node_id, input_enable), \ + .pull_up = DT_PROP(node_id, bias_pull_up), \ + .pull_down = DT_PROP(node_id, bias_pull_down), \ + .high_impedance = DT_PROP(node_id, bias_high_impedance), \ + .slew_rate = DT_ENUM_IDX(node_id, slew_rate), \ + .drive_strength = DT_ENUM_IDX(node_id, drive_strength), \ + .schmitt_enable = DT_PROP(node_id, input_schmitt_enable), \ + }, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_RENESAS_RZT2M_PINCTRL_H_ */