1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_gpio.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.gpio_1"
17 #endif
18 
19 #define PORT_NUMBERS_EACH_GPIO (4U)
20 #define PIN_NUMBERS_EACH_PORT  (8UL)
21 /*******************************************************************************
22  * Variables
23  ******************************************************************************/
24 #if defined(FSL_FEATURE_SOC_GPIO_COUNT) && FSL_FEATURE_SOC_GPIO_COUNT
25 static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
26 #endif
27 
28 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
29 static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
30 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
31 
32 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
33 /*! @brief Array to map FGPIO instance number to clock name. */
34 static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
35 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
36 
37 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
38 
39 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
40 
41 /*******************************************************************************
42  * Prototypes
43  ******************************************************************************/
44 
45 /*******************************************************************************
46  * Code
47  ******************************************************************************/
48 
49 /*!
50  * brief Initializes a GPIO pin used by the board.
51  *
52  * To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
53  * Then, call the GPIO_PinInit() function.
54  *
55  * This is an example to define an input pin or an output pin configuration.
56  * code
57  * Define a digital input pin configuration,
58  * gpio_pin_config_t config =
59  * {
60  *   kGPIO_DigitalInput,
61  *   0,
62  * }
63  * Define a digital output pin configuration,
64  * gpio_pin_config_t config =
65  * {
66  *   kGPIO_DigitalOutput,
67  *   0,
68  * }
69  * endcode
70  *
71  * param port   GPIO PORT number, see "gpio_port_num_t".
72  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
73  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
74  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
75  *   ...
76  * param pin    GPIO port pin number
77  * param config GPIO pin configuration pointer
78  */
GPIO_PinInit(gpio_port_num_t port,uint8_t pin,const gpio_pin_config_t * config)79 void GPIO_PinInit(gpio_port_num_t port, uint8_t pin, const gpio_pin_config_t *config)
80 {
81     assert(config);
82 
83     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
84     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
85     GPIO_Type *base  = s_gpioBases[instance];
86 
87     if (config->pinDirection == kGPIO_DigitalInput)
88     {
89         base->PDDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
90         base->PIDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
91     }
92     else
93     {
94         GPIO_PinWrite(port, pin, config->outputLogic);
95         base->PDDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
96         base->PIDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
97     }
98 }
99 
100 /*!
101  * brief Sets the output level of the multiple GPIO pins to the logic 1 or 0.
102  *
103  * param port   GPIO PORT number, see "gpio_port_num_t".
104  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
105  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
106  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
107  *   ...
108  * param pin     GPIO pin number
109  * param output  GPIO pin output logic level.
110  *        - 0: corresponding pin output low-logic level.
111  *        - 1: corresponding pin output high-logic level.
112  */
GPIO_PinWrite(gpio_port_num_t port,uint8_t pin,uint8_t output)113 void GPIO_PinWrite(gpio_port_num_t port, uint8_t pin, uint8_t output)
114 {
115     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
116     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
117     GPIO_Type *base  = s_gpioBases[instance];
118 
119     if (output == 0U)
120     {
121         base->PCOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
122     }
123     else
124     {
125         base->PSOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
126     }
127 }
128 
129 /*!
130  * brief Sets the output level of the multiple GPIO pins to the logic 1.
131  *
132  * param port   GPIO PORT number, see "gpio_port_num_t".
133  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
134  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
135  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
136  *   ...
137  * param mask GPIO pin number macro
138  */
GPIO_PortSet(gpio_port_num_t port,uint8_t mask)139 void GPIO_PortSet(gpio_port_num_t port, uint8_t mask)
140 {
141     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
142     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
143     GPIO_Type *base  = s_gpioBases[instance];
144 
145     base->PSOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
146 }
147 
148 /*!
149  * brief Sets the output level of the multiple GPIO pins to the logic 0.
150  *
151  * param port   GPIO PORT number, see "gpio_port_num_t".
152  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
153  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
154  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
155  *   ...
156  * param mask GPIO pin number macro
157  */
GPIO_PortClear(gpio_port_num_t port,uint8_t mask)158 void GPIO_PortClear(gpio_port_num_t port, uint8_t mask)
159 {
160     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
161     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
162     GPIO_Type *base  = s_gpioBases[instance];
163 
164     base->PCOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
165 }
166 
167 /*!
168  * brief Reverses the current output logic of the multiple GPIO pins.
169  *
170  * param port   GPIO PORT number, see "gpio_port_num_t".
171  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
172  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
173  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
174  *   ...
175  * param mask GPIO pin number macro
176  */
GPIO_PortToggle(gpio_port_num_t port,uint8_t mask)177 void GPIO_PortToggle(gpio_port_num_t port, uint8_t mask)
178 {
179     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
180     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
181     GPIO_Type *base  = s_gpioBases[instance];
182 
183     base->PTOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
184 }
185 
186 /*!
187  * brief Reads the current input value of the GPIO port.
188  *
189  * param port   GPIO PORT number, see "gpio_port_num_t".
190  *  For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
191  *  GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
192  *  GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
193  *   ...
194  * param pin     GPIO pin number
195  * retval GPIO port input value
196  *        - 0: corresponding pin input low-logic level.
197  *        - 1: corresponding pin input high-logic level.
198  */
GPIO_PinRead(gpio_port_num_t port,uint8_t pin)199 uint32_t GPIO_PinRead(gpio_port_num_t port, uint8_t pin)
200 {
201     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
202     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
203     GPIO_Type *base  = s_gpioBases[instance];
204 
205     return (((base->PDIR) >> ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT))) & 0x01UL);
206 }
207 
208 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
209 
210 /*******************************************************************************
211  * Variables
212  ******************************************************************************/
213 
214 /*******************************************************************************
215  * Prototypes
216  ******************************************************************************/
217 /*!
218  * @brief Enable the FGPIO clock.
219  *
220  * @param port FGPIO PORT number.
221  */
222 static void FGPIO_EnableClock(gpio_port_num_t port);
223 
224 /*******************************************************************************
225  * Code
226  ******************************************************************************/
FGPIO_EnableClock(gpio_port_num_t port)227 static void FGPIO_EnableClock(gpio_port_num_t port)
228 {
229 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
230     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
231     FGPIO_Type *base = s_fgpioBases[instance];
232 
233 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
234     /* Ungate FGPIO periphral clock */
235     CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
236 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
237 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
238 }
239 
FGPIO_PortInit(gpio_port_num_t port)240 void FGPIO_PortInit(gpio_port_num_t port)
241 {
242     FGPIO_EnableClock(port);
243 }
244 
245 /*!
246  * brief Initializes a FGPIO pin used by the board.
247  *
248  * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
249  * Then, call the FGPIO_PinInit() function.
250  *
251  * This is an example to define an input pin or an output pin configuration:
252  * code
253  * Define a digital input pin configuration,
254  * gpio_pin_config_t config =
255  * {
256  *   kGPIO_DigitalInput,
257  *   0,
258  * }
259  * Define a digital output pin configuration,
260  * gpio_pin_config_t config =
261  * {
262  *   kGPIO_DigitalOutput,
263  *   0,
264  * }
265  * endcode
266  *
267  * param port   FGPIO PORT number, see "gpio_port_num_t".
268  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
269  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
270  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
271  *   ...
272  * param pin    FGPIO port pin number
273  * param config FGPIO pin configuration pointer
274  */
FGPIO_PinInit(gpio_port_num_t port,uint8_t pin,const gpio_pin_config_t * config)275 void FGPIO_PinInit(gpio_port_num_t port, uint8_t pin, const gpio_pin_config_t *config)
276 {
277     assert(config);
278 
279     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
280     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
281     FGPIO_Type *base = s_fgpioBases[instance];
282 
283     FGPIO_EnableClock(port);
284 
285     if (config->pinDirection == kGPIO_DigitalInput)
286     {
287         base->PDDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
288     }
289     else
290     {
291         FGPIO_PinWrite(port, pin, config->outputLogic);
292         base->PDDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
293     }
294 }
295 
296 /*!
297  * brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0.
298  *
299  * param port   FGPIO PORT number, see "gpio_port_num_t".
300  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
301  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
302  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
303  *   ...
304  * param pin     FGPIO pin number
305  * param output  FGPIOpin output logic level.
306  *        - 0: corresponding pin output low-logic level.
307  *        - 1: corresponding pin output high-logic level.
308  */
FGPIO_PinWrite(gpio_port_num_t port,uint8_t pin,uint8_t output)309 void FGPIO_PinWrite(gpio_port_num_t port, uint8_t pin, uint8_t output)
310 {
311     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
312     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
313     FGPIO_Type *base = s_fgpioBases[instance];
314 
315     if (output == 0U)
316     {
317         base->PCOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
318     }
319     else
320     {
321         base->PSOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
322     }
323 }
324 
325 /*!
326  * brief Sets the output level of the multiple FGPIO pins to the logic 1.
327  *
328  * param port   FGPIO PORT number, see "gpio_port_num_t".
329  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
330  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
331  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
332  *   ...
333  * param mask FGPIO pin number macro
334  */
FGPIO_PortSet(gpio_port_num_t port,uint8_t mask)335 void FGPIO_PortSet(gpio_port_num_t port, uint8_t mask)
336 {
337     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
338     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
339     FGPIO_Type *base = s_fgpioBases[instance];
340 
341     base->PSOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
342 }
343 
344 /*!
345  * brief Sets the output level of the multiple FGPIO pins to the logic 0.
346  *
347  * param port   FGPIO PORT number, see "gpio_port_num_t".
348  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
349  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
350  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
351  *   ...
352  * param mask FGPIO pin number macro
353  */
FGPIO_PortClear(gpio_port_num_t port,uint8_t mask)354 void FGPIO_PortClear(gpio_port_num_t port, uint8_t mask)
355 {
356     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
357     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
358     FGPIO_Type *base = s_fgpioBases[instance];
359 
360     base->PCOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
361 }
362 
363 /*!
364  * brief Reverses the current output logic of the multiple FGPIO pins.
365  *
366  * param port   FGPIO PORT number, see "gpio_port_num_t".
367  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
368  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
369  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
370  *   ...
371  * param mask FGPIO pin number macro
372  */
FGPIO_PortToggle(gpio_port_num_t port,uint8_t mask)373 void FGPIO_PortToggle(gpio_port_num_t port, uint8_t mask)
374 {
375     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
376     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
377     FGPIO_Type *base = s_fgpioBases[instance];
378 
379     base->PTOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
380 }
381 
382 /*!
383  * brief Reads the current input value of the FGPIO port.
384  *
385  * param port   FGPIO PORT number, see "gpio_port_num_t".
386  *  For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
387  *  FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
388  *  FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
389  *   ...
390  * param pin  FGPIO pin number
391  * retval FGPIO port input value
392  *        - 0: corresponding pin input low-logic level.
393  *        - 1: corresponding pin input high-logic level.
394  */
FGPIO_PinRead(gpio_port_num_t port,uint8_t pin)395 uint32_t FGPIO_PinRead(gpio_port_num_t port, uint8_t pin)
396 {
397     uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
398     uint8_t shift    = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
399     FGPIO_Type *base = s_fgpioBases[instance];
400 
401     return (((base->PDIR) >> ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT))) & 0x01UL);
402 }
403 
404 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
405