1 /*
2 * Copyright (c) 2021 Teslabs Engineering S.L.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/clock_control.h>
8 #include <zephyr/drivers/clock_control/gd32.h>
9 #include <zephyr/drivers/pinctrl.h>
10
11 #include <gd32_gpio.h>
12
13 BUILD_ASSERT((GD32_PUPD_NONE == GPIO_PUPD_NONE) &&
14 (GD32_PUPD_PULLUP == GPIO_PUPD_PULLUP) &&
15 (GD32_PUPD_PULLDOWN == GPIO_PUPD_PULLDOWN),
16 "pinctrl pull-up/down definitions != HAL definitions");
17
18 BUILD_ASSERT((GD32_OTYPE_PP == GPIO_OTYPE_PP) &&
19 (GD32_OTYPE_OD == GPIO_OTYPE_OD),
20 "pinctrl output type definitions != HAL definitions");
21
22 BUILD_ASSERT((GD32_OSPEED_2MHZ == GPIO_OSPEED_2MHZ) &&
23 #if defined(CONFIG_SOC_SERIES_GD32F3X0) || \
24 defined(CONFIG_SOC_SERIES_GD32A50X) || \
25 defined(CONFIG_SOC_SERIES_GD32L23X)
26 (GD32_OSPEED_10MHZ == GPIO_OSPEED_10MHZ) &&
27 (GD32_OSPEED_50MHZ == GPIO_OSPEED_50MHZ) &&
28 #else
29 (GD32_OSPEED_25MHZ == GPIO_OSPEED_25MHZ) &&
30 (GD32_OSPEED_50MHZ == GPIO_OSPEED_50MHZ) &&
31 (GD32_OSPEED_MAX == GPIO_OSPEED_MAX) &&
32 #endif
33 1U,
34 "pinctrl output speed definitions != HAL definitions");
35
36 /** Utility macro that expands to the GPIO port address if it exists */
37 #define GD32_PORT_ADDR_OR_NONE(nodelabel) \
38 COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \
39 (DT_REG_ADDR(DT_NODELABEL(nodelabel)),), ())
40
41 /** Utility macro that expands to the GPIO clock id if it exists */
42 #define GD32_PORT_CLOCK_ID_OR_NONE(nodelabel) \
43 COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \
44 (DT_CLOCKS_CELL(DT_NODELABEL(nodelabel), id),), ())
45
46 /** GD32 port addresses */
47 static const uint32_t gd32_port_addrs[] = {
48 GD32_PORT_ADDR_OR_NONE(gpioa)
49 GD32_PORT_ADDR_OR_NONE(gpiob)
50 GD32_PORT_ADDR_OR_NONE(gpioc)
51 GD32_PORT_ADDR_OR_NONE(gpiod)
52 GD32_PORT_ADDR_OR_NONE(gpioe)
53 GD32_PORT_ADDR_OR_NONE(gpiof)
54 GD32_PORT_ADDR_OR_NONE(gpiog)
55 GD32_PORT_ADDR_OR_NONE(gpioh)
56 GD32_PORT_ADDR_OR_NONE(gpioi)
57 };
58
59 /** GD32 port clock identifiers */
60 static const uint16_t gd32_port_clkids[] = {
61 GD32_PORT_CLOCK_ID_OR_NONE(gpioa)
62 GD32_PORT_CLOCK_ID_OR_NONE(gpiob)
63 GD32_PORT_CLOCK_ID_OR_NONE(gpioc)
64 GD32_PORT_CLOCK_ID_OR_NONE(gpiod)
65 GD32_PORT_CLOCK_ID_OR_NONE(gpioe)
66 GD32_PORT_CLOCK_ID_OR_NONE(gpiof)
67 GD32_PORT_CLOCK_ID_OR_NONE(gpiog)
68 GD32_PORT_CLOCK_ID_OR_NONE(gpioh)
69 GD32_PORT_CLOCK_ID_OR_NONE(gpioi)
70 };
71
72 /**
73 * @brief Configure a pin.
74 *
75 * @param pin The pin to configure.
76 */
pinctrl_configure_pin(pinctrl_soc_pin_t pin)77 static void pinctrl_configure_pin(pinctrl_soc_pin_t pin)
78 {
79 uint8_t port_idx;
80 uint32_t port, pin_num, af, mode;
81 uint16_t clkid;
82
83 port_idx = GD32_PORT_GET(pin);
84 __ASSERT_NO_MSG(port_idx < ARRAY_SIZE(gd32_port_addrs));
85
86 clkid = gd32_port_clkids[port_idx];
87 port = gd32_port_addrs[port_idx];
88 pin_num = BIT(GD32_PIN_GET(pin));
89 af = GD32_AF_GET(pin);
90
91 (void)clock_control_on(GD32_CLOCK_CONTROLLER,
92 (clock_control_subsys_t)&clkid);
93
94 if (af != GD32_ANALOG) {
95 mode = GPIO_MODE_AF;
96 gpio_af_set(port, af, pin_num);
97 } else {
98 mode = GPIO_MODE_ANALOG;
99 }
100
101 gpio_mode_set(port, mode, GD32_PUPD_GET(pin), pin_num);
102 gpio_output_options_set(port, GD32_OTYPE_GET(pin),
103 GD32_OSPEED_GET(pin), pin_num);
104 }
105
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)106 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
107 uintptr_t reg)
108 {
109 ARG_UNUSED(reg);
110
111 for (uint8_t i = 0U; i < pin_cnt; i++) {
112 pinctrl_configure_pin(pins[i]);
113 }
114
115 return 0;
116 }
117