1 /*
2 * Copyright (c) 2016 Open-RnD Sp. z o.o.
3 * Copyright (c) 2021 Linaro Limited
4 * Copyright (c) 2021 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/init.h>
10 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <gpio/gpio_stm32.h>
13
14 #include <stm32_ll_bus.h>
15 #include <stm32_ll_gpio.h>
16 #include <stm32_ll_system.h>
17
18 /** Helper to extract IO port number from STM32PIN() encoded value */
19 #define STM32_PORT(__pin) \
20 ((__pin) >> 4)
21
22 /** Helper to extract IO pin number from STM32PIN() encoded value */
23 #define STM32_PIN(__pin) \
24 ((__pin) & 0xf)
25
26 /** Helper to extract IO port number from STM32_PINMUX() encoded value */
27 #define STM32_DT_PINMUX_PORT(__pin) \
28 (((__pin) >> STM32_PORT_SHIFT) & STM32_PORT_MASK)
29
30 /** Helper to extract IO pin number from STM32_PINMUX() encoded value */
31 #define STM32_DT_PINMUX_LINE(__pin) \
32 (((__pin) >> STM32_LINE_SHIFT) & STM32_LINE_MASK)
33
34 /** Helper to extract IO pin func from STM32_PINMUX() encoded value */
35 #define STM32_DT_PINMUX_FUNC(__pin) \
36 (((__pin) >> STM32_MODE_SHIFT) & STM32_MODE_MASK)
37
38 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
39 /** Helper to extract IO pin remap from STM32_PINMUX() encoded value */
40 #define STM32_DT_PINMUX_REMAP(__pin) \
41 (((__pin) >> STM32_REMAP_SHIFT) & STM32_REMAP_MASK)
42 #endif
43
44 /**
45 * @brief Array containing pointers to each GPIO port.
46 *
47 * Entries will be NULL if the GPIO port is not enabled.
48 */
49 static const struct device *const gpio_ports[] = {
50 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioa)),
51 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiob)),
52 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioc)),
53 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiod)),
54 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioe)),
55 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiof)),
56 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiog)),
57 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioh)),
58 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioi)),
59 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioj)),
60 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiok)),
61 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiol)),
62 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiom)),
63 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpion)),
64 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioo)),
65 DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiop)),
66 };
67
68 /** Number of GPIO ports. */
69 static const size_t gpio_ports_cnt = ARRAY_SIZE(gpio_ports);
70
71 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa11)
72 #define REMAP_PA11 DT_PROP(DT_NODELABEL(pinctrl), remap_pa11)
73 #endif
74 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa12)
75 #define REMAP_PA12 DT_PROP(DT_NODELABEL(pinctrl), remap_pa12)
76 #endif
77 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa11_pa12)
78 #define REMAP_PA11_PA12 DT_PROP(DT_NODELABEL(pinctrl), remap_pa11_pa12)
79 #endif
80
81 #if REMAP_PA11 || REMAP_PA12 || REMAP_PA11_PA12
82
stm32_pinmux_init_remap(void)83 int stm32_pinmux_init_remap(void)
84 {
85
86 #if REMAP_PA11 || REMAP_PA12
87
88 #if !defined(CONFIG_SOC_SERIES_STM32G0X) && !defined(CONFIG_SOC_SERIES_STM32C0X)
89 #error "Pin remap property available only on STM32G0 and STM32C0 SoC series"
90 #endif
91
92 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
93 #if REMAP_PA11
94 LL_SYSCFG_EnablePinRemap(LL_SYSCFG_PIN_RMP_PA11);
95 #endif
96 #if REMAP_PA12
97 LL_SYSCFG_EnablePinRemap(LL_SYSCFG_PIN_RMP_PA12);
98 #endif
99
100 #elif REMAP_PA11_PA12
101
102 #if !defined(SYSCFG_CFGR1_PA11_PA12_RMP)
103 #error "Pin remap property available only on STM32F070x SoC series"
104 #endif
105
106 LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
107 LL_SYSCFG_EnablePinRemap();
108
109 #endif /* (REMAP_PA11 || REMAP_PA12) || REMAP_PA11_PA12 */
110
111 return 0;
112 }
113
114 SYS_INIT(stm32_pinmux_init_remap, PRE_KERNEL_1,
115 CONFIG_PINCTRL_STM32_REMAP_INIT_PRIORITY);
116
117 #endif /* REMAP_PA11 || REMAP_PA12 || REMAP_PA11_PA12 */
118
119 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
120
121 /* ignore swj-cfg reset state (default value) */
122 #if ((DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), swj_cfg)) && \
123 (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) != 0))
124
stm32f1_swj_cfg_init(void)125 static int stm32f1_swj_cfg_init(void)
126 {
127
128 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
129
130 /* reset state is '000' (Full SWJ, (JTAG-DP + SW-DP)) */
131 /* only one of the 3 bits can be set */
132 #if (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 1)
133 /* 001: Full SWJ (JTAG-DP + SW-DP) but without NJTRST */
134 /* releases: PB4 */
135 LL_GPIO_AF_Remap_SWJ_NONJTRST();
136 #elif (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 2)
137 /* 010: JTAG-DP Disabled and SW-DP Enabled */
138 /* releases: PB4 PB3 PA15 */
139 LL_GPIO_AF_Remap_SWJ_NOJTAG();
140 #elif (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 3)
141 /* 100: JTAG-DP Disabled and SW-DP Disabled */
142 /* releases: PB4 PB3 PA13 PA14 PA15 */
143 LL_GPIO_AF_DisableRemap_SWJ();
144 #endif
145
146 return 0;
147 }
148
149 SYS_INIT(stm32f1_swj_cfg_init, PRE_KERNEL_1, 0);
150
151 #endif /* DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), swj_cfg) */
152
153 /**
154 * @brief Helper function to check and apply provided pinctrl remap
155 * configuration.
156 *
157 * Check operation verifies that pin remapping configuration is the same on all
158 * pins. If configuration is valid AFIO clock is enabled and remap is applied
159 *
160 * @param pins List of pins to be configured.
161 * @param pin_cnt Number of pins.
162 *
163 * @retval 0 If successful
164 * @retval -EINVAL If pins have an incompatible set of remaps.
165 */
stm32_pins_remap(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt)166 static int stm32_pins_remap(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt)
167 {
168 uint32_t reg_val;
169 uint16_t remap;
170
171 remap = (uint16_t)STM32_DT_PINMUX_REMAP(pins[0].pinmux);
172
173 /* not remappable */
174 if (remap == NO_REMAP) {
175 return 0;
176 }
177
178 for (size_t i = 1U; i < pin_cnt; i++) {
179 if (STM32_DT_PINMUX_REMAP(pins[i].pinmux) != remap) {
180 return -EINVAL;
181 }
182 }
183
184 /* A valid remapping configuration is available */
185 /* Apply remapping before proceeding with pin configuration */
186 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
187
188 if (STM32_REMAP_REG_GET(remap) == 0U) {
189 /* read initial value, ignore write-only SWJ_CFG */
190 reg_val = AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG;
191 reg_val |= STM32_REMAP_VAL_GET(remap) << STM32_REMAP_SHIFT_GET(remap);
192 /* apply undocumented '111' (AFIO_MAPR_SWJ_CFG) to affirm SWJ_CFG */
193 /* the pins are not remapped without that (when SWJ_CFG is not default) */
194 AFIO->MAPR = reg_val | AFIO_MAPR_SWJ_CFG;
195 } else {
196 reg_val = AFIO->MAPR2;
197 reg_val |= STM32_REMAP_VAL_GET(remap) << STM32_REMAP_SHIFT_GET(remap);
198 AFIO->MAPR2 = reg_val;
199 }
200
201 return 0;
202 }
203
204 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
205
stm32_pin_configure(uint32_t pin,uint32_t pin_cgf,uint32_t pin_func)206 static int stm32_pin_configure(uint32_t pin, uint32_t pin_cgf, uint32_t pin_func)
207 {
208 const struct device *port_device;
209
210 if (STM32_PORT(pin) >= gpio_ports_cnt) {
211 return -EINVAL;
212 }
213
214 port_device = gpio_ports[STM32_PORT(pin)];
215
216 if ((port_device == NULL) || (!device_is_ready(port_device))) {
217 return -ENODEV;
218 }
219
220 return gpio_stm32_configure(port_device, STM32_PIN(pin), pin_cgf, pin_func);
221 }
222
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)223 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
224 uintptr_t reg)
225 {
226 uint32_t pin, mux;
227 uint32_t pin_cgf = 0;
228 int ret = 0;
229
230 ARG_UNUSED(reg);
231
232 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
233 ret = stm32_pins_remap(pins, pin_cnt);
234 if (ret < 0) {
235 return ret;
236 }
237 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
238
239 for (uint8_t i = 0U; i < pin_cnt; i++) {
240 mux = pins[i].pinmux;
241
242 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
243 uint32_t pupd;
244
245 if (STM32_DT_PINMUX_FUNC(mux) == ALTERNATE) {
246 pin_cgf = pins[i].pincfg | STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC;
247 } else if (STM32_DT_PINMUX_FUNC(mux) == ANALOG) {
248 pin_cgf = pins[i].pincfg | STM32_MODE_INPUT | STM32_CNF_IN_ANALOG;
249 } else if (STM32_DT_PINMUX_FUNC(mux) == GPIO_IN) {
250 pin_cgf = pins[i].pincfg | STM32_MODE_INPUT;
251 pupd = pin_cgf & (STM32_PUPD_MASK << STM32_PUPD_SHIFT);
252 if (pupd == STM32_PUPD_NO_PULL) {
253 pin_cgf = pin_cgf | STM32_CNF_IN_FLOAT;
254 } else {
255 pin_cgf = pin_cgf | STM32_CNF_IN_PUPD;
256 }
257 } else if (STM32_DT_PINMUX_FUNC(mux) == GPIO_OUT) {
258 pin_cgf = pins[i].pincfg | STM32_MODE_OUTPUT | STM32_CNF_GP_OUTPUT;
259 } else {
260 /* Not supported */
261 __ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
262 }
263 #else
264 if (STM32_DT_PINMUX_FUNC(mux) < STM32_ANALOG) {
265 pin_cgf = pins[i].pincfg | STM32_MODER_ALT_MODE;
266 } else if (STM32_DT_PINMUX_FUNC(mux) == STM32_ANALOG) {
267 pin_cgf = STM32_MODER_ANALOG_MODE;
268 } else if (STM32_DT_PINMUX_FUNC(mux) == STM32_GPIO) {
269 pin_cgf = pins[i].pincfg;
270 } else {
271 /* Not supported */
272 __ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
273 }
274 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
275
276 pin = STM32PIN(STM32_DT_PINMUX_PORT(mux),
277 STM32_DT_PINMUX_LINE(mux));
278
279 ret = stm32_pin_configure(pin, pin_cgf, STM32_DT_PINMUX_FUNC(mux));
280 if (ret < 0) {
281 return ret;
282 }
283 }
284
285 return 0;
286 }
287