From f9e0c7a7c931b52a88cbbb189cba1abe28e8d8af Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 21:41:06 +0100 Subject: [PATCH 01/13] modules: hal_gigadevice: include module headers Include the module `include` folder to allow access to the dt-bindings helpers. Signed-off-by: Gerard Marull-Paretas --- modules/hal_gigadevice/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/hal_gigadevice/CMakeLists.txt b/modules/hal_gigadevice/CMakeLists.txt index d19c83fb88a82..9315c9b9a35d5 100644 --- a/modules/hal_gigadevice/CMakeLists.txt +++ b/modules/hal_gigadevice/CMakeLists.txt @@ -17,6 +17,7 @@ zephyr_compile_definitions(${gd32_soc_uc}) # Global includes to be used outside hal_gigadevice zephyr_include_directories(${gd32_cmsis_dir}/include) zephyr_include_directories(${gd32_std_dir}/include) +zephyr_include_directories(${ZEPHYR_HAL_GIGADEVICE_MODULE_DIR}/include) zephyr_library_sources(${gd32_cmsis_dir}/source/system_${CONFIG_SOC_SERIES}.c) From a1faabec34bca627cd7988f44bdee1a4dec74b9d Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 21:37:04 +0100 Subject: [PATCH 02/13] drivers: pinctrl: gd32: initial support for AF based SoCs Add a pin control driver for GD32 SoCs using the AF model. Signed-off-by: Gerard Marull-Paretas --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 2 + drivers/pinctrl/Kconfig.gd32 | 12 ++ drivers/pinctrl/pinctrl_gd32_af.c | 104 +++++++++++ dts/bindings/gpio/gd,gd32-gpio.yaml | 27 +++ dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml | 111 ++++++++++++ .../pinctrl/gd,gd32-pinctrl-common.yaml | 26 +++ modules/hal_gigadevice/Kconfig | 5 + soc/arm/gigadevice/CMakeLists.txt | 1 + soc/arm/gigadevice/common/CMakeLists.txt | 4 + soc/arm/gigadevice/common/pinctrl_soc.h | 162 ++++++++++++++++++ 11 files changed, 455 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.gd32 create mode 100644 drivers/pinctrl/pinctrl_gd32_af.c create mode 100644 dts/bindings/gpio/gd,gd32-gpio.yaml create mode 100644 dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml create mode 100644 dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml create mode 100644 soc/arm/gigadevice/common/CMakeLists.txt create mode 100644 soc/arm/gigadevice/common/pinctrl_soc.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index cd3eca95d8d74..ec6cb34b0d270 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -3,3 +3,4 @@ zephyr_library() zephyr_library_sources(common.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7e1a67175b84c..7744ea475b002 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -29,4 +29,6 @@ config PINCTRL_DYNAMIC runtime. This can be useful, for example, to change the pins assigned to a peripheral at early boot stages depending on a certain input. +source "drivers/pinctrl/Kconfig.gd32" + endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.gd32 b/drivers/pinctrl/Kconfig.gd32 new file mode 100644 index 0000000000000..f7ff8c3567e75 --- /dev/null +++ b/drivers/pinctrl/Kconfig.gd32 @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_GIGADEVICE_GD32_PINCTRL_AF := gd,gd32-pinctrl-af + +config PINCTRL_GD32_AF + bool "GD32 AF pin controller driver" + depends on SOC_FAMILY_GD32 && GD32_HAS_AF_PINMUX + default $(dt_compat_enabled,$(DT_COMPAT_GIGADEVICE_GD32_PINCTRL_AF)) + help + GD32 AF pin controller driver. This driver is used by series using the + AF pin multiplexing model. diff --git a/drivers/pinctrl/pinctrl_gd32_af.c b/drivers/pinctrl/pinctrl_gd32_af.c new file mode 100644 index 0000000000000..d86b36e2e0ddc --- /dev/null +++ b/drivers/pinctrl/pinctrl_gd32_af.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +BUILD_ASSERT((GD32_PUPD_NONE == GPIO_PUPD_NONE) && + (GD32_PUPD_PULLUP == GPIO_PUPD_PULLUP) && + (GD32_PUPD_PULLDOWN == GPIO_PUPD_PULLDOWN), + "pinctrl pull-up/down definitions != HAL definitions"); + +BUILD_ASSERT((GD32_OTYPE_PP == GPIO_OTYPE_PP) && + (GD32_OTYPE_OD == GPIO_OTYPE_OD), + "pinctrl output type definitions != HAL definitions"); + +BUILD_ASSERT((GD32_OSPEED_2MHZ == GPIO_OSPEED_2MHZ) && + (GD32_OSPEED_25MHZ == GPIO_OSPEED_25MHZ) && + (GD32_OSPEED_50MHZ == GPIO_OSPEED_50MHZ) && + (GD32_OSPEED_200MHZ == GPIO_OSPEED_200MHZ), + "pinctrl output speed definitions != HAL definitions"); + +/** Utility macro that expands to the GPIO port address if it exists */ +#define GD32_PORT_ADDR_OR_NONE(nodelabel) \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),), ()) + +/** Utility macro that expands to the GPIO RCU if it exists */ +#define GD32_PORT_RCU_OR_NONE(nodelabel) \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_PROP(DT_NODELABEL(nodelabel), rcu_periph_clock),), ()) + +/** GD32 port addresses */ +static const uint32_t gd32_port_addrs[] = { + GD32_PORT_ADDR_OR_NONE(gpioa) + GD32_PORT_ADDR_OR_NONE(gpiob) + GD32_PORT_ADDR_OR_NONE(gpioc) + GD32_PORT_ADDR_OR_NONE(gpiod) + GD32_PORT_ADDR_OR_NONE(gpioe) + GD32_PORT_ADDR_OR_NONE(gpiof) + GD32_PORT_ADDR_OR_NONE(gpiog) + GD32_PORT_ADDR_OR_NONE(gpioh) + GD32_PORT_ADDR_OR_NONE(gpioi) +}; + +/** GD32 port RCUs */ +static const uint32_t gd32_port_rcus[] = { + GD32_PORT_RCU_OR_NONE(gpioa) + GD32_PORT_RCU_OR_NONE(gpiob) + GD32_PORT_RCU_OR_NONE(gpioc) + GD32_PORT_RCU_OR_NONE(gpiod) + GD32_PORT_RCU_OR_NONE(gpioe) + GD32_PORT_RCU_OR_NONE(gpiof) + GD32_PORT_RCU_OR_NONE(gpiog) + GD32_PORT_RCU_OR_NONE(gpioh) + GD32_PORT_RCU_OR_NONE(gpioi) +}; + +/** + * @brief Configure a pin. + * + * @param pin The pin to configure. + */ +static void pinctrl_configure_pin(pinctrl_soc_pin_t pin) +{ + uint8_t port_idx; + uint32_t rcu, port, pin_num, af, mode; + + port_idx = GD32_PORT_GET(pin); + __ASSERT_NO_MSG(port_idx < ARRAY_SIZE(gd32_port_addrs)); + + rcu = gd32_port_rcus[port_idx]; + port = gd32_port_addrs[port_idx]; + pin_num = BIT(GD32_PIN_GET(pin)); + af = GD32_AF_GET(pin); + + rcu_periph_clock_enable(rcu); + + if (af != GD32_ANALOG) { + mode = GPIO_MODE_AF; + gpio_af_set(port, af, pin_num); + } else { + mode = GPIO_MODE_ANALOG; + } + + gpio_mode_set(port, mode, GD32_PUPD_GET(pin), pin_num); + gpio_output_options_set(port, GD32_OTYPE_GET(pin), + GD32_OSPEED_GET(pin), pin_num); + + rcu_periph_clock_disable(rcu); +} + +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[i]); + } + + return 0; +} diff --git a/dts/bindings/gpio/gd,gd32-gpio.yaml b/dts/bindings/gpio/gd,gd32-gpio.yaml new file mode 100644 index 0000000000000..36c9ef1e6be3c --- /dev/null +++ b/dts/bindings/gpio/gd,gd32-gpio.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +description: GD32 GPIO node + +compatible: "gd,gd32-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + label: + required: true + + rcu-periph-clock: + type: int + description: Reset Control Unit Peripheral Clock ID + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml b/dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml new file mode 100644 index 0000000000000..2089e72b26101 --- /dev/null +++ b/dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml @@ -0,0 +1,111 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +description: | + The GD32 pin controller (AF model) is a singleton node responsible for + controlling pin function selection and pin properties. For example, you can + use this node to route USART0 RX to pin PA10 and enable the pull-up resistor + on the pin. + + 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 { + /* configuration for the usart0 "default" state */ + usart0_default: usart0_default { + /* group 1 */ + group1 { + /* configure PA9 as USART0 TX and PA11 as USART0 CTS */ + pinmux = , ; + }; + /* group 2 */ + group2 { + /* configure PA10 as USART0 RX and PA12 as USART0 RTS */ + pinmux = , ; + /* both PA10 and PA12 have pull-up enabled */ + bias-pull-up; + }; + + /* configuration for the usart0 "sleep" state */ + usart0_sleep: usart0_sleep { + /* group 1 */ + group1 { + /* configure PA9, PA10, PA11 and PA12 in analog mode */ + pinmux = , , , ; + }; + }; + + The 'usart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. Similarly, 'usart0_sleep' child node encodes the pin configurations + for the sleep state (used in device low power mode). Note that analog mode + is used for low power states because it disconnects the pin pull-up/down + resistor, schmitt trigger, and output buffer. + + 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 'bias-pull-up' property in group 2. Here is a list of + supported standard pin properties: + + - drive-push-pull: Push-pull drive mode (default, not required). + - drive-open-drain: Open-drain drive mode. + - bias-disable: Disable pull-up/down (default, not required). + - bias-pull-up: Enable pull-up resistor. + - bias-pull-down: Enable pull-down resistor. + - slew-rate: Set the maximum speed (and so the slew-rate) of the output + signal (default: 2MHz). + + Note that drive and bias options are mutually exclusive. + + To link pin configurations with a device, use a pinctrl-N property for some + number N, like this example you could place in your board's DTS file: + + #include "board-pinctrl.dtsi" + + &usart0 { + pinctrl-0 = <&usart0_default>; + pinctrl-1 = <&usart0_sleep>; + pinctrl-names = "default", "sleep"; + }; + +compatible: "gd,gd32-pinctrl-af" + +include: gd,gd32-pinctrl-common.yaml + +child-binding: + description: | + Each child node defines the configuration for a particular state. + child-binding: + description: | + The grandchild nodes group pins that share the same pin configuration. + properties: + slew-rate: + required: false + type: string + default: "max-speed-2mhz" + enum: + - "max-speed-2mhz" + - "max-speed-25mhz" + - "max-speed-50mhz" + - "max-speed-200mhz" + description: | + Set the maximum speed of a pin. This setting effectively limits the + slew rate of the output signal. Defaults to "max-speed-2mhz", the SoC + default. diff --git a/dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml b/dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml new file mode 100644 index 0000000000000..c8f1dfbba0082 --- /dev/null +++ b/dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml @@ -0,0 +1,26 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +include: + - name: base.yaml + - name: pincfg-node-group.yaml + child-binding: + child-binding: + property-allowlist: + - drive-push-pull + - drive-open-drain + - bias-disable + - bias-pull-down + - bias-pull-up + +child-binding: + child-binding: + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins should + be defined using pre-defined macros or, alternatively, using the + GD32_PINMUX_AF or GD32_PINMUX_AFIO utility macros depending on the + pinmux model used by the SoC series. diff --git a/modules/hal_gigadevice/Kconfig b/modules/hal_gigadevice/Kconfig index 542c65620dbcc..b327b9a5c71e4 100644 --- a/modules/hal_gigadevice/Kconfig +++ b/modules/hal_gigadevice/Kconfig @@ -4,6 +4,11 @@ config ZEPHYR_HAL_GIGADEVICE_MODULE bool +config GD32_HAS_AF_PINMUX + bool + help + This option should be selected if the series use an AF pinmux model. + config HAS_GD32_HAL bool select HAS_CMSIS_CORE if SOC_FAMILY_GD32_ARM diff --git a/soc/arm/gigadevice/CMakeLists.txt b/soc/arm/gigadevice/CMakeLists.txt index 6c5e7b454f67f..e6525b0312829 100644 --- a/soc/arm/gigadevice/CMakeLists.txt +++ b/soc/arm/gigadevice/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (c) 2021, ATL Electronics # SPDX-License-Identifier: Apache-2.0 +add_subdirectory(common) add_subdirectory(${SOC_SERIES}) diff --git a/soc/arm/gigadevice/common/CMakeLists.txt b/soc/arm/gigadevice/common/CMakeLists.txt new file mode 100644 index 0000000000000..83dce5d012756 --- /dev/null +++ b/soc/arm/gigadevice/common/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(.) diff --git a/soc/arm/gigadevice/common/pinctrl_soc.h b/soc/arm/gigadevice/common/pinctrl_soc.h new file mode 100644 index 0000000000000..062deb5b7037c --- /dev/null +++ b/soc/arm/gigadevice/common/pinctrl_soc.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * Gigadevice SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_ARM_GIGADEVICE_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_GIGADEVICE_COMMON_PINCTRL_SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +/** @brief Type for GD32 pin. + * + * Bits: + * - 0-12: GD32_PINMUX_AF bit field. + * - 13-25: Reserved. + * - 26-31: Pin configuration bit field (@ref GD32_PINCFG). + */ +typedef uint32_t pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + (DT_PROP_BY_IDX(node_id, prop, idx) | \ + ((GD32_PUPD_PULLUP * DT_PROP(node_id, bias_pull_up)) \ + << GD32_PUPD_POS) | \ + ((GD32_PUPD_PULLDOWN * DT_PROP(node_id, bias_pull_down)) \ + << GD32_PUPD_POS) | \ + ((GD32_OTYPE_OD * DT_PROP(node_id, drive_open_drain)) \ + << GD32_OTYPE_POS) | \ + (DT_ENUM_IDX(node_id, slew_rate) << GD32_OSPEED_POS)), + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#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)} + +/** @endcond */ + +/** + * @name GD32 PUPD (values match the ones in the HAL). + * @{ + */ + +/** No pull-up/down */ +#define GD32_PUPD_NONE 0U +/** Pull-up */ +#define GD32_PUPD_PULLUP 1U +/** Pull-down */ +#define GD32_PUPD_PULLDOWN 2U + +/** @} */ + +/** + * @name GD32 OTYPE (values match the ones in the HAL). + * @{ + */ + +/** Push-pull */ +#define GD32_OTYPE_PP 0U +/** Open-drain */ +#define GD32_OTYPE_OD 1U + +/** @} */ + +/** + * @name GD32 OSPEED (values match the ones in the HAL). + * @{ + */ + +/** Maximum 2MHz */ +#define GD32_OSPEED_2MHZ 0U +/** Maximum 25MHz */ +#define GD32_OSPEED_25MHZ 1U +/** Maximum 50MHz */ +#define GD32_OSPEED_50MHZ 2U +/** Maximum 200MHz */ +#define GD32_OSPEED_200MHZ 3U + +/** @} */ + +/** + * @name GD32 pin configuration bit field mask and positions. + * @anchor GD32_PINCFG + * + * Fields: + * + * - 31..29: Pull-up/down + * - 28: Output type + * - 27..26: Output speed + * + * @{ + */ + +/** PUPD field mask. */ +#define GD32_PUPD_MSK 0x3U +/** PUPD field position. */ +#define GD32_PUPD_POS 29U +/** OTYPE field mask. */ +#define GD32_OTYPE_MSK 0x1U +/** OTYPE field position. */ +#define GD32_OTYPE_POS 28U +/** OSPEED field mask. */ +#define GD32_OSPEED_MSK 0x3U +/** OSPEED field position. */ +#define GD32_OSPEED_POS 26U + +/** @} */ + +/** + * Obtain PUPD field from pinctrl_soc_pin_t configuration. + * + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define GD32_PUPD_GET(pincfg) \ + (((pincfg) >> GD32_PUPD_POS) & GD32_PUPD_MSK) + +/** + * Obtain OTYPE field from pinctrl_soc_pin_t configuration. + * + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define GD32_OTYPE_GET(pincfg) \ + (((pincfg) >> GD32_OTYPE_POS) & GD32_OTYPE_MSK) + +/** + * Obtain OSPEED field from pinctrl_soc_pin_t configuration. + * + * @param pincfg pinctrl_soc_pin_t bit field value. + */ +#define GD32_OSPEED_GET(pincfg) \ + (((pincfg) >> GD32_OSPEED_POS) & GD32_OSPEED_MSK) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_GIGADEVICE_COMMON_PINCTRL_SOC_H_ */ From cbefb5287f0f42d941fd4cb43d3bfc41f463dddd Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 22:24:14 +0100 Subject: [PATCH 03/13] dts: arm: gd32f4xx: add pinctrl and gpio nodes Add definitions for the pinctrl and gpio nodes. Signed-off-by: Gerard Marull-Paretas --- dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi | 81 +++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi b/dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi index 6dd0d177dd9a1..f85500e262d20 100644 --- a/dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi +++ b/dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi @@ -53,6 +53,87 @@ status = "disabled"; label = "USART0"; }; + + pinctrl: pin-controller@40020000 { + compatible = "gd,gd32-pinctrl-af"; + reg = <0x40020000 0x2400>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + label = "PINCTRL"; + + gpioa: gpio@40020000 { + compatible = "gd,gd32-gpio"; + reg = <0x40020000 0x400>; + rcu-periph-clock = <0xc00>; + status = "disabled"; + label = "GPIOA"; + }; + + gpiob: gpio@40020400 { + compatible = "gd,gd32-gpio"; + reg = <0x40020400 0x400>; + rcu-periph-clock = <0xc01>; + status = "disabled"; + label = "GPIOB"; + }; + + gpioc: gpio@40020800 { + compatible = "gd,gd32-gpio"; + reg = <0x40020800 0x400>; + rcu-periph-clock = <0xc02>; + status = "disabled"; + label = "GPIOC"; + }; + + gpiod: gpio@40020c00 { + compatible = "gd,gd32-gpio"; + reg = <0x40020c00 0x400>; + rcu-periph-clock = <0xc03>; + status = "disabled"; + label = "GPIOD"; + }; + + gpioe: gpio@40021000 { + compatible = "gd,gd32-gpio"; + reg = <0x40021000 0x400>; + rcu-periph-clock = <0xc04>; + status = "disabled"; + label = "GPIOE"; + }; + + gpiof: gpio@40021400 { + compatible = "gd,gd32-gpio"; + reg = <0x40021400 0x400>; + rcu-periph-clock = <0xc05>; + status = "disabled"; + label = "GPIOF"; + }; + + gpiog: gpio@40021800 { + compatible = "gd,gd32-gpio"; + reg = <0x40021800 0x400>; + rcu-periph-clock = <0xc06>; + status = "disabled"; + label = "GPIOG"; + }; + + gpioh: gpio@40021c00 { + compatible = "gd,gd32-gpio"; + reg = <0x40021c00 0x400>; + rcu-periph-clock = <0xc07>; + status = "disabled"; + label = "GPIOH"; + }; + + gpioi: gpio@40022000 { + compatible = "gd,gd32-gpio"; + reg = <0x40022000 0x400>; + rcu-periph-clock = <0xc08>; + status = "disabled"; + label = "GPIOI"; + }; + }; }; }; From e42de1ed13e6c0f171abbe63e01b4b83a3b55608 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 22:25:13 +0100 Subject: [PATCH 04/13] soc: arm: gigadevice: gd32f4xx: select AF pinmux GD32F4XX series have AF based pinmux. Signed-off-by: Gerard Marull-Paretas --- soc/arm/gigadevice/gd32f4xx/Kconfig.series | 1 + 1 file changed, 1 insertion(+) diff --git a/soc/arm/gigadevice/gd32f4xx/Kconfig.series b/soc/arm/gigadevice/gd32f4xx/Kconfig.series index 7fcfca925816a..722666d91a78f 100644 --- a/soc/arm/gigadevice/gd32f4xx/Kconfig.series +++ b/soc/arm/gigadevice/gd32f4xx/Kconfig.series @@ -8,5 +8,6 @@ config SOC_SERIES_GD32F4XX select CPU_HAS_FPU select CPU_CORTEX_M4 select SOC_FAMILY_GD32_ARM + select GD32_HAS_AF_PINMUX help Enable support for GigaDevice GD32F4XX MCU series From 305b7e6c28a4867698b61f809f8fac0ba3f5d92d Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 4 Nov 2021 23:18:09 +0100 Subject: [PATCH 05/13] drivers: pinctrl: gd32: initial support for AFIO based SoCs Add a pin control driver for GD32 SoCs using the AFIO model. Thanks to Gerson Fernando Budke for testing and implementation suggestions. Co-authored-by: Gerson Fernando Budke Signed-off-by: Gerard Marull-Paretas --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig.gd32 | 9 + drivers/pinctrl/pinctrl_gd32_afio.c | 219 ++++++++++++++++++ dts/bindings/pinctrl/gd,gd32-afio.yaml | 30 +++ .../pinctrl/gd,gd32-pinctrl-afio.yaml | 137 +++++++++++ modules/hal_gigadevice/Kconfig | 5 + soc/arm/gigadevice/common/pinctrl_soc.h | 32 ++- 7 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 drivers/pinctrl/pinctrl_gd32_afio.c create mode 100644 dts/bindings/pinctrl/gd,gd32-afio.yaml create mode 100644 dts/bindings/pinctrl/gd,gd32-pinctrl-afio.yaml diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index ec6cb34b0d270..4bee9b55c8a71 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -4,3 +4,4 @@ zephyr_library() zephyr_library_sources(common.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c) diff --git a/drivers/pinctrl/Kconfig.gd32 b/drivers/pinctrl/Kconfig.gd32 index f7ff8c3567e75..7822033f0169e 100644 --- a/drivers/pinctrl/Kconfig.gd32 +++ b/drivers/pinctrl/Kconfig.gd32 @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 DT_COMPAT_GIGADEVICE_GD32_PINCTRL_AF := gd,gd32-pinctrl-af +DT_COMPAT_GIGADEVICE_GD32_PINCTRL_AFIO := gd,gd32-pinctrl-afio config PINCTRL_GD32_AF bool "GD32 AF pin controller driver" @@ -10,3 +11,11 @@ config PINCTRL_GD32_AF help GD32 AF pin controller driver. This driver is used by series using the AF pin multiplexing model. + +config PINCTRL_GD32_AFIO + bool "GD32 AFIO pin controller driver" + depends on SOC_FAMILY_GD32 && GD32_HAS_AFIO_PINMUX + default $(dt_compat_enabled,$(DT_COMPAT_GIGADEVICE_GD32_PINCTRL_AFIO)) + help + GD32 AFIO pin controller driver. This driver is used by series using the + AFIO pin multiplexing model. diff --git a/drivers/pinctrl/pinctrl_gd32_afio.c b/drivers/pinctrl/pinctrl_gd32_afio.c new file mode 100644 index 0000000000000..409d0c4f012ae --- /dev/null +++ b/drivers/pinctrl/pinctrl_gd32_afio.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/** AFIO DT node */ +#define AFIO_NODE DT_NODELABEL(afio) + +/** GPIO mode: input floating (CTL bits) */ +#define GPIO_MODE_INP_FLOAT 0x4U +/** GPIO mode: input with pull-up/down (CTL bits) */ +#define GPIO_MODE_INP_PUPD 0x8U +/** GPIO mode: output push-pull (CTL bits) */ +#define GPIO_MODE_ALT_PP 0x8U +/** GPIO mode: output open-drain (CTL bits) */ +#define GPIO_MODE_ALT_OD 0xCU + +/** Utility macro that expands to the GPIO port address if it exists */ +#define GD32_PORT_ADDR_OR_NONE(nodelabel) \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),), ()) + +/** Utility macro that expands to the GPIO RCU if it exists */ +#define GD32_PORT_RCU_OR_NONE(nodelabel) \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_PROP(DT_NODELABEL(nodelabel), rcu_periph_clock),), ()) + +/** GD32 port addresses */ +static const uint32_t gd32_port_addrs[] = { + GD32_PORT_ADDR_OR_NONE(gpioa) + GD32_PORT_ADDR_OR_NONE(gpiob) + GD32_PORT_ADDR_OR_NONE(gpioc) + GD32_PORT_ADDR_OR_NONE(gpiod) + GD32_PORT_ADDR_OR_NONE(gpioe) + GD32_PORT_ADDR_OR_NONE(gpiof) + GD32_PORT_ADDR_OR_NONE(gpiog) +}; + +/** GD32 port RCUs */ +static const uint32_t gd32_port_rcus[] = { + GD32_PORT_RCU_OR_NONE(gpioa) + GD32_PORT_RCU_OR_NONE(gpiob) + GD32_PORT_RCU_OR_NONE(gpioc) + GD32_PORT_RCU_OR_NONE(gpiod) + GD32_PORT_RCU_OR_NONE(gpioe) + GD32_PORT_RCU_OR_NONE(gpiof) + GD32_PORT_RCU_OR_NONE(gpiog) +}; + +/** + * @brief Initialize AFIO + * + * This function enables AFIO clock and configures the I/O compensation if + * available and enabled in Devicetree. + * + * @retval 0 Always + */ +static int afio_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + rcu_periph_clock_enable(DT_PROP(AFIO_NODE, rcu_periph_clock)); + +#ifdef AFIO_CPSCTL + if (DT_PROP(AFIO_NODE, enable_cps)) { + gpio_compensation_config(GPIO_COMPENSATION_ENABLE); + while (gpio_compensation_flag_get() == RESET) + ; + } +#endif /* AFIO_CPSCTL */ + + return 0; +} + +SYS_INIT(afio_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +/** + * @brief Helper function to configure the SPD register if available. + * + * @param port GPIO port address. + * @param pin_bit GPIO pin, set as bit position. + * @param speed GPIO speed. + * + * @return Value of the mode register (speed) that should be set later. + */ +static inline uint8_t configure_spd(uint32_t port, uint32_t pin_bit, + uint8_t speed) +{ + switch (speed) { + case GD32_OSPEED_MAX: +#ifdef GPIOx_SPD + GPIOx_SPD(port) |= pin_bit; +#endif /* GPIOx_SPD */ + return speed; + default: +#ifdef GPIOx_SPD + GPIOx_SPD(port) &= ~pin_bit; +#endif /* GPIOx_SPD */ + return speed + 1U; + } +} + +/** + * @brief Configure a pin. + * + * @param pin The pin to configure. + */ +static void configure_pin(pinctrl_soc_pin_t pin) +{ + uint8_t port_idx, mode, pin_num; + uint32_t rcu, port, pin_bit, reg_val; + volatile uint32_t *reg; + + port_idx = GD32_PORT_GET(pin); + __ASSERT_NO_MSG(port_idx < ARRAY_SIZE(gd32_port_addrs)); + + rcu = gd32_port_rcus[port_idx]; + port = gd32_port_addrs[port_idx]; + pin_num = GD32_PIN_GET(pin); + pin_bit = BIT(pin_num); + mode = GD32_MODE_GET(pin); + + if (pin_num < 8U) { + reg = &GPIO_CTL0(port); + } else { + reg = &GPIO_CTL1(port); + pin_num -= 8U; + } + + rcu_periph_clock_enable(rcu); + + reg_val = *reg; + reg_val &= ~GPIO_MODE_MASK(pin_num); + + if (mode == GD32_MODE_ALTERNATE) { + uint8_t mode; + + mode = configure_spd(port, pin_bit, GD32_OSPEED_GET(pin)); + + if (GD32_OTYPE_GET(pin) == GD32_OTYPE_PP) { + mode |= GPIO_MODE_ALT_PP; + } else { + mode |= GPIO_MODE_ALT_OD; + } + + reg_val |= GPIO_MODE_SET(pin_num, mode); + } else if (mode == GD32_MODE_GPIO_IN) { + uint8_t pupd = GD32_PUPD_GET(pin); + + if (pupd == GD32_PUPD_NONE) { + reg_val |= GPIO_MODE_SET(pin_num, GPIO_MODE_INP_FLOAT); + } else { + reg_val |= GPIO_MODE_SET(pin_num, GPIO_MODE_INP_PUPD); + + if (pupd == GD32_PUPD_PULLDOWN) { + GPIO_BC(port) = pin_bit; + } else if (pupd == GD32_PUPD_PULLUP) { + GPIO_BOP(port) = pin_bit; + } + } + } + + *reg = reg_val; + + rcu_periph_clock_disable(rcu); +} + +/** + * @brief Configure remap. + * + * @param remap Remap bit field as encoded by #GD32_REMAP. + */ +static void configure_remap(uint16_t remap) +{ + uint8_t pos; + uint32_t reg_val; + volatile uint32_t *reg; + + /* not remappable */ + if (remap == GD32_NORMP) { + return; + } + + if (GD32_REMAP_REG_GET(remap) == 0U) { + reg = &AFIO_PCF0; + } else { + reg = &AFIO_PCF1; + } + + pos = GD32_REMAP_POS_GET(remap); + + reg_val = *reg; + reg_val &= ~(GD32_REMAP_MSK_GET(remap) << pos); + reg_val |= GD32_REMAP_VAL_GET(remap) << pos; + *reg = reg_val; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ + ARG_UNUSED(reg); + + if (pin_cnt == 0U) { + return -EINVAL; + } + + /* same remap is encoded in all pins, so just pick the first */ + configure_remap(GD32_REMAP_GET(pins[0])); + + /* configure all pins */ + for (uint8_t i = 0U; i < pin_cnt; i++) { + configure_pin(pins[i]); + } + + return 0; +} diff --git a/dts/bindings/pinctrl/gd,gd32-afio.yaml b/dts/bindings/pinctrl/gd,gd32-afio.yaml new file mode 100644 index 0000000000000..f47b541c89f27 --- /dev/null +++ b/dts/bindings/pinctrl/gd,gd32-afio.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +description: | + The AFIO peripheral is used to configure pin remapping, EXTI sources and, + when available, enable the I/O compensation cell. + +compatible: "gd,gd32-afio" + +include: base.yaml + +properties: + reg: + required: true + + label: + required: true + + rcu-periph-clock: + type: int + description: Reset Control Unit Peripheral Clock ID + required: true + + enable-cps: + required: false + type: boolean + description: | + Enable the I/O compensation cell. This option should be enabled when the + output speed is greater than 50MHz to reduce the I/O noise effects on + the power supply. This option is only available on certain GD32 series. diff --git a/dts/bindings/pinctrl/gd,gd32-pinctrl-afio.yaml b/dts/bindings/pinctrl/gd,gd32-pinctrl-afio.yaml new file mode 100644 index 0000000000000..265db6112757f --- /dev/null +++ b/dts/bindings/pinctrl/gd,gd32-pinctrl-afio.yaml @@ -0,0 +1,137 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +description: | + The GD32 pin controller (AFIO model) is a singleton node responsible for + controlling pin function selection and pin properties. For example, you can + use this node to route USART0 RX to pin PA10 and enable the pull-up resistor + on the pin. Remapping is also supported. + + 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 { + /* configuration for the usart0 "default" state */ + usart0_default: usart0_default { + /* group 1 */ + group1 { + /* configure PA9 as USART0 TX and PA11 as USART0 CTS (no remap) */ + pinmux = , ; + }; + /* group 2 */ + group2 { + /* configure PA10 as USART0 RX and PA12 as USART0 RTS (no remap) */ + pinmux = , ; + /* both PA10 and PA12 have pull-up enabled */ + bias-pull-up; + }; + + /* configuration for the usart0 "sleep" state */ + usart0_sleep: usart0_sleep { + /* group 1 */ + group1 { + /* configure PA9, PA10, PA11 and PA12 in analog mode */ + pinmux = , , , ; + }; + }; + + The 'usart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. Similarly, 'usart0_sleep' child node encodes the pin configurations + for the sleep state (used in device low power mode). Note that analog mode + is used for low power states because it disconnects the pin pull-up/down + resistor, schmitt trigger, and output buffer. + + 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 'bias-pull-up' property in group 2. Here is a list of + supported standard pin properties: + + - drive-push-pull: Push-pull drive mode (default, not required). Only + applies for GPIO_IN mode. + - drive-open-drain: Open-drain drive mode. Only applies for GPIO_IN mode. + - bias-disable: Disable pull-up/down (default, not required). Only applies + for GPIO_IN mode. + - bias-pull-up: Enable pull-up resistor. Only applies for GPIO_IN mode. + - bias-pull-down: Enable pull-down resistor. Only applies for GPIO_IN mode. + - slew-rate: Set the maximum speed (and so the slew-rate) of the output + signal (default: 2MHz). Only applies for ALTERNATE mode. + + Note that drive and bias options are mutually exclusive. + + Peripherals that are remappable will have their pre-defined macros suffixed + with the remap option being selected, for example: + + - CAN0_RX_PA11_NORMP: No remap + - CAN0_RX_PB8_PRMP: Partial remap + - CAN0_RX_PD0_FRMP: Full remap + + It is important that **ALL** pinmux entries share the same remap. For + example: + + &pinctrl { + can0_default: can0_default { + group1 { + pinmux = , ; + /* ^^^^ ^^^^ */ + /* CAN0 pins are remapped choosing the full remap option */ + }; + }; + }; + + To link pin configurations with a device, use a pinctrl-N property for some + number N, like this example you could place in your board's DTS file: + + #include "board-pinctrl.dtsi" + + &usart0 { + pinctrl-0 = <&usart0_default>; + pinctrl-1 = <&usart0_sleep>; + pinctrl-names = "default", "sleep"; + }; + +compatible: "gd,gd32-pinctrl-afio" + +include: gd,gd32-pinctrl-common.yaml + +child-binding: + description: | + Each child node defines the configuration for a particular state. + child-binding: + description: | + The grandchild nodes group pins that share the same pin configuration. + properties: + slew-rate: + required: false + type: string + default: "max-speed-2mhz" + enum: + - "max-speed-10mhz" + - "max-speed-2mhz" + - "max-speed-50mhz" + - "max-speed-highest" + description: | + Set the maximum speed of a pin. This setting effectively limits the + slew rate of the output signal. Defaults to "max-speed-2mhz", the SoC + default. The max-speed-highest option may not be available on all SoC + variants. If selected and not available the 50 MHz maximum speed will + be used instead. Note that usage of max-speed-highest may require + enabling the I/O compensation cell (refer to the gd,gd32-afio binding + for more details). diff --git a/modules/hal_gigadevice/Kconfig b/modules/hal_gigadevice/Kconfig index b327b9a5c71e4..21c60b0ec6009 100644 --- a/modules/hal_gigadevice/Kconfig +++ b/modules/hal_gigadevice/Kconfig @@ -9,6 +9,11 @@ config GD32_HAS_AF_PINMUX help This option should be selected if the series use an AF pinmux model. +config GD32_HAS_AFIO_PINMUX + bool + help + This option should be selected if the series use an AFIO pinmux model. + config HAS_GD32_HAL bool select HAS_CMSIS_CORE if SOC_FAMILY_GD32_ARM diff --git a/soc/arm/gigadevice/common/pinctrl_soc.h b/soc/arm/gigadevice/common/pinctrl_soc.h index 062deb5b7037c..979a9eb465a55 100644 --- a/soc/arm/gigadevice/common/pinctrl_soc.h +++ b/soc/arm/gigadevice/common/pinctrl_soc.h @@ -13,9 +13,14 @@ #define ZEPHYR_SOC_ARM_GIGADEVICE_COMMON_PINCTRL_SOC_H_ #include -#include #include +#ifdef CONFIG_PINCTRL_GD32_AF +#include +#else +#include +#endif /* CONFIG_PINCTRL_GD32_AF */ + #ifdef __cplusplus extern "C" { #endif @@ -24,10 +29,15 @@ extern "C" { /** @brief Type for GD32 pin. * - * Bits: + * Bits (AF model): * - 0-12: GD32_PINMUX_AF bit field. * - 13-25: Reserved. * - 26-31: Pin configuration bit field (@ref GD32_PINCFG). + * + * Bits (AFIO model): + * - 0-19: GD32_PINMUX_AFIO bit field. + * - 20-25: Reserved. + * - 26-31: Pin configuration bit field (@ref GD32_PINCFG). */ typedef uint32_t pinctrl_soc_pin_t; @@ -62,7 +72,7 @@ typedef uint32_t pinctrl_soc_pin_t; /** @endcond */ /** - * @name GD32 PUPD (values match the ones in the HAL). + * @name GD32 PUPD (values match the ones in the HAL for AF model). * @{ */ @@ -76,7 +86,7 @@ typedef uint32_t pinctrl_soc_pin_t; /** @} */ /** - * @name GD32 OTYPE (values match the ones in the HAL). + * @name GD32 OTYPE (values match the ones in the HAL for AF model). * @{ */ @@ -88,10 +98,12 @@ typedef uint32_t pinctrl_soc_pin_t; /** @} */ /** - * @name GD32 OSPEED (values match the ones in the HAL). + * @name GD32 OSPEED (values match the ones in the HAL for AF model, mode minus + * one for AFIO model). * @{ */ +#ifdef CONFIG_PINCTRL_GD32_AF /** Maximum 2MHz */ #define GD32_OSPEED_2MHZ 0U /** Maximum 25MHz */ @@ -100,6 +112,16 @@ typedef uint32_t pinctrl_soc_pin_t; #define GD32_OSPEED_50MHZ 2U /** Maximum 200MHz */ #define GD32_OSPEED_200MHZ 3U +#else +/** Maximum 10MHz */ +#define GD32_OSPEED_10MHZ 0U +/** Maximum 2MHz */ +#define GD32_OSPEED_2MHZ 1U +/** Maximum 50MHz */ +#define GD32_OSPEED_50MHZ 2U +/** Maximum speed */ +#define GD32_OSPEED_MAX 3U +#endif /* CONFIG_PINCTRL_GD32_AF */ /** @} */ From 307b600ffaf212afd876834a46875d796dd00afb Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 4 Nov 2021 23:16:07 +0100 Subject: [PATCH 06/13] dts: arm: gigadevice: gd32f403: add afio and pinctrl Add afio, pinctrl and gpioa...g entries for the GD32F403 series. Signed-off-by: Gerard Marull-Paretas --- dts/arm/gigadevice/gd32f403/gd32f403.dtsi | 73 +++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/dts/arm/gigadevice/gd32f403/gd32f403.dtsi b/dts/arm/gigadevice/gd32f403/gd32f403.dtsi index c6b81fea778c9..9aa5ea2e09711 100644 --- a/dts/arm/gigadevice/gd32f403/gd32f403.dtsi +++ b/dts/arm/gigadevice/gd32f403/gd32f403.dtsi @@ -46,6 +46,79 @@ }; }; + afio: afio@40010000 { + compatible = "gd,gd32-afio"; + reg = <0x40010000 0x400>; + rcu-periph-clock = <0x600>; + status = "okay"; + label = "AFIO"; + }; + + pinctrl: pin-controller@40010800 { + compatible = "gd,gd32-pinctrl-afio"; + reg = <0x40010800 0x1c00>; + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + label = "PINCTRL"; + + gpioa: gpio@40010800 { + compatible = "gd,gd32-gpio"; + reg = <0x40010800 0x400>; + rcu-periph-clock = <0x602>; + status = "disabled"; + label = "GPIOA"; + }; + + gpiob: gpio@40010c00 { + compatible = "gd,gd32-gpio"; + reg = <0x40010c00 0x400>; + rcu-periph-clock = <0x603>; + status = "disabled"; + label = "GPIOB"; + }; + + gpioc: gpio@40011000 { + compatible = "gd,gd32-gpio"; + reg = <0x40011000 0x400>; + rcu-periph-clock = <0x604>; + status = "disabled"; + label = "GPIOC"; + }; + + gpiod: gpio@40011400 { + compatible = "gd,gd32-gpio"; + reg = <0x40011400 0x400>; + rcu-periph-clock = <0x605>; + status = "disabled"; + label = "GPIOD"; + }; + + gpioe: gpio@40011800 { + compatible = "gd,gd32-gpio"; + reg = <0x40011800 0x400>; + rcu-periph-clock = <0x606>; + status = "disabled"; + label = "GPIOE"; + }; + + gpiof: gpio@40011c00 { + compatible = "gd,gd32-gpio"; + reg = <0x40011c00 0x400>; + rcu-periph-clock = <0x607>; + status = "disabled"; + label = "GPIOF"; + }; + + gpiog: gpio@40012000 { + compatible = "gd,gd32-gpio"; + reg = <0x40012000 0x400>; + rcu-periph-clock = <0x608>; + status = "disabled"; + label = "GPIOG"; + }; + }; + usart0: usart@40013800 { compatible = "gd,gd32-usart"; reg = <0x40013800 0x400>; From aea9d02ecd40368f82ca7566cc3ddbc25f3c493a Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 7 Nov 2021 20:44:14 +0100 Subject: [PATCH 07/13] soc: arm: gigadevice: gd32f403: select AFIO pinmux GD32F403 series use AFIO pinmux model. Signed-off-by: Gerard Marull-Paretas --- soc/arm/gigadevice/gd32f403/Kconfig.series | 1 + 1 file changed, 1 insertion(+) diff --git a/soc/arm/gigadevice/gd32f403/Kconfig.series b/soc/arm/gigadevice/gd32f403/Kconfig.series index 9fe193e62c656..c96e1c731dde6 100644 --- a/soc/arm/gigadevice/gd32f403/Kconfig.series +++ b/soc/arm/gigadevice/gd32f403/Kconfig.series @@ -10,5 +10,6 @@ config SOC_SERIES_GD32F403 select CPU_CORTEX_M_HAS_SYSTICK select CPU_CORTEX_M_HAS_VTOR select SOC_FAMILY_GD32_ARM + select GD32_HAS_AFIO_PINMUX help Enable support for GigaDevice GD32F403 MCU series From 92054b6c6bfe493dcb67be2b0870236c141ca25b Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sat, 13 Nov 2021 18:19:13 +0100 Subject: [PATCH 08/13] soc: arm: gigadevice: enable pinctrl by default Enable pinctrl by default, since it is an essential component on almost every firmware. Inclusion of series defconfig has also been guarded with SoC availability (was missing). Signed-off-by: Gerard Marull-Paretas --- soc/arm/gigadevice/Kconfig.defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/soc/arm/gigadevice/Kconfig.defconfig b/soc/arm/gigadevice/Kconfig.defconfig index 1a17f737aec90..72911e9335cc4 100644 --- a/soc/arm/gigadevice/Kconfig.defconfig +++ b/soc/arm/gigadevice/Kconfig.defconfig @@ -1,4 +1,11 @@ # Copyright (c) 2021, ATL Electronics # SPDX-License-Identifier: Apache-2.0 +if SOC_FAMILY_GD32 + source "soc/arm/gigadevice/*/Kconfig.defconfig.series" + +config PINCTRL + default y + +endif # SOC_FAMILY_GD32 From aee0268fd2bfe6474c76cafcde24adf8a56153f1 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 22:22:04 +0100 Subject: [PATCH 09/13] drivers: serial: gd32: use pinctrl Use the pinctrl API to configure peripheral pins. Signed-off-by: Gerard Marull-Paretas --- drivers/serial/usart_gd32.c | 10 +++++++++- dts/bindings/serial/gd,gd32-usart.yaml | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/serial/usart_gd32.c b/drivers/serial/usart_gd32.c index 012824a7c202f..16486ef769b25 100644 --- a/drivers/serial/usart_gd32.c +++ b/drivers/serial/usart_gd32.c @@ -5,11 +5,13 @@ #define DT_DRV_COMPAT gd_gd32_usart +#include #include struct gd32_usart_config { uint32_t reg; uint32_t rcu_periph_clock; + const struct pinctrl_dev_config *pcfg; }; struct gd32_usart_data { @@ -20,8 +22,12 @@ static int usart_gd32_init(const struct device *dev) { const struct gd32_usart_config *const cfg = dev->config; struct gd32_usart_data *const data = dev->data; + int ret; - /* NOTE: pins are configured at board_init till pinctrl be available */ + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } rcu_periph_clock_enable(cfg->rcu_periph_clock); usart_deinit(cfg->reg); @@ -100,12 +106,14 @@ static const struct uart_driver_api usart_gd32_driver_api = { }; #define GD32_USART_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n) \ static struct gd32_usart_data usart##n##_gd32_data = { \ .baud_rate = DT_INST_PROP(n, current_speed), \ }; \ static const struct gd32_usart_config usart##n##_gd32_config = { \ .reg = DT_INST_REG_ADDR(n), \ .rcu_periph_clock = DT_INST_PROP(n, rcu_periph_clock), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ }; \ DEVICE_DT_INST_DEFINE(n, &usart_gd32_init, \ NULL, \ diff --git a/dts/bindings/serial/gd,gd32-usart.yaml b/dts/bindings/serial/gd,gd32-usart.yaml index b12eca413276a..1110c3bea3305 100644 --- a/dts/bindings/serial/gd,gd32-usart.yaml +++ b/dts/bindings/serial/gd,gd32-usart.yaml @@ -5,7 +5,7 @@ description: GigaDevice USART compatible: "gd,gd32-usart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: From 4dfd336526be44053f94c219d76828a40407efe7 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 21:40:37 +0100 Subject: [PATCH 10/13] boards: gd32f450i_eval: use pinctrl Enable usage of the pinctrl driver. Signed-off-by: Gerard Marull-Paretas --- boards/arm/gd32f450i_eval/CMakeLists.txt | 5 ---- boards/arm/gd32f450i_eval/board.c | 27 ------------------- .../gd32f450i_eval-pinctrl.dtsi | 14 ++++++++++ boards/arm/gd32f450i_eval/gd32f450i_eval.dts | 3 +++ 4 files changed, 17 insertions(+), 32 deletions(-) delete mode 100644 boards/arm/gd32f450i_eval/CMakeLists.txt delete mode 100644 boards/arm/gd32f450i_eval/board.c create mode 100644 boards/arm/gd32f450i_eval/gd32f450i_eval-pinctrl.dtsi diff --git a/boards/arm/gd32f450i_eval/CMakeLists.txt b/boards/arm/gd32f450i_eval/CMakeLists.txt deleted file mode 100644 index abca855a4b82a..0000000000000 --- a/boards/arm/gd32f450i_eval/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021, Teslabs Engineering S.L. -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() -zephyr_library_sources(board.c) diff --git a/boards/arm/gd32f450i_eval/board.c b/boards/arm/gd32f450i_eval/board.c deleted file mode 100644 index 28555ee344c73..0000000000000 --- a/boards/arm/gd32f450i_eval/board.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2021, Teslabs Engineering S.L. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -static int board_init(const struct device *dev) -{ - rcu_periph_clock_enable(RCU_GPIOA); - - /* PA9: USART0 TX */ - gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9); - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_9); - - /* PA10: USART0 RX */ - gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10); - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_10); - - rcu_periph_clock_disable(RCU_GPIOA); - - return 0; -} - -SYS_INIT(board_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY); diff --git a/boards/arm/gd32f450i_eval/gd32f450i_eval-pinctrl.dtsi b/boards/arm/gd32f450i_eval/gd32f450i_eval-pinctrl.dtsi new file mode 100644 index 0000000000000..3ba9e064d4765 --- /dev/null +++ b/boards/arm/gd32f450i_eval/gd32f450i_eval-pinctrl.dtsi @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + usart0_default: usart0_default { + group1 { + pinmux = , ; + }; + }; +}; diff --git a/boards/arm/gd32f450i_eval/gd32f450i_eval.dts b/boards/arm/gd32f450i_eval/gd32f450i_eval.dts index 56d6757461cf0..729468a5cca5b 100644 --- a/boards/arm/gd32f450i_eval/gd32f450i_eval.dts +++ b/boards/arm/gd32f450i_eval/gd32f450i_eval.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include "gd32f450i_eval-pinctrl.dtsi" / { model = "GigaDevice GD32F450I-EVAL"; @@ -22,4 +23,6 @@ &usart0 { status = "okay"; current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; }; From 436447d653bd09963158ddc4e579e0650d1baefb Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 7 Nov 2021 19:47:55 +0100 Subject: [PATCH 11/13] boards: gd32f403z_eval: use pinctrl Enable usage of pinctrl. Signed-off-by: Gerard Marull-Paretas --- boards/arm/gd32f403z_eval/CMakeLists.txt | 5 ----- boards/arm/gd32f403z_eval/board.c | 18 ------------------ .../gd32f403z_eval/gd32f403z_eval-pinctrl.dtsi | 14 ++++++++++++++ boards/arm/gd32f403z_eval/gd32f403z_eval.dts | 4 +++- 4 files changed, 17 insertions(+), 24 deletions(-) delete mode 100644 boards/arm/gd32f403z_eval/CMakeLists.txt delete mode 100644 boards/arm/gd32f403z_eval/board.c create mode 100644 boards/arm/gd32f403z_eval/gd32f403z_eval-pinctrl.dtsi diff --git a/boards/arm/gd32f403z_eval/CMakeLists.txt b/boards/arm/gd32f403z_eval/CMakeLists.txt deleted file mode 100644 index 159b5bc2592c9..0000000000000 --- a/boards/arm/gd32f403z_eval/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() -zephyr_library_sources(board.c) diff --git a/boards/arm/gd32f403z_eval/board.c b/boards/arm/gd32f403z_eval/board.c deleted file mode 100644 index 9786e5339e5c0..0000000000000 --- a/boards/arm/gd32f403z_eval/board.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2021 ATL Electronics - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -static int board_init(const struct device *dev) -{ - rcu_periph_clock_enable(RCU_GPIOA); - - gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); - gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); - - return 0; -} - -SYS_INIT(board_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY); diff --git a/boards/arm/gd32f403z_eval/gd32f403z_eval-pinctrl.dtsi b/boards/arm/gd32f403z_eval/gd32f403z_eval-pinctrl.dtsi new file mode 100644 index 0000000000000..bcd17d6692cc8 --- /dev/null +++ b/boards/arm/gd32f403z_eval/gd32f403z_eval-pinctrl.dtsi @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + usart0_default: usart0_default { + group1 { + pinmux = , ; + }; + }; +}; diff --git a/boards/arm/gd32f403z_eval/gd32f403z_eval.dts b/boards/arm/gd32f403z_eval/gd32f403z_eval.dts index 6dda970076793..29ba67b12a717 100644 --- a/boards/arm/gd32f403z_eval/gd32f403z_eval.dts +++ b/boards/arm/gd32f403z_eval/gd32f403z_eval.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include "gd32f403z_eval-pinctrl.dtsi" / { model = "GigaDevice GD32F403Z Evaluation Kit"; @@ -21,6 +22,7 @@ &usart0 { status = "okay"; - current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; }; From b74a90761f98671fd6675033b925ef079c99fb7d Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 1 Nov 2021 22:52:54 +0100 Subject: [PATCH 12/13] tests: drivers: pinctrl: gd32: add DT AF parse test Add a test to check that DT information for AF model is extracted correctly. Signed-off-by: Gerard Marull-Paretas --- tests/drivers/pinctrl/gd32/CMakeLists.txt | 12 ++ tests/drivers/pinctrl/gd32/Kconfig | 13 ++ .../gd32/boards/gd32f450i_eval.overlay | 63 +++++++++ tests/drivers/pinctrl/gd32/prj.conf | 5 + tests/drivers/pinctrl/gd32/src/main_af.c | 128 ++++++++++++++++++ tests/drivers/pinctrl/gd32/testcase.yaml | 7 + 6 files changed, 228 insertions(+) create mode 100644 tests/drivers/pinctrl/gd32/CMakeLists.txt create mode 100644 tests/drivers/pinctrl/gd32/Kconfig create mode 100644 tests/drivers/pinctrl/gd32/boards/gd32f450i_eval.overlay create mode 100644 tests/drivers/pinctrl/gd32/prj.conf create mode 100644 tests/drivers/pinctrl/gd32/src/main_af.c create mode 100644 tests/drivers/pinctrl/gd32/testcase.yaml diff --git a/tests/drivers/pinctrl/gd32/CMakeLists.txt b/tests/drivers/pinctrl/gd32/CMakeLists.txt new file mode 100644 index 0000000000000..898ed03c80468 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(pinctrl_gd32) + +target_sources(app PRIVATE ../common/test_device.c) +if(CONFIG_PINCTRL_GD32_AF) + target_sources(app PRIVATE src/main_af.c) +endif() diff --git a/tests/drivers/pinctrl/gd32/Kconfig b/tests/drivers/pinctrl/gd32/Kconfig new file mode 100644 index 0000000000000..363b78eff6443 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "pinctrl GD32 DT Test" + +source "Kconfig.zephyr" + +config PINCTRL_TEST_NON_STATIC + bool "Enable access to pin control configuration" + select PINCTRL_NON_STATIC + help + This option should be selected by unit tests that need to access the pin + control configuration defined in a device driver. diff --git a/tests/drivers/pinctrl/gd32/boards/gd32f450i_eval.overlay b/tests/drivers/pinctrl/gd32/boards/gd32f450i_eval.overlay new file mode 100644 index 0000000000000..361605f5d5d2b --- /dev/null +++ b/tests/drivers/pinctrl/gd32/boards/gd32f450i_eval.overlay @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + test_device: test_device { + compatible = "vnd,pinctrl-device"; + pinctrl-0 = <&test_device_default>; + pinctrl-names = "default"; + }; +}; + +&pinctrl { + test_device_default: test_device_default { + /* Note: the groups are just meant for testing if properties and + pins are parsed correctly, but do not necessarily represent a + feasible combination */ + pins1 { + pinmux = , + ; + }; + pins2 { + pinmux = ; + drive-push-pull; + }; + pins3 { + pinmux = ; + drive-open-drain; + }; + pins4 { + pinmux = ; + bias-disable; + }; + pins5 { + pinmux = ; + bias-pull-up; + }; + pins6 { + pinmux = ; + bias-pull-down; + }; + pins7 { + pinmux = ; + slew-rate = "max-speed-2mhz"; + }; + pins8 { + pinmux = ; + slew-rate = "max-speed-25mhz"; + }; + pins9 { + pinmux = ; + slew-rate = "max-speed-50mhz"; + }; + pins10 { + pinmux = ; + slew-rate = "max-speed-200mhz"; + }; + pins11 { + pinmux = ; + }; + }; +}; diff --git a/tests/drivers/pinctrl/gd32/prj.conf b/tests/drivers/pinctrl/gd32/prj.conf new file mode 100644 index 0000000000000..bb844ad2efa15 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/prj.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_PINCTRL_TEST_NON_STATIC=y diff --git a/tests/drivers/pinctrl/gd32/src/main_af.c b/tests/drivers/pinctrl/gd32/src/main_af.c new file mode 100644 index 0000000000000..f38ed74c3b042 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/src/main_af.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* pin configuration for test device */ +#define TEST_DEVICE DT_NODELABEL(test_device) +PINCTRL_DT_DEV_CONFIG_DECLARE(TEST_DEVICE); +static const struct pinctrl_dev_config *pcfg = PINCTRL_DT_DEV_CONFIG_GET(TEST_DEVICE); + +static void test_dt_extract(void) +{ + const struct pinctrl_state *scfg; + pinctrl_soc_pin_t pin; + + zassert_equal(pcfg->state_cnt, 1U, NULL); + + scfg = &pcfg->states[0]; + + zassert_equal(scfg->id, PINCTRL_STATE_DEFAULT, NULL); + zassert_equal(scfg->pin_cnt, 12U, NULL); + + pin = scfg->pins[0]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 0, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF0, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[1]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 1, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF1, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[2]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 2, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF2, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[3]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 3, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF3, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_OD, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[4]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 4, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF4, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[5]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 5, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF5, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_PULLUP, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[6]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 6, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF6, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_PULLDOWN, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[7]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 7, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF7, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[8]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 8, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF8, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_25MHZ, NULL); + + pin = scfg->pins[9]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 9, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF9, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_50MHZ, NULL); + + pin = scfg->pins[10]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 10, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_AF10, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_200MHZ, NULL); + + pin = scfg->pins[11]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 11, NULL); + zassert_equal(GD32_AF_GET(pin), GD32_ANALOG, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); +} + +void test_main(void) +{ + ztest_test_suite(pinctrl_gd32, + ztest_unit_test(test_dt_extract)); + ztest_run_test_suite(pinctrl_gd32); +} diff --git a/tests/drivers/pinctrl/gd32/testcase.yaml b/tests/drivers/pinctrl/gd32/testcase.yaml new file mode 100644 index 0000000000000..881f9c963e276 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/testcase.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +tests: + drivers.pinctrl.gd32_af: + tags: drivers pinctrl + platform_allow: gd32f450i_eval From 148b495d8a50ad8a483233bb03aa08af15184fee Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Sun, 7 Nov 2021 21:27:20 +0100 Subject: [PATCH 13/13] tests: drivers: pinctrl: gd32: add DT AFIO parse test Add a test to check that DT information for the AFIO model is extracted correctly. Signed-off-by: Gerard Marull-Paretas --- tests/drivers/pinctrl/gd32/CMakeLists.txt | 2 + .../gd32/boards/gd32f403z_eval.overlay | 67 +++++++++ tests/drivers/pinctrl/gd32/src/main_afio.c | 142 ++++++++++++++++++ tests/drivers/pinctrl/gd32/testcase.yaml | 3 + 4 files changed, 214 insertions(+) create mode 100644 tests/drivers/pinctrl/gd32/boards/gd32f403z_eval.overlay create mode 100644 tests/drivers/pinctrl/gd32/src/main_afio.c diff --git a/tests/drivers/pinctrl/gd32/CMakeLists.txt b/tests/drivers/pinctrl/gd32/CMakeLists.txt index 898ed03c80468..0595ab1980116 100644 --- a/tests/drivers/pinctrl/gd32/CMakeLists.txt +++ b/tests/drivers/pinctrl/gd32/CMakeLists.txt @@ -9,4 +9,6 @@ project(pinctrl_gd32) target_sources(app PRIVATE ../common/test_device.c) if(CONFIG_PINCTRL_GD32_AF) target_sources(app PRIVATE src/main_af.c) +elseif(CONFIG_PINCTRL_GD32_AFIO) + target_sources(app PRIVATE src/main_afio.c) endif() diff --git a/tests/drivers/pinctrl/gd32/boards/gd32f403z_eval.overlay b/tests/drivers/pinctrl/gd32/boards/gd32f403z_eval.overlay new file mode 100644 index 0000000000000..08255bf651750 --- /dev/null +++ b/tests/drivers/pinctrl/gd32/boards/gd32f403z_eval.overlay @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +#define GD32_TEST_DEVICE_RMP GD32_REMAP(0, 0, 0x1U, 1) + +/ { + test_device: test_device { + compatible = "vnd,pinctrl-device"; + pinctrl-0 = <&test_device_default>; + pinctrl-names = "default"; + }; +}; + +&pinctrl { + test_device_default: test_device_default { + /* Note: the groups are just meant for testing if properties and + pins are parsed correctly, but do not necessarily represent a + feasible combination */ + pins1 { + pinmux = , + , + ; + }; + pins2 { + pinmux = , + ; + }; + pins3 { + pinmux = ; + drive-push-pull; + }; + pins4 { + pinmux = ; + drive-open-drain; + }; + pins5 { + pinmux = ; + bias-disable; + }; + pins6 { + pinmux = ; + bias-pull-up; + }; + pins7 { + pinmux = ; + bias-pull-down; + }; + pins8 { + pinmux = ; + slew-rate = "max-speed-2mhz"; + }; + pins9 { + pinmux = ; + slew-rate = "max-speed-10mhz"; + }; + pins10 { + pinmux = ; + slew-rate = "max-speed-50mhz"; + }; + pins11 { + pinmux = ; + slew-rate = "max-speed-highest"; + }; + }; +}; diff --git a/tests/drivers/pinctrl/gd32/src/main_afio.c b/tests/drivers/pinctrl/gd32/src/main_afio.c new file mode 100644 index 0000000000000..97ad8550eecea --- /dev/null +++ b/tests/drivers/pinctrl/gd32/src/main_afio.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Teslabs Engineering S.L. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* pin configuration for test device */ +#define TEST_DEVICE DT_NODELABEL(test_device) +PINCTRL_DT_DEV_CONFIG_DECLARE(TEST_DEVICE); +static const struct pinctrl_dev_config *pcfg = PINCTRL_DT_DEV_CONFIG_GET(TEST_DEVICE); + +static void test_dt_extract(void) +{ + const struct pinctrl_state *scfg; + pinctrl_soc_pin_t pin; + + zassert_equal(pcfg->state_cnt, 1U, NULL); + + scfg = &pcfg->states[0]; + + zassert_equal(scfg->id, PINCTRL_STATE_DEFAULT, NULL); + zassert_equal(scfg->pin_cnt, 14U, NULL); + + pin = scfg->pins[0]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 0, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ANALOG, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + + pin = scfg->pins[1]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 1, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[2]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 2, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[3]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 3, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_REG_GET(GD32_REMAP_GET(pin)), 0, NULL); + zassert_equal(GD32_REMAP_POS_GET(GD32_REMAP_GET(pin)), 0, NULL); + zassert_equal(GD32_REMAP_MSK_GET(GD32_REMAP_GET(pin)), 0x1, NULL); + zassert_equal(GD32_REMAP_VAL_GET(GD32_REMAP_GET(pin)), 1, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[4]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 4, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_REG_GET(GD32_REMAP_GET(pin)), 0, NULL); + zassert_equal(GD32_REMAP_POS_GET(GD32_REMAP_GET(pin)), 0, NULL); + zassert_equal(GD32_REMAP_MSK_GET(GD32_REMAP_GET(pin)), 0x1, NULL); + zassert_equal(GD32_REMAP_VAL_GET(GD32_REMAP_GET(pin)), 1, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[5]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 5, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[6]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 6, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_OD, NULL); + + pin = scfg->pins[7]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 7, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_NONE, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[8]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 8, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_PULLUP, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[9]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 9, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_GPIO_IN, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_PUPD_GET(pin), GD32_PUPD_PULLDOWN, NULL); + zassert_equal(GD32_OTYPE_GET(pin), GD32_OTYPE_PP, NULL); + + pin = scfg->pins[10]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 10, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_2MHZ, NULL); + + pin = scfg->pins[11]; + zassert_equal(GD32_PORT_GET(pin), 2, NULL); + zassert_equal(GD32_PIN_GET(pin), 11, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_10MHZ, NULL); + + pin = scfg->pins[12]; + zassert_equal(GD32_PORT_GET(pin), 0, NULL); + zassert_equal(GD32_PIN_GET(pin), 12, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_50MHZ, NULL); + + pin = scfg->pins[13]; + zassert_equal(GD32_PORT_GET(pin), 1, NULL); + zassert_equal(GD32_PIN_GET(pin), 13, NULL); + zassert_equal(GD32_MODE_GET(pin), GD32_MODE_ALTERNATE, NULL); + zassert_equal(GD32_REMAP_GET(pin), GD32_NORMP, NULL); + zassert_equal(GD32_OSPEED_GET(pin), GD32_OSPEED_MAX, NULL); +} + +void test_main(void) +{ + ztest_test_suite(pinctrl_gd32, + ztest_unit_test(test_dt_extract)); + ztest_run_test_suite(pinctrl_gd32); +} diff --git a/tests/drivers/pinctrl/gd32/testcase.yaml b/tests/drivers/pinctrl/gd32/testcase.yaml index 881f9c963e276..2d4e164b65196 100644 --- a/tests/drivers/pinctrl/gd32/testcase.yaml +++ b/tests/drivers/pinctrl/gd32/testcase.yaml @@ -5,3 +5,6 @@ tests: drivers.pinctrl.gd32_af: tags: drivers pinctrl platform_allow: gd32f450i_eval + drivers.pinctrl.gd32_afio: + tags: drivers pinctrl + platform_allow: gd32f403z_eval