Commit 543a3843 authored by Gerard Marull-Paretas's avatar Gerard Marull-Paretas Committed by Anas Nashif
Browse files

drivers: pinctrl: gd32: initial support for AF based SoCs



Add a pin control driver for GD32 SoCs using the AF model.

Signed-off-by: default avatarGerard Marull-Paretas <gerard@teslabs.com>
parent df6dd42c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,3 +3,4 @@

zephyr_library()
zephyr_library_sources(common.c)
zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c)
+2 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
# 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 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
# 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
Loading