1717
1818#include <zephyr/drivers/gpio/gpio_utils.h>
1919
20+ #if defined(CONFIG_PINCTRL_NXP_IOCON )
21+ #include <fsl_iopctl.h>
22+ #include <fsl_reset.h>
23+ #include <fsl_clock.h>
24+ #include <fsl_gpio.h>
25+ /* Use IOCON to configure electrical characteristic, set PORT_Type as void. */
26+ #define PORT_Type void
27+ #endif
28+
2029struct gpio_mcux_config {
2130 /* gpio_driver_config needs to be first */
2231 struct gpio_driver_config common ;
2332 GPIO_Type * gpio_base ;
2433 PORT_Type * port_base ;
2534 unsigned int flags ;
35+ uint32_t port_no ;
2636};
2737
2838struct gpio_mcux_data {
@@ -32,7 +42,80 @@ struct gpio_mcux_data {
3242 sys_slist_t callbacks ;
3343};
3444
35- static int gpio_mcux_configure (const struct device * dev , gpio_pin_t pin , gpio_flags_t flags )
45+ #if defined(CONFIG_PINCTRL_NXP_IOCON )
46+ static int gpio_mcux_iopctl_configure (const struct device * dev , gpio_pin_t pin , gpio_flags_t flags )
47+ {
48+ const struct gpio_mcux_config * config = dev -> config ;
49+ GPIO_Type * gpio_base = config -> gpio_base ;
50+ uint32_t port_no = config -> port_no ;
51+ volatile uint32_t pinconfig = 0 ;
52+
53+ if (((flags & GPIO_INPUT ) != 0 ) && ((flags & GPIO_OUTPUT ) != 0 )) {
54+ return - ENOTSUP ;
55+ }
56+
57+ if ((flags & GPIO_SINGLE_ENDED ) != 0 ) {
58+ return - ENOTSUP ;
59+ }
60+
61+ /* The flags contain options that require touching registers in the
62+ * GPIO module and the corresponding PORT module.
63+ *
64+ * Start with the GPIO module and set up the pin direction register.
65+ * 0 - pin is input, 1 - pin is output
66+ */
67+
68+ switch (flags & GPIO_DIR_MASK ) {
69+ case GPIO_INPUT :
70+ gpio_base -> PDDR &= ~BIT (pin );
71+ /* Enable input buffer for input pins */
72+ pinconfig |= IOPCTL_INBUF_EN ;
73+ break ;
74+ case GPIO_OUTPUT :
75+ if ((flags & GPIO_OUTPUT_INIT_HIGH ) != 0 ) {
76+ gpio_base -> PSOR = BIT (pin );
77+ } else if ((flags & GPIO_OUTPUT_INIT_LOW ) != 0 ) {
78+ gpio_base -> PCOR = BIT (pin );
79+ }
80+ gpio_base -> PDDR |= BIT (pin );
81+ break ;
82+ default :
83+ return - ENOTSUP ;
84+ }
85+
86+ /* Select GPIO mux for this pin (func 0 is always GPIO) */
87+ pinconfig |= IOPCTL_FUNC0 ;
88+
89+ if ((flags & GPIO_PULL_UP ) != 0 ) {
90+ /* Enable and select pull up. */
91+ pinconfig |= (IOPCTL_PUPD_EN | IOPCTL_PULLUP_EN );
92+ } else if ((flags & GPIO_PULL_DOWN ) != 0 ) {
93+ /* Enable and select pull down. */
94+ pinconfig |= (IOPCTL_PUPD_EN | IOPCTL_PULLDOWN_EN );
95+ }
96+
97+ #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH ) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
98+ /* Determine the drive strength */
99+ switch (flags & KINETIS_GPIO_DS_MASK ) {
100+ case KINETIS_GPIO_DS_DFLT :
101+ /* Default is low drive strength */
102+ pinconfig |= IOPCTL_DRIVE_100OHM ;
103+ break ;
104+ case KINETIS_GPIO_DS_ALT :
105+ /* Alternate is high drive strength */
106+ pinconfig |= IOPCTL_DRIVE_33OHM ;
107+ break ;
108+ default :
109+ return - ENOTSUP ;
110+ }
111+ #endif /* defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
112+
113+ IOPCTL_PinMuxSet (port_no , pin , pinconfig );
114+
115+ return 0 ;
116+ }
117+ #else
118+ static int gpio_mcux_port_configure (const struct device * dev , gpio_pin_t pin , gpio_flags_t flags )
36119{
37120 const struct gpio_mcux_config * config = dev -> config ;
38121 GPIO_Type * gpio_base = config -> gpio_base ;
@@ -122,6 +205,7 @@ static int gpio_mcux_configure(const struct device *dev, gpio_pin_t pin, gpio_fl
122205
123206 return 0 ;
124207}
208+ #endif /* defined(CONFIG_PINCTRL_NXP_IOCON) */
125209
126210static int gpio_mcux_port_get_raw (const struct device * dev , uint32_t * value )
127211{
@@ -173,6 +257,7 @@ static int gpio_mcux_port_toggle_bits(const struct device *dev, uint32_t mask)
173257 return 0 ;
174258}
175259
260+ #if !(defined(CONFIG_PINCTRL_NXP_IOCON ))
176261#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT ) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT )
177262static uint32_t get_port_pcr_irqc_value_from_flags (const struct device * dev , uint32_t pin ,
178263 enum gpio_int_mode mode , enum gpio_int_trig trig )
@@ -208,9 +293,10 @@ static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev, uin
208293 return PORT_PCR_IRQC (port_interrupt );
209294}
210295#endif /* !defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
296+ #endif /* !(defined(CONFIG_PINCTRL_NXP_IOCON)) */
211297
212- #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
213- FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
298+ #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
299+ FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
214300
215301#define GPIO_MCUX_INTERRUPT_DISABLED 0
216302#define GPIO_MCUX_INTERRUPT_LOGIC_0 0x8
@@ -259,12 +345,14 @@ static int gpio_mcux_pin_interrupt_configure(const struct device *dev, gpio_pin_
259345{
260346 const struct gpio_mcux_config * config = dev -> config ;
261347 GPIO_Type * gpio_base = config -> gpio_base ;
348+ #if !(defined(CONFIG_PINCTRL_NXP_IOCON ))
262349 PORT_Type * port_base = config -> port_base ;
263350
264351 /* Check for an invalid pin number */
265352 if (pin >= ARRAY_SIZE (port_base -> PCR )) {
266353 return - EINVAL ;
267354 }
355+ #endif
268356
269357 /* Check for an invalid pin configuration */
270358 if ((mode != GPIO_INT_MODE_DISABLED ) && ((gpio_base -> PDDR & BIT (pin )) != 0 )) {
@@ -276,15 +364,15 @@ static int gpio_mcux_pin_interrupt_configure(const struct device *dev, gpio_pin_
276364 return - ENOTSUP ;
277365 }
278366
279- #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT ) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT )
280- uint32_t pcr = get_port_pcr_irqc_value_from_flags (dev , pin , mode , trig );
281-
282- port_base -> PCR [pin ] = (port_base -> PCR [pin ] & ~PORT_PCR_IRQC_MASK ) | pcr ;
283- #elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
284- FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
367+ #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
368+ FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
285369 uint32_t icr = get_gpio_icr_irqc_value_from_flags (dev , pin , mode , trig );
286370
287371 gpio_base -> ICR [pin ] = (gpio_base -> ICR [pin ] & ~GPIO_ICR_IRQC_MASK ) | icr ;
372+ #elif !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT ) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT )
373+ uint32_t pcr = get_port_pcr_irqc_value_from_flags (dev , pin , mode , trig );
374+
375+ port_base -> PCR [pin ] = (port_base -> PCR [pin ] & ~PORT_PCR_IRQC_MASK ) | pcr ;
288376#endif /* !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) */
289377
290378 return 0 ;
@@ -304,17 +392,17 @@ static void gpio_mcux_port_isr(const struct device *dev)
304392 struct gpio_mcux_data * data = dev -> data ;
305393 uint32_t int_status ;
306394
307- #if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT ) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT )
308- int_status = config -> port_base -> ISFR ;
309-
310- /* Clear the port interrupts */
311- config -> port_base -> ISFR = int_status ;
312- #elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
313- FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
395+ #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT ) && \
396+ FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT )
314397 int_status = config -> gpio_base -> ISFR [0 ];
315398
316399 /* Clear the gpio interrupts */
317400 config -> gpio_base -> ISFR [0 ] = int_status ;
401+ #elif !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT ) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT )
402+ int_status = config -> port_base -> ISFR ;
403+
404+ /* Clear the port interrupts */
405+ config -> port_base -> ISFR = int_status ;
318406#else
319407 int_status = 0U ;
320408 ARG_UNUSED (config );
@@ -377,7 +465,11 @@ static int gpio_mcux_port_get_direction(const struct device *dev, gpio_port_pins
377465#endif /* CONFIG_GPIO_GET_DIRECTION */
378466
379467static DEVICE_API (gpio , gpio_mcux_driver_api ) = {
380- .pin_configure = gpio_mcux_configure ,
468+ #if defined(CONFIG_PINCTRL_NXP_IOCON )
469+ .pin_configure = gpio_mcux_iopctl_configure ,
470+ #else
471+ .pin_configure = gpio_mcux_port_configure ,
472+ #endif
381473 .port_get_raw = gpio_mcux_port_get_raw ,
382474 .port_set_masked_raw = gpio_mcux_port_set_masked_raw ,
383475 .port_set_bits_raw = gpio_mcux_port_set_bits_raw ,
@@ -399,6 +491,8 @@ static DEVICE_API(gpio, gpio_mcux_driver_api) = {
399491 } while (false)
400492
401493#define GPIO_PORT_BASE_ADDR (n ) DT_REG_ADDR(DT_INST_PHANDLE(n, nxp_kinetis_port))
494+ #define GPIO_PORT_NUMBER (n ) COND_CODE_1(DT_INST_NODE_HAS_PROP(n, gpio_port_offest), \
495+ (DT_INST_PROP(n, gpio_port_offest) + n), (n)) \
402496
403497#define GPIO_DEVICE_INIT_MCUX (n ) \
404498 static int gpio_mcux_port##n##_init(const struct device *dev); \
@@ -412,6 +506,7 @@ static DEVICE_API(gpio, gpio_mcux_driver_api) = {
412506 .port_base = (PORT_Type *)GPIO_PORT_BASE_ADDR(n), \
413507 .flags = UTIL_AND(UTIL_OR(DT_INST_IRQ_HAS_IDX(n, 0), GPIO_HAS_SHARED_IRQ), \
414508 GPIO_INT_ENABLE), \
509+ .port_no = GPIO_PORT_NUMBER(n), \
415510 }; \
416511 \
417512 static struct gpio_mcux_data gpio_mcux_port##n##_data; \
0 commit comments