1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_rgpio.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.rgpio"
14 #endif
15
16 /*******************************************************************************
17 * Variables
18 ******************************************************************************/
19 #if defined(FSL_FEATURE_SOC_PORT_COUNT) && FSL_FEATURE_SOC_PORT_COUNT
20 static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
21 #endif /* FSL_FEATURE_SOC_PORT_COUNT */
22
23 static RGPIO_Type *const s_rgpioBases[] = RGPIO_BASE_PTRS;
24
25 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
26
27 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
28
29 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
30 /*! @brief Array to map FGPIO instance number to clock name. */
31 static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
32 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
33
34 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
35
36 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
37
38 /*******************************************************************************
39 * Prototypes
40 ******************************************************************************/
41
42 /*******************************************************************************
43 * Code
44 ******************************************************************************/
45
46 /*!
47 * brief Gets the RGPIO instance according to the RGPIO base
48 *
49 * param base RGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
50 * retval RGPIO instance
51 */
RGPIO_GetInstance(RGPIO_Type * base)52 uint32_t RGPIO_GetInstance(RGPIO_Type *base)
53 {
54 uint32_t instance;
55
56 /* Find the instance index from base address mappings. */
57 for (instance = 0U; instance < ARRAY_SIZE(s_rgpioBases); instance++)
58 {
59 if (s_rgpioBases[instance] == base)
60 {
61 break;
62 }
63 }
64
65 assert(instance < ARRAY_SIZE(s_rgpioBases));
66
67 return instance;
68 }
69
70 /*!
71 * brief Initializes a RGPIO pin used by the board.
72 *
73 * To initialize the RGPIO, define a pin configuration, as either input or output, in the user file.
74 * Then, call the RGPIO_PinInit() function.
75 *
76 * This is an example to define an input pin or an output pin configuration.
77 * code
78 * Define a digital input pin configuration,
79 * rgpio_pin_config_t config =
80 * {
81 * kRGPIO_DigitalInput,
82 * 0,
83 * }
84 * Define a digital output pin configuration,
85 * rgpio_pin_config_t config =
86 * {
87 * kRGPIO_DigitalOutput,
88 * 0,
89 * }
90 * endcode
91 *
92 * param base RGPIO peripheral base pointer (RGPIOA, RGPIOB, RGPIOC, and so on.)
93 * param pin RGPIO port pin number
94 * param config RGPIO pin configuration pointer
95 */
RGPIO_PinInit(RGPIO_Type * base,uint32_t pin,const rgpio_pin_config_t * config)96 void RGPIO_PinInit(RGPIO_Type *base, uint32_t pin, const rgpio_pin_config_t *config)
97 {
98 assert(NULL != config);
99
100 if (config->pinDirection == kRGPIO_DigitalInput)
101 {
102 base->PDDR &= ~(1UL << pin);
103 }
104 else
105 {
106 RGPIO_WritePinOutput(base, pin, config->outputLogic);
107 base->PDDR |= (1UL << pin);
108 }
109 }
110
111 #if defined(FSL_FEATURE_SOC_PORT_COUNT) && FSL_FEATURE_SOC_PORT_COUNT
112 /*!
113 * brief Reads the RGPIO port interrupt status flag.
114 *
115 * If a pin is configured to generate the DMA request, the corresponding flag
116 * is cleared automatically at the completion of the requested DMA transfer.
117 * Otherwise, the flag remains set until a logic one is written to that flag.
118 * If configured for a level sensitive interrupt that remains asserted, the flag
119 * is set again immediately.
120 *
121 * param base RGPIO peripheral base pointer (RGPIOA, RGPIOB, RGPIOC, and so on.)
122 * retval The current RGPIO port interrupt status flag, for example, 0x00010001 means the
123 * pin 0 and 17 have the interrupt.
124 */
RGPIO_PortGetInterruptFlags(RGPIO_Type * base)125 uint32_t RGPIO_PortGetInterruptFlags(RGPIO_Type *base)
126 {
127 uint8_t instance;
128 PORT_Type *portBase;
129 instance = RGPIO_GetInstance(base);
130 portBase = s_portBases[instance];
131 return portBase->ISFR;
132 }
133
134 /*!
135 * brief Clears multiple RGPIO pin interrupt status flags.
136 *
137 * param base RGPIO peripheral base pointer (RGPIOA, RGPIOB, RGPIOC, and so on.)
138 * param mask RGPIO pin number macro
139 */
RGPIO_PortClearInterruptFlags(RGPIO_Type * base,uint32_t mask)140 void RGPIO_PortClearInterruptFlags(RGPIO_Type *base, uint32_t mask)
141 {
142 uint8_t instance;
143 PORT_Type *portBase;
144 instance = RGPIO_GetInstance(base);
145 portBase = s_portBases[instance];
146 portBase->ISFR = mask;
147 }
148 #endif /* FSL_FEATURE_SOC_PORT_COUNT */
149
150 #if defined(FSL_FEATURE_RGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_RGPIO_HAS_ATTRIBUTE_CHECKER
151 /*!
152 * brief The RGPIO module supports a device-specific number of data ports, organized as 32-bit
153 * words. Each 32-bit data port includes a GACR register, which defines the byte-level
154 * attributes required for a successful access to the RGPIO programming model. The attribute controls for the 4 data
155 * bytes in the GACR follow a standard little endian
156 * data convention.
157 *
158 * param base RGPIO peripheral base pointer (RGPIOA, RGPIOB, RGPIOC, and so on.)
159 * param mask RGPIO pin number macro
160 */
RGPIO_CheckAttributeBytes(RGPIO_Type * base,rgpio_checker_attribute_t attribute)161 void RGPIO_CheckAttributeBytes(RGPIO_Type *base, rgpio_checker_attribute_t attribute)
162 {
163 base->GACR = ((uint32_t)attribute << RGPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << RGPIO_GACR_ACB1_SHIFT) |
164 ((uint32_t)attribute << RGPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << RGPIO_GACR_ACB3_SHIFT);
165 }
166 #endif
167
168 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
169
170 /*******************************************************************************
171 * Variables
172 ******************************************************************************/
173 static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
174
175 /*******************************************************************************
176 * Prototypes
177 ******************************************************************************/
178
179 /*******************************************************************************
180 * Code
181 ******************************************************************************/
182
183 /*!
184 * brief Gets the FGPIO instance according to the RGPIO base
185 *
186 * param base FGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
187 * retval FGPIO instance
188 */
FGPIO_GetInstance(FGPIO_Type * base)189 uint32_t FGPIO_GetInstance(FGPIO_Type *base)
190 {
191 uint32_t instance;
192
193 /* Find the instance index from base address mappings. */
194 for (instance = 0U; instance < ARRAY_SIZE(s_fgpioBases); instance++)
195 {
196 if (s_fgpioBases[instance] == base)
197 {
198 break;
199 }
200 }
201
202 assert(instance < ARRAY_SIZE(s_fgpioBases));
203
204 return instance;
205 }
206
207 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
FGPIO_PortInit(FGPIO_Type * base)208 void FGPIO_PortInit(FGPIO_Type *base)
209 {
210 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
211 /* Ungate FGPIO periphral clock */
212 CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
213 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
214 }
215 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
216
217 /*!
218 * brief Initializes a FGPIO pin used by the board.
219 *
220 * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
221 * Then, call the FGPIO_PinInit() function.
222 *
223 * This is an example to define an input pin or an output pin configuration:
224 * code
225 * Define a digital input pin configuration,
226 * rgpio_pin_config_t config =
227 * {
228 * kRGPIO_DigitalInput,
229 * 0,
230 * }
231 * Define a digital output pin configuration,
232 * rgpio_pin_config_t config =
233 * {
234 * kRGPIO_DigitalOutput,
235 * 0,
236 * }
237 * endcode
238 *
239 * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
240 * param pin FGPIO port pin number
241 * param config FGPIO pin configuration pointer
242 */
FGPIO_PinInit(FGPIO_Type * base,uint32_t pin,const rgpio_pin_config_t * config)243 void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const rgpio_pin_config_t *config)
244 {
245 assert(NULL != config);
246
247 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
248 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
249 /* Ungate FGPIO periphral clock */
250 CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
251 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
252 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
253
254 if (config->pinDirection == kRGPIO_DigitalInput)
255 {
256 base->PDDR &= ~(1UL << pin);
257 }
258 else
259 {
260 FGPIO_WritePinOutput(base, pin, config->outputLogic);
261 base->PDDR |= (1UL << pin);
262 }
263 }
264
265 #if defined(FSL_FEATURE_SOC_PORT_COUNT) && FSL_FEATURE_SOC_PORT_COUNT
266 /*!
267 * brief Reads the FGPIO port interrupt status flag.
268 *
269 * If a pin is configured to generate the DMA request, the corresponding flag
270 * is cleared automatically at the completion of the requested DMA transfer.
271 * Otherwise, the flag remains set until a logic one is written to that flag.
272 * If configured for a level-sensitive interrupt that remains asserted, the flag
273 * is set again immediately.
274 *
275 * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
276 * retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the
277 * pin 0 and 17 have the interrupt.
278 */
FGPIO_PortGetInterruptFlags(FGPIO_Type * base)279 uint32_t FGPIO_PortGetInterruptFlags(FGPIO_Type *base)
280 {
281 uint8_t instance;
282 instance = FGPIO_GetInstance(base);
283 PORT_Type *portBase;
284 portBase = s_portBases[instance];
285 return portBase->ISFR;
286 }
287
288 /*!
289 * brief Clears the multiple FGPIO pin interrupt status flag.
290 *
291 * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
292 * param mask FGPIO pin number macro
293 */
FGPIO_PortClearInterruptFlags(FGPIO_Type * base,uint32_t mask)294 void FGPIO_PortClearInterruptFlags(FGPIO_Type *base, uint32_t mask)
295 {
296 uint8_t instance;
297 instance = FGPIO_GetInstance(base);
298 PORT_Type *portBase;
299 portBase = s_portBases[instance];
300 portBase->ISFR = mask;
301 }
302 #endif /* FSL_FEATURE_SOC_PORT_COUNT */
303
304 #if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER
305 /*!
306 * brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit
307 * words. Each 32-bit data port includes a GACR register, which defines the byte-level
308 * attributes required for a successful access to the RGPIO programming model. The attribute controls for the 4 data
309 * bytes in the GACR follow a standard little endian
310 * data convention.
311 *
312 * param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
313 * param mask FGPIO pin number macro
314 */
FGPIO_CheckAttributeBytes(FGPIO_Type * base,rgpio_checker_attribute_t attribute)315 void FGPIO_CheckAttributeBytes(FGPIO_Type *base, rgpio_checker_attribute_t attribute)
316 {
317 base->GACR = (attribute << FGPIO_GACR_ACB0_SHIFT) | (attribute << FGPIO_GACR_ACB1_SHIFT) |
318 (attribute << FGPIO_GACR_ACB2_SHIFT) | (attribute << FGPIO_GACR_ACB3_SHIFT);
319 }
320 #endif
321
322 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
323