1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_PORT_H_
9 #define _FSL_PORT_H_
10 
11 #include "fsl_common.h"
12 
13 /*!
14  * @addtogroup port
15  * @{
16  */
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*! @name Driver version */
23 /*@{*/
24 /*! Version 2.0.2. */
25 #define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
26 /*@}*/
27 
28 #if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
29 /*! @brief Internal resistor pull feature selection */
30 enum _port_pull
31 {
32     kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */
33     kPORT_PullDown = 2U,    /*!< Internal pull-down resistor is enabled. */
34     kPORT_PullUp = 3U,      /*!< Internal pull-up resistor is enabled. */
35 };
36 #endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
37 
38 #if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
39 /*! @brief Slew rate selection */
40 enum _port_slew_rate
41 {
42     kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */
43     kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */
44 };
45 #endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
46 
47 #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
48 /*! @brief Open Drain feature enable/disable */
49 enum _port_open_drain_enable
50 {
51     kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */
52     kPORT_OpenDrainEnable = 1U,  /*!< Open drain output is enabled. */
53 };
54 #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
55 
56 #if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
57 /*! @brief Passive filter feature enable/disable */
58 enum _port_passive_filter_enable
59 {
60     kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */
61     kPORT_PassiveFilterEnable = 1U,  /*!< Passive input filter is enabled. */
62 };
63 #endif
64 
65 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
66 /*! @brief Configures the drive strength. */
67 enum _port_drive_strength
68 {
69     kPORT_LowDriveStrength = 0U,  /*!< Low-drive strength is configured. */
70     kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */
71 };
72 #endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
73 
74 #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
75 /*! @brief Unlock/lock the pin control register field[15:0] */
76 enum _port_lock_register
77 {
78     kPORT_UnlockRegister = 0U, /*!< Pin Control Register fields [15:0] are not locked. */
79     kPORT_LockRegister = 1U,   /*!< Pin Control Register fields [15:0] are locked. */
80 };
81 #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
82 
83 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
84 /*! @brief Pin mux selection */
85 typedef enum _port_mux
86 {
87     kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */
88     kPORT_MuxAsGpio = 1U,           /*!< Corresponding pin is configured as GPIO. */
89     kPORT_MuxAlt2 = 2U,             /*!< Chip-specific */
90     kPORT_MuxAlt3 = 3U,             /*!< Chip-specific */
91     kPORT_MuxAlt4 = 4U,             /*!< Chip-specific */
92     kPORT_MuxAlt5 = 5U,             /*!< Chip-specific */
93     kPORT_MuxAlt6 = 6U,             /*!< Chip-specific */
94     kPORT_MuxAlt7 = 7U,             /*!< Chip-specific */
95     kPORT_MuxAlt8 = 8U,             /*!< Chip-specific */
96     kPORT_MuxAlt9 = 9U,             /*!< Chip-specific */
97     kPORT_MuxAlt10 = 10U,           /*!< Chip-specific */
98     kPORT_MuxAlt11 = 11U,           /*!< Chip-specific */
99     kPORT_MuxAlt12 = 12U,           /*!< Chip-specific */
100     kPORT_MuxAlt13 = 13U,           /*!< Chip-specific */
101     kPORT_MuxAlt14 = 14U,           /*!< Chip-specific */
102     kPORT_MuxAlt15 = 15U,           /*!< Chip-specific */
103 } port_mux_t;
104 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
105 
106 /*! @brief Configures the interrupt generation condition. */
107 typedef enum _port_interrupt
108 {
109     kPORT_InterruptOrDMADisabled = 0x0U, /*!< Interrupt/DMA request is disabled. */
110 #if defined(FSL_FEATURE_PORT_HAS_DMA_REQUEST) && FSL_FEATURE_PORT_HAS_DMA_REQUEST
111     kPORT_DMARisingEdge = 0x1U,  /*!< DMA request on rising edge. */
112     kPORT_DMAFallingEdge = 0x2U, /*!< DMA request on falling edge. */
113     kPORT_DMAEitherEdge = 0x3U,  /*!< DMA request on either edge. */
114 #endif
115 #if defined(FSL_FEATURE_PORT_HAS_IRQC_FLAG) && FSL_FEATURE_PORT_HAS_IRQC_FLAG
116     kPORT_FlagRisingEdge = 0x05U,  /*!< Flag sets on rising edge. */
117     kPORT_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
118     kPORT_FlagEitherEdge = 0x07U,  /*!< Flag sets on either edge. */
119 #endif
120     kPORT_InterruptLogicZero = 0x8U,   /*!< Interrupt when logic zero. */
121     kPORT_InterruptRisingEdge = 0x9U,  /*!< Interrupt on rising edge. */
122     kPORT_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
123     kPORT_InterruptEitherEdge = 0xBU,  /*!< Interrupt on either edge. */
124     kPORT_InterruptLogicOne = 0xCU,    /*!< Interrupt when logic one. */
125 #if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER
126     kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */
127     kPORT_ActiveLowTriggerOutputEnable = 0xEU,  /*!< Enable active low-trigger output. */
128 #endif
129 } port_interrupt_t;
130 
131 #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
132 /*! @brief Digital filter clock source selection */
133 typedef enum _port_digital_filter_clock_source
134 {
135     kPORT_BusClock = 0U, /*!< Digital filters are clocked by the bus clock. */
136     kPORT_LpoClock = 1U, /*!< Digital filters are clocked by the 1 kHz LPO clock. */
137 } port_digital_filter_clock_source_t;
138 
139 /*! @brief PORT digital filter feature configuration definition */
140 typedef struct _port_digital_filter_config
141 {
142     uint32_t digitalFilterWidth;                    /*!< Set digital filter width */
143     port_digital_filter_clock_source_t clockSource; /*!< Set digital filter clockSource */
144 } port_digital_filter_config_t;
145 #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
146 
147 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
148 /*! @brief PORT pin configuration structure */
149 typedef struct _port_pin_config
150 {
151 #if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
152     uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */
153 #else
154     uint16_t : 2;
155 #endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
156 
157 #if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
158     uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */
159 #else
160     uint16_t : 1;
161 #endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
162 
163     uint16_t : 1;
164 
165 #if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
166     uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */
167 #else
168     uint16_t : 1;
169 #endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */
170 
171 #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
172     uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */
173 #else
174     uint16_t : 1;
175 #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
176 
177 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
178     uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */
179 #else
180     uint16_t : 1;
181 #endif
182 
183     uint16_t : 1;
184 
185 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 3)
186     uint16_t mux : 3; /*!< Pin mux Configure */
187     uint16_t : 4;
188 #elif defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 4)
189     uint16_t mux : 4; /*!< Pin mux Configure */
190     uint16_t : 3;
191 #else
192     uint16_t : 7,
193 #endif
194 
195 #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
196     uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */
197 #else
198     uint16_t : 1;
199 #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
200 } port_pin_config_t;
201 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
202 
203 /*******************************************************************************
204 * API
205 ******************************************************************************/
206 
207 #if defined(__cplusplus)
208 extern "C" {
209 #endif
210 
211 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
212 /*! @name Configuration */
213 /*@{*/
214 
215 /*!
216  * @brief Sets the port PCR register.
217  *
218  * This is an example to define an input pin or output pin PCR configuration.
219  * @code
220  * // Define a digital input pin PCR configuration
221  * port_pin_config_t config = {
222  *      kPORT_PullUp,
223  *      kPORT_FastSlewRate,
224  *      kPORT_PassiveFilterDisable,
225  *      kPORT_OpenDrainDisable,
226  *      kPORT_LowDriveStrength,
227  *      kPORT_MuxAsGpio,
228  *      kPORT_UnLockRegister,
229  * };
230  * @endcode
231  *
232  * @param base   PORT peripheral base pointer.
233  * @param pin    PORT pin number.
234  * @param config PORT PCR register configuration structure.
235  */
PORT_SetPinConfig(PORT_Type * base,uint32_t pin,const port_pin_config_t * config)236 static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
237 {
238     assert(config);
239     uint32_t addr = (uint32_t)&base->PCR[pin];
240     *(volatile uint16_t *)(addr) = *((const uint16_t *)config);
241 }
242 
243 /*!
244  * @brief Sets the port PCR register for multiple pins.
245  *
246  * This is an example to define input pins or output pins PCR configuration.
247  * @code
248  * // Define a digital input pin PCR configuration
249  * port_pin_config_t config = {
250  *      kPORT_PullUp ,
251  *      kPORT_PullEnable,
252  *      kPORT_FastSlewRate,
253  *      kPORT_PassiveFilterDisable,
254  *      kPORT_OpenDrainDisable,
255  *      kPORT_LowDriveStrength,
256  *      kPORT_MuxAsGpio,
257  *      kPORT_UnlockRegister,
258  * };
259  * @endcode
260  *
261  * @param base   PORT peripheral base pointer.
262  * @param mask   PORT pin number macro.
263  * @param config PORT PCR register configuration structure.
264  */
PORT_SetMultiplePinsConfig(PORT_Type * base,uint32_t mask,const port_pin_config_t * config)265 static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config)
266 {
267     assert(config);
268 
269     uint16_t pcrl = *((const uint16_t *)config);
270 
271     if (mask & 0xffffU)
272     {
273         base->GPCLR = ((mask & 0xffffU) << 16) | pcrl;
274     }
275     if (mask >> 16)
276     {
277         base->GPCHR = (mask & 0xffff0000U) | pcrl;
278     }
279 }
280 
281 #if defined(FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG) && FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG
282 /*!
283  * @brief Sets the port interrupt configuration in PCR register for multiple pins.
284  *
285  * @param base   PORT peripheral base pointer.
286  * @param mask   PORT pin number macro.
287  * @param config  PORT pin interrupt configuration.
288  *        - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
289  *        - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
290  *        - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
291  *        - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
292  *        - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
293  *        - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
294  *        - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
295  *        - #kPORT_InterruptLogicZero  : Interrupt when logic zero.
296  *        - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
297  *        - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
298  *        - #kPORT_InterruptEitherEdge : Interrupt on either edge.
299  *        - #kPORT_InterruptLogicOne   : Interrupt when logic one.
300  *        - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
301  *        - #kPORT_ActiveLowTriggerOutputEnable  : Enable active low-trigger output (if the trigger states exit)..
302  */
PORT_SetMultipleInterruptPinsConfig(PORT_Type * base,uint32_t mask,port_interrupt_t config)303 static inline void PORT_SetMultipleInterruptPinsConfig(PORT_Type *base, uint32_t mask, port_interrupt_t config)
304 {
305     assert(config);
306 
307     if (mask & 0xffffU)
308     {
309         base->GICLR = (config << 16) | (mask & 0xffffU);
310     }
311     if (mask >> 16)
312     {
313         base->GICHR = (config << 16) | (mask & 0xffff0000U);
314     }
315 }
316 #endif
317 
318 /*!
319  * @brief Configures the pin muxing.
320  *
321  * @param base  PORT peripheral base pointer.
322  * @param pin   PORT pin number.
323  * @param mux   pin muxing slot selection.
324  *        - #kPORT_PinDisabledOrAnalog: Pin disabled or work in analog function.
325  *        - #kPORT_MuxAsGpio          : Set as GPIO.
326  *        - #kPORT_MuxAlt2            : chip-specific.
327  *        - #kPORT_MuxAlt3            : chip-specific.
328  *        - #kPORT_MuxAlt4            : chip-specific.
329  *        - #kPORT_MuxAlt5            : chip-specific.
330  *        - #kPORT_MuxAlt6            : chip-specific.
331  *        - #kPORT_MuxAlt7            : chip-specific.
332  * @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because
333  *         the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is
334  *         reset to zero : kPORT_PinDisabledOrAnalog).
335  *        This function is recommended to use to reset the pin mux
336  *
337  */
PORT_SetPinMux(PORT_Type * base,uint32_t pin,port_mux_t mux)338 static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
339 {
340     base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux);
341 }
342 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
343 
344 #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
345 
346 /*!
347  * @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin.
348  *
349  * @param base  PORT peripheral base pointer.
350  * @param mask  PORT pin number macro.
351  */
PORT_EnablePinsDigitalFilter(PORT_Type * base,uint32_t mask,bool enable)352 static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable)
353 {
354     if (enable == true)
355     {
356         base->DFER |= mask;
357     }
358     else
359     {
360         base->DFER &= ~mask;
361     }
362 }
363 
364 /*!
365  * @brief Sets the digital filter in one port, each bit of the 32-bit register represents one pin.
366  *
367  * @param base   PORT peripheral base pointer.
368  * @param config PORT digital filter configuration structure.
369  */
PORT_SetDigitalFilterConfig(PORT_Type * base,const port_digital_filter_config_t * config)370 static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digital_filter_config_t *config)
371 {
372     assert(config);
373 
374     base->DFCR = PORT_DFCR_CS(config->clockSource);
375     base->DFWR = PORT_DFWR_FILT(config->digitalFilterWidth);
376 }
377 
378 #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
379 
380 /*@}*/
381 
382 /*! @name Interrupt */
383 /*@{*/
384 
385 /*!
386  * @brief Configures the port pin interrupt/DMA request.
387  *
388  * @param base    PORT peripheral base pointer.
389  * @param pin     PORT pin number.
390  * @param config  PORT pin interrupt configuration.
391  *        - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
392  *        - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
393  *        - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
394  *        - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
395  *        - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
396  *        - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
397  *        - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
398  *        - #kPORT_InterruptLogicZero  : Interrupt when logic zero.
399  *        - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
400  *        - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
401  *        - #kPORT_InterruptEitherEdge : Interrupt on either edge.
402  *        - #kPORT_InterruptLogicOne   : Interrupt when logic one.
403  *        - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
404  *        - #kPORT_ActiveLowTriggerOutputEnable  : Enable active low-trigger output (if the trigger states exit).
405  */
PORT_SetPinInterruptConfig(PORT_Type * base,uint32_t pin,port_interrupt_t config)406 static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
407 {
408     base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
409 }
410 
411 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
412 /*!
413  * @brief Configures the port pin drive strength.
414  *
415  * @param base    PORT peripheral base pointer.
416  * @param pin     PORT pin number.
417  * @param config  PORT pin drive strength
418  *        - #kPORT_LowDriveStrength = 0U - Low-drive strength is configured.
419  *        - #kPORT_HighDriveStrength = 1U - High-drive strength is configured.
420  */
PORT_SetPinDriveStrength(PORT_Type * base,uint32_t pin,uint8_t strength)421 static inline void PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)
422 {
423     base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_DSE_MASK) |  PORT_PCR_DSE(strength);
424 }
425 #endif
426 
427 /*!
428  * @brief Reads the whole port status flag.
429  *
430  * If a pin is configured to generate the DMA request,  the corresponding flag
431  * is cleared automatically at the completion of the requested DMA transfer.
432  * Otherwise, the flag remains set until a logic one is written to that flag.
433  * If configured for a level sensitive interrupt that remains asserted, the flag
434  * is set again immediately.
435  *
436  * @param base PORT peripheral base pointer.
437  * @return Current port interrupt status flags, for example, 0x00010001 means the
438  *         pin 0 and 16 have the interrupt.
439  */
PORT_GetPinsInterruptFlags(PORT_Type * base)440 static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
441 {
442     return base->ISFR;
443 }
444 
445 /*!
446  * @brief Clears the multiple pin interrupt status flag.
447  *
448  * @param base PORT peripheral base pointer.
449  * @param mask PORT pin number macro.
450  */
PORT_ClearPinsInterruptFlags(PORT_Type * base,uint32_t mask)451 static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
452 {
453     base->ISFR = mask;
454 }
455 
456 /*@}*/
457 
458 #if defined(__cplusplus)
459 }
460 #endif
461 
462 /*! @}*/
463 
464 #endif /* _FSL_PORT_H_ */
465