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 <gerard@teslabs.com>
This commit is contained in:
parent
df6dd42ca3
commit
543a3843ff
11 changed files with 455 additions and 0 deletions
|
@ -3,3 +3,4 @@
|
|||
|
||||
zephyr_library()
|
||||
zephyr_library_sources(common.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c)
|
||||
|
|
|
@ -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
|
||||
|
|
12
drivers/pinctrl/Kconfig.gd32
Normal file
12
drivers/pinctrl/Kconfig.gd32
Normal file
|
@ -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.
|
104
drivers/pinctrl/pinctrl_gd32_af.c
Normal file
104
drivers/pinctrl/pinctrl_gd32_af.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Teslabs Engineering S.L.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <drivers/pinctrl.h>
|
||||
|
||||
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;
|
||||
}
|
27
dts/bindings/gpio/gd,gd32-gpio.yaml
Normal file
27
dts/bindings/gpio/gd,gd32-gpio.yaml
Normal file
|
@ -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
|
111
dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml
Normal file
111
dts/bindings/pinctrl/gd,gd32-pinctrl-af.yaml
Normal file
|
@ -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 <dt-bindings/pinctrl/gd32f450i(g-i-k)xx-pinctrl.h>
|
||||
|
||||
&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 = <USART0_TX_PA9>, <USART0_CTS_PA11>;
|
||||
};
|
||||
/* group 2 */
|
||||
group2 {
|
||||
/* configure PA10 as USART0 RX and PA12 as USART0 RTS */
|
||||
pinmux = <USART0_RX_PA10>, <USART0_RTS_PA12>;
|
||||
/* 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 = <ANALOG_PA9>, <ANALOG_PA10>, <ANALOG_PA12>, <ANALOG_PA11>;
|
||||
};
|
||||
};
|
||||
|
||||
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.
|
26
dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml
Normal file
26
dts/bindings/pinctrl/gd,gd32-pinctrl-common.yaml
Normal file
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright (c) 2021, ATL Electronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(${SOC_SERIES})
|
||||
|
|
4
soc/arm/gigadevice/common/CMakeLists.txt
Normal file
4
soc/arm/gigadevice/common/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) 2021 Teslabs Engineering S.L.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_include_directories(.)
|
162
soc/arm/gigadevice/common/pinctrl_soc.h
Normal file
162
soc/arm/gigadevice/common/pinctrl_soc.h
Normal file
|
@ -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 <devicetree.h>
|
||||
#include <dt-bindings/pinctrl/gd32-af.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#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_ */
|
Loading…
Add table
Add a link
Reference in a new issue