1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * GPIO - General purpose input/output
9  * https://infocenter.nordicsemi.com/topic/ps_nrf52833/gpio.html?cp=5_1_0_5_7
10  *
11  * This model has the following limitations:
12  *  * Note a.1:
13  *    PIN_CNF.PULL is ignored. If a pin input is disconnected and not driven externally it will
14  *    just remain at zero/low.
15  *  * Note a.2:
16  *    PIN_CNF.DRIVE / drive strength is ignored
17  *    It is not possible to connect two outputs together building a logical AND or OR
18  *  * Note a.3:
19  *    Reading OUTCLR & DIRCLR reads always 0
20  *  * Note a.4: There is no modeling of system idle/off, and as such a DETECT raising edge from the
21  *    GPIO will not cause the system to exit those states.
22  *
23  * This model has the following approximations:
24  *  * Note b.1:
25  *    If a DIR bit is cleared for a pin which was being driven as a high output,
26  *    that pin will be lowered immediately (like if it was driven low)
27  *  * Note b.2:
28  *    All drives are instantaneous.
29  *  * Note b.3:
30  *    During pin reconfigurations, there can be spurious transitions in the pins outputs
31  *    which may not correspond to how the real HW would behave
32  *  * In real HW, after a write to LATCH, the DETECT event output to the GPIOTE is kept low for
33  *    a few clocks, before being raised again (if it needs to), in the model the new pulse/raise
34  *    is sent instantaneously to the GPIOTE
35  */
36 
37 #include <stdint.h>
38 #include <stdbool.h>
39 #include <string.h>
40 #include "NHW_common_types.h"
41 #include "NHW_config.h"
42 #include "NHW_common_types.h"
43 #include "NHW_config.h"
44 #include "NHW_peri_types.h"
45 #include "NRF_GPIO.h"
46 #include "NRF_GPIOTE.h"
47 #include "bs_tracing.h"
48 #include "nsi_tasks.h"
49 
50 NRF_GPIO_Type NRF_GPIO_regs[NRF_GPIOS];
51 
52 /* Number of pins per port: */
53 static int GPIO_n_ports_pins[NRF_GPIOS] = NRF_GPIO_PORTS_PINS;
54 
55 static uint32_t IO_level[NRF_GPIOS]; /* Actual level in the pin */
56 static uint32_t DETECT[NRF_GPIOS];   /* Sense output / unlatched/non-sticky detect */
57 static uint32_t LDETECT[NRF_GPIOS];  /* Latched sense output */
58 static bool DETECT_signal[NRF_GPIOS]; /* Individual detect signal to the GPIOTE */
59 
60 static uint32_t INPUT_mask[NRF_GPIOS]; /* As a 32bit mask, PIN_CNF[*].INPUT (0: enabled; 1: disabled)*/
61 static uint32_t SENSE_mask[NRF_GPIOS]; /* As a 32bit mask, PIN_CNF[*].SENSE.en (1: enabled; 0: disabled)*/
62 static uint32_t SENSE_inv[NRF_GPIOS];  /* As a 32bit mask, PIN_CNF[*].SENSE.inv (1: inverted;0: not inverted) */
63 
64 /*
65  * Is the output driven by another peripheral (1) or the GPIO directly (0).
66  * Note that we don't keep track of who "owns" a pin, only that somebody else does
67  */
68 static uint32_t out_override[NRF_GPIOS];
69 /* Out value provided by other peripherals */
70 static uint32_t external_OUT[NRF_GPIOS];
71 
72 /* Is the pin input controlled by a peripheral(1) or the GPIO(0) */
73 static uint32_t input_override[NRF_GPIOS];
74 /* If input_override, is the peripheral configuring the input buffer as connected (1) or disconnected (0) */
75 static uint32_t input_override_connected[NRF_GPIOS];
76 
77 /* Is "dir" controlled by a peripheral(1) or the GPIO(0) */
78 static uint32_t dir_override[NRF_GPIOS];
79 /* If dir_override is set, is the peripheral configuring the output as connected (1) or disconnected (0) */
80 static uint32_t dir_override_set[NRF_GPIOS];
81 
82 /* Callbacks for peripherals to be informed of input changes */
83 static nrf_gpio_input_callback_t per_intoggle_callbacks[NRF_GPIOS][NRF_GPIO_MAX_PINS_PER_PORT];
84 /* Callbacks for test code to be informed of input/output changes: */
85 static nrf_gpio_input_callback_t test_intoggle_callback;
86 static nrf_gpio_input_callback_t test_outtoggle_callback;
87 
88 /*
89  * Initialize the GPIOs model
90  */
nrf_gpio_init(void)91 static void nrf_gpio_init(void) {
92 	memset(NRF_GPIO_regs, 0, sizeof(NRF_GPIO_regs));
93 
94 	for (int p = 0; p < NRF_GPIOS; p ++) {
95 		for (int n = 0; n < GPIO_n_ports_pins[p]; n++) {
96 			NRF_GPIO_regs[p].PIN_CNF[n] = 0x2; /* Disconnected out of reset */
97 		}
98 		INPUT_mask[p] = UINT32_MAX; /* All disconnected out of reset */
99 	}
100 
101 	nrf_gpio_backend_init();
102 }
103 
104 NSI_TASK(nrf_gpio_init, HW_INIT, 100);
105 
nrf_gpio_get_number_pins_in_port(int port)106 unsigned int nrf_gpio_get_number_pins_in_port(int port) {
107 	return GPIO_n_ports_pins[port];
108 }
109 
110 static void nrf_gpio_eval_outputs(unsigned int port);
111 static void nrf_gpio_eval_inputs(unsigned int port);
112 void nrf_gpio_eval_input(unsigned int port, unsigned int n, bool value);
113 
114 /*
115  * Register a test callback to be called whenever a pin IN register changes
116  */
nrf_gpio_test_register_in_callback(nrf_gpio_input_callback_t fptr)117 void nrf_gpio_test_register_in_callback(nrf_gpio_input_callback_t fptr) {
118 	test_intoggle_callback = fptr;
119 }
120 
121 /*
122  * Register a test callback to be called whenever an *output* pin changes
123  */
nrf_gpio_test_register_out_callback(nrf_gpio_input_callback_t fptr)124 void nrf_gpio_test_register_out_callback(nrf_gpio_input_callback_t fptr) {
125 	test_outtoggle_callback = fptr;
126 }
127 
128 /*
129  * Change a pin input value
130  *
131  * Note: The pin must not be currently driven by the SOC, or you will get an error
132  *
133  * Inputs:
134  *  * port: Which GPIO port
135  *  * n: which pin in that GPIO port
136  *  * value: true: high, false: low
137  */
nrf_gpio_test_change_pin_level(unsigned int port,unsigned int n,bool value)138 void nrf_gpio_test_change_pin_level(unsigned int port, unsigned int n, bool value) {
139 	nrf_gpio_eval_input(port, n, value);
140 }
141 
142 /*
143  * Get a pin level
144  *
145  * Inputs:
146  *  * port: Which GPIO port
147  *  * n: which pin in that GPIO port
148  * Return: true (high), false (low)
149  */
nrf_gpio_get_pin_level(unsigned int port,unsigned int n)150 bool nrf_gpio_get_pin_level(unsigned int port, unsigned int n) {
151 	return (IO_level[port] >> n) & 0x1;
152 }
153 
154 #define CHECK_PIN_EXISTS(port, n, dir) \
155 	if (port >= NRF_GPIOS || n >= GPIO_n_ports_pins[port]) { \
156 		bs_trace_error_time_line("%s: Error, attempted to toggle "dir" for nonexistent " \
157 					"GPIO port %i, pin %i\n", \
158 					__func__, port, n); \
159 	}
160 
get_enabled_inputs(unsigned int port)161 static inline uint32_t get_enabled_inputs(unsigned int port){
162 	return (~input_override[port] & ~INPUT_mask[port])
163 		| (input_override[port] & input_override_connected[port]);
164 }
165 
get_dir(unsigned int port)166 static inline uint32_t get_dir(unsigned int port){
167 	return (~dir_override[port] & NRF_GPIO_regs[port].DIR)
168 		| (dir_override[port] & dir_override_set[port]);
169 }
170 
171 /*
172  * Function with which another peripheral can claim configuration control of a pin.
173  *
174  * Inputs:
175  *	* port: Which GPIO port
176  *	* n : which pin in that GPIO port
177  *	* override_output:
178  *		* -1 : Don't change
179  *		*  0 : Leave for GPIO control (GPIO OUT register sets the output value)
180  *		*  1 : Take external control of pin output value (peripheral sets the output value
181  *		       with nrf_gpio_peri_change_output() )
182  *	* override_input:
183  *		* -1 : Don't change
184  *		*  0 : Leave input to be controlled by the GPIO module
185  *		*  2 : Take external control of input, and disconnect
186  *		*  3 : Take external control of input, and connect
187  *	* override_dir:
188  *		* -1 : Don't change
189  *		*  0 : Leave DIR to be controlled by the GPIO module
190  *		*  2 : Take external control of DIR, and disconnect
191  *		*  3 : Take external control of DIR, and connect
192  *      * fptr: Function to be called whenever that input toggles (if enabled).
193  *              Set to NULL if not needed.
194  *      * new_level:
195  *              * -1: Don't change
196  *              *  0: low
197  *              *  1: high
198  */
nrf_gpio_peri_pin_control(unsigned int port,unsigned int n,int override_output,int override_input,int override_dir,nrf_gpio_input_callback_t fptr,int new_level)199 void nrf_gpio_peri_pin_control(unsigned int port, unsigned int n,
200 			      int override_output, int override_input, int override_dir,
201 			      nrf_gpio_input_callback_t fptr, int new_level) {
202 
203 	if (port >= NRF_GPIOS || n >= GPIO_n_ports_pins[port]) { /* LCOV_EXCL_BR_LINE */
204 		bs_trace_error_time_line("Programming error\n"); /* LCOV_EXCL_LINE */
205 	}
206 
207 	uint32_t mask = 1<<n;
208 	bool need_output_eval = false;
209 	bool need_input_eval = false;
210 
211 	if (override_output >= 0) {
212 		out_override[port] &= ~mask;
213 		out_override[port] |= (uint32_t)(override_output?1:0) << n;
214 		need_output_eval = true;
215 	}
216 	if (override_input >= 0) {
217 		input_override[port] &= ~mask;
218 		input_override[port] |= (uint32_t)(override_input?1:0) << n;
219 
220 		input_override_connected[port] &= ~mask;
221 		input_override_connected[port] |= (uint32_t)(override_input==3?1:0) << n;
222 
223 		need_input_eval = true;
224 	}
225 	if (override_dir >= 0) {
226 		dir_override[port] &= ~mask;
227 		dir_override[port] |= (uint32_t)(override_dir?1:0) << n;
228 
229 		dir_override_set[port] &= ~mask;
230 		dir_override_set[port] |= (uint32_t)(override_dir==3?1:0) << n;
231 
232 		need_output_eval = true;
233 	}
234 	per_intoggle_callbacks[port][n] = fptr;
235 	if (new_level >= 0) {
236 		external_OUT[port] &= ~((uint32_t)1 << n);
237 		external_OUT[port] |= (uint32_t)(new_level?1:0) << n;
238 		need_output_eval = true;
239 	}
240 
241 	if (need_output_eval) {
242 		nrf_gpio_eval_outputs(port);
243 	}
244 	if (need_input_eval) {
245 		nrf_gpio_eval_inputs(port);
246 	}
247 }
248 
249 /*
250  * A peripheral wants to toggle a GPIO output to a new value <value>.
251  * Note: The value may be the same as it was, in which case nothing will happen.
252  *
253  * Inputs:
254  *  * port is the GPIO port
255  *  * n is the pin number inside that GPIO port (0..31)
256  *  * value is the new output value high (true) or low (false)
257  */
nrf_gpio_peri_change_output(unsigned int port,unsigned int n,bool value)258 void nrf_gpio_peri_change_output(unsigned int port, unsigned int n, bool value)
259 {
260 	CHECK_PIN_EXISTS(port, n, "output"); /* LCOV_EXCL_BR_LINE */
261 
262 	if (((out_override[port] >> n) & 0x1) != 1) { /* LCOV_EXCL_START */
263 		bs_trace_error_time_line("%s: Programming error, a peripheral is trying to toggle "
264 					"a GPIO output it does not own, GPIO port %i, pin %i\n",
265 					__func__, port, n);
266 	}
267 
268 	if (((get_dir(port) >> n) & 0x1) != 1) {
269 		bs_trace_warning_time_line("%s: A peripheral is trying to toggle "
270 					   "a GPIO output but the output is disabled, "
271 					   "GPIO port %i, pin %i\n",
272 					   __func__, port, n);
273 	} /* LCOV_EXCL_STOP */
274 
275 	external_OUT[port] &= ~((uint32_t)1 << n);
276 	external_OUT[port] |= (uint32_t)value << n;
277 	nrf_gpio_eval_outputs(port);
278 }
279 
nrf_gpio_update_detect_signal(unsigned int port)280 static void nrf_gpio_update_detect_signal(unsigned int port) {
281 	if (NRF_GPIO_regs[port].DETECTMODE == 0){ //gpio.detect signal from not latched detect
282 		DETECT_signal[port] = (DETECT[port] != 0);
283 	} else {//gpio.detect signal from latched detect
284 		DETECT_signal[port] = (LDETECT[port] != 0);
285 	}
286 }
287 
288 /*
289  * Evaluate sense output (after a change of input or configuration)
290  */
nrf_gpio_eval_sense(unsigned int port)291 static void nrf_gpio_eval_sense(unsigned int port){
292 	/* Note SENSE_dir inverts the output */
293 	DETECT[port] = (NRF_GPIO_regs[port].IN ^ SENSE_inv[port]) & SENSE_mask[port];
294 	LDETECT[port] |= DETECT[port];
295 	NRF_GPIO_regs[port].LATCH = LDETECT[port];
296 
297 	bool old_DETECT_signal = DETECT_signal[port];
298 
299 	nrf_gpio_update_detect_signal(port);
300 
301 	if ((DETECT_signal[port] == true) && (old_DETECT_signal==false)) {
302 		nrf_gpiote_port_event_raise(port);
303 	}
304 }
305 
306 /*
307  * Return the level of the DETECT output signal for a GPIO instance
308  *
309  * input: port: The GPIO instance number
310  */
nrf_gpio_get_detect_level(unsigned int port)311 bool nrf_gpio_get_detect_level(unsigned int port){
312 	return DETECT_signal[port];
313 }
314 
315 /*
316  * The input has changed and the driver is connected,
317  * notify as necessary
318  */
nrf_gpio_input_change_sideeffects(unsigned int port,unsigned int n)319 static void nrf_gpio_input_change_sideeffects(unsigned int port,unsigned int n)
320 {
321 	if (per_intoggle_callbacks[port][n] != NULL) {
322 		per_intoggle_callbacks[port][n](port, n, (NRF_GPIO_regs[port].IN >> n) & 0x1);
323 	}
324 	if (test_intoggle_callback != NULL) {
325 		test_intoggle_callback(port, n, (NRF_GPIO_regs[port].IN >> n) & 0x1);
326 	}
327 }
328 
329 /*
330  * Get the level of the IN signal for GPIO <port> pin <n>
331  */
nrf_gpio_get_IN(unsigned int port,unsigned int n)332 bool nrf_gpio_get_IN(unsigned int port, unsigned int n) {
333 	return (NRF_GPIO_regs[port].IN >> n) & 0x1;
334 }
335 
336 /*
337  * An input pin has toggled or the input configuration has changed,
338  * propagate it
339  */
nrf_gpio_eval_inputs(unsigned int port)340 static void nrf_gpio_eval_inputs(unsigned int port)
341 {
342 	uint32_t new_IN = IO_level[port] & get_enabled_inputs(port);
343 
344 	uint32_t diff = new_IN ^ NRF_GPIO_regs[port].IN;
345 
346 	NRF_GPIO_regs[port].IN = new_IN;
347 
348 	for (int n = __builtin_ffs(diff) - 1; n >= 0; n = __builtin_ffs(diff) - 1) {
349 		nrf_gpio_input_change_sideeffects(port, n);
350 		diff &= ~(1 << n);
351 	}
352 
353 	nrf_gpio_eval_sense(port);
354 }
355 
356 /*
357  * An input *may* be changing to a new value <value>.
358  * Note: The value may be the same as it was, in which case nothing will happen.
359  *
360  * This function is meant to be called from something which drives the input
361  * **externally**
362  *
363  * Inputs:
364  *  * port is the GPIO port
365  *  * n is the pin number inside that GPIO port (0..31)
366  *  * value: is the input high (true) or low (false)
367  */
nrf_gpio_eval_input(unsigned int port,unsigned int n,bool value)368 void nrf_gpio_eval_input(unsigned int port, unsigned int n, bool value)
369 {
370 	CHECK_PIN_EXISTS(port, n, "input"); /* LCOV_EXCL_BR_LINE */
371 
372 	uint32_t dir = get_dir(port);
373 
374 	if ((dir >> n) & 0x1) { /* LCOV_EXCL_START */
375 		bs_trace_warning_time_line("%s: Attempted to drive externally a pin which is "
376 					   "currently being driven by the SOC. It will be ignored."
377 					   "GPIO port %i, pin %i\n",
378 					   __func__, port, n);
379 		return;
380 	}			/* LCOV_EXCL_STOP */
381 
382 	int diff = ((IO_level[port] >> n) & 0x1) ^ (uint32_t)value;
383 
384 	if (diff == 0) {
385 		/* No toggle */
386 		return;
387 	}
388 
389 	IO_level[port] ^= (uint32_t)1 << n;
390 
391 	nrf_gpio_eval_inputs(port);
392 }
393 
394 /*
395  * The output is being changed, propagate it as necessary and/or record it.
396  */
nrf_gpio_output_change_sideeffects(unsigned int port,unsigned int n,bool value)397 static void nrf_gpio_output_change_sideeffects(unsigned int port,unsigned  int n, bool value)
398 {
399 	nrf_gpio_backend_write_output_change(port, n, value);
400 	if (test_outtoggle_callback != NULL) {
401 		test_outtoggle_callback(port, n, value);
402 	}
403 	nrf_gpio_backend_short_propagate(port, n, value);
404 }
405 
406 /*
407  * Reevaluate outputs after a configuration or OUT/external_OUT change
408  */
nrf_gpio_eval_outputs(unsigned int port)409 static void nrf_gpio_eval_outputs(unsigned int port)
410 {
411 	/* Actual level in the pin, but only of the bits driven by output: */
412 	static uint32_t O_level[NRF_GPIOS];
413 
414 	uint32_t dir = get_dir(port); /* Which pins are driven by output */
415 
416 	uint32_t out = (~out_override[port] & NRF_GPIO_regs[port].OUT)
417 			| (out_override[port] & external_OUT[port]);
418 
419 	uint32_t new_output = dir & out;
420 
421 	uint32_t diff = new_output ^ O_level[port];
422 
423 	if (diff == 0) {
424 		return;
425 	}
426 
427 	O_level[port] = new_output;
428 
429 	IO_level[port] &= ~dir;
430 	IO_level[port] |= O_level[port];
431 
432 	for (int n = __builtin_ffs(diff) - 1; n >= 0; n = __builtin_ffs(diff) - 1) {
433 		nrf_gpio_output_change_sideeffects(port, n, (new_output >> n) & 0x1);
434 		diff &= ~(1 << n);
435 	}
436 
437 	/* Inputs may be connected to pins driven by outputs, let's check */
438 	nrf_gpio_eval_inputs(port);
439 }
440 
441 
442 /*
443  * Register write side-effecting functions:
444  */
445 
nrf_gpio_regw_sideeffects_OUT(unsigned int port)446 void nrf_gpio_regw_sideeffects_OUT(unsigned int port) {
447 	nrf_gpio_eval_outputs(port);
448 }
449 
nrf_gpio_regw_sideeffects_OUTSET(unsigned int port)450 void nrf_gpio_regw_sideeffects_OUTSET(unsigned int port) {
451 	if (NRF_GPIO_regs[port].OUTSET) {
452 		NRF_GPIO_regs[port].OUT |= NRF_GPIO_regs[port].OUTSET;
453 		nrf_gpio_eval_outputs(port);
454 	}
455 	NRF_GPIO_regs[port].OUTSET = NRF_GPIO_regs[port].OUT;
456 }
457 
nrf_gpio_regw_sideeffects_OUTCLR(unsigned int port)458 void nrf_gpio_regw_sideeffects_OUTCLR(unsigned int port) {
459 	if (NRF_GPIO_regs[port].OUTCLR) {
460 		NRF_GPIO_regs[port].OUT &= ~NRF_GPIO_regs[port].OUTCLR;
461 		NRF_GPIO_regs[port].OUTCLR = 0;
462 		nrf_gpio_eval_outputs(port);
463 	}
464 }
465 
nrf_gpio_regw_sideeffects_DIR(unsigned int port)466 void nrf_gpio_regw_sideeffects_DIR(unsigned int port) {
467 	/* Mirror change into PIN_CNF[*].DIR */
468 	for (int n = 0; n < GPIO_n_ports_pins[port]; n++ ) {
469 		NRF_GPIO_regs[port].PIN_CNF[n] &= ~GPIO_PIN_CNF_DIR_Msk;
470 		NRF_GPIO_regs[port].PIN_CNF[n] |= (NRF_GPIO_regs[port].DIR >> n) & 0x1;
471 	}
472 
473 	nrf_gpio_eval_outputs(port);
474 }
475 
nrf_gpio_regw_sideeffects_DIRSET(unsigned int port)476 void nrf_gpio_regw_sideeffects_DIRSET(unsigned int port) {
477 	if (NRF_GPIO_regs[port].DIRSET) {
478 		NRF_GPIO_regs[port].DIR |= NRF_GPIO_regs[port].DIRSET;
479 		nrf_gpio_regw_sideeffects_DIR(port);
480 	}
481 	NRF_GPIO_regs[port].DIRSET = NRF_GPIO_regs[port].DIR;
482 }
483 
nrf_gpio_regw_sideeffects_DIRCLR(unsigned int port)484 void nrf_gpio_regw_sideeffects_DIRCLR(unsigned int port) {
485 	if (NRF_GPIO_regs[port].DIRCLR) {
486 		NRF_GPIO_regs[port].DIR &= ~NRF_GPIO_regs[port].DIRCLR;
487 		NRF_GPIO_regs[port].DIRCLR = 0;
488 		nrf_gpio_regw_sideeffects_DIR(port);
489 	}
490 }
491 
nrf_gpio_regw_sideeffects_LATCH(unsigned int port)492 void nrf_gpio_regw_sideeffects_LATCH(unsigned int port) {
493 
494 	/* LATCH contains what SW wrote: */
495 	uint32_t sw_input = NRF_GPIO_regs[port].LATCH;
496 
497 	/* Whatever bits SW set to 1, it is trying to clear: */
498 	LDETECT[port] &= ~sw_input;
499 
500 	/* But where the sense output is high, the bits are kept high: */
501 	LDETECT[port] |= DETECT[port];
502 
503 	NRF_GPIO_regs[port].LATCH = LDETECT[port];
504 
505 	nrf_gpio_update_detect_signal(port);
506 
507 	/*
508 	 * Note the text from the spec:
509 	 *   If one or more bits in the LATCH register are '1' after the CPU has
510 	 *   performed a clear operation on the LATCH registers, a rising edge will be generated
511 	 *   on the LDETECT signal.
512 	 * "the CPU has performed a clear operation" == after writing LATCH with any bit to 1
513 	 */
514 	if (sw_input != 0 && LDETECT[port] != 0 && NRF_GPIO_regs[port].DETECTMODE == 1) {
515 		nrf_gpiote_port_event_raise(port);
516 	}
517 }
518 
nrf_gpio_regw_sideeffects_DETECTMODE(unsigned int port)519 void nrf_gpio_regw_sideeffects_DETECTMODE(unsigned int port) {
520 	nrf_gpio_eval_sense(port);
521 }
522 
nrf_gpio_regw_sideeffects_PIN_CNF(unsigned int port,unsigned int n)523 void nrf_gpio_regw_sideeffects_PIN_CNF(unsigned int port,unsigned  int n) {
524 
525 	bool need_output_eval = false;
526 	bool need_input_eval = false;
527 	bool need_sense_eval = false;
528 
529 	int dir = NRF_GPIO_regs[port].PIN_CNF[n] & GPIO_PIN_CNF_DIR_Msk;
530 
531 	if (dir != ((NRF_GPIO_regs[port].DIR >> n) & 0x1)) {
532 		NRF_GPIO_regs[port].DIR ^= 1 << n;
533 		need_output_eval = true;
534 	}
535 
536 	/* Note: DRIVE and PULL are not yet used in this model
537 	int pull = (NRF_GPIO_regs[port].PIN_CNF[n] & GPIO_PIN_CNF_PULL_Msk)
538 					>> GPIO_PIN_CNF_PULL_Pos;
539 
540 	int drive = (NRF_GPIO_regs[port].PIN_CNF[n] & GPIO_PIN_CNF_DRIVE_Msk)
541 					>> GPIO_PIN_CNF_DRIVE_Pos;
542 	*/
543 
544 	int input = (NRF_GPIO_regs[port].PIN_CNF[n] & GPIO_PIN_CNF_INPUT_Msk)
545 			>> GPIO_PIN_CNF_INPUT_Pos;
546 	if (input != ((INPUT_mask[port] >> n) & 0x1)) {
547 		INPUT_mask[port] ^= 1 << n;
548 		need_input_eval = true;
549 	}
550 
551 	int sense = (NRF_GPIO_regs[port].PIN_CNF[n] & GPIO_PIN_CNF_SENSE_Msk)
552 			>> GPIO_PIN_CNF_SENSE_Pos;
553 	if (((sense >> 1) & 0x1) != ((SENSE_mask[port] >> n) & 0x1)) {
554 		SENSE_mask[port] ^= 1 << n;
555 		need_sense_eval = true;
556 	}
557 	if ((sense & 0x1) != ((SENSE_inv[port] >> n) & 0x1)) {
558 		SENSE_inv[port] ^= 1 << n;
559 		need_sense_eval = true;
560 	}
561 
562 	if (need_output_eval) {
563 		nrf_gpio_eval_outputs(port);
564 	}
565 	if (need_input_eval) {
566 		nrf_gpio_eval_inputs(port);
567 	}
568 	if (need_sense_eval) {
569 		nrf_gpio_eval_sense(port);
570 	}
571 }
572