1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/drivers/pinctrl.h>
8 
9 #include <hal/nrf_gpio.h>
10 
11 BUILD_ASSERT(((NRF_PULL_NONE == NRF_GPIO_PIN_NOPULL) &&
12 	      (NRF_PULL_DOWN == NRF_GPIO_PIN_PULLDOWN) &&
13 	      (NRF_PULL_UP == NRF_GPIO_PIN_PULLUP)),
14 	      "nRF pinctrl pull settings do not match HAL values");
15 
16 #if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0)
17 #define NRF_DRIVE_COUNT (NRF_DRIVE_E0E1 + 1)
18 #else
19 #define NRF_DRIVE_COUNT (NRF_DRIVE_H0D1 + 1)
20 #endif
21 static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = {
22 	[NRF_DRIVE_S0S1] = NRF_GPIO_PIN_S0S1,
23 	[NRF_DRIVE_H0S1] = NRF_GPIO_PIN_H0S1,
24 	[NRF_DRIVE_S0H1] = NRF_GPIO_PIN_S0H1,
25 	[NRF_DRIVE_H0H1] = NRF_GPIO_PIN_H0H1,
26 	[NRF_DRIVE_D0S1] = NRF_GPIO_PIN_D0S1,
27 	[NRF_DRIVE_D0H1] = NRF_GPIO_PIN_D0H1,
28 	[NRF_DRIVE_S0D1] = NRF_GPIO_PIN_S0D1,
29 	[NRF_DRIVE_H0D1] = NRF_GPIO_PIN_H0D1,
30 #if defined(GPIO_PIN_CNF_DRIVE_E0E1) || defined(GPIO_PIN_CNF_DRIVE0_E0)
31 	[NRF_DRIVE_E0E1] = NRF_GPIO_PIN_E0E1,
32 #endif
33 };
34 
35 /* value to indicate pin level doesn't need initialization */
36 #define NO_WRITE UINT32_MAX
37 
38 #define PSEL_DISCONNECTED 0xFFFFFFFFUL
39 
40 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_uart) || defined(CONFIG_NRFX_UART)
41 #define NRF_PSEL_UART(reg, line) ((NRF_UART_Type *)reg)->PSEL##line
42 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_uarte) || defined(CONFIG_NRFX_UARTE)
43 #include <hal/nrf_uarte.h>
44 #define NRF_PSEL_UART(reg, line) ((NRF_UARTE_Type *)reg)->PSEL.line
45 #endif
46 
47 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spi) || defined(CONFIG_NRFX_SPI)
48 #define NRF_PSEL_SPIM(reg, line) ((NRF_SPI_Type *)reg)->PSEL##line
49 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spim) || defined(CONFIG_NRFX_SPIM)
50 #include <hal/nrf_spim.h>
51 #define NRF_PSEL_SPIM(reg, line) ((NRF_SPIM_Type *)reg)->PSEL.line
52 #endif
53 
54 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_spis) || defined(CONFIG_NRFX_SPIS)
55 #include <hal/nrf_spis.h>
56 #if defined(NRF51)
57 #define NRF_PSEL_SPIS(reg, line) ((NRF_SPIS_Type *)reg)->PSEL##line
58 #else
59 #define NRF_PSEL_SPIS(reg, line) ((NRF_SPIS_Type *)reg)->PSEL.line
60 #endif
61 #endif
62 
63 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_twi) || defined(CONFIG_NRFX_TWI)
64 #if !defined(TWI_PSEL_SCL_CONNECT_Pos)
65 #define NRF_PSEL_TWIM(reg, line) ((NRF_TWI_Type *)reg)->PSEL##line
66 #else
67 #define NRF_PSEL_TWIM(reg, line) ((NRF_TWI_Type *)reg)->PSEL.line
68 #endif
69 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_twim) || defined(CONFIG_NRFX_TWIM)
70 #include <hal/nrf_twim.h>
71 #define NRF_PSEL_TWIM(reg, line) ((NRF_TWIM_Type *)reg)->PSEL.line
72 #endif
73 
74 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_i2s) || defined(CONFIG_NRFX_I2S)
75 #define NRF_PSEL_I2S(reg, line) ((NRF_I2S_Type *)reg)->PSEL.line
76 #endif
77 
78 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_pdm) || defined(CONFIG_NRFX_PDM)
79 #define NRF_PSEL_PDM(reg, line) ((NRF_PDM_Type *)reg)->PSEL.line
80 #endif
81 
82 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_pwm) || defined(CONFIG_NRFX_PWM)
83 #define NRF_PSEL_PWM(reg, line) ((NRF_PWM_Type *)reg)->PSEL.line
84 #endif
85 
86 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_qdec) || defined(CONFIG_NRFX_QDEC)
87 #define NRF_PSEL_QDEC(reg, line) ((NRF_QDEC_Type *)reg)->PSEL.line
88 #endif
89 
90 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_qspi) || defined(CONFIG_NRFX_QSPI)
91 #define NRF_PSEL_QSPI(reg, line) ((NRF_QSPI_Type *)reg)->PSEL.line
92 #endif
93 
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)94 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt,
95 			   uintptr_t reg)
96 {
97 	for (uint8_t i = 0U; i < pin_cnt; i++) {
98 		nrf_gpio_pin_drive_t drive;
99 		uint8_t drive_idx = NRF_GET_DRIVE(pins[i]);
100 		uint32_t psel = NRF_GET_PIN(pins[i]);
101 		uint32_t write = NO_WRITE;
102 		nrf_gpio_pin_dir_t dir;
103 		nrf_gpio_pin_input_t input;
104 #if NRF_GPIO_HAS_CLOCKPIN
105 		bool clockpin = false;
106 #endif
107 
108 		if (drive_idx < ARRAY_SIZE(drive_modes)) {
109 			drive = drive_modes[drive_idx];
110 		} else {
111 			return -EINVAL;
112 		}
113 
114 		if (psel == NRF_PIN_DISCONNECTED) {
115 			psel = PSEL_DISCONNECTED;
116 		}
117 
118 		switch (NRF_GET_FUN(pins[i])) {
119 #if defined(NRF_PSEL_UART)
120 		case NRF_FUN_UART_TX:
121 			NRF_PSEL_UART(reg, TXD) = psel;
122 			write = 1U;
123 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
124 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
125 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_UARTE_CLOCKPIN_TXD_NEEDED)
126 			clockpin = true;
127 #endif
128 			break;
129 		case NRF_FUN_UART_RX:
130 			NRF_PSEL_UART(reg, RXD) = psel;
131 			dir = NRF_GPIO_PIN_DIR_INPUT;
132 			input = NRF_GPIO_PIN_INPUT_CONNECT;
133 			break;
134 		case NRF_FUN_UART_RTS:
135 			NRF_PSEL_UART(reg, RTS) = psel;
136 			write = 1U;
137 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
138 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
139 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_UARTE_CLOCKPIN_RTS_NEEDED)
140 			clockpin = true;
141 #endif
142 			break;
143 		case NRF_FUN_UART_CTS:
144 			NRF_PSEL_UART(reg, CTS) = psel;
145 			dir = NRF_GPIO_PIN_DIR_INPUT;
146 			input = NRF_GPIO_PIN_INPUT_CONNECT;
147 			break;
148 #endif /* defined(NRF_PSEL_UART) */
149 #if defined(NRF_PSEL_SPIM)
150 		case NRF_FUN_SPIM_SCK:
151 			NRF_PSEL_SPIM(reg, SCK) = psel;
152 			write = 0U;
153 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
154 			input = NRF_GPIO_PIN_INPUT_CONNECT;
155 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIM_CLOCKPIN_SCK_NEEDED)
156 			clockpin = true;
157 #endif
158 			break;
159 		case NRF_FUN_SPIM_MOSI:
160 			NRF_PSEL_SPIM(reg, MOSI) = psel;
161 			write = 0U;
162 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
163 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
164 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIM_CLOCKPIN_MOSI_NEEDED)
165 			/* CLOCKPIN setting must not be applied to SPIM12x instances. */
166 			if (!NRF_SPIM_IS_320MHZ_SPIM((void *)reg)) {
167 				clockpin = true;
168 			}
169 #endif
170 			break;
171 		case NRF_FUN_SPIM_MISO:
172 			NRF_PSEL_SPIM(reg, MISO) = psel;
173 			dir = NRF_GPIO_PIN_DIR_INPUT;
174 			input = NRF_GPIO_PIN_INPUT_CONNECT;
175 			break;
176 #endif /* defined(NRF_PSEL_SPIM) */
177 #if defined(NRF_PSEL_SPIS)
178 		case NRF_FUN_SPIS_SCK:
179 			NRF_PSEL_SPIS(reg, SCK) = psel;
180 			dir = NRF_GPIO_PIN_DIR_INPUT;
181 			input = NRF_GPIO_PIN_INPUT_CONNECT;
182 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIS_CLOCKPIN_SCK_NEEDED)
183 			clockpin = true;
184 #endif
185 			break;
186 		case NRF_FUN_SPIS_MOSI:
187 			NRF_PSEL_SPIS(reg, MOSI) = psel;
188 			dir = NRF_GPIO_PIN_DIR_INPUT;
189 			input = NRF_GPIO_PIN_INPUT_CONNECT;
190 			break;
191 		case NRF_FUN_SPIS_MISO:
192 			NRF_PSEL_SPIS(reg, MISO) = psel;
193 			dir = NRF_GPIO_PIN_DIR_INPUT;
194 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
195 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIS_CLOCKPIN_MISO_NEEDED)
196 			clockpin = true;
197 #endif
198 			break;
199 		case NRF_FUN_SPIS_CSN:
200 			NRF_PSEL_SPIS(reg, CSN) = psel;
201 			dir = NRF_GPIO_PIN_DIR_INPUT;
202 			input = NRF_GPIO_PIN_INPUT_CONNECT;
203 			break;
204 #endif /* defined(NRF_PSEL_SPIS) */
205 #if defined(NRF_PSEL_TWIM)
206 		case NRF_FUN_TWIM_SCL:
207 			NRF_PSEL_TWIM(reg, SCL) = psel;
208 			if (drive == NRF_GPIO_PIN_S0S1) {
209 				/* Override the default drive setting with one
210 				 * suitable for TWI/TWIM peripherals (S0D1).
211 				 * This drive cannot be used always so that
212 				 * users are able to select e.g. H0D1 or E0E1
213 				 * in devicetree.
214 				 */
215 				drive = NRF_GPIO_PIN_S0D1;
216 			}
217 			dir = NRF_GPIO_PIN_DIR_INPUT;
218 			input = NRF_GPIO_PIN_INPUT_CONNECT;
219 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_TWIM_CLOCKPIN_SCL_NEEDED)
220 			clockpin = true;
221 #endif
222 			break;
223 		case NRF_FUN_TWIM_SDA:
224 			NRF_PSEL_TWIM(reg, SDA) = psel;
225 			if (drive == NRF_GPIO_PIN_S0S1) {
226 				drive = NRF_GPIO_PIN_S0D1;
227 			}
228 			dir = NRF_GPIO_PIN_DIR_INPUT;
229 			input = NRF_GPIO_PIN_INPUT_CONNECT;
230 #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_TWIM_CLOCKPIN_SDA_NEEDED)
231 			clockpin = true;
232 #endif
233 			break;
234 #endif /* defined(NRF_PSEL_TWIM) */
235 #if defined(NRF_PSEL_I2S)
236 		case NRF_FUN_I2S_SCK_M:
237 			NRF_PSEL_I2S(reg, SCK) = psel;
238 			write = 0U;
239 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
240 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
241 			break;
242 		case NRF_FUN_I2S_SCK_S:
243 			NRF_PSEL_I2S(reg, SCK) = psel;
244 			dir = NRF_GPIO_PIN_DIR_INPUT;
245 			input = NRF_GPIO_PIN_INPUT_CONNECT;
246 			break;
247 		case NRF_FUN_I2S_LRCK_M:
248 			NRF_PSEL_I2S(reg, LRCK) = psel;
249 			write = 0U;
250 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
251 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
252 			break;
253 		case NRF_FUN_I2S_LRCK_S:
254 			NRF_PSEL_I2S(reg, LRCK) = psel;
255 			dir = NRF_GPIO_PIN_DIR_INPUT;
256 			input = NRF_GPIO_PIN_INPUT_CONNECT;
257 			break;
258 		case NRF_FUN_I2S_SDIN:
259 			NRF_PSEL_I2S(reg, SDIN) = psel;
260 			dir = NRF_GPIO_PIN_DIR_INPUT;
261 			input = NRF_GPIO_PIN_INPUT_CONNECT;
262 			break;
263 		case NRF_FUN_I2S_SDOUT:
264 			NRF_PSEL_I2S(reg, SDOUT) = psel;
265 			write = 0U;
266 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
267 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
268 			break;
269 		case NRF_FUN_I2S_MCK:
270 			NRF_PSEL_I2S(reg, MCK) = psel;
271 			write = 0U;
272 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
273 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
274 			break;
275 #endif /* defined(NRF_PSEL_I2S) */
276 #if defined(NRF_PSEL_PDM)
277 		case NRF_FUN_PDM_CLK:
278 			NRF_PSEL_PDM(reg, CLK) = psel;
279 			write = 0U;
280 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
281 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
282 			break;
283 		case NRF_FUN_PDM_DIN:
284 			NRF_PSEL_PDM(reg, DIN) = psel;
285 			dir = NRF_GPIO_PIN_DIR_INPUT;
286 			input = NRF_GPIO_PIN_INPUT_CONNECT;
287 			break;
288 #endif /* defined(NRF_PSEL_PDM) */
289 #if defined(NRF_PSEL_PWM)
290 		case NRF_FUN_PWM_OUT0:
291 			NRF_PSEL_PWM(reg, OUT[0]) = psel;
292 			write = NRF_GET_INVERT(pins[i]);
293 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
294 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
295 			break;
296 		case NRF_FUN_PWM_OUT1:
297 			NRF_PSEL_PWM(reg, OUT[1]) = psel;
298 			write = NRF_GET_INVERT(pins[i]);
299 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
300 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
301 			break;
302 		case NRF_FUN_PWM_OUT2:
303 			NRF_PSEL_PWM(reg, OUT[2]) = psel;
304 			write = NRF_GET_INVERT(pins[i]);
305 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
306 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
307 			break;
308 		case NRF_FUN_PWM_OUT3:
309 			NRF_PSEL_PWM(reg, OUT[3]) = psel;
310 			write = NRF_GET_INVERT(pins[i]);
311 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
312 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
313 			break;
314 #endif /* defined(NRF_PSEL_PWM) */
315 #if defined(NRF_PSEL_QDEC)
316 		case NRF_FUN_QDEC_A:
317 			NRF_PSEL_QDEC(reg, A) = psel;
318 			dir = NRF_GPIO_PIN_DIR_INPUT;
319 			input = NRF_GPIO_PIN_INPUT_CONNECT;
320 			break;
321 		case NRF_FUN_QDEC_B:
322 			NRF_PSEL_QDEC(reg, B) = psel;
323 			dir = NRF_GPIO_PIN_DIR_INPUT;
324 			input = NRF_GPIO_PIN_INPUT_CONNECT;
325 			break;
326 		case NRF_FUN_QDEC_LED:
327 			NRF_PSEL_QDEC(reg, LED) = psel;
328 			dir = NRF_GPIO_PIN_DIR_INPUT;
329 			input = NRF_GPIO_PIN_INPUT_CONNECT;
330 			break;
331 #endif /* defined(NRF_PSEL_QDEC) */
332 #if defined(NRF_PSEL_QSPI)
333 		case NRF_FUN_QSPI_SCK:
334 			NRF_PSEL_QSPI(reg, SCK) = psel;
335 			dir = NRF_GPIO_PIN_DIR_INPUT;
336 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
337 			break;
338 		case NRF_FUN_QSPI_CSN:
339 			NRF_PSEL_QSPI(reg, CSN) = psel;
340 			write = 1U;
341 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
342 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
343 			break;
344 		case NRF_FUN_QSPI_IO0:
345 			NRF_PSEL_QSPI(reg, IO0) = psel;
346 			dir = NRF_GPIO_PIN_DIR_INPUT;
347 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
348 			break;
349 		case NRF_FUN_QSPI_IO1:
350 			NRF_PSEL_QSPI(reg, IO1) = psel;
351 			dir = NRF_GPIO_PIN_DIR_INPUT;
352 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
353 			break;
354 		case NRF_FUN_QSPI_IO2:
355 			NRF_PSEL_QSPI(reg, IO2) = psel;
356 			dir = NRF_GPIO_PIN_DIR_INPUT;
357 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
358 			break;
359 		case NRF_FUN_QSPI_IO3:
360 			NRF_PSEL_QSPI(reg, IO3) = psel;
361 			write = 1U;
362 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
363 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
364 			break;
365 #endif /* defined(NRF_PSEL_QSPI) */
366 #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can)
367 		/* Pin routing is controlled by secure domain, via UICR */
368 		case NRF_FUN_CAN_TX:
369 			dir = NRF_GPIO_PIN_DIR_OUTPUT;
370 			input = NRF_GPIO_PIN_INPUT_DISCONNECT;
371 			break;
372 		case NRF_FUN_CAN_RX:
373 			dir = NRF_GPIO_PIN_DIR_INPUT;
374 			input = NRF_GPIO_PIN_INPUT_CONNECT;
375 			break;
376 #endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) */
377 		default:
378 			return -ENOTSUP;
379 		}
380 
381 		/* configure GPIO properties */
382 		if (psel != PSEL_DISCONNECTED) {
383 			uint32_t pin = psel;
384 
385 			if (write != NO_WRITE) {
386 				nrf_gpio_pin_write(pin, write);
387 			}
388 
389 			/* force input and disconnected buffer for low power */
390 			if (NRF_GET_LP(pins[i]) == NRF_LP_ENABLE) {
391 				dir = NRF_GPIO_PIN_DIR_INPUT;
392 				input = NRF_GPIO_PIN_INPUT_DISCONNECT;
393 			}
394 
395 			nrf_gpio_cfg(pin, dir, input, NRF_GET_PULL(pins[i]),
396 				     drive, NRF_GPIO_PIN_NOSENSE);
397 #if NRF_GPIO_HAS_CLOCKPIN
398 			nrf_gpio_pin_clock_set(pin, clockpin);
399 #endif
400 		}
401 	}
402 
403 	return 0;
404 }
405