1 /*
2 * Copyright (c) 2016 Open-RnD Sp. z o.o.
3 * Copyright (c) 2021 Linaro Limited
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @brief
10 *
11 * A common driver for STM32 pinmux.
12 */
13
14 #include <errno.h>
15
16 #include <kernel.h>
17 #include <device.h>
18 #include <soc.h>
19 #include <stm32_ll_bus.h>
20 #include <stm32_ll_gpio.h>
21 #include <drivers/pinmux.h>
22 #include <gpio/gpio_stm32.h>
23 #include <drivers/clock_control/stm32_clock_control.h>
24 #include <pinmux/pinmux_stm32.h>
25 #include <pm/device_runtime.h>
26
27 #define GPIO_DEVICE(gpio_port) \
28 COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(gpio_port), okay), \
29 (DEVICE_DT_GET(DT_NODELABEL(gpio_port))), \
30 ((const struct device *)NULL))
31
32 const struct device * const gpio_ports[STM32_PORTS_MAX] = {
33 GPIO_DEVICE(gpioa),
34 GPIO_DEVICE(gpiob),
35 GPIO_DEVICE(gpioc),
36 GPIO_DEVICE(gpiod),
37 GPIO_DEVICE(gpioe),
38 GPIO_DEVICE(gpiof),
39 GPIO_DEVICE(gpiog),
40 GPIO_DEVICE(gpioh),
41 GPIO_DEVICE(gpioi),
42 GPIO_DEVICE(gpioj),
43 GPIO_DEVICE(gpiok),
44 };
45
stm32_pin_configure(uint32_t pin,uint32_t func,uint32_t altf)46 static int stm32_pin_configure(uint32_t pin, uint32_t func, uint32_t altf)
47 {
48 const struct device *port_device;
49 int ret = 0;
50
51 if (STM32_PORT(pin) >= STM32_PORTS_MAX) {
52 return -EINVAL;
53 }
54
55 port_device = gpio_ports[STM32_PORT(pin)];
56
57 if ((port_device == NULL) || (!device_is_ready(port_device))) {
58 return -ENODEV;
59 }
60
61 #ifdef CONFIG_PM_DEVICE_RUNTIME
62 ret = pm_device_get(port_device);
63 if (ret != 0) {
64 return ret;
65 }
66 #endif
67
68 gpio_stm32_configure(port_device, STM32_PIN(pin), func, altf);
69
70 #ifdef CONFIG_PM_DEVICE_RUNTIME
71 ret = pm_device_put(port_device);
72 #endif
73
74 return ret;
75 }
76
77 /**
78 * @brief helper for converting dt stm32 pinctrl format to existing pin config
79 * format
80 *
81 * @param *pinctrl pointer to soc_gpio_pinctrl list
82 * @param list_size list size
83 * @param base device base register value
84 *
85 * @return 0 on success, -EINVAL otherwise
86 */
stm32_dt_pinctrl_configure(const struct soc_gpio_pinctrl * pinctrl,size_t list_size,uint32_t base)87 int stm32_dt_pinctrl_configure(const struct soc_gpio_pinctrl *pinctrl,
88 size_t list_size, uint32_t base)
89 {
90 uint32_t pin, mux;
91 uint32_t func = 0;
92 int ret = 0;
93
94 if (!list_size) {
95 /* Empty pinctrl. Exit */
96 return 0;
97 }
98
99 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
100 if (stm32_dt_pinctrl_remap(pinctrl, list_size, base)) {
101 /* Wrong remap config. Exit */
102 return -EINVAL;
103 }
104 #else
105 ARG_UNUSED(base);
106 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
107
108 for (int i = 0; i < list_size; i++) {
109 mux = pinctrl[i].pinmux;
110
111 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
112 uint32_t pupd;
113
114 if (STM32_DT_PINMUX_FUNC(mux) == ALTERNATE) {
115 func = pinctrl[i].pincfg | STM32_MODE_OUTPUT |
116 STM32_CNF_ALT_FUNC;
117 } else if (STM32_DT_PINMUX_FUNC(mux) == ANALOG) {
118 func = pinctrl[i].pincfg | STM32_MODE_INPUT |
119 STM32_CNF_IN_ANALOG;
120 } else if (STM32_DT_PINMUX_FUNC(mux) == GPIO_IN) {
121 func = pinctrl[i].pincfg | STM32_MODE_INPUT;
122 pupd = func & (STM32_PUPD_MASK << STM32_PUPD_SHIFT);
123 if (pupd == STM32_PUPD_NO_PULL) {
124 func = func | STM32_CNF_IN_FLOAT;
125 } else {
126 func = func | STM32_CNF_IN_PUPD;
127 }
128 } else {
129 /* Not supported */
130 __ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
131 }
132 #else
133 if (STM32_DT_PINMUX_FUNC(mux) < STM32_ANALOG) {
134 func = pinctrl[i].pincfg | STM32_MODER_ALT_MODE;
135 } else if (STM32_DT_PINMUX_FUNC(mux) == STM32_ANALOG) {
136 func = STM32_MODER_ANALOG_MODE;
137 } else {
138 /* Not supported */
139 __ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
140 }
141 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
142
143 pin = STM32PIN(STM32_DT_PINMUX_PORT(mux),
144 STM32_DT_PINMUX_LINE(mux));
145
146 ret = stm32_pin_configure(pin, func, STM32_DT_PINMUX_FUNC(mux));
147 if (ret != 0) {
148 return ret;
149 }
150 }
151
152 return 0;
153 }
154
155 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
156 /**
157 * @brief Helper function to check and apply provided pinctrl remap
158 * configuration
159 *
160 * Check operation verifies that pin remapping configuration is the same on all
161 * pins. If configuration is valid AFIO clock is enabled and remap is applied
162 *
163 * @param *pinctrl pointer to soc_gpio_pinctrl list
164 * @param list_size list size
165 * @param base device base register value
166 *
167 * @return 0 on success, -EINVAL otherwise
168 */
stm32_dt_pinctrl_remap(const struct soc_gpio_pinctrl * pinctrl,size_t list_size,uint32_t base)169 int stm32_dt_pinctrl_remap(const struct soc_gpio_pinctrl *pinctrl,
170 size_t list_size, uint32_t base)
171 {
172 uint8_t remap;
173
174 remap = (uint8_t)STM32_DT_PINMUX_REMAP(pinctrl[0].pinmux);
175
176 for (size_t i = 1U; i < list_size; i++) {
177 if (STM32_DT_PINMUX_REMAP(pinctrl[i].pinmux) != remap) {
178 return -EINVAL;
179 }
180 }
181
182 /* A valid remapping configuration is available */
183 /* Apply remapping before proceeding with pin configuration */
184 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
185
186 switch (base) {
187 #if DT_NODE_HAS_STATUS(DT_NODELABEL(can1), okay)
188 case DT_REG_ADDR(DT_NODELABEL(can1)):
189 if (remap == REMAP_1) {
190 /* PB8/PB9 */
191 LL_GPIO_AF_RemapPartial2_CAN1();
192 } else if (remap == REMAP_2) {
193 /* PD0/PD1 */
194 LL_GPIO_AF_RemapPartial3_CAN1();
195 } else {
196 /* NO_REMAP: PA11/PA12 */
197 LL_GPIO_AF_RemapPartial1_CAN1();
198 }
199 break;
200 #endif
201 #if DT_NODE_HAS_STATUS(DT_NODELABEL(can2), okay)
202 case DT_REG_ADDR(DT_NODELABEL(can2)):
203 if (remap == REMAP_1) {
204 /* PB5/PB6 */
205 LL_GPIO_AF_EnableRemap_CAN2();
206 } else {
207 /* PB12/PB13 */
208 LL_GPIO_AF_DisableRemap_CAN2();
209 }
210 break;
211 #endif
212 #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay)
213 case DT_REG_ADDR(DT_NODELABEL(i2c1)):
214 if (remap == REMAP_1) {
215 LL_GPIO_AF_EnableRemap_I2C1();
216 } else {
217 LL_GPIO_AF_DisableRemap_I2C1();
218 }
219 break;
220 #endif
221 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers1), okay)
222 case DT_REG_ADDR(DT_NODELABEL(timers1)):
223 if (remap == REMAP_1) {
224 LL_GPIO_AF_RemapPartial_TIM1();
225 } else if (remap == REMAP_2) {
226 LL_GPIO_AF_EnableRemap_TIM1();
227 } else {
228 LL_GPIO_AF_DisableRemap_TIM1();
229 }
230 break;
231 #endif
232 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers2), okay)
233 case DT_REG_ADDR(DT_NODELABEL(timers2)):
234 if (remap == REMAP_1) {
235 LL_GPIO_AF_RemapPartial1_TIM2();
236 } else if (remap == REMAP_2) {
237 LL_GPIO_AF_RemapPartial2_TIM2();
238 } else if (remap == REMAP_FULL) {
239 LL_GPIO_AF_EnableRemap_TIM2();
240 } else {
241 LL_GPIO_AF_DisableRemap_TIM2();
242 }
243 break;
244 #endif
245 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers3), okay)
246 case DT_REG_ADDR(DT_NODELABEL(timers3)):
247 if (remap == REMAP_1) {
248 LL_GPIO_AF_RemapPartial_TIM3();
249 } else if (remap == REMAP_2) {
250 LL_GPIO_AF_EnableRemap_TIM3();
251 } else {
252 LL_GPIO_AF_DisableRemap_TIM3();
253 }
254 break;
255 #endif
256 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers4), okay)
257 case DT_REG_ADDR(DT_NODELABEL(timers4)):
258 if (remap == REMAP_1) {
259 LL_GPIO_AF_EnableRemap_TIM4();
260 } else {
261 LL_GPIO_AF_DisableRemap_TIM4();
262 }
263 break;
264 #endif
265 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers9), okay)
266 case DT_REG_ADDR(DT_NODELABEL(timers9)):
267 if (remap == REMAP_1) {
268 LL_GPIO_AF_EnableRemap_TIM9();
269 } else {
270 LL_GPIO_AF_DisableRemap_TIM9();
271 }
272 break;
273 #endif
274 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers10), okay)
275 case DT_REG_ADDR(DT_NODELABEL(timers10)):
276 if (remap == REMAP_1) {
277 LL_GPIO_AF_EnableRemap_TIM10();
278 } else {
279 LL_GPIO_AF_DisableRemap_TIM10();
280 }
281 break;
282 #endif
283 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers11), okay)
284 case DT_REG_ADDR(DT_NODELABEL(timers11)):
285 if (remap == REMAP_1) {
286 LL_GPIO_AF_EnableRemap_TIM11();
287 } else {
288 LL_GPIO_AF_DisableRemap_TIM11();
289 }
290 break;
291 #endif
292 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers12), okay)
293 case DT_REG_ADDR(DT_NODELABEL(timers12)):
294 if (remap == REMAP_1) {
295 LL_GPIO_AF_EnableRemap_TIM12();
296 } else {
297 LL_GPIO_AF_DisableRemap_TIM12();
298 }
299 break;
300 #endif
301 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers13), okay)
302 case DT_REG_ADDR(DT_NODELABEL(timers13)):
303 if (remap == REMAP_1) {
304 LL_GPIO_AF_EnableRemap_TIM13();
305 } else {
306 LL_GPIO_AF_DisableRemap_TIM13();
307 }
308 break;
309 #endif
310 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers14), okay)
311 case DT_REG_ADDR(DT_NODELABEL(timers14)):
312 if (remap == REMAP_1) {
313 LL_GPIO_AF_EnableRemap_TIM14();
314 } else {
315 LL_GPIO_AF_DisableRemap_TIM14();
316 }
317 break;
318 #endif
319 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers15), okay)
320 case DT_REG_ADDR(DT_NODELABEL(timers15)):
321 if (remap == REMAP_1) {
322 LL_GPIO_AF_EnableRemap_TIM15();
323 } else {
324 LL_GPIO_AF_DisableRemap_TIM15();
325 }
326 break;
327 #endif
328 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers16), okay)
329 case DT_REG_ADDR(DT_NODELABEL(timers16)):
330 if (remap == REMAP_1) {
331 LL_GPIO_AF_EnableRemap_TIM16();
332 } else {
333 LL_GPIO_AF_DisableRemap_TIM16();
334 }
335 break;
336 #endif
337 #if DT_NODE_HAS_STATUS(DT_NODELABEL(timers17), okay)
338 case DT_REG_ADDR(DT_NODELABEL(timers17)):
339 if (remap == REMAP_1) {
340 LL_GPIO_AF_EnableRemap_TIM17();
341 } else {
342 LL_GPIO_AF_DisableRemap_TIM17();
343 }
344 break;
345 #endif
346 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart1), okay)
347 case DT_REG_ADDR(DT_NODELABEL(usart1)):
348 if (remap == REMAP_1) {
349 LL_GPIO_AF_EnableRemap_USART1();
350 } else {
351 LL_GPIO_AF_DisableRemap_USART1();
352 }
353 break;
354 #endif
355 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart2), okay)
356 case DT_REG_ADDR(DT_NODELABEL(usart2)):
357 if (remap == REMAP_1) {
358 LL_GPIO_AF_EnableRemap_USART2();
359 } else {
360 LL_GPIO_AF_DisableRemap_USART2();
361 }
362 break;
363 #endif
364 #if DT_NODE_HAS_STATUS(DT_NODELABEL(usart3), okay)
365 case DT_REG_ADDR(DT_NODELABEL(usart3)):
366 if (remap == REMAP_2) {
367 LL_GPIO_AF_EnableRemap_USART3();
368 } else if (remap == REMAP_1) {
369 LL_GPIO_AF_RemapPartial_USART3();
370 } else {
371 LL_GPIO_AF_DisableRemap_USART3();
372 }
373 break;
374 #endif
375 #if DT_NODE_HAS_STATUS(DT_NODELABEL(spi1), okay)
376 case DT_REG_ADDR(DT_NODELABEL(spi1)):
377 if (remap == REMAP_1) {
378 LL_GPIO_AF_EnableRemap_SPI1();
379 } else {
380 LL_GPIO_AF_DisableRemap_SPI1();
381 }
382 break;
383 #endif
384 }
385
386 return 0;
387 }
388 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
389
390
391 /**
392 * @brief pin setup
393 *
394 * @param pin STM32PIN() encoded pin ID
395 * @param func SoC specific function assignment
396 * @param clk optional clock device
397 *
398 * @return 0 on success, error otherwise
399 */
z_pinmux_stm32_set(uint32_t pin,uint32_t func)400 int z_pinmux_stm32_set(uint32_t pin, uint32_t func)
401 {
402 const struct device *port_device = gpio_ports[STM32_PORT(pin)];
403
404 /* make sure to enable port clock first */
405 if (gpio_stm32_clock_request(port_device, true)) {
406 return -EIO;
407 }
408
409 return stm32_pin_configure(pin, func, func & STM32_AFR_MASK);
410 }
411
412 /**
413 * @brief setup pins according to their assignments
414 *
415 * @param pinconf board pin configuration array
416 * @param pins array size
417 */
stm32_setup_pins(const struct pin_config * pinconf,size_t pins)418 void stm32_setup_pins(const struct pin_config *pinconf,
419 size_t pins)
420 {
421 int i;
422
423 for (i = 0; i < pins; i++) {
424 z_pinmux_stm32_set(pinconf[i].pin_num,
425 pinconf[i].mode);
426 }
427 }
428