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