105 lines
2.8 KiB
C
105 lines
2.8 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|