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 <lucien.zhao@nxp.com>
This commit is contained in:
parent
7f64d8f214
commit
87e4db9b86
2 changed files with 118 additions and 17 deletions
|
@ -17,12 +17,22 @@
|
|||
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
|
||||
#if defined(CONFIG_PINCTRL_NXP_IOCON)
|
||||
#include <fsl_iopctl.h>
|
||||
#include <fsl_reset.h>
|
||||
#include <fsl_clock.h>
|
||||
#include <fsl_gpio.h>
|
||||
/* Use IOCON to configure electrical characteristic, set PORT_Type as void. */
|
||||
#define PORT_Type void
|
||||
#endif
|
||||
|
||||
struct gpio_mcux_config {
|
||||
/* gpio_driver_config needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
GPIO_Type *gpio_base;
|
||||
PORT_Type *port_base;
|
||||
unsigned int flags;
|
||||
uint32_t port_no;
|
||||
};
|
||||
|
||||
struct gpio_mcux_data {
|
||||
|
@ -32,7 +42,80 @@ struct gpio_mcux_data {
|
|||
sys_slist_t callbacks;
|
||||
};
|
||||
|
||||
static int gpio_mcux_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
|
||||
#if defined(CONFIG_PINCTRL_NXP_IOCON)
|
||||
static int gpio_mcux_iopctl_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
const struct gpio_mcux_config *config = dev->config;
|
||||
GPIO_Type *gpio_base = config->gpio_base;
|
||||
uint32_t port_no = config->port_no;
|
||||
volatile uint32_t pinconfig = 0;
|
||||
|
||||
if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* The flags contain options that require touching registers in the
|
||||
* GPIO module and the corresponding PORT module.
|
||||
*
|
||||
* Start with the GPIO module and set up the pin direction register.
|
||||
* 0 - pin is input, 1 - pin is output
|
||||
*/
|
||||
|
||||
switch (flags & GPIO_DIR_MASK) {
|
||||
case GPIO_INPUT:
|
||||
gpio_base->PDDR &= ~BIT(pin);
|
||||
/* Enable input buffer for input pins */
|
||||
pinconfig |= IOPCTL_INBUF_EN;
|
||||
break;
|
||||
case GPIO_OUTPUT:
|
||||
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
|
||||
gpio_base->PSOR = BIT(pin);
|
||||
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
|
||||
gpio_base->PCOR = BIT(pin);
|
||||
}
|
||||
gpio_base->PDDR |= BIT(pin);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Select GPIO mux for this pin (func 0 is always GPIO) */
|
||||
pinconfig |= IOPCTL_FUNC0;
|
||||
|
||||
if ((flags & GPIO_PULL_UP) != 0) {
|
||||
/* Enable and select pull up. */
|
||||
pinconfig |= (IOPCTL_PUPD_EN | IOPCTL_PULLUP_EN);
|
||||
} else if ((flags & GPIO_PULL_DOWN) != 0) {
|
||||
/* Enable and select pull down. */
|
||||
pinconfig |= (IOPCTL_PUPD_EN | IOPCTL_PULLDOWN_EN);
|
||||
}
|
||||
|
||||
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
|
||||
/* Determine the drive strength */
|
||||
switch (flags & KINETIS_GPIO_DS_MASK) {
|
||||
case KINETIS_GPIO_DS_DFLT:
|
||||
/* Default is low drive strength */
|
||||
pinconfig |= IOPCTL_DRIVE_100OHM;
|
||||
break;
|
||||
case KINETIS_GPIO_DS_ALT:
|
||||
/* Alternate is high drive strength */
|
||||
pinconfig |= IOPCTL_DRIVE_33OHM;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif /* defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
|
||||
|
||||
IOPCTL_PinMuxSet(port_no, pin, pinconfig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int gpio_mcux_port_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
const struct gpio_mcux_config *config = dev->config;
|
||||
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
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(CONFIG_PINCTRL_NXP_IOCON) */
|
||||
|
||||
static int gpio_mcux_port_get_raw(const struct device *dev, uint32_t *value)
|
||||
{
|
||||
|
@ -173,6 +257,7 @@ static int gpio_mcux_port_toggle_bits(const struct device *dev, uint32_t mask)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if !(defined(CONFIG_PINCTRL_NXP_IOCON))
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev, uint32_t pin,
|
||||
enum gpio_int_mode mode, enum gpio_int_trig trig)
|
||||
|
@ -208,6 +293,7 @@ static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev, uin
|
|||
return PORT_PCR_IRQC(port_interrupt);
|
||||
}
|
||||
#endif /* !defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
|
||||
#endif /* !(defined(CONFIG_PINCTRL_NXP_IOCON)) */
|
||||
|
||||
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
|
@ -259,12 +345,14 @@ static int gpio_mcux_pin_interrupt_configure(const struct device *dev, gpio_pin_
|
|||
{
|
||||
const struct gpio_mcux_config *config = dev->config;
|
||||
GPIO_Type *gpio_base = config->gpio_base;
|
||||
#if !(defined(CONFIG_PINCTRL_NXP_IOCON))
|
||||
PORT_Type *port_base = config->port_base;
|
||||
|
||||
/* Check for an invalid pin number */
|
||||
if (pin >= ARRAY_SIZE(port_base->PCR)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for an invalid pin configuration */
|
||||
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_
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
uint32_t pcr = get_port_pcr_irqc_value_from_flags(dev, pin, mode, trig);
|
||||
|
||||
port_base->PCR[pin] = (port_base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | pcr;
|
||||
#elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
uint32_t icr = get_gpio_icr_irqc_value_from_flags(dev, pin, mode, trig);
|
||||
|
||||
gpio_base->ICR[pin] = (gpio_base->ICR[pin] & ~GPIO_ICR_IRQC_MASK) | icr;
|
||||
#elif !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
uint32_t pcr = get_port_pcr_irqc_value_from_flags(dev, pin, mode, trig);
|
||||
|
||||
port_base->PCR[pin] = (port_base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | pcr;
|
||||
#endif /* !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) */
|
||||
|
||||
return 0;
|
||||
|
@ -304,17 +392,17 @@ static void gpio_mcux_port_isr(const struct device *dev)
|
|||
struct gpio_mcux_data *data = dev->data;
|
||||
uint32_t int_status;
|
||||
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
int_status = config->port_base->ISFR;
|
||||
|
||||
/* Clear the port interrupts */
|
||||
config->port_base->ISFR = int_status;
|
||||
#elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
int_status = config->gpio_base->ISFR[0];
|
||||
|
||||
/* Clear the gpio interrupts */
|
||||
config->gpio_base->ISFR[0] = int_status;
|
||||
#elif !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
int_status = config->port_base->ISFR;
|
||||
|
||||
/* Clear the port interrupts */
|
||||
config->port_base->ISFR = int_status;
|
||||
#else
|
||||
int_status = 0U;
|
||||
ARG_UNUSED(config);
|
||||
|
@ -377,7 +465,11 @@ static int gpio_mcux_port_get_direction(const struct device *dev, gpio_port_pins
|
|||
#endif /* CONFIG_GPIO_GET_DIRECTION */
|
||||
|
||||
static DEVICE_API(gpio, gpio_mcux_driver_api) = {
|
||||
.pin_configure = gpio_mcux_configure,
|
||||
#if defined(CONFIG_PINCTRL_NXP_IOCON)
|
||||
.pin_configure = gpio_mcux_iopctl_configure,
|
||||
#else
|
||||
.pin_configure = gpio_mcux_port_configure,
|
||||
#endif
|
||||
.port_get_raw = gpio_mcux_port_get_raw,
|
||||
.port_set_masked_raw = gpio_mcux_port_set_masked_raw,
|
||||
.port_set_bits_raw = gpio_mcux_port_set_bits_raw,
|
||||
|
@ -399,6 +491,8 @@ static DEVICE_API(gpio, gpio_mcux_driver_api) = {
|
|||
} while (false)
|
||||
|
||||
#define GPIO_PORT_BASE_ADDR(n) DT_REG_ADDR(DT_INST_PHANDLE(n, nxp_kinetis_port))
|
||||
#define GPIO_PORT_NUMBER(n) COND_CODE_1(DT_INST_NODE_HAS_PROP(n, gpio_port_offest), \
|
||||
(DT_INST_PROP(n, gpio_port_offest) + n), (n)) \
|
||||
|
||||
#define GPIO_DEVICE_INIT_MCUX(n) \
|
||||
static int gpio_mcux_port##n##_init(const struct device *dev); \
|
||||
|
@ -412,6 +506,7 @@ static DEVICE_API(gpio, gpio_mcux_driver_api) = {
|
|||
.port_base = (PORT_Type *)GPIO_PORT_BASE_ADDR(n), \
|
||||
.flags = UTIL_AND(UTIL_OR(DT_INST_IRQ_HAS_IDX(n, 0), GPIO_HAS_SHARED_IRQ), \
|
||||
GPIO_INT_ENABLE), \
|
||||
.port_no = GPIO_PORT_NUMBER(n), \
|
||||
}; \
|
||||
\
|
||||
static struct gpio_mcux_data gpio_mcux_port##n##_data; \
|
||||
|
|
|
@ -18,6 +18,12 @@ properties:
|
|||
A phandle reference to the device tree node that contains the pinmux
|
||||
port associated with this GPIO controller.
|
||||
|
||||
gpio-port-offest:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Describes an offset between inst index and actual GPIO port number.
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue