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