1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019, 2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_gpio.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.gpio"
17 #endif
18 
19 #if defined(GPIO_RSTS)
20 #define GPIO_RESETS_ARRAY GPIO_RSTS
21 #endif
22 
23 /*******************************************************************************
24  * Variables
25  ******************************************************************************/
26 
27 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
28     defined(FSL_FEATURE_SOC_PORT_COUNT)
29 static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
30 static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
31 #else
32 #if defined(GPIO_RESETS_ARRAY)
33 static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
34 #endif
35 #endif
36 
37 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
38 
39 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
40 
41 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
42 /*! @brief Array to map FGPIO instance number to clock name. */
43 static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
44 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
45 
46 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
47 
48 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
49 
50 #if defined(GPIO_RESETS_ARRAY)
51 /* Reset array */
52 static const reset_ip_name_t s_gpioResets[] = GPIO_RESETS_ARRAY;
53 #endif
54 
55 /*******************************************************************************
56  * Prototypes
57  ******************************************************************************/
58 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
59     defined(FSL_FEATURE_SOC_PORT_COUNT)
60 /*!
61  * @brief Gets the GPIO instance according to the GPIO base
62  *
63  * @param base    GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
64  * @retval GPIO instance
65  */
66 static uint32_t GPIO_GetInstance(GPIO_Type *base);
67 #endif
68 /*******************************************************************************
69  * Code
70  ******************************************************************************/
71 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
72     defined(FSL_FEATURE_SOC_PORT_COUNT) || defined(GPIO_RESETS_ARRAY)
GPIO_GetInstance(GPIO_Type * base)73 static uint32_t GPIO_GetInstance(GPIO_Type *base)
74 {
75     uint32_t instance;
76 
77     /* Find the instance index from base address mappings. */
78     for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++)
79     {
80         if (MSDK_REG_SECURE_ADDR(s_gpioBases[instance]) == MSDK_REG_SECURE_ADDR(base))
81         {
82             break;
83         }
84     }
85 
86     assert(instance < ARRAY_SIZE(s_gpioBases));
87 
88     return instance;
89 }
90 #endif
91 /*!
92  * brief Initializes a GPIO pin used by the board.
93  *
94  * To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
95  * Then, call the GPIO_PinInit() function.
96  *
97  * This is an example to define an input pin or an output pin configuration.
98  * code
99  * Define a digital input pin configuration,
100  * gpio_pin_config_t config =
101  * {
102  *   kGPIO_DigitalInput,
103  *   0,
104  * }
105  * Define a digital output pin configuration,
106  * gpio_pin_config_t config =
107  * {
108  *   kGPIO_DigitalOutput,
109  *   0,
110  * }
111  * endcode
112  *
113  * param base   GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
114  * param pin    GPIO port pin number
115  * param config GPIO pin configuration pointer
116  */
GPIO_PinInit(GPIO_Type * base,uint32_t pin,const gpio_pin_config_t * config)117 void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
118 {
119     assert(NULL != config);
120 
121 #if defined(GPIO_RESETS_ARRAY)
122     RESET_ReleasePeripheralReset(s_gpioResets[GPIO_GetInstance(base)]);
123 #endif
124 
125     if (config->pinDirection == kGPIO_DigitalInput)
126     {
127         base->PDDR &= GPIO_FIT_REG(~(1UL << pin));
128     }
129     else
130     {
131         GPIO_PinWrite(base, pin, config->outputLogic);
132         base->PDDR |= GPIO_FIT_REG((1UL << pin));
133     }
134 }
135 
136 #if defined(FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER
GPIO_GetVersionInfo(GPIO_Type * base,gpio_version_info_t * info)137 void GPIO_GetVersionInfo(GPIO_Type *base, gpio_version_info_t *info)
138 {
139     info->feature = (uint16_t)base->VERID;
140     info->minor   = (uint8_t)(base->VERID >> GPIO_VERID_MINOR_SHIFT);
141     info->major   = (uint8_t)(base->VERID >> GPIO_VERID_MAJOR_SHIFT);
142 }
143 #endif /* FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER */
144 
145 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
146     defined(FSL_FEATURE_SOC_PORT_COUNT)
147 /*!
148  * brief Reads the GPIO port interrupt status flag.
149  *
150  * If a pin is configured to generate the DMA request, the corresponding flag
151  * is cleared automatically at the completion of the requested DMA transfer.
152  * Otherwise, the flag remains set until a logic one is written to that flag.
153  * If configured for a level sensitive interrupt that remains asserted, the flag
154  * is set again immediately.
155  *
156  * param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
157  * retval The current GPIO port interrupt status flag, for example, 0x00010001 means the
158  *         pin 0 and 17 have the interrupt.
159  */
GPIO_PortGetInterruptFlags(GPIO_Type * base)160 uint32_t GPIO_PortGetInterruptFlags(GPIO_Type *base)
161 {
162     uint8_t instance;
163     PORT_Type *portBase;
164     instance = (uint8_t)GPIO_GetInstance(base);
165     portBase = s_portBases[instance];
166     return portBase->ISFR;
167 }
168 #else
169 /*!
170  * brief Read the GPIO interrupt status flags.
171  *
172  * param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
173  * return The current GPIO's interrupt status flag.
174  *         '1' means the related pin's flag is set, '0' means the related pin's flag not set.
175  *          For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
176  */
GPIO_GpioGetInterruptFlags(GPIO_Type * base)177 uint32_t GPIO_GpioGetInterruptFlags(GPIO_Type *base)
178 {
179     return base->ISFR[0];
180 }
181 #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
182 /*!
183  * brief Read the GPIO interrupt status flags based on selected interrupt channel(IRQS).
184  * param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
185  * param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
186  *
187  * return The current GPIO's interrupt status flag based on the selected interrupt channel.
188  *         '1' means the related pin's flag is set, '0' means the related pin's flag not set.
189  *          For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
190  */
GPIO_GpioGetInterruptChannelFlags(GPIO_Type * base,uint32_t channel)191 uint32_t GPIO_GpioGetInterruptChannelFlags(GPIO_Type *base, uint32_t channel)
192 {
193     assert(channel < 2U);
194     return base->ISFR[channel];
195 }
196 #endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT */
197 /*!
198  * brief Read individual pin's interrupt status flag.
199  *
200  * param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on)
201  * param pin GPIO specific pin number.
202  * return The current selected pin's interrupt status flag.
203  */
GPIO_PinGetInterruptFlag(GPIO_Type * base,uint32_t pin)204 uint8_t GPIO_PinGetInterruptFlag(GPIO_Type *base, uint32_t pin)
205 {
206     return (uint8_t)((base->ICR[pin] & GPIO_ICR_ISF_MASK) >> GPIO_ICR_ISF_SHIFT);
207 }
208 #endif /* FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
209 
210 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
211     defined(FSL_FEATURE_SOC_PORT_COUNT)
212 /*!
213  * brief Clears multiple GPIO pin interrupt status flags.
214  *
215  * param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
216  * param mask GPIO pin number macro
217  */
GPIO_PortClearInterruptFlags(GPIO_Type * base,uint32_t mask)218 void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t mask)
219 {
220     uint8_t instance;
221     PORT_Type *portBase;
222     instance       = (uint8_t)GPIO_GetInstance(base);
223     portBase       = s_portBases[instance];
224     portBase->ISFR = mask;
225 }
226 #else
227 /*!
228  * brief Clears GPIO pin interrupt status flags.
229  *
230  * param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
231  * param mask GPIO pin number macro
232  */
GPIO_GpioClearInterruptFlags(GPIO_Type * base,uint32_t mask)233 void GPIO_GpioClearInterruptFlags(GPIO_Type *base, uint32_t mask)
234 {
235     base->ISFR[0] = GPIO_FIT_REG(mask);
236 }
237 #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
238 /*!
239  * brief Clears GPIO pin interrupt status flags based on selected interrupt channel(IRQS).
240  *
241  * param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
242  * param mask GPIO pin number macro
243  * param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
244  */
GPIO_GpioClearInterruptChannelFlags(GPIO_Type * base,uint32_t mask,uint32_t channel)245 void GPIO_GpioClearInterruptChannelFlags(GPIO_Type *base, uint32_t mask, uint32_t channel)
246 {
247     assert(channel < 2U);
248     base->ISFR[channel] = GPIO_FIT_REG(mask);
249 }
250 #endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT */
251 /*!
252  * brief Clear GPIO individual pin's interrupt status flag.
253  *
254  * param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on).
255  * param pin GPIO specific pin number.
256  */
GPIO_PinClearInterruptFlag(GPIO_Type * base,uint32_t pin)257 void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t pin)
258 {
259     base->ICR[pin] |= GPIO_FIT_REG(GPIO_ICR_ISF(1U));
260 }
261 #endif /* FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
262 
263 #if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
264 /*!
265  * brief The GPIO module supports a device-specific number of data ports, organized as 32-bit
266  * words/8-bit Bytes. Each 32-bit/8-bit data port includes a GACR register, which defines the byte-level
267  * attributes required for a successful access to the GPIO programming model. If the GPIO module's GACR register
268  * organized as 32-bit words, the attribute controls for the 4 data bytes in the GACR follow a standard little
269  * endian data convention.
270  *
271  * param base      GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
272  * param attribute GPIO checker attribute
273  */
GPIO_CheckAttributeBytes(GPIO_Type * base,gpio_checker_attribute_t attribute)274 void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute)
275 {
276 #if defined(FSL_FEATURE_GPIO_REGISTERS_WIDTH) && (FSL_FEATURE_GPIO_REGISTERS_WIDTH == 8U)
277     base->GACR = ((uint8_t)attribute << GPIO_GACR_ACB_SHIFT);
278 #else
279     base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) |
280                  ((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT);
281 #endif /* FSL_FEATURE_GPIO_REGISTERS_WIDTH */
282 }
283 #endif
284 
285 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
286 
287 /*******************************************************************************
288  * Variables
289  ******************************************************************************/
290 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
291     defined(FSL_FEATURE_SOC_PORT_COUNT)
292 static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
293 #endif
294 /*******************************************************************************
295  * Prototypes
296  ******************************************************************************/
297 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
298     defined(FSL_FEATURE_SOC_PORT_COUNT)
299 /*!
300  * @brief Gets the FGPIO instance according to the GPIO base
301  *
302  * @param base    FGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
303  * @retval FGPIO instance
304  */
305 static uint32_t FGPIO_GetInstance(FGPIO_Type *base);
306 #endif
307 /*******************************************************************************
308  * Code
309  ******************************************************************************/
310 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
311     defined(FSL_FEATURE_SOC_PORT_COUNT)
FGPIO_GetInstance(FGPIO_Type * base)312 static uint32_t FGPIO_GetInstance(FGPIO_Type *base)
313 {
314     uint32_t instance;
315 
316     /* Find the instance index from base address mappings. */
317     for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++)
318     {
319         if (MSDK_REG_SECURE_ADDR(s_fgpioBases[instance]) == MSDK_REG_SECURE_ADDR(base))
320         {
321             break;
322         }
323     }
324 
325     assert(instance < ARRAY_SIZE(s_fgpioBases));
326 
327     return instance;
328 }
329 #endif
330 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
331 /*!
332  * brief Initializes the FGPIO peripheral.
333  *
334  * This function ungates the FGPIO clock.
335  *
336  * param base   FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
337  */
FGPIO_PortInit(FGPIO_Type * base)338 void FGPIO_PortInit(FGPIO_Type *base)
339 {
340 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
341     /* Ungate FGPIO periphral clock */
342     CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
343 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
344 }
345 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
346 
347 /*!
348  * brief Initializes a FGPIO pin used by the board.
349  *
350  * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
351  * Then, call the FGPIO_PinInit() function.
352  *
353  * This is an example to define an input pin or an output pin configuration:
354  * code
355  * Define a digital input pin configuration,
356  * gpio_pin_config_t config =
357  * {
358  *   kGPIO_DigitalInput,
359  *   0,
360  * }
361  * Define a digital output pin configuration,
362  * gpio_pin_config_t config =
363  * {
364  *   kGPIO_DigitalOutput,
365  *   0,
366  * }
367  * endcode
368  *
369  * param base   FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
370  * param pin    FGPIO port pin number
371  * param config FGPIO pin configuration pointer
372  */
FGPIO_PinInit(FGPIO_Type * base,uint32_t pin,const gpio_pin_config_t * config)373 void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
374 {
375     assert(NULL != config);
376 
377     if (config->pinDirection == kGPIO_DigitalInput)
378     {
379         base->PDDR &= ~(1UL << pin);
380     }
381     else
382     {
383         FGPIO_PinWrite(base, pin, config->outputLogic);
384         base->PDDR |= (1UL << pin);
385     }
386 }
387 #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
388     defined(FSL_FEATURE_SOC_PORT_COUNT)
389 /*!
390  * brief Reads the FGPIO port interrupt status flag.
391  *
392  * If a pin is configured to generate the DMA request, the corresponding flag
393  * is cleared automatically at the completion of the requested DMA transfer.
394  * Otherwise, the flag remains set until a logic one is written to that flag.
395  * If configured for a level-sensitive interrupt that remains asserted, the flag
396  * is set again immediately.
397  *
398  * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
399  * retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the
400  *         pin 0 and 17 have the interrupt.
401  */
FGPIO_PortGetInterruptFlags(FGPIO_Type * base)402 uint32_t FGPIO_PortGetInterruptFlags(FGPIO_Type *base)
403 {
404     uint8_t instance;
405     instance = (uint8_t)FGPIO_GetInstance(base);
406     PORT_Type *portBase;
407     portBase = s_portBases[instance];
408     return portBase->ISFR;
409 }
410 
411 /*!
412  * brief Clears the multiple FGPIO pin interrupt status flag.
413  *
414  * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
415  * param mask FGPIO pin number macro
416  */
FGPIO_PortClearInterruptFlags(FGPIO_Type * base,uint32_t mask)417 void FGPIO_PortClearInterruptFlags(FGPIO_Type *base, uint32_t mask)
418 {
419     uint8_t instance;
420     instance = (uint8_t)FGPIO_GetInstance(base);
421     PORT_Type *portBase;
422     portBase       = s_portBases[instance];
423     portBase->ISFR = mask;
424 }
425 #endif
426 #if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER
427 /*!
428  * brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit
429  * words. Each 32-bit data port includes a GACR register, which defines the byte-level
430  * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data
431  * bytes in the GACR follow a standard little endian
432  * data convention.
433  *
434  * param base      FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
435  * param attribute FGPIO checker attribute
436  */
FGPIO_CheckAttributeBytes(FGPIO_Type * base,gpio_checker_attribute_t attribute)437 void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute)
438 {
439     base->GACR = ((uint32_t)attribute << FGPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << FGPIO_GACR_ACB1_SHIFT) |
440                  ((uint32_t)attribute << FGPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << FGPIO_GACR_ACB3_SHIFT);
441 }
442 #endif
443 
444 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
445