1 /*
2 * Copyright 2018 - 2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_device_registers.h"
10 #include "fsl_gpio.h"
11 #if (defined(FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER) && (FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER > 0U))
12 #include "fsl_syscon.h"
13 #else
14 #include "fsl_inputmux.h"
15 #endif
16 #include "fsl_pint.h"
17 #include "fsl_adapter_gpio.h"
18
19 /* Component ID definition, used by tools. */
20 #ifndef FSL_COMPONENT_ID
21 #define FSL_COMPONENT_ID "component.lpc_gpio_adapter"
22 #endif
23
24 /*******************************************************************************
25 * Definitions
26 ******************************************************************************/
27
28 #if (defined(FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER) && (FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER > 0U))
29 #define HAL_INPUTMUX_GpioPortPinToPintsel(port, pin) \
30 ((uint32_t)(pin) + ((uint32_t)(port) << 5U) + ((uint32_t)PINTSEL_ID << SYSCON_SHIFT))
31 #else
32 #define HAL_INPUTMUX_GpioPortPinToPintsel(port, pin) \
33 ((uint32_t)(pin) + ((uint32_t)(port) << 5U) + ((uint32_t)PINTSEL_PMUX_ID << PMUX_SHIFT))
34 #endif
35
36 /*! @brief The pin config struct of gpio adapter. */
37 typedef struct _hal_gpio_pin
38 {
39 uint8_t port;
40 uint8_t pin;
41 struct
42 {
43 uint8_t direction : 1U;
44 uint8_t trigger : 3U;
45 uint8_t reserved : 4U;
46 } pinSet;
47 struct
48 {
49 uint8_t pintInitialized : 1U;
50 uint8_t pintIndex : 4U;
51 uint8_t reserved : 3U;
52 } pint;
53 } hal_gpio_pin_t;
54
55 typedef struct _hal_gpio_state
56 {
57 struct _hal_gpio_state *next;
58 hal_gpio_callback_t callback;
59 void *callbackParam;
60 hal_gpio_pin_t pin;
61 } hal_gpio_state_t;
62
63 #define HAL_GPIO_INPUTMUX_PIN_FLAG(port, pin) (((port) << 5U) + (pin))
64 #define HAL_GPIO_INPUTMUX_GET_PIN(flag) ((flag)&0x1FU)
65 #define HAL_GPIO_INPUTMUX_GET_PORT(flag) ((flag) >> 5U)
66
67 #define HAL_GPIO_PORT_INIT_SET_FLAG(port) (s_GpioPortInitializedFlag |= ((uint32_t)1U << (port)))
68 #define HAL_GPIO_PORT_INIT_GET_FLAG(port) ((0U != (s_GpioPortInitializedFlag & ((uint32_t)1U << (port)))) ? 1U : 0U)
69
70 /*******************************************************************************
71 * Prototypes
72 ******************************************************************************/
73
74 static void HAL_GpioInterruptHandle(uint8_t port, uint8_t pin);
75
76 /*******************************************************************************
77 * Variables
78 ******************************************************************************/
79
80 static uint8_t s_GpioPintInitialized = 0;
81 static uint32_t s_GpioPortInitializedFlag = 0;
82
83 static uint8_t s_GpioInputMux[(FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS + 7) / 8];
84 static uint8_t s_GpioInputMuxPin[FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS];
85
86 static hal_gpio_state_t *s_GpioHead;
87
88 static const IRQn_Type s_PintIRQ[] = PINT_IRQS;
89 static GPIO_Type *const s_GpioList[] = GPIO_BASE_PTRS;
90 /*******************************************************************************
91 * Code
92 ******************************************************************************/
93
HAL_GpioInterruptCallback(pint_pin_int_t pintr,uint32_t pmatch_status)94 static void HAL_GpioInterruptCallback(pint_pin_int_t pintr, uint32_t pmatch_status)
95 {
96 if (0U != (s_GpioInputMux[(uint8_t)pintr >> 3U] & (1U << ((uint8_t)pintr & 0x07U))))
97 {
98 HAL_GpioInterruptHandle(HAL_GPIO_INPUTMUX_GET_PORT(s_GpioInputMuxPin[pintr]),
99 HAL_GPIO_INPUTMUX_GET_PIN(s_GpioInputMuxPin[pintr]));
100 }
101 }
102
HAL_GpioInterruptHandle(uint8_t port,uint8_t pin)103 static void HAL_GpioInterruptHandle(uint8_t port, uint8_t pin)
104 {
105 hal_gpio_state_t *head = s_GpioHead;
106
107 while (NULL != head)
108 {
109 if ((pin == head->pin.pin) && (port == head->pin.port))
110 {
111 if ((NULL != head->callback))
112 {
113 head->callback(head->callbackParam);
114 }
115 }
116 head = head->next;
117 }
118 }
119
HAL_GpioConflictSearch(hal_gpio_state_t * head,uint8_t port,uint8_t pin)120 static hal_gpio_status_t HAL_GpioConflictSearch(hal_gpio_state_t *head, uint8_t port, uint8_t pin)
121 {
122 while (NULL != head)
123 {
124 if ((head->pin.port == port) && (head->pin.pin == pin))
125 {
126 return kStatus_HAL_GpioPinConflict;
127 }
128 head = head->next;
129 }
130 return kStatus_HAL_GpioSuccess;
131 }
132
HAL_GpioAddItem(hal_gpio_state_t ** head,hal_gpio_state_t * node)133 static hal_gpio_status_t HAL_GpioAddItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
134 {
135 hal_gpio_state_t *p = *head;
136 uint32_t regPrimask;
137
138 regPrimask = DisableGlobalIRQ();
139
140 if (NULL == p)
141 {
142 *head = node;
143 }
144 else
145 {
146 while (NULL != p->next)
147 {
148 if (p == node)
149 {
150 EnableGlobalIRQ(regPrimask);
151 return kStatus_HAL_GpioPinConflict;
152 }
153 p = p->next;
154 }
155
156 p->next = node;
157 }
158 node->next = NULL;
159 EnableGlobalIRQ(regPrimask);
160 return kStatus_HAL_GpioSuccess;
161 }
162
HAL_GpioRemoveItem(hal_gpio_state_t ** head,hal_gpio_state_t * node)163 static hal_gpio_status_t HAL_GpioRemoveItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
164 {
165 hal_gpio_state_t *p = *head;
166 hal_gpio_state_t *q = NULL;
167 uint32_t regPrimask;
168
169 regPrimask = DisableGlobalIRQ();
170 while (NULL != p)
171 {
172 if (p == node)
173 {
174 if (NULL == q)
175 {
176 *head = p->next;
177 }
178 else
179 {
180 q->next = p->next;
181 }
182 break;
183 }
184 else
185 {
186 q = p;
187 p = p->next;
188 }
189 }
190 EnableGlobalIRQ(regPrimask);
191 return kStatus_HAL_GpioSuccess;
192 }
193
HAL_GpioPreInit(void)194 void HAL_GpioPreInit(void)
195 {
196 s_GpioPintInitialized = 0U;
197 s_GpioPortInitializedFlag = 0U;
198 s_GpioHead = NULL;
199 }
200
HAL_GpioInit(hal_gpio_handle_t gpioHandle,hal_gpio_pin_config_t * pinConfig)201 hal_gpio_status_t HAL_GpioInit(hal_gpio_handle_t gpioHandle, hal_gpio_pin_config_t *pinConfig)
202 {
203 hal_gpio_state_t *gpioState;
204 hal_gpio_status_t status = kStatus_HAL_GpioSuccess;
205 gpio_pin_config_t gpioPinconfig = {
206 kGPIO_DigitalInput,
207 0U,
208 };
209
210 assert(gpioHandle);
211 assert(pinConfig);
212 assert(HAL_GPIO_HANDLE_SIZE >= sizeof(hal_gpio_state_t));
213
214 gpioState = (hal_gpio_state_t *)gpioHandle;
215
216 if ((NULL != s_GpioHead) &&
217 (kStatus_HAL_GpioSuccess != HAL_GpioConflictSearch(s_GpioHead, pinConfig->port, pinConfig->pin)))
218 {
219 return kStatus_HAL_GpioPinConflict;
220 }
221
222 status = HAL_GpioAddItem(&s_GpioHead, gpioState);
223 if (kStatus_HAL_GpioSuccess != status)
224 {
225 return status;
226 }
227
228 gpioState->pin.pin = pinConfig->pin;
229 gpioState->pin.port = pinConfig->port;
230 gpioState->pin.pinSet.direction = (uint8_t)pinConfig->direction;
231 gpioState->pin.pint.pintInitialized = 0U;
232
233 if (kHAL_GpioDirectionOut == pinConfig->direction)
234 {
235 gpioPinconfig.pinDirection = kGPIO_DigitalOutput;
236 gpioPinconfig.outputLogic = pinConfig->level;
237 }
238 else
239 {
240 gpioPinconfig.pinDirection = kGPIO_DigitalInput;
241 }
242 if (0U == (uint32_t)HAL_GPIO_PORT_INIT_GET_FLAG(pinConfig->port))
243 {
244 HAL_GPIO_PORT_INIT_SET_FLAG(pinConfig->port);
245 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
246 /*! @brief Array to map FGPIO instance number to clock name. */
247 const clock_ip_name_t gpioClockName[] = GPIO_CLOCKS;
248
249 assert(gpioState->pin.port < ARRAY_SIZE(gpioClockName));
250 CLOCK_EnableClock(gpioClockName[gpioState->pin.port]);
251 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
252
253 #if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
254 /*! @brief Pointers to GPIO resets for each instance. */
255 const reset_ip_name_t gpioResets[] = GPIO_RSTS_N;
256
257 RESET_ClearPeripheralReset(gpioResets[gpioState->pin.port]);
258 #endif /* FSL_FEATURE_GPIO_HAS_NO_RESET */
259 }
260
261 GPIO_PinInit(s_GpioList[0], pinConfig->port, pinConfig->pin, &gpioPinconfig);
262
263 return kStatus_HAL_GpioSuccess;
264 }
265
HAL_GpioDeinit(hal_gpio_handle_t gpioHandle)266 hal_gpio_status_t HAL_GpioDeinit(hal_gpio_handle_t gpioHandle)
267 {
268 hal_gpio_state_t *gpioStateHandle;
269 uint32_t i;
270 uint32_t k;
271
272 assert(gpioHandle);
273
274 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
275
276 if (0U != gpioStateHandle->pin.pint.pintInitialized)
277 {
278 /* Disable the pin's PINT callback */
279 PINT_DisableCallbackByIndex(PINT, (pint_pin_int_t)gpioStateHandle->pin.pint.pintIndex);
280 }
281
282 for (k = 0U; k < (uint32_t)FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; k++)
283 {
284 if (HAL_GPIO_INPUTMUX_PIN_FLAG(gpioStateHandle->pin.port, gpioStateHandle->pin.pin) == s_GpioInputMuxPin[k])
285 {
286 s_GpioInputMux[k >> 3U] &= ~(1U << (k & 0x07U));
287 s_GpioInputMuxPin[k] = 0U;
288 gpioStateHandle->pin.pint.pintInitialized = 0U;
289 break;
290 }
291 }
292
293 for (i = 0U; i < (uint32_t)FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS; i++)
294 {
295 if (0U != (s_GpioInputMux[i >> 3] & (1U << (i & 0x07U))))
296 {
297 break;
298 }
299 }
300
301 if (i >= (uint32_t)FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS)
302 {
303 if (0U != s_GpioPintInitialized)
304 {
305 s_GpioPintInitialized = 0U;
306 /* Deinitialize PINT */
307 PINT_Deinit(PINT);
308 }
309 }
310
311 (void)HAL_GpioRemoveItem(&s_GpioHead, gpioStateHandle);
312 return kStatus_HAL_GpioSuccess;
313 }
314
HAL_GpioGetInput(hal_gpio_handle_t gpioHandle,uint8_t * pinState)315 hal_gpio_status_t HAL_GpioGetInput(hal_gpio_handle_t gpioHandle, uint8_t *pinState)
316 {
317 hal_gpio_state_t *gpioStateHandle;
318
319 assert(gpioHandle);
320
321 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
322
323 *pinState = ((0U != GPIO_PinRead(s_GpioList[0], gpioStateHandle->pin.port, gpioStateHandle->pin.pin)) ? 1U : 0U);
324 return kStatus_HAL_GpioSuccess;
325 }
326
HAL_GpioSetOutput(hal_gpio_handle_t gpioHandle,uint8_t pinState)327 hal_gpio_status_t HAL_GpioSetOutput(hal_gpio_handle_t gpioHandle, uint8_t pinState)
328 {
329 hal_gpio_state_t *gpioStateHandle;
330
331 assert(gpioHandle);
332
333 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
334
335 GPIO_PinWrite(s_GpioList[0], gpioStateHandle->pin.port, gpioStateHandle->pin.pin, (0U != pinState) ? 1U : 0U);
336 return kStatus_HAL_GpioSuccess;
337 }
338
HAL_GpioInstallCallback(hal_gpio_handle_t gpioHandle,hal_gpio_callback_t callback,void * callbackParam)339 hal_gpio_status_t HAL_GpioInstallCallback(hal_gpio_handle_t gpioHandle,
340 hal_gpio_callback_t callback,
341 void *callbackParam)
342 {
343 hal_gpio_state_t *gpioStateHandle;
344
345 assert(gpioHandle);
346
347 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
348
349 gpioStateHandle->callbackParam = callbackParam;
350 gpioStateHandle->callback = callback;
351
352 return kStatus_HAL_GpioSuccess;
353 }
354
HAL_GpioGetTriggerMode(hal_gpio_handle_t gpioHandle,hal_gpio_interrupt_trigger_t * gpioTrigger)355 hal_gpio_status_t HAL_GpioGetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t *gpioTrigger)
356 {
357 hal_gpio_state_t *gpioStateHandle;
358
359 assert(gpioHandle);
360
361 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
362
363 if ((uint8_t)kHAL_GpioDirectionOut == gpioStateHandle->pin.pinSet.direction)
364 {
365 return kStatus_HAL_GpioError;
366 }
367
368 *gpioTrigger = (hal_gpio_interrupt_trigger_t)gpioStateHandle->pin.pinSet.trigger;
369 return kStatus_HAL_GpioSuccess;
370 }
371
HAL_GpioSetTriggerMode(hal_gpio_handle_t gpioHandle,hal_gpio_interrupt_trigger_t gpioTrigger)372 hal_gpio_status_t HAL_GpioSetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t gpioTrigger)
373 {
374 hal_gpio_state_t *gpioStateHandle;
375 pint_pin_enable_t triggerType;
376 uint32_t typeConvTemp; /* MISRA C-2012 Rule 10.8 */
377
378 assert(gpioHandle);
379
380 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
381
382 if ((uint8_t)kHAL_GpioDirectionOut == gpioStateHandle->pin.pinSet.direction)
383 {
384 return kStatus_HAL_GpioError;
385 }
386
387 switch (gpioTrigger)
388 {
389 case kHAL_GpioInterruptLogicZero:
390 triggerType = kPINT_PinIntEnableLowLevel;
391 break;
392 case kHAL_GpioInterruptLogicOne:
393 triggerType = kPINT_PinIntEnableHighLevel;
394 break;
395 case kHAL_GpioInterruptRisingEdge:
396 triggerType = kPINT_PinIntEnableRiseEdge;
397 break;
398 case kHAL_GpioInterruptFallingEdge:
399 triggerType = kPINT_PinIntEnableFallEdge;
400 break;
401 case kHAL_GpioInterruptEitherEdge:
402 triggerType = kPINT_PinIntEnableBothEdges;
403 break;
404 default:
405 triggerType = kPINT_PinIntEnableNone;
406 break;
407 }
408
409 gpioStateHandle->pin.pinSet.trigger = (uint8_t)gpioTrigger;
410
411 /* Enable callbacks for PINT */
412 if (0U == s_GpioPintInitialized)
413 {
414 s_GpioPintInitialized = 1U;
415 /* Initialize PINT */
416 PINT_Init(PINT);
417 }
418
419 /* initialize port interrupt */
420 if (0U == gpioStateHandle->pin.pint.pintInitialized)
421 {
422 for (uint32_t inputMuxIndex = 0; inputMuxIndex < (uint32_t)FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS;
423 inputMuxIndex++)
424 {
425 if (0U == (s_GpioInputMux[inputMuxIndex >> 3] & (1U << (inputMuxIndex & 0x07U))))
426 {
427 s_GpioInputMux[inputMuxIndex >> 3] |= 1U << (inputMuxIndex & 0x07U);
428 gpioStateHandle->pin.pint.pintIndex = (uint8_t)inputMuxIndex;
429 gpioStateHandle->pin.pint.pintInitialized = 1U;
430 break;
431 }
432 }
433 }
434 if (0U != gpioStateHandle->pin.pint.pintInitialized)
435 {
436 NVIC_SetPriority(s_PintIRQ[gpioStateHandle->pin.pint.pintIndex], HAL_GPIO_ISR_PRIORITY);
437 s_GpioInputMuxPin[gpioStateHandle->pin.pint.pintIndex] =
438 HAL_GPIO_INPUTMUX_PIN_FLAG(gpioStateHandle->pin.port, gpioStateHandle->pin.pin);
439 /* Connect trigger sources to PINT */
440 #if (defined(FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER) && (FSL_FEATURE_SYSCON_HAS_PINT_SEL_REGISTER > 0U))
441 typeConvTemp = HAL_INPUTMUX_GpioPortPinToPintsel(gpioStateHandle->pin.port, gpioStateHandle->pin.pin);
442 SYSCON_AttachSignal(SYSCON, (uint32_t)gpioStateHandle->pin.pint.pintIndex, (syscon_connection_t)typeConvTemp);
443 #else
444 INPUTMUX_Init(INPUTMUX);
445 typeConvTemp = HAL_INPUTMUX_GpioPortPinToPintsel(gpioStateHandle->pin.port, gpioStateHandle->pin.pin);
446 INPUTMUX_AttachSignal(INPUTMUX, (uint32_t)gpioStateHandle->pin.pint.pintIndex,
447 (inputmux_connection_t)typeConvTemp);
448 /* Turnoff clock to inputmux to save power. Clock is only needed to make changes */
449 INPUTMUX_Deinit(INPUTMUX);
450 #endif
451 /* Setup Pin Interrupt 0 for rising edge */
452 PINT_PinInterruptConfig(PINT, (pint_pin_int_t)gpioStateHandle->pin.pint.pintIndex, triggerType,
453 HAL_GpioInterruptCallback);
454 /* Enable the pin's PINT call back */
455 PINT_EnableCallbackByIndex(PINT, (pint_pin_int_t)gpioStateHandle->pin.pint.pintIndex);
456 }
457 else
458 {
459 return kStatus_HAL_GpioLackSource;
460 }
461 return kStatus_HAL_GpioSuccess;
462 }
463
HAL_GpioWakeUpSetting(hal_gpio_handle_t gpioHandle,uint8_t enable)464 hal_gpio_status_t HAL_GpioWakeUpSetting(hal_gpio_handle_t gpioHandle, uint8_t enable)
465 {
466 #if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) && \
467 (!(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS))
468
469 hal_gpio_state_t *gpioStateHandle;
470 assert(gpioHandle);
471
472 gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
473
474 if ((uint8_t)kHAL_GpioDirectionOut == gpioStateHandle->pin.pinSet.direction)
475 {
476 return kStatus_HAL_GpioError;
477 }
478
479 if (0U != enable)
480 {
481 EnableDeepSleepIRQ(s_PintIRQ[gpioStateHandle->pin.pint.pintIndex]);
482 }
483 else
484 {
485 DisableDeepSleepIRQ(s_PintIRQ[gpioStateHandle->pin.pint.pintIndex]);
486 }
487
488 return kStatus_HAL_GpioSuccess;
489 #else
490 assert(gpioHandle);
491
492 (void)gpioHandle;
493 (void)enable;
494
495 return kStatus_HAL_GpioError;
496 #endif
497 }
498
HAL_GpioEnterLowpower(hal_gpio_handle_t gpioHandle)499 hal_gpio_status_t HAL_GpioEnterLowpower(hal_gpio_handle_t gpioHandle)
500 {
501 assert(gpioHandle);
502
503 return kStatus_HAL_GpioSuccess;
504 }
505
HAL_GpioExitLowpower(hal_gpio_handle_t gpioHandle)506 hal_gpio_status_t HAL_GpioExitLowpower(hal_gpio_handle_t gpioHandle)
507 {
508 assert(gpioHandle);
509
510 return kStatus_HAL_GpioSuccess;
511 }
512