1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_gpio.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.lpc_gpio"
14 #endif
15 
16 /*******************************************************************************
17  * Variables
18  ******************************************************************************/
19 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
20 /*! @brief Array to map FGPIO instance number to clock name. */
21 static const clock_ip_name_t s_gpioClockName[] = GPIO_CLOCKS;
22 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
23 
24 #if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
25 /*! @brief Pointers to GPIO resets for each instance. */
26 static const reset_ip_name_t s_gpioResets[] = GPIO_RSTS_N;
27 #endif
28 /*******************************************************************************
29  * Prototypes
30  ************ ******************************************************************/
31 /*!
32  * @brief Enable GPIO port clock.
33  *
34  * @param base   GPIO peripheral base pointer.
35  * @param port   GPIO port number.
36  */
37 static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port);
38 
39 /*******************************************************************************
40  * Code
41  ******************************************************************************/
GPIO_EnablePortClock(GPIO_Type * base,uint32_t port)42 static void GPIO_EnablePortClock(GPIO_Type *base, uint32_t port)
43 {
44 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
45     assert(port < ARRAY_SIZE(s_gpioClockName));
46 
47     /* Upgate the GPIO clock */
48     CLOCK_EnableClock(s_gpioClockName[port]);
49 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
50 }
51 
52 /*!
53  * brief Initializes the GPIO peripheral.
54  *
55  * This function ungates the GPIO clock.
56  *
57  * param base   GPIO peripheral base pointer.
58  * param port   GPIO port number.
59  */
GPIO_PortInit(GPIO_Type * base,uint32_t port)60 void GPIO_PortInit(GPIO_Type *base, uint32_t port)
61 {
62     GPIO_EnablePortClock(base, port);
63 
64 #if !(defined(FSL_FEATURE_GPIO_HAS_NO_RESET) && FSL_FEATURE_GPIO_HAS_NO_RESET)
65     /* Reset the GPIO module */
66     RESET_PeripheralReset(s_gpioResets[port]);
67 #endif
68 }
69 
70 /*!
71  * brief Initializes a GPIO pin used by the board.
72  *
73  * To initialize the GPIO, define a pin configuration, either input or output, in the user file.
74  * Then, call the GPIO_PinInit() function.
75  *
76  * This is an example to define an input pin or output pin configuration:
77  * code
78  * Define a digital input pin configuration,
79  * gpio_pin_config_t config =
80  * {
81  *   kGPIO_DigitalInput,
82  *   0,
83  * }
84  * Define a digital output pin configuration,
85  * gpio_pin_config_t config =
86  * {
87  *   kGPIO_DigitalOutput,
88  *   0,
89  * }
90  * endcode
91  *
92  * param base   GPIO peripheral base pointer(Typically GPIO)
93  * param port   GPIO port number
94  * param pin    GPIO pin number
95  * param config GPIO pin configuration pointer
96  */
GPIO_PinInit(GPIO_Type * base,uint32_t port,uint32_t pin,const gpio_pin_config_t * config)97 void GPIO_PinInit(GPIO_Type *base, uint32_t port, uint32_t pin, const gpio_pin_config_t *config)
98 {
99     GPIO_EnablePortClock(base, port);
100 
101     if (config->pinDirection == kGPIO_DigitalInput)
102     {
103 #if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
104         base->DIRCLR[port] = 1UL << pin;
105 #else
106         base->DIR[port] &= ~(1UL << pin);
107 #endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
108     }
109     else
110     {
111         /* Set default output value */
112         if (config->outputLogic == 0U)
113         {
114             base->CLR[port] = (1UL << pin);
115         }
116         else
117         {
118             base->SET[port] = (1UL << pin);
119         }
120 /* Set pin direction */
121 #if defined(FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR) && (FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR)
122         base->DIRSET[port] = 1UL << pin;
123 #else
124         base->DIR[port] |= 1UL << pin;
125 #endif /*FSL_FEATURE_GPIO_DIRSET_AND_DIRCLR*/
126     }
127 }
128 
129 #if defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT
130 /*!
131  * @brief Set the configuration of pin interrupt.
132  *
133  * @param base GPIO base pointer.
134  * @param port GPIO port number
135  * @param pin GPIO pin number.
136  * @param config GPIO pin interrupt configuration..
137  */
GPIO_SetPinInterruptConfig(GPIO_Type * base,uint32_t port,uint32_t pin,gpio_interrupt_config_t * config)138 void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t port, uint32_t pin, gpio_interrupt_config_t *config)
139 {
140     base->INTEDG[port] = (base->INTEDG[port] & ~(1UL << pin)) | ((uint32_t)config->mode << pin);
141 
142     base->INTPOL[port] = (base->INTPOL[port] & ~(1UL << pin)) | ((uint32_t)config->polarity << pin);
143 }
144 
145 /*!
146  * @brief Enables multiple pins interrupt.
147  *
148  * @param base GPIO base pointer.
149  * @param port   GPIO port number.
150  * @param index GPIO interrupt number.
151  * @param mask GPIO pin number macro.
152  */
GPIO_PortEnableInterrupts(GPIO_Type * base,uint32_t port,uint32_t index,uint32_t mask)153 void GPIO_PortEnableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
154 {
155     if ((uint32_t)kGPIO_InterruptA == index)
156     {
157         base->INTENA[port] = base->INTENA[port] | mask;
158     }
159     else if ((uint32_t)kGPIO_InterruptB == index)
160     {
161         base->INTENB[port] = base->INTENB[port] | mask;
162     }
163     else
164     {
165         /*Should not enter here*/
166     }
167 }
168 
169 /*!
170  * @brief Disables multiple pins interrupt.
171  *
172  * @param base GPIO base pointer.
173  * @param port   GPIO port number.
174  * @param index GPIO interrupt number.
175  * @param mask GPIO pin number macro.
176  */
GPIO_PortDisableInterrupts(GPIO_Type * base,uint32_t port,uint32_t index,uint32_t mask)177 void GPIO_PortDisableInterrupts(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
178 {
179     if ((uint32_t)kGPIO_InterruptA == index)
180     {
181         base->INTENA[port] = base->INTENA[port] & ~mask;
182     }
183     else if ((uint32_t)kGPIO_InterruptB == index)
184     {
185         base->INTENB[port] = base->INTENB[port] & ~mask;
186     }
187     else
188     {
189         /*Should not enter here*/
190     }
191 }
192 
193 /*!
194  * @brief Clears multiple pins interrupt flag. Status flags are cleared by
195  *        writing a 1 to the corresponding bit position.
196  *
197  * @param base GPIO base pointer.
198  * @param port GPIO port number.
199  * @param index GPIO interrupt number.
200  * @param mask GPIO pin number macro.
201  */
GPIO_PortClearInterruptFlags(GPIO_Type * base,uint32_t port,uint32_t index,uint32_t mask)202 void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t port, uint32_t index, uint32_t mask)
203 {
204     if ((uint32_t)kGPIO_InterruptA == index)
205     {
206         base->INTSTATA[port] = mask;
207     }
208     else if ((uint32_t)kGPIO_InterruptB == index)
209     {
210         base->INTSTATB[port] = mask;
211     }
212     else
213     {
214         /*Should not enter here*/
215     }
216 }
217 
218 /*!
219  * @ Read port interrupt status.
220  *
221  * @param base GPIO base pointer.
222  * @param port GPIO port number
223  * @param index GPIO interrupt number.
224  * @retval masked GPIO status value
225  */
GPIO_PortGetInterruptStatus(GPIO_Type * base,uint32_t port,uint32_t index)226 uint32_t GPIO_PortGetInterruptStatus(GPIO_Type *base, uint32_t port, uint32_t index)
227 {
228     uint32_t status = 0U;
229 
230     if ((uint32_t)kGPIO_InterruptA == index)
231     {
232         status = base->INTSTATA[port];
233     }
234     else if ((uint32_t)kGPIO_InterruptB == index)
235     {
236         status = base->INTSTATB[port];
237     }
238     else
239     {
240         /*Should not enter here*/
241     }
242     return status;
243 }
244 
245 /*!
246  * @brief Enables the specific pin interrupt.
247  *
248  * @param base GPIO base pointer.
249  * @param port   GPIO port number.
250  * @param pin GPIO pin number.
251  * @param index GPIO interrupt number.
252  */
GPIO_PinEnableInterrupt(GPIO_Type * base,uint32_t port,uint32_t pin,uint32_t index)253 void GPIO_PinEnableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
254 {
255     if ((uint32_t)kGPIO_InterruptA == index)
256     {
257         base->INTENA[port] = base->INTENA[port] | (1UL << pin);
258     }
259     else if ((uint32_t)kGPIO_InterruptB == index)
260     {
261         base->INTENB[port] = base->INTENB[port] | (1UL << pin);
262     }
263     else
264     {
265         /*Should not enter here*/
266     }
267 }
268 
269 /*!
270  * @brief Disables the specific pin interrupt.
271  *
272  * @param base GPIO base pointer.
273  * @param port   GPIO port number.
274  * @param pin GPIO pin number.
275  * @param index GPIO interrupt number.
276  */
GPIO_PinDisableInterrupt(GPIO_Type * base,uint32_t port,uint32_t pin,uint32_t index)277 void GPIO_PinDisableInterrupt(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
278 {
279     if ((uint32_t)kGPIO_InterruptA == index)
280     {
281         base->INTENA[port] = base->INTENA[port] & ~(1UL << pin);
282     }
283     else if ((uint32_t)kGPIO_InterruptB == index)
284     {
285         base->INTENB[port] = base->INTENB[port] & ~(1UL << pin);
286     }
287     else
288     {
289         /*Should not enter here*/
290     }
291 }
292 
293 /*!
294  * @brief Clears the specific pin interrupt flag. Status flags are cleared by
295  *        writing a 1 to the corresponding bit position.
296  *
297  * @param base GPIO base pointer.
298  * @param port GPIO port number.
299  * @param index GPIO interrupt number.
300  * @param mask GPIO pin number macro.
301  */
GPIO_PinClearInterruptFlag(GPIO_Type * base,uint32_t port,uint32_t pin,uint32_t index)302 void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t port, uint32_t pin, uint32_t index)
303 {
304     if ((uint32_t)kGPIO_InterruptA == index)
305     {
306         base->INTSTATA[port] = 1UL << pin;
307     }
308     else if ((uint32_t)kGPIO_InterruptB == index)
309     {
310         base->INTSTATB[port] = 1UL << pin;
311     }
312     else
313     {
314         /*Should not enter here*/
315     }
316 }
317 #endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT */
318