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