drivers: nxp: convert SIUL2 drivers to native
Convert pin control, GPIO and external interrupt controller drivers based on SIUL2 peripheral to native drivers. This must be done in a single commit to preserve atomicity, as these drivers depend on each other. Signed-off-by: Manuel Argüelles <manuel.arguelles@nxp.com>
This commit is contained in:
parent
1eed39e4ac
commit
6c7d836b0c
15 changed files with 591 additions and 502 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2022-2023 NXP
|
||||
* Copyright 2022-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -9,12 +9,10 @@
|
|||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/dt-bindings/gpio/nxp-s32-gpio.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <Siul2_Port_Ip.h>
|
||||
#include <Siul2_Dio_Ip.h>
|
||||
|
||||
LOG_MODULE_REGISTER(nxp_s32_gpio, CONFIG_GPIO_LOG_LEVEL);
|
||||
|
||||
#ifdef CONFIG_NXP_S32_EIRQ
|
||||
|
@ -24,6 +22,19 @@ LOG_MODULE_REGISTER(nxp_s32_gpio, CONFIG_GPIO_LOG_LEVEL);
|
|||
#include <zephyr/drivers/interrupt_controller/intc_wkpu_nxp_s32.h>
|
||||
#endif
|
||||
|
||||
/* SIUL2 Multiplexed Signal Configuration Register (offset from port base) */
|
||||
#define SIUL2_MSCR(n) (0x4 * (n))
|
||||
/* SIUL2 Parallel GPIO Pad Data Out (offset from gpio base) */
|
||||
#define SIUL2_PGPDO 0
|
||||
/* SIUL2 Parallel GPIO Pad Data In */
|
||||
#define SIUL2_PGPDI 0x40
|
||||
|
||||
/* Handy accessors */
|
||||
#define GPIO_READ(r) sys_read16(config->gpio_base + (r))
|
||||
#define GPIO_WRITE(r, v) sys_write16((v), config->gpio_base + (r))
|
||||
#define PORT_READ(p) sys_read32(config->port_base + SIUL2_MSCR(p))
|
||||
#define PORT_WRITE(p, v) sys_write32((v), config->port_base + SIUL2_MSCR(p))
|
||||
|
||||
#if defined(CONFIG_NXP_S32_EIRQ) || defined(CONFIG_NXP_S32_WKPU)
|
||||
#define NXP_S32_GPIO_LINE_NOT_FOUND 0xff
|
||||
|
||||
|
@ -42,10 +53,8 @@ struct gpio_nxp_s32_irq_config {
|
|||
struct gpio_nxp_s32_config {
|
||||
/* gpio_driver_config needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
|
||||
Siul2_Dio_Ip_GpioType *gpio_base;
|
||||
Siul2_Port_Ip_PortType *port_base;
|
||||
|
||||
mem_addr_t gpio_base;
|
||||
mem_addr_t port_base;
|
||||
#ifdef CONFIG_NXP_S32_EIRQ
|
||||
struct gpio_nxp_s32_irq_config *eirq_info;
|
||||
#endif
|
||||
|
@ -66,13 +75,17 @@ struct gpio_nxp_s32_data {
|
|||
#endif
|
||||
};
|
||||
|
||||
static ALWAYS_INLINE uint16_t reverse_bits_16(uint16_t value)
|
||||
{
|
||||
return (uint16_t)(__RBIT((uint32_t)value) >> 16);
|
||||
}
|
||||
|
||||
static int nxp_s32_gpio_configure(const struct device *dev, gpio_pin_t pin,
|
||||
gpio_flags_t flags)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *port_config = dev->config;
|
||||
Siul2_Dio_Ip_GpioType *gpio_base = port_config->gpio_base;
|
||||
Siul2_Port_Ip_PortType *port_base = port_config->port_base;
|
||||
Siul2_Port_Ip_PortPullConfig pull_config;
|
||||
const struct gpio_nxp_s32_config *config = dev->config;
|
||||
uint32_t mscr_val;
|
||||
uint32_t pgpdo_val;
|
||||
|
||||
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
||||
return -ENOTSUP;
|
||||
|
@ -88,43 +101,31 @@ static int nxp_s32_gpio_configure(const struct device *dev, gpio_pin_t pin,
|
|||
}
|
||||
#endif
|
||||
|
||||
switch (flags & GPIO_DIR_MASK) {
|
||||
case GPIO_INPUT:
|
||||
Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_IN);
|
||||
break;
|
||||
case GPIO_OUTPUT:
|
||||
Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_OUT);
|
||||
break;
|
||||
case GPIO_INPUT | GPIO_OUTPUT:
|
||||
Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_IN_OUT);
|
||||
break;
|
||||
default:
|
||||
Siul2_Port_Ip_SetPinDirection(port_base, pin, SIUL2_PORT_HI_Z);
|
||||
break;
|
||||
}
|
||||
mscr_val = PORT_READ(pin);
|
||||
mscr_val &= ~(SIUL2_MSCR_SSS_MASK | SIUL2_MSCR_OBE_MASK | SIUL2_MSCR_IBE_MASK |
|
||||
SIUL2_MSCR_PUE_MASK | SIUL2_MSCR_PUS_MASK);
|
||||
|
||||
Siul2_Port_Ip_SetOutputBuffer(port_base, pin,
|
||||
(flags & GPIO_OUTPUT), PORT_MUX_AS_GPIO);
|
||||
if (flags & GPIO_OUTPUT) {
|
||||
mscr_val |= SIUL2_MSCR_OBE(1U);
|
||||
|
||||
switch (flags & (GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOW)) {
|
||||
case GPIO_OUTPUT_HIGH:
|
||||
Siul2_Dio_Ip_WritePin(gpio_base, pin, 1);
|
||||
break;
|
||||
case GPIO_OUTPUT_LOW:
|
||||
Siul2_Dio_Ip_WritePin(gpio_base, pin, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
pgpdo_val = GPIO_READ(SIUL2_PGPDO);
|
||||
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
||||
pgpdo_val |= BIT(15 - pin);
|
||||
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||
pgpdo_val &= ~BIT(15 - pin);
|
||||
}
|
||||
GPIO_WRITE(SIUL2_PGPDO, pgpdo_val);
|
||||
}
|
||||
|
||||
if ((flags & GPIO_PULL_UP) != 0) {
|
||||
pull_config = PORT_INTERNAL_PULL_UP_ENABLED;
|
||||
} else if ((flags & GPIO_PULL_DOWN) != 0) {
|
||||
pull_config = PORT_INTERNAL_PULL_DOWN_ENABLED;
|
||||
} else {
|
||||
pull_config = PORT_INTERNAL_PULL_NOT_ENABLED;
|
||||
if (flags & GPIO_INPUT) {
|
||||
mscr_val |= SIUL2_MSCR_IBE(1U);
|
||||
}
|
||||
Siul2_Port_Ip_SetPullSel(port_base, pin, pull_config);
|
||||
if (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) {
|
||||
mscr_val |= SIUL2_MSCR_PUE(1U);
|
||||
if (flags & GPIO_PULL_UP) {
|
||||
mscr_val |= SIUL2_MSCR_PUS(1U);
|
||||
}
|
||||
}
|
||||
PORT_WRITE(pin, mscr_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,7 +134,7 @@ static int nxp_s32_gpio_port_get_raw(const struct device *port, uint32_t *value)
|
|||
{
|
||||
const struct gpio_nxp_s32_config *config = port->config;
|
||||
|
||||
*value = Siul2_Dio_Ip_ReadPins(config->gpio_base);
|
||||
*value = reverse_bits_16(GPIO_READ(SIUL2_PGPDI));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -143,11 +144,11 @@ static int nxp_s32_gpio_port_set_masked_raw(const struct device *port,
|
|||
gpio_port_value_t value)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = port->config;
|
||||
Siul2_Dio_Ip_GpioType *gpio_base = config->gpio_base;
|
||||
gpio_port_pins_t pins_value = Siul2_Dio_Ip_GetPinsOutput(gpio_base);
|
||||
gpio_port_pins_t pins_value;
|
||||
|
||||
pins_value = reverse_bits_16(GPIO_READ(SIUL2_PGPDO));
|
||||
pins_value = (pins_value & ~mask) | (mask & value);
|
||||
Siul2_Dio_Ip_WritePins(gpio_base, pins_value);
|
||||
GPIO_WRITE(SIUL2_PGPDO, reverse_bits_16(pins_value));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -156,8 +157,11 @@ static int nxp_s32_gpio_port_set_bits_raw(const struct device *port,
|
|||
gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = port->config;
|
||||
uint16_t reg_val;
|
||||
|
||||
Siul2_Dio_Ip_SetPins(config->gpio_base, pins);
|
||||
reg_val = GPIO_READ(SIUL2_PGPDO);
|
||||
reg_val |= reverse_bits_16(pins);
|
||||
GPIO_WRITE(SIUL2_PGPDO, reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -166,8 +170,11 @@ static int nxp_s32_gpio_port_clear_bits_raw(const struct device *port,
|
|||
gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = port->config;
|
||||
uint16_t reg_val;
|
||||
|
||||
Siul2_Dio_Ip_ClearPins(config->gpio_base, pins);
|
||||
reg_val = GPIO_READ(SIUL2_PGPDO);
|
||||
reg_val &= ~reverse_bits_16(pins);
|
||||
GPIO_WRITE(SIUL2_PGPDO, reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -176,8 +183,11 @@ static int nxp_s32_gpio_port_toggle_bits(const struct device *port,
|
|||
gpio_port_pins_t pins)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = port->config;
|
||||
uint16_t reg_val;
|
||||
|
||||
Siul2_Dio_Ip_TogglePins(config->gpio_base, pins);
|
||||
reg_val = GPIO_READ(SIUL2_PGPDO);
|
||||
reg_val ^= reverse_bits_16(pins);
|
||||
GPIO_WRITE(SIUL2_PGPDO, reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -207,28 +217,18 @@ static void nxp_s32_gpio_isr(uint8_t pin, void *arg)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_NXP_S32_EIRQ)
|
||||
static int nxp_s32_gpio_eirq_get_trigger(Siul2_Icu_Ip_EdgeType *edge_type,
|
||||
enum gpio_int_mode mode,
|
||||
static int nxp_s32_gpio_eirq_get_trigger(enum eirq_nxp_s32_trigger *eirq_trigger,
|
||||
enum gpio_int_trig trigger)
|
||||
{
|
||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||
*edge_type = SIUL2_ICU_DISABLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (trigger) {
|
||||
case GPIO_INT_TRIG_LOW:
|
||||
*edge_type = SIUL2_ICU_FALLING_EDGE;
|
||||
*eirq_trigger = EIRQ_NXP_S32_FALLING_EDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_HIGH:
|
||||
*edge_type = SIUL2_ICU_RISING_EDGE;
|
||||
*eirq_trigger = EIRQ_NXP_S32_RISING_EDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_BOTH:
|
||||
*edge_type = SIUL2_ICU_BOTH_EDGES;
|
||||
*eirq_trigger = EIRQ_NXP_S32_BOTH_EDGES;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
|
@ -245,37 +245,39 @@ static int nxp_s32_gpio_config_eirq(const struct device *dev,
|
|||
const struct gpio_nxp_s32_config *config = dev->config;
|
||||
const struct gpio_nxp_s32_irq_config *irq_cfg = config->eirq_info;
|
||||
uint8_t irq_line;
|
||||
Siul2_Icu_Ip_EdgeType edge_type;
|
||||
enum eirq_nxp_s32_trigger eirq_trigger;
|
||||
|
||||
if (irq_cfg == NULL) {
|
||||
LOG_ERR("external interrupt controller not available or enabled");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (nxp_s32_gpio_eirq_get_trigger(&edge_type, mode, trig)) {
|
||||
LOG_ERR("trigger or mode not supported");
|
||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
irq_line = nxp_s32_gpio_pin_to_line(irq_cfg, pin);
|
||||
if (irq_line == NXP_S32_GPIO_LINE_NOT_FOUND) {
|
||||
if (edge_type == SIUL2_ICU_DISABLE) {
|
||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||
return 0;
|
||||
}
|
||||
LOG_ERR("pin %d cannot be used for external interrupt", pin);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (edge_type == SIUL2_ICU_DISABLE) {
|
||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||
eirq_nxp_s32_disable_interrupt(irq_cfg->ctrl, irq_line);
|
||||
eirq_nxp_s32_unset_callback(irq_cfg->ctrl, irq_line);
|
||||
} else {
|
||||
if (eirq_nxp_s32_set_callback(irq_cfg->ctrl, irq_line,
|
||||
nxp_s32_gpio_isr, pin, (void *)dev)) {
|
||||
if (nxp_s32_gpio_eirq_get_trigger(&eirq_trigger, trig)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (eirq_nxp_s32_set_callback(irq_cfg->ctrl, irq_line, pin,
|
||||
nxp_s32_gpio_isr, (void *)dev)) {
|
||||
LOG_ERR("pin %d is already in use", pin);
|
||||
return -EBUSY;
|
||||
}
|
||||
eirq_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, edge_type);
|
||||
eirq_nxp_s32_enable_interrupt(irq_cfg->ctrl, irq_line, eirq_trigger);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -391,34 +393,34 @@ static int nxp_s32_gpio_pin_get_config(const struct device *dev,
|
|||
gpio_flags_t *out_flags)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = dev->config;
|
||||
Siul2_Dio_Ip_GpioType *gpio_base = config->gpio_base;
|
||||
Siul2_Port_Ip_PortType *port_base = config->port_base;
|
||||
Siul2_Dio_Ip_PinsChannelType pins_output;
|
||||
uint16_t pins_output;
|
||||
uint32_t mscr_val;
|
||||
gpio_flags_t flags = 0;
|
||||
|
||||
if ((port_base->MSCR[pin] & SIUL2_MSCR_IBE_MASK) != 0) {
|
||||
mscr_val = PORT_READ(pin);
|
||||
if ((mscr_val & SIUL2_MSCR_IBE_MASK) != 0) {
|
||||
flags |= GPIO_INPUT;
|
||||
}
|
||||
|
||||
if ((port_base->MSCR[pin] & SIUL2_MSCR_OBE_MASK) != 0) {
|
||||
if ((mscr_val & SIUL2_MSCR_OBE_MASK) != 0) {
|
||||
flags |= GPIO_OUTPUT;
|
||||
|
||||
pins_output = Siul2_Dio_Ip_GetPinsOutput(gpio_base);
|
||||
if ((pins_output & BIT(pin)) != 0) {
|
||||
pins_output = GPIO_READ(SIUL2_PGPDO);
|
||||
if ((pins_output & BIT(15 - pin)) != 0) {
|
||||
flags |= GPIO_OUTPUT_HIGH;
|
||||
} else {
|
||||
flags |= GPIO_OUTPUT_LOW;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SIUL2_PORT_IP_HAS_OPEN_DRAIN
|
||||
if ((port_base->MSCR[pin] & SIUL2_MSCR_ODE_MASK) != 0) {
|
||||
#if defined(SIUL2_MSCR_ODE_MASK)
|
||||
if ((mscr_val & SIUL2_MSCR_ODE_MASK) != 0) {
|
||||
flags |= GPIO_OPEN_DRAIN;
|
||||
}
|
||||
#endif /* FEATURE_SIUL2_PORT_IP_HAS_OPEN_DRAIN */
|
||||
#endif /* SIUL2_MSCR_ODE_MASK */
|
||||
}
|
||||
|
||||
if ((port_base->MSCR[pin] & SIUL2_MSCR_PUE_MASK) != 0) {
|
||||
if ((port_base->MSCR[pin] & SIUL2_MSCR_PUS_MASK) != 0) {
|
||||
if ((mscr_val & SIUL2_MSCR_PUE_MASK) != 0) {
|
||||
if ((mscr_val & SIUL2_MSCR_PUS_MASK) != 0) {
|
||||
flags |= GPIO_PULL_UP;
|
||||
} else {
|
||||
flags |= GPIO_PULL_DOWN;
|
||||
|
@ -438,7 +440,6 @@ static int nxp_s32_gpio_port_get_direction(const struct device *dev,
|
|||
gpio_port_pins_t *outputs)
|
||||
{
|
||||
const struct gpio_nxp_s32_config *config = dev->config;
|
||||
Siul2_Port_Ip_PortType *port_base = config->port_base;
|
||||
gpio_port_pins_t ip = 0;
|
||||
gpio_port_pins_t op = 0;
|
||||
uint32_t pin;
|
||||
|
@ -448,7 +449,7 @@ static int nxp_s32_gpio_port_get_direction(const struct device *dev,
|
|||
if (inputs != NULL) {
|
||||
while (map) {
|
||||
pin = find_lsb_set(map) - 1;
|
||||
ip |= (!!(port_base->MSCR[pin] & SIUL2_MSCR_IBE_MASK)) * BIT(pin);
|
||||
ip |= (!!(PORT_READ(pin) & SIUL2_MSCR_IBE_MASK)) * BIT(pin);
|
||||
map &= ~BIT(pin);
|
||||
}
|
||||
|
||||
|
@ -458,7 +459,7 @@ static int nxp_s32_gpio_port_get_direction(const struct device *dev,
|
|||
if (outputs != NULL) {
|
||||
while (map) {
|
||||
pin = find_lsb_set(map) - 1;
|
||||
op |= (!!(port_base->MSCR[pin] & SIUL2_MSCR_OBE_MASK)) * BIT(pin);
|
||||
op |= (!!(PORT_READ(pin) & SIUL2_MSCR_OBE_MASK)) * BIT(pin);
|
||||
map &= ~BIT(pin);
|
||||
}
|
||||
|
||||
|
@ -513,12 +514,6 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = {
|
|||
& ~(GPIO_NXP_S32_RESERVED_PIN_MASK(n))), \
|
||||
(GPIO_PORT_PIN_MASK_FROM_DT_INST(n)))
|
||||
|
||||
#define GPIO_NXP_S32_REG_ADDR(n) \
|
||||
((Siul2_Dio_Ip_GpioType *)DT_INST_REG_ADDR_BY_NAME(n, pgpdo))
|
||||
|
||||
#define GPIO_NXP_S32_PORT_REG_ADDR(n) \
|
||||
((Siul2_Port_Ip_PortType *)DT_INST_REG_ADDR_BY_NAME(n, mscr))
|
||||
|
||||
#ifdef CONFIG_NXP_S32_EIRQ
|
||||
#define GPIO_NXP_S32_EIRQ_NODE(n) \
|
||||
DT_INST_PHANDLE(n, interrupt_parent)
|
||||
|
@ -587,8 +582,8 @@ static const struct gpio_driver_api gpio_nxp_s32_driver_api = {
|
|||
.common = { \
|
||||
.port_pin_mask = GPIO_NXP_S32_PORT_PIN_MASK(n), \
|
||||
}, \
|
||||
.gpio_base = GPIO_NXP_S32_REG_ADDR(n), \
|
||||
.port_base = GPIO_NXP_S32_PORT_REG_ADDR(n), \
|
||||
.gpio_base = DT_INST_REG_ADDR_BY_NAME(n, pgpdo), \
|
||||
.port_base = DT_INST_REG_ADDR_BY_NAME(n, mscr), \
|
||||
GPIO_NXP_S32_GET_EIRQ_INFO(n) \
|
||||
GPIO_NXP_S32_GET_WKPU_INFO(n) \
|
||||
}; \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue