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 	DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioq)),
67 };
68 
69 /** Number of GPIO ports. */
70 static const size_t gpio_ports_cnt = ARRAY_SIZE(gpio_ports);
71 
72 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa11)
73 #define REMAP_PA11	DT_PROP(DT_NODELABEL(pinctrl), remap_pa11)
74 #endif
75 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa12)
76 #define REMAP_PA12	DT_PROP(DT_NODELABEL(pinctrl), remap_pa12)
77 #endif
78 #if DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), remap_pa11_pa12)
79 #define REMAP_PA11_PA12	DT_PROP(DT_NODELABEL(pinctrl), remap_pa11_pa12)
80 #endif
81 
82 #if REMAP_PA11 || REMAP_PA12 || REMAP_PA11_PA12
83 
stm32_pinmux_init_remap(void)84 int stm32_pinmux_init_remap(void)
85 {
86 
87 #if REMAP_PA11 || REMAP_PA12
88 
89 #if !defined(CONFIG_SOC_SERIES_STM32G0X) && !defined(CONFIG_SOC_SERIES_STM32C0X)
90 #error "Pin remap property available only on STM32G0 and STM32C0 SoC series"
91 #endif
92 
93 	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
94 #if REMAP_PA11
95 	LL_SYSCFG_EnablePinRemap(LL_SYSCFG_PIN_RMP_PA11);
96 #endif
97 #if REMAP_PA12
98 	LL_SYSCFG_EnablePinRemap(LL_SYSCFG_PIN_RMP_PA12);
99 #endif
100 
101 #elif REMAP_PA11_PA12
102 
103 #if !defined(SYSCFG_CFGR1_PA11_PA12_RMP)
104 #error "Pin remap property available only on STM32F070x SoC series"
105 #endif
106 
107 	LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_SYSCFG);
108 	LL_SYSCFG_EnablePinRemap();
109 
110 #endif /* (REMAP_PA11 || REMAP_PA12) || REMAP_PA11_PA12 */
111 
112 	return 0;
113 }
114 
115 SYS_INIT(stm32_pinmux_init_remap, PRE_KERNEL_1,
116 	 CONFIG_PINCTRL_STM32_REMAP_INIT_PRIORITY);
117 
118 #endif /* REMAP_PA11 || REMAP_PA12 || REMAP_PA11_PA12 */
119 
120 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
121 
122 /* ignore swj-cfg reset state (default value) */
123 #if ((DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), swj_cfg)) && \
124 	(DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) != 0))
125 
stm32f1_swj_cfg_init(void)126 static int stm32f1_swj_cfg_init(void)
127 {
128 
129 	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
130 
131 	/* reset state is '000' (Full SWJ, (JTAG-DP + SW-DP)) */
132 	/* only one of the 3 bits can be set */
133 #if (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 1)
134 	/* 001: Full SWJ (JTAG-DP + SW-DP) but without NJTRST */
135 	/* releases: PB4 */
136 	LL_GPIO_AF_Remap_SWJ_NONJTRST();
137 #elif (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 2)
138 	/* 010: JTAG-DP Disabled and SW-DP Enabled */
139 	/* releases: PB4 PB3 PA15 */
140 	LL_GPIO_AF_Remap_SWJ_NOJTAG();
141 #elif (DT_ENUM_IDX(DT_NODELABEL(pinctrl), swj_cfg) == 3)
142 	/* 100: JTAG-DP Disabled and SW-DP Disabled */
143 	/* releases: PB4 PB3 PA13 PA14 PA15 */
144 	LL_GPIO_AF_DisableRemap_SWJ();
145 #endif
146 
147 	return 0;
148 }
149 
150 SYS_INIT(stm32f1_swj_cfg_init, PRE_KERNEL_1, 0);
151 
152 #endif /* DT_NODE_HAS_PROP(DT_NODELABEL(pinctrl), swj_cfg) */
153 
154 /**
155  * @brief Helper function to check and apply provided pinctrl remap
156  * configuration.
157  *
158  * Check operation verifies that pin remapping configuration is the same on all
159  * pins. If configuration is valid AFIO clock is enabled and remap is applied
160  *
161  * @param pins List of pins to be configured.
162  * @param pin_cnt Number of pins.
163  *
164  * @retval 0 If successful
165  * @retval -EINVAL If pins have an incompatible set of remaps.
166  */
stm32_pins_remap(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt)167 static int stm32_pins_remap(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt)
168 {
169 	uint32_t reg_val;
170 	uint16_t remap;
171 
172 	remap = NO_REMAP;
173 
174 	for (size_t i = 0U; i < pin_cnt; i++) {
175 		if (remap == NO_REMAP) {
176 			remap = STM32_DT_PINMUX_REMAP(pins[i].pinmux);
177 		} else if (STM32_DT_PINMUX_REMAP(pins[i].pinmux) == NO_REMAP) {
178 			continue;
179 		} else if (STM32_DT_PINMUX_REMAP(pins[i].pinmux) != remap) {
180 			return -EINVAL;
181 		}
182 	}
183 
184 	/* not remappable */
185 	if (remap == NO_REMAP) {
186 		return 0;
187 	}
188 
189 	/* A valid remapping configuration is available */
190 	/* Apply remapping before proceeding with pin configuration */
191 	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
192 
193 	if (STM32_REMAP_REG_GET(remap) == 0U) {
194 		/* read initial value, ignore write-only SWJ_CFG */
195 		reg_val = AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG;
196 		reg_val |= STM32_REMAP_VAL_GET(remap) << STM32_REMAP_SHIFT_GET(remap);
197 		/* apply undocumented '111' (AFIO_MAPR_SWJ_CFG) to affirm SWJ_CFG */
198 		/* the pins are not remapped without that (when SWJ_CFG is not default) */
199 		AFIO->MAPR = reg_val | AFIO_MAPR_SWJ_CFG;
200 	} else {
201 		reg_val = AFIO->MAPR2;
202 		reg_val |= STM32_REMAP_VAL_GET(remap) << STM32_REMAP_SHIFT_GET(remap);
203 		AFIO->MAPR2 = reg_val;
204 	}
205 
206 	return 0;
207 }
208 
209 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
210 
stm32_pin_configure(uint32_t pin,uint32_t pin_cgf,uint32_t pin_func)211 static int stm32_pin_configure(uint32_t pin, uint32_t pin_cgf, uint32_t pin_func)
212 {
213 	const struct device *port_device;
214 
215 	if (STM32_PORT(pin) >= gpio_ports_cnt) {
216 		return -EINVAL;
217 	}
218 
219 	port_device = gpio_ports[STM32_PORT(pin)];
220 
221 	if ((port_device == NULL) || (!device_is_ready(port_device))) {
222 		return -ENODEV;
223 	}
224 
225 	return gpio_stm32_configure(port_device, STM32_PIN(pin), pin_cgf, pin_func);
226 }
227 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)228 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
229 			   uintptr_t reg)
230 {
231 	uint32_t pin, mux;
232 	uint32_t pin_cgf = 0;
233 	int ret = 0;
234 
235 	ARG_UNUSED(reg);
236 
237 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
238 	ret = stm32_pins_remap(pins, pin_cnt);
239 	if (ret < 0) {
240 		return ret;
241 	}
242 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
243 
244 	for (uint8_t i = 0U; i < pin_cnt; i++) {
245 		mux = pins[i].pinmux;
246 
247 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
248 		uint32_t pupd;
249 
250 		if (STM32_DT_PINMUX_FUNC(mux) == ALTERNATE) {
251 			pin_cgf = pins[i].pincfg | STM32_MODE_OUTPUT | STM32_CNF_ALT_FUNC;
252 		} else if (STM32_DT_PINMUX_FUNC(mux) == ANALOG) {
253 			pin_cgf = pins[i].pincfg | STM32_MODE_INPUT | STM32_CNF_IN_ANALOG;
254 		} else if (STM32_DT_PINMUX_FUNC(mux) == GPIO_IN) {
255 			pin_cgf = pins[i].pincfg | STM32_MODE_INPUT;
256 			pupd = pin_cgf & (STM32_PUPD_MASK << STM32_PUPD_SHIFT);
257 			if (pupd == STM32_PUPD_NO_PULL) {
258 				pin_cgf = pin_cgf | STM32_CNF_IN_FLOAT;
259 			} else {
260 				pin_cgf = pin_cgf | STM32_CNF_IN_PUPD;
261 			}
262 		} else if (STM32_DT_PINMUX_FUNC(mux) == GPIO_OUT) {
263 			pin_cgf = pins[i].pincfg | STM32_MODE_OUTPUT | STM32_CNF_GP_OUTPUT;
264 		} else {
265 			/* Not supported */
266 			__ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
267 		}
268 #else
269 		if (STM32_DT_PINMUX_FUNC(mux) < STM32_ANALOG) {
270 			pin_cgf = pins[i].pincfg | STM32_MODER_ALT_MODE;
271 		} else if (STM32_DT_PINMUX_FUNC(mux) == STM32_ANALOG) {
272 			pin_cgf = STM32_MODER_ANALOG_MODE;
273 		} else if (STM32_DT_PINMUX_FUNC(mux) == STM32_GPIO) {
274 			pin_cgf = pins[i].pincfg;
275 		} else {
276 			/* Not supported */
277 			__ASSERT_NO_MSG(STM32_DT_PINMUX_FUNC(mux));
278 		}
279 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
280 
281 		pin = STM32PIN(STM32_DT_PINMUX_PORT(mux),
282 			       STM32_DT_PINMUX_LINE(mux));
283 
284 		ret = stm32_pin_configure(pin, pin_cgf, STM32_DT_PINMUX_FUNC(mux));
285 		if (ret < 0) {
286 			return ret;
287 		}
288 	}
289 
290 	return 0;
291 }
292