1 /*
2 * Copyright (c) 2023 Silicon Labs
3 * Copyright (c) 2024 Capgemini
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/drivers/pinctrl.h>
9
10 #include <soc_gpio.h>
11
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)12 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
13 {
14 USART_TypeDef *base = (USART_TypeDef *)reg;
15 uint8_t loc;
16 #ifdef CONFIG_SOC_FAMILY_SILABS_S1
17 LEUART_TypeDef *lebase = (LEUART_TypeDef *)reg;
18 #endif
19
20 #ifdef CONFIG_I2C_GECKO
21 I2C_TypeDef *i2c_base = (I2C_TypeDef *)reg;
22 #endif
23
24 #ifdef CONFIG_UART_GECKO
25 struct soc_gpio_pin rxpin = {0, 0, 0, 0};
26 struct soc_gpio_pin txpin = {0, 0, 0, 0};
27 #endif /* CONFIG_UART_GECKO */
28
29 struct soc_gpio_pin pin_config = {0, 0, 0, 0};
30
31 for (uint8_t i = 0U; i < pin_cnt; i++) {
32 pin_config.port = GECKO_GET_PORT(pins[i]);
33 pin_config.pin = GECKO_GET_PIN(pins[i]);
34 loc = GECKO_GET_LOC(pins[i]);
35
36 switch (GECKO_GET_FUN(pins[i])) {
37 #ifdef CONFIG_UART_GECKO
38 case GECKO_FUN_UART_RX:
39 rxpin.port = GECKO_GET_PORT(pins[i]);
40 rxpin.pin = GECKO_GET_PIN(pins[i]);
41 rxpin.mode = gpioModeInput;
42 rxpin.out = 1;
43 GPIO_PinModeSet(rxpin.port, rxpin.pin, rxpin.mode,
44 rxpin.out);
45 break;
46
47 case GECKO_FUN_UART_TX:
48 txpin.port = GECKO_GET_PORT(pins[i]);
49 txpin.pin = GECKO_GET_PIN(pins[i]);
50 txpin.mode = gpioModePushPull;
51 txpin.out = 1;
52 GPIO_PinModeSet(txpin.port, txpin.pin, txpin.mode,
53 txpin.out);
54 break;
55
56 #ifdef CONFIG_SOC_FAMILY_SILABS_S1
57 case GECKO_FUN_UART_RTS:
58 pin_config.mode = gpioModePushPull;
59 pin_config.out = 1;
60 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
61 pin_config.out);
62 break;
63
64 case GECKO_FUN_UART_CTS:
65 pin_config.mode = gpioModeInput;
66 pin_config.out = 1;
67 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
68 pin_config.out);
69 break;
70
71 case GECKO_FUN_UART_RX_LOC:
72 base->ROUTEPEN |= USART_ROUTEPEN_RXPEN;
73 base->ROUTELOC0 &= ~_USART_ROUTELOC0_RXLOC_MASK;
74 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_RXLOC_SHIFT);
75 break;
76
77 case GECKO_FUN_UART_TX_LOC:
78 base->ROUTEPEN |= USART_ROUTEPEN_TXPEN;
79 base->ROUTELOC0 &= ~_USART_ROUTELOC0_TXLOC_MASK;
80 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_TXLOC_SHIFT);
81 break;
82
83 case GECKO_FUN_UART_RTS_LOC:
84 base->ROUTEPEN |= USART_ROUTEPEN_RTSPEN;
85 base->ROUTELOC1 &= ~_USART_ROUTELOC1_RTSLOC_MASK;
86 base->ROUTELOC1 |= (loc << _USART_ROUTELOC1_RTSLOC_SHIFT);
87 break;
88
89 case GECKO_FUN_UART_CTS_LOC:
90 base->ROUTEPEN |= USART_ROUTEPEN_CTSPEN;
91 base->ROUTELOC1 &= ~_USART_ROUTELOC1_CTSLOC_MASK;
92 base->ROUTELOC1 |= (loc << _USART_ROUTELOC1_CTSLOC_SHIFT);
93 break;
94
95 case GECKO_FUN_LEUART_RX_LOC:
96 lebase->ROUTEPEN |= LEUART_ROUTEPEN_RXPEN;
97 lebase->ROUTELOC0 &= ~_LEUART_ROUTELOC0_RXLOC_MASK;
98 lebase->ROUTELOC0 |= (loc << _LEUART_ROUTELOC0_RXLOC_SHIFT);
99 break;
100
101 case GECKO_FUN_LEUART_TX_LOC:
102 lebase->ROUTEPEN |= LEUART_ROUTEPEN_TXPEN;
103 lebase->ROUTELOC0 &= ~_LEUART_ROUTELOC0_TXLOC_MASK;
104 lebase->ROUTELOC0 |= (loc << _LEUART_ROUTELOC0_TXLOC_SHIFT);
105 break;
106 #else /* CONFIG_SOC_FAMILY_SILABS_S1 */
107 case GECKO_FUN_UART_LOC:
108 #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION
109 /* For SOCs with configurable pin_cfg locations (set in SOC Kconfig) */
110 base->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
111 base->ROUTELOC0 = (loc << _USART_ROUTELOC0_TXLOC_SHIFT) |
112 (loc << _USART_ROUTELOC0_RXLOC_SHIFT);
113 base->ROUTELOC1 = _USART_ROUTELOC1_RESETVALUE;
114 #elif defined(USART_ROUTE_RXPEN) && defined(USART_ROUTE_TXPEN)
115 /* For olders SOCs with only one pin location */
116 base->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (loc << 8);
117 #endif /* CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION */
118
119 #ifdef UART_GECKO_HW_FLOW_CONTROL
120 /* Configure HW flow control (RTS, CTS) */
121 if (config->hw_flowcontrol) {
122 GPIO_PinModeSet(config->pin_rts.port,
123 config->pin_rts.pin,
124 config->pin_rts.mode,
125 config->pin_rts.out);
126 GPIO_PinModeSet(config->pin_cts.port,
127 config->pin_cts.pin,
128 config->pin_cts.mode,
129 config->pin_cts.out);
130 #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION
131 config->base->ROUTEPEN =
132 USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN |
133 USART_ROUTEPEN_RTSPEN | USART_ROUTEPEN_CTSPEN;
134
135 config->base->ROUTELOC1 =
136 (config->loc_rts << _USART_ROUTELOC1_RTSLOC_SHIFT) |
137 (config->loc_cts << _USART_ROUTELOC1_CTSLOC_SHIFT);
138 #endif /* CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION */
139 }
140 #endif /* UART_GECKO_HW_FLOW_CONTROL */
141 break;
142 #endif /* CONFIG_SOC_FAMILY_SILABS_S1 */
143 #endif /* CONFIG_UART_GECKO */
144
145 #ifdef CONFIG_SPI_GECKO_USART
146 #ifdef CONFIG_SOC_FAMILY_SILABS_S1
147 case GECKO_FUN_SPIM_SCK:
148 pin_config.mode = gpioModePushPull;
149 pin_config.out = 1;
150 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
151 pin_config.out);
152 break;
153
154 case GECKO_FUN_SPIM_MOSI:
155 pin_config.mode = gpioModePushPull;
156 pin_config.out = 1;
157 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
158 pin_config.out);
159 break;
160
161 case GECKO_FUN_SPIM_MISO:
162 pin_config.mode = gpioModeInput;
163 pin_config.out = 1;
164 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
165 pin_config.out);
166 break;
167
168 case GECKO_FUN_SPIM_CS:
169 pin_config.mode = gpioModePushPull;
170 pin_config.out = 1;
171 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
172 pin_config.out);
173 break;
174
175 case GECKO_FUN_SPIS_SCK:
176 pin_config.mode = gpioModeInput;
177 pin_config.out = 1;
178 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
179 pin_config.out);
180 break;
181
182 case GECKO_FUN_SPIS_MOSI:
183 pin_config.mode = gpioModeInput;
184 pin_config.out = 1;
185 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
186 pin_config.out);
187 break;
188
189 case GECKO_FUN_SPIS_MISO:
190 pin_config.mode = gpioModePushPull;
191 pin_config.out = 1;
192 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
193 pin_config.out);
194 break;
195
196 case GECKO_FUN_SPIS_CS:
197 pin_config.mode = gpioModeInput;
198 pin_config.out = 1;
199 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
200 pin_config.out);
201 break;
202
203 case GECKO_FUN_SPI_SCK_LOC:
204 base->ROUTEPEN |= USART_ROUTEPEN_CLKPEN;
205 base->ROUTELOC0 &= ~_USART_ROUTELOC0_CLKLOC_MASK;
206 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_CLKLOC_SHIFT);
207 break;
208
209 case GECKO_FUN_SPI_MOSI_LOC:
210 base->ROUTEPEN |= USART_ROUTEPEN_TXPEN;
211 base->ROUTELOC0 &= ~_USART_ROUTELOC0_TXLOC_MASK;
212 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_TXLOC_SHIFT);
213 break;
214
215 case GECKO_FUN_SPI_MISO_LOC:
216 base->ROUTEPEN |= USART_ROUTEPEN_RXPEN;
217 base->ROUTELOC0 &= ~_USART_ROUTELOC0_RXLOC_MASK;
218 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_RXLOC_SHIFT);
219 break;
220
221 case GECKO_FUN_SPI_CS_LOC:
222 base->ROUTEPEN |= USART_ROUTEPEN_CSPEN;
223 base->ROUTELOC0 &= ~_USART_ROUTELOC0_CSLOC_MASK;
224 base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_CSLOC_SHIFT);
225 break;
226 #endif /* CONFIG_SOC_FAMILY_SILABS_S1 */
227 #endif /* CONFIG_SPI_GECKO_USART */
228
229 #ifdef CONFIG_I2C_GECKO
230 case GECKO_FUN_I2C_SDA:
231 pin_config.mode = gpioModeWiredAnd;
232 pin_config.out = 1;
233 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
234 pin_config.out);
235 break;
236
237 case GECKO_FUN_I2C_SCL:
238 pin_config.mode = gpioModeWiredAnd;
239 pin_config.out = 1;
240 GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode,
241 pin_config.out);
242 break;
243
244 case GECKO_FUN_I2C_SDA_LOC:
245 #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION
246 i2c_base->ROUTEPEN |= I2C_ROUTEPEN_SDAPEN;
247 i2c_base->ROUTELOC0 &= ~_I2C_ROUTELOC0_SDALOC_MASK;
248 i2c_base->ROUTELOC0 |= (loc << _I2C_ROUTELOC0_SDALOC_SHIFT);
249 #elif defined(I2C_ROUTE_SDAPEN)
250 i2c_base->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << 8);
251 #endif
252 break;
253
254 case GECKO_FUN_I2C_SCL_LOC:
255 #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION
256 i2c_base->ROUTEPEN |= I2C_ROUTEPEN_SCLPEN;
257 i2c_base->ROUTELOC0 &= ~_I2C_ROUTELOC0_SCLLOC_MASK;
258 i2c_base->ROUTELOC0 |= (loc << _I2C_ROUTELOC0_SCLLOC_SHIFT);
259 #elif defined(I2C_ROUTE_SCLPEN)
260 i2c_base->ROUTE = I2C_ROUTE_SDAPEN | I2C_ROUTE_SCLPEN | (loc << 8);
261 #endif
262 break;
263
264 #endif /* CONFIG_I2C_GECKO */
265
266 default:
267 return -ENOTSUP;
268 }
269 }
270
271 return 0;
272 }
273