drivers: gpio: gpio_mcux_lpc: remove PINT code
Remove PINT management code from the LPC GPIO driver, as this code is now contained within the PINT interrupt controller driver, which exposes an interface to install interrupt callbacks. Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
parent
6f938f347b
commit
b8a99a27cc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2020, NXP
|
||||
* Copyright 2017-2020,2023 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -21,30 +21,14 @@
|
|||
#include <soc.h>
|
||||
#include <fsl_common.h>
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
#include <zephyr/drivers/interrupt_controller/nxp_pint.h>
|
||||
#include <fsl_gpio.h>
|
||||
#include <fsl_pint.h>
|
||||
#include <fsl_inputmux.h>
|
||||
#include <fsl_device_registers.h>
|
||||
|
||||
#define PIN_TO_INPUT_MUX_CONNECTION(port, pin) \
|
||||
((PINTSEL_PMUX_ID << PMUX_SHIFT) + (32 * port) + (pin))
|
||||
|
||||
#ifndef FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS
|
||||
#define FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS 0
|
||||
#endif
|
||||
#ifndef FSL_FEATURE_SECPINT_NUMBER_OF_CONNECTED_OUTPUTS
|
||||
#define FSL_FEATURE_SECPINT_NUMBER_OF_CONNECTED_OUTPUTS 0
|
||||
#endif
|
||||
|
||||
#define NO_PINT_INT \
|
||||
MAX(FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS, \
|
||||
FSL_FEATURE_SECPINT_NUMBER_OF_CONNECTED_OUTPUTS)
|
||||
|
||||
struct gpio_mcux_lpc_config {
|
||||
/* gpio_driver_config needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
GPIO_Type *gpio_base;
|
||||
PINT_Type *pint_base;
|
||||
#ifdef IOPCTL
|
||||
IOPCTL_Type *pinmux_base;
|
||||
#else
|
||||
|
@ -59,12 +43,6 @@ struct gpio_mcux_lpc_data {
|
|||
struct gpio_driver_data common;
|
||||
/* port ISR callback routine address */
|
||||
sys_slist_t callbacks;
|
||||
/* pin association with PINT id */
|
||||
pint_pin_int_t pint_id[32];
|
||||
/* ISR allocated in device tree to this port */
|
||||
uint32_t isr_list[INPUTMUX_PINTSEL_COUNT];
|
||||
/* index to to table above */
|
||||
uint32_t isr_list_idx;
|
||||
};
|
||||
|
||||
static int gpio_mcux_lpc_configure(const struct device *dev, gpio_pin_t pin,
|
||||
|
@ -211,83 +189,23 @@ static int gpio_mcux_lpc_port_toggle_bits(const struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_mcux_lpc_port_isr(const struct device *dev)
|
||||
|
||||
/* Called by PINT when pin interrupt fires */
|
||||
static void gpio_mcux_lpc_pint_cb(uint8_t pin, void *user)
|
||||
{
|
||||
const struct device *dev = user;
|
||||
const struct gpio_mcux_lpc_config *config = dev->config;
|
||||
struct gpio_mcux_lpc_data *data = dev->data;
|
||||
uint32_t enabled_int;
|
||||
uint32_t int_flags;
|
||||
uint32_t pin;
|
||||
uint32_t gpio_pin;
|
||||
|
||||
for (pin = 0; pin < 32; pin++) {
|
||||
if (data->pint_id[pin] != NO_PINT_INT) {
|
||||
int_flags = PINT_PinInterruptGetStatus(
|
||||
config->pint_base, data->pint_id[pin]);
|
||||
enabled_int = int_flags << pin;
|
||||
|
||||
if (int_flags) {
|
||||
PINT_PinInterruptClrStatus(config->pint_base,
|
||||
data->pint_id[pin]);
|
||||
}
|
||||
|
||||
gpio_fire_callbacks(&data->callbacks, dev, enabled_int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_free_isr(struct gpio_mcux_lpc_data *data)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t isr;
|
||||
|
||||
for (i = 0; i < data->isr_list_idx; i++) {
|
||||
if (data->isr_list[i] != -1) {
|
||||
isr = data->isr_list[i];
|
||||
data->isr_list[i] = -1;
|
||||
return isr;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Function configures INPUTMUX device to route pin interrupts to a certain
|
||||
* PINT. PINT no. is unknown, rather it's determined from ISR no.
|
||||
*/
|
||||
static uint32_t attach_pin_to_isr(uint32_t port, uint32_t pin, uint32_t isr_no)
|
||||
{
|
||||
uint32_t pint_idx;
|
||||
/* Connect trigger sources to PINT */
|
||||
INPUTMUX_Init(INPUTMUX);
|
||||
|
||||
/* Code asumes PIN_INT values are grouped [0..3] and [4..7].
|
||||
* This scenario is true in LPC54xxx/LPC55xxx.
|
||||
/* Subtract port number times 32 from pin number to get GPIO API
|
||||
* pin number.
|
||||
*/
|
||||
#if (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 8)
|
||||
#error having more than 8 PINT IRQs not supported in driver
|
||||
#elif (FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS > 4)
|
||||
if (isr_no < PIN_INT4_IRQn) {
|
||||
pint_idx = isr_no - PIN_INT0_IRQn;
|
||||
} else {
|
||||
pint_idx = isr_no - PIN_INT4_IRQn + 4;
|
||||
}
|
||||
#else
|
||||
pint_idx = isr_no - PIN_INT0_IRQn;
|
||||
#endif
|
||||
gpio_pin = pin - (config->port_no * 32);
|
||||
|
||||
INPUTMUX_AttachSignal(INPUTMUX, pint_idx,
|
||||
PIN_TO_INPUT_MUX_CONNECTION(port, pin));
|
||||
|
||||
/* Turnoff clock to inputmux to save power. Clock is only needed to make
|
||||
* changes. Can be turned off after.
|
||||
*/
|
||||
INPUTMUX_Deinit(INPUTMUX);
|
||||
|
||||
return pint_idx;
|
||||
gpio_fire_callbacks(&data->callbacks, dev, BIT(gpio_pin));
|
||||
}
|
||||
|
||||
static void gpio_mcux_lpc_port_isr(const struct device *dev);
|
||||
|
||||
|
||||
static int gpio_mcux_lpc_pin_interrupt_configure(const struct device *dev,
|
||||
gpio_pin_t pin,
|
||||
|
@ -295,13 +213,10 @@ static int gpio_mcux_lpc_pin_interrupt_configure(const struct device *dev,
|
|||
enum gpio_int_trig trig)
|
||||
{
|
||||
const struct gpio_mcux_lpc_config *config = dev->config;
|
||||
struct gpio_mcux_lpc_data *data = dev->data;
|
||||
pint_pin_enable_t interruptMode = kPINT_PinIntEnableNone;
|
||||
enum nxp_pint_trigger interrupt_mode = NXP_PINT_NONE;
|
||||
GPIO_Type *gpio_base = config->gpio_base;
|
||||
uint32_t port = config->port_no;
|
||||
uint32_t isr;
|
||||
uint32_t pint_idx;
|
||||
static bool pint_inited;
|
||||
int ret;
|
||||
|
||||
/* Ensure pin used as interrupt is set as input*/
|
||||
if ((mode & GPIO_INT_ENABLE) &&
|
||||
|
@ -311,50 +226,39 @@ static int gpio_mcux_lpc_pin_interrupt_configure(const struct device *dev,
|
|||
|
||||
switch (mode) {
|
||||
case GPIO_INT_MODE_DISABLED:
|
||||
interruptMode = kPINT_PinIntEnableNone;
|
||||
break;
|
||||
nxp_pint_pin_disable((config->port_no * 32) + pin);
|
||||
return 0;
|
||||
case GPIO_INT_MODE_LEVEL:
|
||||
if (trig == GPIO_INT_TRIG_HIGH) {
|
||||
interruptMode = kPINT_PinIntEnableHighLevel;
|
||||
interrupt_mode = NXP_PINT_HIGH;
|
||||
} else if (trig == GPIO_INT_TRIG_LOW) {
|
||||
interruptMode = kPINT_PinIntEnableLowLevel;
|
||||
interrupt_mode = NXP_PINT_LOW;
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
case GPIO_INT_MODE_EDGE:
|
||||
if (trig == GPIO_INT_TRIG_HIGH) {
|
||||
interruptMode = kPINT_PinIntEnableRiseEdge;
|
||||
interrupt_mode = NXP_PINT_RISING;
|
||||
} else if (trig == GPIO_INT_TRIG_LOW) {
|
||||
interruptMode = kPINT_PinIntEnableFallEdge;
|
||||
interrupt_mode = NXP_PINT_FALLING;
|
||||
} else {
|
||||
interruptMode = kPINT_PinIntEnableBothEdges;
|
||||
interrupt_mode = NXP_PINT_BOTH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* First time calling this function routes PIN->PINT->INPUTMUX->NVIC */
|
||||
if (data->pint_id[pin] == NO_PINT_INT) {
|
||||
isr = get_free_isr(data);
|
||||
if (isr == -EINVAL) {
|
||||
/* Didn't find any free interrupt in this port */
|
||||
return -EBUSY;
|
||||
}
|
||||
pint_idx = attach_pin_to_isr(port, pin, isr);
|
||||
data->pint_id[pin] = pint_idx;
|
||||
/* PINT treats GPIO pins as continuous. Each port has 32 pins */
|
||||
ret = nxp_pint_pin_enable((config->port_no * 32) + pin, interrupt_mode);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!pint_inited) {
|
||||
PINT_Init(config->pint_base);
|
||||
pint_inited = true;
|
||||
}
|
||||
PINT_PinInterruptConfig(config->pint_base, data->pint_id[pin],
|
||||
interruptMode,
|
||||
(pint_cb_t)gpio_mcux_lpc_port_isr);
|
||||
|
||||
return 0;
|
||||
/* Install callback */
|
||||
return nxp_pint_pin_set_callback((config->port_no * 32) + pin,
|
||||
gpio_mcux_lpc_pint_cb,
|
||||
(struct device *)dev);
|
||||
}
|
||||
|
||||
static int gpio_mcux_lpc_manage_cb(const struct device *port,
|
||||
|
@ -368,17 +272,9 @@ static int gpio_mcux_lpc_manage_cb(const struct device *port,
|
|||
static int gpio_mcux_lpc_init(const struct device *dev)
|
||||
{
|
||||
const struct gpio_mcux_lpc_config *config = dev->config;
|
||||
struct gpio_mcux_lpc_data *data = dev->data;
|
||||
int i;
|
||||
|
||||
GPIO_PortInit(config->gpio_base, config->port_no);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
data->pint_id[i] = NO_PINT_INT;
|
||||
}
|
||||
|
||||
data->isr_list_idx = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -401,20 +297,6 @@ static const clock_ip_name_t gpio_clock_names[] = GPIO_CLOCKS;
|
|||
#define PINMUX_BASE IOCON
|
||||
#endif
|
||||
|
||||
#define GPIO_MCUX_LPC_IRQ_CONNECT(n, m) \
|
||||
do { \
|
||||
struct gpio_mcux_lpc_data *data = dev->data; \
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, m, irq), \
|
||||
DT_INST_IRQ_BY_IDX(n, m, priority), \
|
||||
gpio_mcux_lpc_port_isr, DEVICE_DT_INST_GET(n), 0); \
|
||||
irq_enable(DT_INST_IRQ_BY_IDX(n, m, irq)); \
|
||||
data->isr_list[data->isr_list_idx++] = DT_INST_IRQ_BY_IDX(n, m, irq); \
|
||||
} while (false)
|
||||
|
||||
#define GPIO_MCUX_LPC_IRQ(idx, inst) \
|
||||
COND_CODE_1(DT_INST_IRQ_HAS_IDX(inst, idx), \
|
||||
(GPIO_MCUX_LPC_IRQ_CONNECT(inst, idx)), ())
|
||||
|
||||
|
||||
#define GPIO_MCUX_LPC(n) \
|
||||
static int lpc_gpio_init_##n(const struct device *dev); \
|
||||
|
@ -424,7 +306,6 @@ static const clock_ip_name_t gpio_clock_names[] = GPIO_CLOCKS;
|
|||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
|
||||
}, \
|
||||
.gpio_base = GPIO, \
|
||||
.pint_base = PINT, /* TODO: SECPINT issue #16330 */ \
|
||||
.pinmux_base = PINMUX_BASE, \
|
||||
.port_no = DT_INST_PROP(n, port), \
|
||||
.clock_ip_name = gpio_clock_names[DT_INST_PROP(n, port)], \
|
||||
|
@ -442,8 +323,6 @@ static const clock_ip_name_t gpio_clock_names[] = GPIO_CLOCKS;
|
|||
{ \
|
||||
gpio_mcux_lpc_init(dev); \
|
||||
\
|
||||
LISTIFY(8, GPIO_MCUX_LPC_IRQ, (;), n) \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue