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