2017-08-15 21:05:10 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2017, NXP
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2020-03-24 20:11:52 +01:00
|
|
|
#define DT_DRV_COMPAT nxp_imx_gpio
|
|
|
|
|
2017-08-15 21:05:10 +02:00
|
|
|
#include <errno.h>
|
2022-05-06 10:25:46 +02:00
|
|
|
#include <zephyr/device.h>
|
|
|
|
#include <zephyr/drivers/gpio.h>
|
2022-10-04 15:33:53 +02:00
|
|
|
#include <zephyr/irq.h>
|
2017-08-15 21:05:10 +02:00
|
|
|
#include <soc.h>
|
|
|
|
#include <fsl_common.h>
|
2018-02-26 23:23:40 +01:00
|
|
|
#include <fsl_gpio.h>
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2022-05-06 10:25:46 +02:00
|
|
|
#include <zephyr/drivers/pinctrl.h>
|
2022-03-23 03:16:45 +01:00
|
|
|
|
2022-10-21 20:18:01 +02:00
|
|
|
#include <zephyr/drivers/gpio/gpio_utils.h>
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2022-09-19 23:32:04 +02:00
|
|
|
struct gpio_pin_gaps {
|
|
|
|
uint8_t start;
|
|
|
|
uint8_t len;
|
|
|
|
};
|
|
|
|
|
2017-08-15 21:05:10 +02:00
|
|
|
struct mcux_igpio_config {
|
2019-12-11 17:51:24 +01:00
|
|
|
/* gpio_driver_config needs to be first */
|
|
|
|
struct gpio_driver_config common;
|
2017-08-15 21:05:10 +02:00
|
|
|
GPIO_Type *base;
|
2022-03-23 03:16:45 +01:00
|
|
|
const struct pinctrl_soc_pinmux *pin_muxes;
|
2022-09-19 23:32:04 +02:00
|
|
|
const struct gpio_pin_gaps *pin_gaps;
|
2022-03-23 03:16:45 +01:00
|
|
|
uint8_t mux_count;
|
2022-09-19 23:32:04 +02:00
|
|
|
uint8_t gap_count;
|
2017-08-15 21:05:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct mcux_igpio_data {
|
2019-09-18 00:55:33 +02:00
|
|
|
/* gpio_driver_data needs to be first */
|
|
|
|
struct gpio_driver_data general;
|
2017-08-15 21:05:10 +02:00
|
|
|
/* port ISR callback routine address */
|
|
|
|
sys_slist_t callbacks;
|
|
|
|
};
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_configure(const struct device *dev,
|
2020-01-30 19:12:39 +01:00
|
|
|
gpio_pin_t pin, gpio_flags_t flags)
|
2017-08-15 21:05:10 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2022-03-23 03:16:45 +01:00
|
|
|
struct pinctrl_soc_pin pin_cfg;
|
2022-09-19 23:32:04 +02:00
|
|
|
int cfg_idx = pin, i;
|
2022-04-13 22:50:36 +02:00
|
|
|
|
|
|
|
/* Some SOCs have non-contiguous gpio pin layouts, account for this */
|
2022-09-19 23:32:04 +02:00
|
|
|
for (i = 0; i < config->gap_count; i++) {
|
2022-11-28 17:29:45 +01:00
|
|
|
if (pin >= config->pin_gaps[i].start) {
|
|
|
|
if (pin < (config->pin_gaps[i].start +
|
2022-09-19 23:32:04 +02:00
|
|
|
config->pin_gaps[i].len)) {
|
|
|
|
/* Pin is not connected to a mux */
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
cfg_idx -= config->pin_gaps[i].len;
|
|
|
|
}
|
2022-04-13 22:50:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Init pin configuration struct, and use pinctrl api to apply settings */
|
2022-09-19 23:32:04 +02:00
|
|
|
if (cfg_idx >= config->mux_count) {
|
|
|
|
/* Pin is not connected to a mux */
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
2022-04-13 22:50:36 +02:00
|
|
|
|
2022-03-23 03:16:45 +01:00
|
|
|
/* Set appropriate bits in pin configuration register */
|
|
|
|
volatile uint32_t *gpio_cfg_reg =
|
2022-04-13 22:50:36 +02:00
|
|
|
(volatile uint32_t *)config->pin_muxes[cfg_idx].config_register;
|
2022-03-23 03:16:45 +01:00
|
|
|
uint32_t reg = *gpio_cfg_reg;
|
|
|
|
|
2022-09-14 22:23:15 +02:00
|
|
|
#ifdef CONFIG_SOC_SERIES_IMXRT10XX
|
2022-03-23 03:16:45 +01:00
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
|
|
|
} else {
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
2017-08-15 21:05:10 +02:00
|
|
|
}
|
2022-03-23 03:16:45 +01:00
|
|
|
if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0)) {
|
|
|
|
/* Use 100K pullup */
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS(2);
|
|
|
|
} else {
|
|
|
|
/* 100K pulldown */
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUS_MASK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Set pin to keeper */
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
|
|
|
|
}
|
2022-09-14 22:23:15 +02:00
|
|
|
#elif defined(CONFIG_SOC_SERIES_IMXRT11XX)
|
2022-03-23 03:16:45 +01:00
|
|
|
if (config->pin_muxes[pin].pue_mux) {
|
|
|
|
/* PUE type register layout (GPIO_AD pins) */
|
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
|
|
|
} else {
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0)) {
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS_MASK;
|
|
|
|
} else {
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUS_MASK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Set pin to highz */
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* PDRV/SNVS/LPSR type register layout */
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_PULL_MASK;
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0)) {
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PULL(0x1U);
|
|
|
|
} else {
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PULL(0x2U);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Set pin to no pull */
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_PUS_MASK;
|
|
|
|
}
|
|
|
|
/* PDRV/SNVS/LPSR reg have different ODE bits */
|
2022-04-13 22:50:36 +02:00
|
|
|
if (config->pin_muxes[cfg_idx].pdrv_mux) {
|
2022-03-23 03:16:45 +01:00
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
|
|
|
} else {
|
|
|
|
reg &= ~IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
|
|
|
|
}
|
2022-04-13 22:50:36 +02:00
|
|
|
} else if (config->pin_muxes[cfg_idx].lpsr_mux) {
|
2022-03-23 03:16:45 +01:00
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= (IOMUXC_SW_PAD_CTL_PAD_ODE_MASK << 1);
|
|
|
|
} else {
|
|
|
|
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_ODE_MASK << 1);
|
|
|
|
}
|
2022-04-13 22:50:36 +02:00
|
|
|
} else if (config->pin_muxes[cfg_idx].snvs_mux) {
|
2022-03-23 03:16:45 +01:00
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= (IOMUXC_SW_PAD_CTL_PAD_ODE_MASK << 2);
|
|
|
|
} else {
|
|
|
|
reg &= ~(IOMUXC_SW_PAD_CTL_PAD_ODE_MASK << 2);
|
|
|
|
}
|
|
|
|
}
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2022-03-23 03:16:45 +01:00
|
|
|
|
|
|
|
}
|
2022-09-14 22:23:15 +02:00
|
|
|
#elif defined(CONFIG_SOC_MIMX8MQ6_M4)
|
2022-04-26 00:05:12 +02:00
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= (0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
|
|
|
|
} else {
|
|
|
|
reg &= ~(0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
|
|
|
|
}
|
|
|
|
if ((flags & GPIO_PULL_UP) != 0) {
|
|
|
|
reg |= (0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT);
|
|
|
|
}
|
|
|
|
if ((flag & GPIO_PULL_DOWN) != 0) {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* Default flags, should work for most SOCs */
|
|
|
|
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
|
|
|
/* Set ODE bit */
|
|
|
|
reg |= (0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
|
|
|
|
} else {
|
|
|
|
reg &= ~(0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
|
|
|
|
}
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
|
|
|
|
reg |= (0x1 << MCUX_IMX_BIAS_PULL_ENABLE_SHIFT);
|
|
|
|
if (((flags & GPIO_PULL_UP) != 0)) {
|
|
|
|
reg |= (0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT);
|
|
|
|
} else {
|
|
|
|
reg &= ~(0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Set pin to highz */
|
|
|
|
reg &= ~(0x1 << MCUX_IMX_BIAS_PULL_ENABLE_SHIFT);
|
|
|
|
}
|
2022-09-14 22:23:15 +02:00
|
|
|
#endif /* CONFIG_SOC_SERIES_IMXRT10XX */
|
2022-03-23 03:16:45 +01:00
|
|
|
|
2023-07-20 18:51:05 +02:00
|
|
|
memcpy(&pin_cfg.pinmux, &config->pin_muxes[cfg_idx], sizeof(pin_cfg.pinmux));
|
2022-03-23 03:16:45 +01:00
|
|
|
/* cfg register will be set by pinctrl_configure_pins */
|
|
|
|
pin_cfg.pin_ctrl_flags = reg;
|
|
|
|
pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE);
|
|
|
|
|
|
|
|
if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
2019-09-18 00:55:33 +02:00
|
|
|
|
|
|
|
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
drivers: gpio: Add GPIO support for mimx8ml8_m7 (NXP i.MX8M Plus SoC)
The current MCUX IGPIO driver assumes that the target SoC supports
the DR_SET, DR_CLEAR, and DR_TOGGLE functionality, but some do not
(namely, the M7 core of the i.MX8M Plus SoC). Current releases of
the MCUXpresso SDK IGPIO driver contain utility functions to set,
clear, and toggle pins which include provisions to support SoCs
with and without DR_SET, DR_CLEAR, and DR_TOGGLE, and this change
switches to using these utility functions.
Additionally, this change enables GPIO support on the mimx8ml8_m7
target.
Signed-off-by: Chris Trowbridge <chris.trowbridge@lairdconnect.com>
2022-02-03 14:31:12 +01:00
|
|
|
GPIO_WritePinOutput(base, pin, 1);
|
2019-09-18 00:55:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & GPIO_OUTPUT_INIT_LOW) {
|
drivers: gpio: Add GPIO support for mimx8ml8_m7 (NXP i.MX8M Plus SoC)
The current MCUX IGPIO driver assumes that the target SoC supports
the DR_SET, DR_CLEAR, and DR_TOGGLE functionality, but some do not
(namely, the M7 core of the i.MX8M Plus SoC). Current releases of
the MCUXpresso SDK IGPIO driver contain utility functions to set,
clear, and toggle pins which include provisions to support SoCs
with and without DR_SET, DR_CLEAR, and DR_TOGGLE, and this change
switches to using these utility functions.
Additionally, this change enables GPIO support on the mimx8ml8_m7
target.
Signed-off-by: Chris Trowbridge <chris.trowbridge@lairdconnect.com>
2022-02-03 14:31:12 +01:00
|
|
|
GPIO_WritePinOutput(base, pin, 0);
|
2017-08-15 21:05:10 +02:00
|
|
|
}
|
|
|
|
|
2019-09-18 00:55:33 +02:00
|
|
|
WRITE_BIT(base->GDIR, pin, flags & GPIO_OUTPUT);
|
|
|
|
|
2017-08-15 21:05:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_port_get_raw(const struct device *dev, uint32_t *value)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
|
|
|
|
*value = base->DR;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_port_set_masked_raw(const struct device *dev,
|
|
|
|
uint32_t mask,
|
|
|
|
uint32_t value)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
|
|
|
|
base->DR = (base->DR & ~mask) | (mask & value);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_port_set_bits_raw(const struct device *dev,
|
|
|
|
uint32_t mask)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
|
drivers: gpio: Add GPIO support for mimx8ml8_m7 (NXP i.MX8M Plus SoC)
The current MCUX IGPIO driver assumes that the target SoC supports
the DR_SET, DR_CLEAR, and DR_TOGGLE functionality, but some do not
(namely, the M7 core of the i.MX8M Plus SoC). Current releases of
the MCUXpresso SDK IGPIO driver contain utility functions to set,
clear, and toggle pins which include provisions to support SoCs
with and without DR_SET, DR_CLEAR, and DR_TOGGLE, and this change
switches to using these utility functions.
Additionally, this change enables GPIO support on the mimx8ml8_m7
target.
Signed-off-by: Chris Trowbridge <chris.trowbridge@lairdconnect.com>
2022-02-03 14:31:12 +01:00
|
|
|
GPIO_PortSet(base, mask);
|
2019-09-18 00:55:33 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_port_clear_bits_raw(const struct device *dev,
|
|
|
|
uint32_t mask)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
|
drivers: gpio: Add GPIO support for mimx8ml8_m7 (NXP i.MX8M Plus SoC)
The current MCUX IGPIO driver assumes that the target SoC supports
the DR_SET, DR_CLEAR, and DR_TOGGLE functionality, but some do not
(namely, the M7 core of the i.MX8M Plus SoC). Current releases of
the MCUXpresso SDK IGPIO driver contain utility functions to set,
clear, and toggle pins which include provisions to support SoCs
with and without DR_SET, DR_CLEAR, and DR_TOGGLE, and this change
switches to using these utility functions.
Additionally, this change enables GPIO support on the mimx8ml8_m7
target.
Signed-off-by: Chris Trowbridge <chris.trowbridge@lairdconnect.com>
2022-02-03 14:31:12 +01:00
|
|
|
GPIO_PortClear(base, mask);
|
2019-09-18 00:55:33 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_port_toggle_bits(const struct device *dev,
|
|
|
|
uint32_t mask)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
|
drivers: gpio: Add GPIO support for mimx8ml8_m7 (NXP i.MX8M Plus SoC)
The current MCUX IGPIO driver assumes that the target SoC supports
the DR_SET, DR_CLEAR, and DR_TOGGLE functionality, but some do not
(namely, the M7 core of the i.MX8M Plus SoC). Current releases of
the MCUXpresso SDK IGPIO driver contain utility functions to set,
clear, and toggle pins which include provisions to support SoCs
with and without DR_SET, DR_CLEAR, and DR_TOGGLE, and this change
switches to using these utility functions.
Additionally, this change enables GPIO support on the mimx8ml8_m7
target.
Signed-off-by: Chris Trowbridge <chris.trowbridge@lairdconnect.com>
2022-02-03 14:31:12 +01:00
|
|
|
GPIO_PortToggle(base, mask);
|
2019-09-18 00:55:33 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_pin_interrupt_configure(const struct device *dev,
|
|
|
|
gpio_pin_t pin,
|
|
|
|
enum gpio_int_mode mode,
|
|
|
|
enum gpio_int_trig trig)
|
2019-09-18 00:55:33 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
|
|
|
unsigned int key;
|
2020-05-27 18:26:57 +02:00
|
|
|
uint8_t icr;
|
2019-09-18 00:55:33 +02:00
|
|
|
int shift;
|
|
|
|
|
2020-03-18 15:23:34 +01:00
|
|
|
if (mode == GPIO_INT_MODE_DISABLED) {
|
|
|
|
key = irq_lock();
|
|
|
|
|
|
|
|
WRITE_BIT(base->IMR, pin, 0);
|
|
|
|
|
|
|
|
irq_unlock(key);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-18 00:55:33 +02:00
|
|
|
if ((mode == GPIO_INT_MODE_EDGE) && (trig == GPIO_INT_TRIG_LOW)) {
|
|
|
|
icr = 3;
|
|
|
|
} else if ((mode == GPIO_INT_MODE_EDGE) &&
|
|
|
|
(trig == GPIO_INT_TRIG_HIGH)) {
|
|
|
|
icr = 2;
|
|
|
|
} else if ((mode == GPIO_INT_MODE_LEVEL) &&
|
|
|
|
(trig == GPIO_INT_TRIG_HIGH)) {
|
|
|
|
icr = 1;
|
|
|
|
} else {
|
|
|
|
icr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pin < 16) {
|
|
|
|
shift = 2 * pin;
|
|
|
|
base->ICR1 = (base->ICR1 & ~(3 << shift)) | (icr << shift);
|
|
|
|
} else if (pin < 32) {
|
|
|
|
shift = 2 * (pin - 16);
|
|
|
|
base->ICR2 = (base->ICR2 & ~(3 << shift)) | (icr << shift);
|
|
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
key = irq_lock();
|
|
|
|
|
|
|
|
WRITE_BIT(base->EDGE_SEL, pin, trig == GPIO_INT_TRIG_BOTH);
|
2020-03-18 15:23:34 +01:00
|
|
|
WRITE_BIT(base->ISR, pin, 1);
|
|
|
|
WRITE_BIT(base->IMR, pin, 1);
|
2019-09-18 00:55:33 +02:00
|
|
|
|
|
|
|
irq_unlock(key);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-30 20:33:38 +02:00
|
|
|
static int mcux_igpio_manage_callback(const struct device *dev,
|
|
|
|
struct gpio_callback *callback,
|
|
|
|
bool set)
|
2017-08-15 21:05:10 +02:00
|
|
|
{
|
2020-05-28 21:23:02 +02:00
|
|
|
struct mcux_igpio_data *data = dev->data;
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2019-03-12 22:15:42 +01:00
|
|
|
return gpio_manage_callback(&data->callbacks, callback, set);
|
2017-08-15 21:05:10 +02:00
|
|
|
}
|
|
|
|
|
isr: Normalize usage of device instance through ISR
The goal of this patch is to replace the 'void *' parameter by 'struct
device *' if they use such variable or just 'const void *' on all
relevant ISRs
This will avoid not-so-nice const qualifier tweaks when device instances
will be constant.
Note that only the ISR passed to IRQ_CONNECT are of interest here.
In order to do so, the script fix_isr.py below is necessary:
from pathlib import Path
import subprocess
import pickle
import mmap
import sys
import re
import os
cocci_template = """
@r_fix_isr_0
@
type ret_type;
identifier P;
identifier D;
@@
-ret_type <!fn!>(void *P)
+ret_type <!fn!>(const struct device *P)
{
...
(
const struct device *D = (const struct device *)P;
|
const struct device *D = P;
)
...
}
@r_fix_isr_1
@
type ret_type;
identifier P;
identifier D;
@@
-ret_type <!fn!>(void *P)
+ret_type <!fn!>(const struct device *P)
{
...
const struct device *D;
...
(
D = (const struct device *)P;
|
D = P;
)
...
}
@r_fix_isr_2
@
type ret_type;
identifier A;
@@
-ret_type <!fn!>(void *A)
+ret_type <!fn!>(const void *A)
{
...
}
@r_fix_isr_3
@
const struct device *D;
@@
-<!fn!>((void *)D);
+<!fn!>(D);
@r_fix_isr_4
@
type ret_type;
identifier D;
identifier P;
@@
-ret_type <!fn!>(const struct device *P)
+ret_type <!fn!>(const struct device *D)
{
...
(
-const struct device *D = (const struct device *)P;
|
-const struct device *D = P;
)
...
}
@r_fix_isr_5
@
type ret_type;
identifier D;
identifier P;
@@
-ret_type <!fn!>(const struct device *P)
+ret_type <!fn!>(const struct device *D)
{
...
-const struct device *D;
...
(
-D = (const struct device *)P;
|
-D = P;
)
...
}
"""
def find_isr(fn):
db = []
data = None
start = 0
try:
with open(fn, 'r+') as f:
data = str(mmap.mmap(f.fileno(), 0).read())
except Exception as e:
return db
while True:
isr = ""
irq = data.find('IRQ_CONNECT', start)
while irq > -1:
p = 1
arg = 1
p_o = data.find('(', irq)
if p_o < 0:
irq = -1
break;
pos = p_o + 1
while p > 0:
if data[pos] == ')':
p -= 1
elif data[pos] == '(':
p += 1
elif data[pos] == ',' and p == 1:
arg += 1
if arg == 3:
isr += data[pos]
pos += 1
isr = isr.strip(',\\n\\t ')
if isr not in db and len(isr) > 0:
db.append(isr)
start = pos
break
if irq < 0:
break
return db
def patch_isr(fn, isr_list):
if len(isr_list) <= 0:
return
for isr in isr_list:
tmplt = cocci_template.replace('<!fn!>', isr)
with open('/tmp/isr_fix.cocci', 'w') as f:
f.write(tmplt)
cmd = ['spatch', '--sp-file', '/tmp/isr_fix.cocci', '--in-place', fn]
subprocess.run(cmd)
def process_files(path):
if path.is_file() and path.suffix in ['.h', '.c']:
p = str(path.parent) + '/' + path.name
isr_list = find_isr(p)
patch_isr(p, isr_list)
elif path.is_dir():
for p in path.iterdir():
process_files(p)
if len(sys.argv) < 2:
print("You need to provide a dir/file path")
sys.exit(1)
process_files(Path(sys.argv[1]))
And is run: ./fix_isr.py <zephyr root directory>
Finally, some files needed manual fixes such.
Fixes #27399
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
2020-06-17 14:58:56 +02:00
|
|
|
static void mcux_igpio_port_isr(const struct device *dev)
|
2017-08-15 21:05:10 +02:00
|
|
|
{
|
2020-05-28 20:44:16 +02:00
|
|
|
const struct mcux_igpio_config *config = dev->config;
|
2020-05-28 21:23:02 +02:00
|
|
|
struct mcux_igpio_data *data = dev->data;
|
2019-09-18 00:55:33 +02:00
|
|
|
GPIO_Type *base = config->base;
|
2020-06-13 02:07:29 +02:00
|
|
|
uint32_t int_flags;
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2019-09-18 00:55:33 +02:00
|
|
|
int_flags = base->ISR;
|
2020-06-13 02:07:29 +02:00
|
|
|
base->ISR = int_flags;
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2020-06-13 02:07:29 +02:00
|
|
|
gpio_fire_callbacks(&data->callbacks, dev, int_flags);
|
2017-08-15 21:05:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct gpio_driver_api mcux_igpio_driver_api = {
|
2020-01-30 19:12:39 +01:00
|
|
|
.pin_configure = mcux_igpio_configure,
|
2019-09-18 00:55:33 +02:00
|
|
|
.port_get_raw = mcux_igpio_port_get_raw,
|
|
|
|
.port_set_masked_raw = mcux_igpio_port_set_masked_raw,
|
|
|
|
.port_set_bits_raw = mcux_igpio_port_set_bits_raw,
|
|
|
|
.port_clear_bits_raw = mcux_igpio_port_clear_bits_raw,
|
|
|
|
.port_toggle_bits = mcux_igpio_port_toggle_bits,
|
|
|
|
.pin_interrupt_configure = mcux_igpio_pin_interrupt_configure,
|
2017-08-15 21:05:10 +02:00
|
|
|
.manage_callback = mcux_igpio_manage_callback,
|
|
|
|
};
|
|
|
|
|
2022-03-23 03:16:45 +01:00
|
|
|
|
|
|
|
/* These macros will declare an array of pinctrl_soc_pinmux types */
|
2022-04-25 23:30:58 +02:00
|
|
|
#define PINMUX_INIT(node, prop, idx) MCUX_IMX_PINMUX(DT_PROP_BY_IDX(node, prop, idx)),
|
2022-03-23 03:16:45 +01:00
|
|
|
#define MCUX_IGPIO_PIN_DECLARE(n) \
|
|
|
|
const struct pinctrl_soc_pinmux mcux_igpio_pinmux_##n[] = { \
|
|
|
|
DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), pinmux, PINMUX_INIT) \
|
2022-09-19 23:32:04 +02:00
|
|
|
}; \
|
|
|
|
const uint8_t mcux_igpio_pin_gaps_##n[] = \
|
|
|
|
DT_INST_PROP_OR(n, gpio_reserved_ranges, {});
|
2022-03-23 03:16:45 +01:00
|
|
|
#define MCUX_IGPIO_PIN_INIT(n) \
|
|
|
|
.pin_muxes = mcux_igpio_pinmux_##n, \
|
2022-09-19 23:32:04 +02:00
|
|
|
.pin_gaps = (const struct gpio_pin_gaps *)mcux_igpio_pin_gaps_##n, \
|
|
|
|
.mux_count = DT_PROP_LEN(DT_DRV_INST(n), pinmux), \
|
|
|
|
.gap_count = (ARRAY_SIZE(mcux_igpio_pin_gaps_##n) / 2)
|
2022-03-23 03:16:45 +01:00
|
|
|
|
2020-04-14 17:38:37 +02:00
|
|
|
#define MCUX_IGPIO_IRQ_INIT(n, i) \
|
|
|
|
do { \
|
|
|
|
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, i, irq), \
|
|
|
|
DT_INST_IRQ_BY_IDX(n, i, priority), \
|
|
|
|
mcux_igpio_port_isr, \
|
2020-12-10 17:20:42 +01:00
|
|
|
DEVICE_DT_INST_GET(n), 0); \
|
2020-04-14 17:38:37 +02:00
|
|
|
\
|
|
|
|
irq_enable(DT_INST_IRQ_BY_IDX(n, i, irq)); \
|
2022-07-20 08:37:40 +02:00
|
|
|
} while (false)
|
2020-04-14 17:38:37 +02:00
|
|
|
|
|
|
|
#define MCUX_IGPIO_INIT(n) \
|
2022-03-23 03:16:45 +01:00
|
|
|
MCUX_IGPIO_PIN_DECLARE(n) \
|
2020-07-14 17:02:00 +02:00
|
|
|
static int mcux_igpio_##n##_init(const struct device *dev); \
|
2020-04-14 17:38:37 +02:00
|
|
|
\
|
|
|
|
static const struct mcux_igpio_config mcux_igpio_##n##_config = {\
|
|
|
|
.common = { \
|
|
|
|
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),\
|
|
|
|
}, \
|
|
|
|
.base = (GPIO_Type *)DT_INST_REG_ADDR(n), \
|
2022-03-23 03:16:45 +01:00
|
|
|
MCUX_IGPIO_PIN_INIT(n) \
|
2020-04-14 17:38:37 +02:00
|
|
|
}; \
|
|
|
|
\
|
|
|
|
static struct mcux_igpio_data mcux_igpio_##n##_data; \
|
|
|
|
\
|
2020-12-10 17:20:42 +01:00
|
|
|
DEVICE_DT_INST_DEFINE(n, \
|
2020-04-14 17:38:37 +02:00
|
|
|
mcux_igpio_##n##_init, \
|
2021-04-28 10:55:48 +02:00
|
|
|
NULL, \
|
2020-04-14 17:38:37 +02:00
|
|
|
&mcux_igpio_##n##_data, \
|
|
|
|
&mcux_igpio_##n##_config, \
|
|
|
|
POST_KERNEL, \
|
2021-11-05 22:58:21 +01:00
|
|
|
CONFIG_GPIO_INIT_PRIORITY, \
|
2020-04-14 17:38:37 +02:00
|
|
|
&mcux_igpio_driver_api); \
|
|
|
|
\
|
2020-07-14 17:02:00 +02:00
|
|
|
static int mcux_igpio_##n##_init(const struct device *dev) \
|
2020-04-14 17:38:37 +02:00
|
|
|
{ \
|
2021-06-25 23:54:06 +02:00
|
|
|
IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), \
|
|
|
|
(MCUX_IGPIO_IRQ_INIT(n, 0);)) \
|
2020-04-14 17:38:37 +02:00
|
|
|
\
|
|
|
|
IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 1), \
|
|
|
|
(MCUX_IGPIO_IRQ_INIT(n, 1);)) \
|
|
|
|
\
|
|
|
|
return 0; \
|
|
|
|
}
|
2017-08-15 21:05:10 +02:00
|
|
|
|
2020-05-06 20:23:07 +02:00
|
|
|
DT_INST_FOREACH_STATUS_OKAY(MCUX_IGPIO_INIT)
|