1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017, 2020-2021 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.igpio"
14 #endif
15
16 /*******************************************************************************
17 * Variables
18 ******************************************************************************/
19
20 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
21 /* Array of GPIO peripheral base address. */
22 static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
23 #endif
24
25 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
26 /* Array of GPIO clock name. */
27 static const clock_ip_name_t s_gpioClock[] = GPIO_CLOCKS;
28 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
29
30 /*******************************************************************************
31 * Prototypes
32 ******************************************************************************/
33
34 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
35 /*!
36 * @brief Gets the GPIO instance according to the GPIO base
37 *
38 * @param base GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
39 * @retval GPIO instance
40 */
41 static uint32_t GPIO_GetInstance(GPIO_Type *base);
42
43 /*******************************************************************************
44 * Code
45 ******************************************************************************/
46
GPIO_GetInstance(GPIO_Type * base)47 static uint32_t GPIO_GetInstance(GPIO_Type *base)
48 {
49 uint32_t instance;
50
51 /* Find the instance index from base address mappings. */
52 for (instance = 0U; instance < ARRAY_SIZE(s_gpioBases); instance++)
53 {
54 if (s_gpioBases[instance] == base)
55 {
56 break;
57 }
58 }
59
60 assert(instance < ARRAY_SIZE(s_gpioBases));
61
62 return instance;
63 }
64 #endif
65
66 /*!
67 * brief Initializes the GPIO peripheral according to the specified
68 * parameters in the initConfig.
69 *
70 * param base GPIO base pointer.
71 * param pin Specifies the pin number
72 * param initConfig pointer to a ref gpio_pin_config_t structure that
73 * contains the configuration information.
74 */
GPIO_PinInit(GPIO_Type * base,uint32_t pin,const gpio_pin_config_t * Config)75 void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config)
76 {
77 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
78 /* Enable GPIO clock. */
79 uint32_t instance = GPIO_GetInstance(base);
80
81 /* If The clock IP is valid, enable the clock gate. */
82 if ((instance < ARRAY_SIZE(s_gpioClock)) && (kCLOCK_IpInvalid != s_gpioClock[instance]))
83 {
84 (void)CLOCK_EnableClock(s_gpioClock[instance]);
85 }
86 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
87
88 /* Register reset to default value */
89 base->IMR &= ~(1UL << pin);
90
91 /* Configure GPIO pin direction */
92 if (Config->direction == kGPIO_DigitalInput)
93 {
94 base->GDIR &= ~(1UL << pin);
95 }
96 else
97 {
98 GPIO_PinWrite(base, pin, Config->outputLogic);
99 base->GDIR |= (1UL << pin);
100 }
101
102 /* Configure GPIO pin interrupt mode */
103 GPIO_SetPinInterruptConfig(base, pin, Config->interruptMode);
104 }
105
106 /*!
107 * brief Sets the output level of the individual GPIO pin to logic 1 or 0.
108 *
109 * param base GPIO base pointer.
110 * param pin GPIO port pin number.
111 * param output GPIOpin output logic level.
112 * - 0: corresponding pin output low-logic level.
113 * - 1: corresponding pin output high-logic level.
114 */
GPIO_PinWrite(GPIO_Type * base,uint32_t pin,uint8_t output)115 void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output)
116 {
117 assert(pin < 32U);
118 if (output == 0U)
119 {
120 #if (defined(FSL_FEATURE_IGPIO_HAS_DR_CLEAR) && FSL_FEATURE_IGPIO_HAS_DR_CLEAR)
121 base->DR_CLEAR = (1UL << pin);
122 #else
123 base->DR &= ~(1UL << pin); /* Set pin output to low level.*/
124 #endif
125 }
126 else
127 {
128 #if (defined(FSL_FEATURE_IGPIO_HAS_DR_SET) && FSL_FEATURE_IGPIO_HAS_DR_SET)
129 base->DR_SET = (1UL << pin);
130 #else
131 base->DR |= (1UL << pin); /* Set pin output to high level.*/
132 #endif
133 }
134 }
135
136 /*!
137 * brief Sets the current pin interrupt mode.
138 *
139 * param base GPIO base pointer.
140 * param pin GPIO port pin number.
141 * param pininterruptMode pointer to a ref gpio_interrupt_mode_t structure
142 * that contains the interrupt mode information.
143 */
GPIO_PinSetInterruptConfig(GPIO_Type * base,uint32_t pin,gpio_interrupt_mode_t pinInterruptMode)144 void GPIO_PinSetInterruptConfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_mode_t pinInterruptMode)
145 {
146 volatile uint32_t *icr;
147 uint32_t icrShift;
148
149 icrShift = pin;
150
151 /* Register reset to default value */
152 base->EDGE_SEL &= ~(1UL << pin);
153
154 if (pin < 16U)
155 {
156 icr = &(base->ICR1);
157 }
158 else
159 {
160 icr = &(base->ICR2);
161 icrShift -= 16U;
162 }
163 switch (pinInterruptMode)
164 {
165 case (kGPIO_IntLowLevel):
166 *icr &= ~(3UL << (2UL * icrShift));
167 break;
168 case (kGPIO_IntHighLevel):
169 *icr = (*icr & (~(3UL << (2UL * icrShift)))) | (1UL << (2UL * icrShift));
170 break;
171 case (kGPIO_IntRisingEdge):
172 *icr = (*icr & (~(3UL << (2UL * icrShift)))) | (2UL << (2UL * icrShift));
173 break;
174 case (kGPIO_IntFallingEdge):
175 *icr |= (3UL << (2UL * icrShift));
176 break;
177 case (kGPIO_IntRisingOrFallingEdge):
178 base->EDGE_SEL |= (1UL << pin);
179 break;
180 default:; /* Intentional empty default */
181 break;
182 }
183 }
184