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 #include "fsl_adapter_gpio.h"
12 
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "component.rt_gpio_adapter"
16 #endif
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*! @brief The pin config struct of gpio adapter. */
23 typedef struct _hal_gpio_pin
24 {
25     uint16_t port : 3U;
26     uint16_t pin : 5U;
27     uint16_t direction : 1U;
28     uint16_t trigger : 3U;
29     uint16_t reserved : 4U;
30 } hal_gpio_pin_t;
31 
32 typedef struct _hal_gpio_state
33 {
34     struct _hal_gpio_state *next;
35     hal_gpio_callback_t callback;
36     void *callbackParam;
37     hal_gpio_pin_t pin;
38 } hal_gpio_state_t;
39 
40 /*******************************************************************************
41  * Prototypes
42  ******************************************************************************/
43 
44 /*******************************************************************************
45  * Variables
46  ******************************************************************************/
47 static hal_gpio_state_t *s_GpioHead;
48 static uint32_t s_GPIO_PORT_initFlag = 0U;
49 
50 #define SET_GPIO_PORT_INIT_FLAG(port)   (s_GPIO_PORT_initFlag |= 1UL << (port))
51 #define GET_GPIO_PORT_INIT_FLAG(port)   ((0U != (s_GPIO_PORT_initFlag & (1UL << (port)))) ? 1U : 0U)
52 #define CLEAR_GPIO_PORT_INIT_FLAG(port) (s_GPIO_PORT_initFlag &= ~(1UL << (port)))
53 
54 /*******************************************************************************
55  * Code
56  ******************************************************************************/
57 
HAL_GpioInterruptHandle(uint32_t intNum)58 static void HAL_GpioInterruptHandle(uint32_t intNum)
59 {
60     hal_gpio_state_t *head = s_GpioHead;
61     gpio_interrupt_config_t triggerConfig;
62     uint32_t portIntFlags = 0U;
63     uint8_t pinLevel;
64 
65     while (NULL != head)
66     {
67         portIntFlags = GPIO_PortGetInterruptStatus(GPIO, head->pin.port, intNum);
68         if (0U != (portIntFlags & (1UL << head->pin.pin)))
69         {
70             if (NULL != head->callback)
71             {
72                 head->callback(head->callbackParam);
73             }
74             GPIO_PinClearInterruptFlag(GPIO, head->pin.port, head->pin.pin, intNum);
75             if ((uint16_t)kHAL_GpioInterruptEitherEdge == head->pin.trigger)
76             {
77                 pinLevel           = (uint8_t)GPIO_PinRead(GPIO, head->pin.port, head->pin.pin);
78                 triggerConfig.mode = (uint8_t)kGPIO_PinIntEnableEdge;
79                 triggerConfig.polarity =
80                     (0U != pinLevel) ? (uint8_t)kGPIO_PinIntEnableLowOrFall : (uint8_t)kGPIO_PinIntEnableHighOrRise;
81                 GPIO_SetPinInterruptConfig(GPIO, head->pin.port, head->pin.pin, &triggerConfig);
82             }
83         }
84 
85         head = head->next;
86     }
87 }
88 
89 /*!
90  * @brief Interrupt service fuction of switch.
91  */
92 void GPIO_INTA_DriverIRQHandler(void);
GPIO_INTA_DriverIRQHandler(void)93 void GPIO_INTA_DriverIRQHandler(void)
94 {
95     HAL_GpioInterruptHandle(0);
96     SDK_ISR_EXIT_BARRIER;
97 }
98 
99 void GPIO_INTB_DriverIRQHandler(void);
GPIO_INTB_DriverIRQHandler(void)100 void GPIO_INTB_DriverIRQHandler(void)
101 {
102     HAL_GpioInterruptHandle(1);
103     SDK_ISR_EXIT_BARRIER;
104 }
105 
HAL_GpioConflictSearch(hal_gpio_state_t * head,uint8_t port,uint8_t pin)106 static hal_gpio_status_t HAL_GpioConflictSearch(hal_gpio_state_t *head, uint8_t port, uint8_t pin)
107 {
108     while (NULL != head)
109     {
110         if ((head->pin.port == port) && (head->pin.pin == pin))
111         {
112             return kStatus_HAL_GpioPinConflict;
113         }
114         head = head->next;
115     }
116     return kStatus_HAL_GpioSuccess;
117 }
118 
HAL_GpioAddItem(hal_gpio_state_t ** head,hal_gpio_state_t * node)119 static hal_gpio_status_t HAL_GpioAddItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
120 {
121     hal_gpio_state_t *p = *head;
122     uint32_t regPrimask;
123 
124     regPrimask = DisableGlobalIRQ();
125 
126     if (NULL == p)
127     {
128         *head = node;
129     }
130     else
131     {
132         while (NULL != p->next)
133         {
134             if (p == node)
135             {
136                 EnableGlobalIRQ(regPrimask);
137                 return kStatus_HAL_GpioPinConflict;
138             }
139             p = p->next;
140         }
141 
142         p->next = node;
143     }
144     node->next = NULL;
145     EnableGlobalIRQ(regPrimask);
146     return kStatus_HAL_GpioSuccess;
147 }
148 
HAL_GpioRemoveItem(hal_gpio_state_t ** head,hal_gpio_state_t * node)149 static hal_gpio_status_t HAL_GpioRemoveItem(hal_gpio_state_t **head, hal_gpio_state_t *node)
150 {
151     hal_gpio_state_t *p = *head;
152     hal_gpio_state_t *q = NULL;
153     uint32_t regPrimask;
154 
155     regPrimask = DisableGlobalIRQ();
156     while (NULL != p)
157     {
158         if (p == node)
159         {
160             if (NULL == q)
161             {
162                 *head = p->next;
163             }
164             else
165             {
166                 q->next = p->next;
167             }
168             break;
169         }
170         else
171         {
172             q = p;
173             p = p->next;
174         }
175     }
176     EnableGlobalIRQ(regPrimask);
177     return kStatus_HAL_GpioSuccess;
178 }
179 
HAL_GpioPreInit(void)180 void HAL_GpioPreInit(void)
181 {
182     s_GPIO_PORT_initFlag = 0U;
183     s_GpioHead           = NULL;
184 }
185 
HAL_GpioInit(hal_gpio_handle_t gpioHandle,hal_gpio_pin_config_t * pinConfig)186 hal_gpio_status_t HAL_GpioInit(hal_gpio_handle_t gpioHandle, hal_gpio_pin_config_t *pinConfig)
187 {
188     hal_gpio_state_t *gpioState;
189     hal_gpio_status_t status        = kStatus_HAL_GpioSuccess;
190     gpio_pin_config_t gpioPinConfig = {kGPIO_DigitalInput, 0};
191     uint32_t regPrimask;
192     uint8_t portNeedInit = 0;
193 
194     assert(gpioHandle);
195     assert(pinConfig);
196 
197     gpioState = (hal_gpio_state_t *)gpioHandle;
198 
199     /* Check if it is conflict */
200     if ((NULL != s_GpioHead) &&
201         (kStatus_HAL_GpioSuccess != HAL_GpioConflictSearch(s_GpioHead, pinConfig->port, pinConfig->pin)))
202     {
203         return kStatus_HAL_GpioPinConflict;
204     }
205 
206     status = HAL_GpioAddItem(&s_GpioHead, gpioState);
207     if (kStatus_HAL_GpioSuccess != status)
208     {
209         return status;
210     }
211 
212     gpioState->pin.pin       = pinConfig->pin;
213     gpioState->pin.port      = pinConfig->port;
214     gpioState->pin.direction = (uint16_t)pinConfig->direction;
215     gpioState->pin.trigger   = (uint16_t)kHAL_GpioInterruptDisable;
216 
217     if (kHAL_GpioDirectionOut == pinConfig->direction)
218     {
219         gpioPinConfig.pinDirection = kGPIO_DigitalOutput;
220         gpioPinConfig.outputLogic  = pinConfig->level;
221     }
222     else
223     {
224         gpioPinConfig.pinDirection = kGPIO_DigitalInput;
225     }
226 
227     /* Critical protection */
228     regPrimask = DisableGlobalIRQ();
229     if (0U == GET_GPIO_PORT_INIT_FLAG(gpioState->pin.port))
230     {
231         SET_GPIO_PORT_INIT_FLAG(gpioState->pin.port);
232         portNeedInit = 1U;
233     }
234     EnableGlobalIRQ(regPrimask);
235 
236     if (1U == portNeedInit)
237     {
238 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
239         /*! @brief Array to map FGPIO instance number to clock name. */
240         const clock_ip_name_t gpioClockName[] = GPIO_CLOCKS;
241 
242         assert(gpioState->pin.port < ARRAY_SIZE(gpioClockName));
243         CLOCK_EnableClock(gpioClockName[gpioState->pin.port]);
244 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
245 
246 #if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
247         /*! @brief Pointers to GPIO resets for each instance. */
248         const reset_ip_name_t gpioResets[] = GPIO_RSTS_N;
249 
250         RESET_ClearPeripheralReset(gpioResets[gpioState->pin.port]);
251 #endif /* FSL_FEATURE_GPIO_HAS_NO_RESET */
252     }
253 
254     GPIO_PinInit(GPIO, gpioState->pin.port, gpioState->pin.pin, &gpioPinConfig);
255 
256     return kStatus_HAL_GpioSuccess;
257 }
258 
HAL_GpioDeinit(hal_gpio_handle_t gpioHandle)259 hal_gpio_status_t HAL_GpioDeinit(hal_gpio_handle_t gpioHandle)
260 {
261     hal_gpio_state_t *gpioState;
262 
263     assert(gpioHandle);
264 
265     gpioState = (hal_gpio_state_t *)gpioHandle;
266 
267     if ((uint16_t)kHAL_GpioDirectionIn == gpioState->pin.direction)
268     {
269         GPIO_PinDisableInterrupt(GPIO, gpioState->pin.port, gpioState->pin.pin, 0);
270     }
271 
272     (void)HAL_GpioRemoveItem(&s_GpioHead, gpioState);
273     return kStatus_HAL_GpioSuccess;
274 }
275 
HAL_GpioGetInput(hal_gpio_handle_t gpioHandle,uint8_t * pinState)276 hal_gpio_status_t HAL_GpioGetInput(hal_gpio_handle_t gpioHandle, uint8_t *pinState)
277 {
278     hal_gpio_state_t *gpioStateHandle;
279 
280     assert(gpioHandle);
281 
282     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
283 
284     *pinState = (uint8_t)GPIO_PinRead(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin);
285 
286     return kStatus_HAL_GpioSuccess;
287 }
288 
HAL_GpioSetOutput(hal_gpio_handle_t gpioHandle,uint8_t pinState)289 hal_gpio_status_t HAL_GpioSetOutput(hal_gpio_handle_t gpioHandle, uint8_t pinState)
290 {
291     hal_gpio_state_t *gpioStateHandle;
292 
293     assert(gpioHandle);
294 
295     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
296 
297     GPIO_PinWrite(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin, (0U != pinState) ? 1U : 0U);
298 
299     return kStatus_HAL_GpioSuccess;
300 }
301 
HAL_GpioInstallCallback(hal_gpio_handle_t gpioHandle,hal_gpio_callback_t callback,void * callbackParam)302 hal_gpio_status_t HAL_GpioInstallCallback(hal_gpio_handle_t gpioHandle,
303                                           hal_gpio_callback_t callback,
304                                           void *callbackParam)
305 {
306     hal_gpio_state_t *gpioStateHandle;
307 
308     assert(gpioHandle);
309 
310     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
311 
312     gpioStateHandle->callbackParam = callbackParam;
313     gpioStateHandle->callback      = callback;
314 
315     return kStatus_HAL_GpioSuccess;
316 }
317 
HAL_GpioGetTriggerMode(hal_gpio_handle_t gpioHandle,hal_gpio_interrupt_trigger_t * gpioTrigger)318 hal_gpio_status_t HAL_GpioGetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t *gpioTrigger)
319 {
320     hal_gpio_state_t *gpioStateHandle;
321 
322     assert(gpioHandle);
323 
324     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
325 
326     if ((uint16_t)kHAL_GpioDirectionOut == gpioStateHandle->pin.direction)
327     {
328         return kStatus_HAL_GpioError;
329     }
330 
331     *gpioTrigger = (hal_gpio_interrupt_trigger_t)gpioStateHandle->pin.trigger;
332     return kStatus_HAL_GpioSuccess;
333 }
334 
HAL_GpioSetTriggerMode(hal_gpio_handle_t gpioHandle,hal_gpio_interrupt_trigger_t gpioTrigger)335 hal_gpio_status_t HAL_GpioSetTriggerMode(hal_gpio_handle_t gpioHandle, hal_gpio_interrupt_trigger_t gpioTrigger)
336 {
337     hal_gpio_state_t *gpioStateHandle;
338     gpio_interrupt_config_t triggerConfig;
339     uint32_t pinLevel     = 0U;
340     uint8_t trigerDisable = 0U;
341 
342     assert(gpioHandle);
343 
344     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
345 
346     assert((uint16_t)kHAL_GpioDirectionOut != gpioStateHandle->pin.direction);
347 
348     switch (gpioTrigger)
349     {
350         case kHAL_GpioInterruptLogicZero:
351             triggerConfig.mode     = (uint8_t)kGPIO_PinIntEnableLevel;
352             triggerConfig.polarity = (uint8_t)kGPIO_PinIntEnableLowOrFall;
353             break;
354         case kHAL_GpioInterruptLogicOne:
355             triggerConfig.mode     = (uint8_t)kGPIO_PinIntEnableLevel;
356             triggerConfig.polarity = (uint8_t)kGPIO_PinIntEnableHighOrRise;
357             break;
358         case kHAL_GpioInterruptRisingEdge:
359             triggerConfig.mode     = (uint8_t)kGPIO_PinIntEnableEdge;
360             triggerConfig.polarity = (uint8_t)kGPIO_PinIntEnableHighOrRise;
361             break;
362         case kHAL_GpioInterruptFallingEdge:
363             triggerConfig.mode     = (uint8_t)kGPIO_PinIntEnableEdge;
364             triggerConfig.polarity = (uint8_t)kGPIO_PinIntEnableLowOrFall;
365             break;
366         case kHAL_GpioInterruptEitherEdge:
367             /* Here will get pin's default level to decide which edge trigger for the first time */
368             pinLevel           = GPIO_PinRead(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin);
369             triggerConfig.mode = (uint8_t)kGPIO_PinIntEnableEdge;
370             triggerConfig.polarity =
371                 (0U != pinLevel) ? (uint8_t)kGPIO_PinIntEnableLowOrFall : (uint8_t)kGPIO_PinIntEnableHighOrRise;
372             break;
373         default:
374             trigerDisable = 1U;
375             break;
376     }
377 
378     gpioStateHandle->pin.trigger = (uint16_t)gpioTrigger;
379 
380     /* Set trigger interrupt */
381     if (1U != trigerDisable)
382     {
383         GPIO_SetPinInterruptConfig(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin, &triggerConfig);
384         GPIO_PinEnableInterrupt(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin, 0);
385         NVIC_SetPriority(GPIO_INTA_IRQn, HAL_GPIO_ISR_PRIORITY);
386         NVIC_EnableIRQ(GPIO_INTA_IRQn);
387     }
388     else
389     {
390         GPIO_PinDisableInterrupt(GPIO, gpioStateHandle->pin.port, gpioStateHandle->pin.pin, 0);
391     }
392 
393     return kStatus_HAL_GpioSuccess;
394 }
395 
HAL_GpioWakeUpSetting(hal_gpio_handle_t gpioHandle,uint8_t enable)396 hal_gpio_status_t HAL_GpioWakeUpSetting(hal_gpio_handle_t gpioHandle, uint8_t enable)
397 {
398     hal_gpio_state_t *gpioStateHandle;
399     assert(gpioHandle);
400 
401     gpioStateHandle = (hal_gpio_state_t *)gpioHandle;
402 
403     if ((uint16_t)kHAL_GpioDirectionOut == gpioStateHandle->pin.direction)
404     {
405         return kStatus_HAL_GpioError;
406     }
407 
408     return kStatus_HAL_GpioSuccess;
409 }
410 
HAL_GpioEnterLowpower(hal_gpio_handle_t gpioHandle)411 hal_gpio_status_t HAL_GpioEnterLowpower(hal_gpio_handle_t gpioHandle)
412 {
413     assert(gpioHandle);
414 
415     return kStatus_HAL_GpioSuccess;
416 }
417 
HAL_GpioExitLowpower(hal_gpio_handle_t gpioHandle)418 hal_gpio_status_t HAL_GpioExitLowpower(hal_gpio_handle_t gpioHandle)
419 {
420     assert(gpioHandle);
421 
422     return kStatus_HAL_GpioSuccess;
423 }
424