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