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