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