Skip to content

Commit 8a5930f

Browse files
committed
drivers: gpio: update gpio_mcux.c driver
update gpio driver to adapt rt7xx gpio model: 1. There is no PORT_Type on RT7xx,so set PORT_Type as void 2. Add port_no parameter in gpio_mcux_config to adapt IOPCTL driver 3. Add gpio-port-offest parameter in blinding, it will help map the relation between index n and gpio port when some soc have domain access attribution. 3. Splite gpio_mcux_configure function into two functions( gpio_mcux_iopctl_configure and gpio_mcux_port_configure) according to CONFIG_PINCTRL_NXP_IOCON macro 4. Add code to adapt RT700 GPIO attribute configuration Signed-off-by: Lucien Zhao <[email protected]>
1 parent 14f140e commit 8a5930f

File tree

2 files changed

+118
-17
lines changed

2 files changed

+118
-17
lines changed

drivers/gpio/gpio_mcux.c

Lines changed: 112 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,22 @@
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+
2029
struct 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

2838
struct 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

126210
static 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)
177262
static 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

379467
static 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; \

dts/bindings/gpio/nxp,kinetis-gpio.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ properties:
1818
A phandle reference to the device tree node that contains the pinmux
1919
port associated with this GPIO controller.
2020
21+
gpio-port-offest:
22+
type: int
23+
default: 0
24+
description: |
25+
Describes an offset between inst index and actual GPIO port number.
26+
2127
gpio-cells:
2228
- pin
2329
- flags

0 commit comments

Comments
 (0)