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