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