From 98fdefcee59f46801d056ef3851894e9c7a92ebd Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Thu, 27 Nov 2025 22:09:31 +0800 Subject: [PATCH 1/6] drivers: interrupt: gint: Add GINT driver The GINT peripheral provides grouped GPIO interrupt functionality, allowing multiple pins to be combined into a single interrupt source. Support the peripheral in interrupt controller Signed-off-by: Jason Yu --- drivers/interrupt_controller/CMakeLists.txt | 1 + drivers/interrupt_controller/Kconfig | 1 + drivers/interrupt_controller/Kconfig.nxp_gint | 10 + drivers/interrupt_controller/intc_nxp_gint.c | 308 ++++++++++++++++++ .../interrupt-controller/nxp,gint.yaml | 44 +++ .../interrupt_controller/intc_nxp_gint.h | 121 +++++++ 6 files changed, 485 insertions(+) create mode 100644 drivers/interrupt_controller/Kconfig.nxp_gint create mode 100644 drivers/interrupt_controller/intc_nxp_gint.c create mode 100644 dts/bindings/interrupt-controller/nxp,gint.yaml create mode 100644 include/zephyr/drivers/interrupt_controller/intc_nxp_gint.h diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 35b2de363f9c1..1a152c19d3fa4 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -53,6 +53,7 @@ zephyr_library_sources_ifdef(CONFIG_MCHP_ECIA_XEC intc_mchp_ecia_xec.c) zephyr_library_sources_ifdef(CONFIG_NPCX_MIWU intc_miwu.c) zephyr_library_sources_ifdef(CONFIG_NRFX_CLIC intc_nrfx_clic.S) zephyr_library_sources_ifdef(CONFIG_NRFX_CLIC intc_nrfx_clic.c) +zephyr_library_sources_ifdef(CONFIG_NXP_GINT intc_nxp_gint.c) zephyr_library_sources_ifdef(CONFIG_NXP_IRQSTEER intc_nxp_irqsteer.c) zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c) zephyr_library_sources_ifdef(CONFIG_NXP_S32_WKPU intc_wkpu_nxp_s32.c) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index a7a381771c43e..cc9c9c9676c5d 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -83,6 +83,7 @@ source "drivers/interrupt_controller/Kconfig.loapic" source "drivers/interrupt_controller/Kconfig.mtk_adsp" source "drivers/interrupt_controller/Kconfig.multilevel" source "drivers/interrupt_controller/Kconfig.npcx" +source "drivers/interrupt_controller/Kconfig.nxp_gint" source "drivers/interrupt_controller/Kconfig.nxp_irqsteer" source "drivers/interrupt_controller/Kconfig.nxp_pint" source "drivers/interrupt_controller/Kconfig.nxp_s32" diff --git a/drivers/interrupt_controller/Kconfig.nxp_gint b/drivers/interrupt_controller/Kconfig.nxp_gint new file mode 100644 index 0000000000000..18d9bf40686af --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.nxp_gint @@ -0,0 +1,10 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +config NXP_GINT + bool "Grouped GPIO Input Interrupt(GINT) controller for NXP MCUs" + default y + depends on DT_HAS_NXP_GINT_ENABLED + select RESET + help + Enable GINT driver for NXP MCUs diff --git a/drivers/interrupt_controller/intc_nxp_gint.c b/drivers/interrupt_controller/intc_nxp_gint.c new file mode 100644 index 0000000000000..df06eb1de855a --- /dev/null +++ b/drivers/interrupt_controller/intc_nxp_gint.c @@ -0,0 +1,308 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * GINT (Group GPIO Input Interrupt) Controller Driver + * + * The GINT peripheral provides grouped GPIO interrupt functionality, allowing + * multiple GPIO pins to be combined into a single interrupt source. Key features: + * - Supports monitoring multiple GPIO ports and pins + * - Configurable polarity (rising/falling edge or high/low level) per pin + * - Combinational logic modes: AND or OR of selected pins + * - Edge or level triggered interrupt generation + * + * NOTE: The pin don't need to be configured as GPIO input, GINT can monitor + * any pin configured as digital functions. + */ + +#define DT_DRV_COMPAT nxp_gint + +LOG_MODULE_REGISTER(nxp_gint, CONFIG_INTC_LOG_LEVEL); + +/* GINT register offsets */ +#define GINT_CTRL_OFFSET 0x000 +#define GINT_PORT_POLN_OFFSET(n) (0x020 + 4 * (n)) +#define GINT_PORT_ENAN_OFFSET(n) (0x040 + 4 * (n)) + +/* GINT CTRL register bits */ +#define GINT_CTRL_INT_BIT BIT(0) +#define GINT_CTRL_COMB_BIT BIT(1) +#define GINT_CTRL_TRIG_BIT BIT(2) + +/* Max number of PORT the GINT support. */ +#ifdef GINT_PORT_POL_COUNT +#define GINT_PORT_COUNT GINT_PORT_POL_COUNT +#else +#define GINT_PORT_COUNT 1 +#endif + +struct nxp_gint_config { + /** GINT base address */ + uintptr_t base; + /** IRQ number */ + uint32_t irq; + /** IRQ priority */ + uint32_t irq_priority; + /** Reset controller specification */ + struct reset_dt_spec reset; + /** IRQ initialization function */ + void (*irq_init_func)(void); +}; + +struct nxp_gint_data { + /** Interrupt callback */ + nxp_gint_callback_t callback; + /** User data for callback */ + void *user_data; + /** Spinlock for thread-safe access */ + struct k_spinlock lock; +}; + +static inline uint32_t gint_read_reg(const struct nxp_gint_config *config, uint32_t offset) +{ + return sys_read32(config->base + offset); +} + +static inline void gint_write_reg(const struct nxp_gint_config *config, + uint32_t offset, + uint32_t value) +{ + sys_write32(value, config->base + offset); +} + +static void nxp_gint_isr(const struct device *dev) +{ + struct nxp_gint_data *data = dev->data; + const struct nxp_gint_config *config = dev->config; + uint32_t ctrl; + + /* Clear interrupt flag */ + ctrl = gint_read_reg(config, GINT_CTRL_OFFSET); + gint_write_reg(config, GINT_CTRL_OFFSET, ctrl); + + /* Call user callback if registered */ + if ((0u != (ctrl & GINT_CTRL_INT_BIT)) && (NULL != data->callback)) { + data->callback(dev, data->user_data); + } +} + +int nxp_gint_configure_group(const struct device *dev, const struct nxp_gint_group_config *config) +{ + uint32_t ctrl; + const struct nxp_gint_config *hw_config; + + if (!dev || !config) { + return -EINVAL; + } + + hw_config = dev->config; + + /* Configure control register */ + ctrl = 0; + if (config->combination) { + ctrl |= GINT_CTRL_COMB_BIT; + } + if (config->trigger) { + ctrl |= GINT_CTRL_TRIG_BIT; + } + gint_write_reg(hw_config, GINT_CTRL_OFFSET, ctrl); + + return 0; +} + +int nxp_gint_enable_pin(const struct device *dev, uint8_t port, uint8_t pin, + nxp_gint_polarity_type polarity) +{ + uint32_t reg; + + const struct nxp_gint_config *config = dev->config; + struct nxp_gint_data *data = dev->data; + + /* Validate port number */ + if (port >= GINT_PORT_COUNT) { + LOG_ERR("Invalid port number: %d (max: %d)", port, GINT_PORT_COUNT - 1); + return -EINVAL; + } + + /* Validate pin number */ + if (pin > 31) { + LOG_ERR("Invalid pin number: %d (max: 31)", pin); + return -EINVAL; + } + + K_SPINLOCK(&data->lock) { + /* Set polarity */ + reg = gint_read_reg(config, GINT_PORT_POLN_OFFSET(port)); + if (polarity == NXP_GINT_POL_HIGH) { + reg |= BIT(pin); + } else { + reg &= ~BIT(pin); + } + gint_write_reg(config, GINT_PORT_POLN_OFFSET(port), reg); + + /* Enable pin */ + reg = gint_read_reg(config, GINT_PORT_ENAN_OFFSET(port)); + reg |= BIT(pin); + gint_write_reg(config, GINT_PORT_ENAN_OFFSET(port), reg); + } + + LOG_DBG("Enabled port %d pin %d with polarity %d", port, pin, polarity); + + return 0; +} + +int nxp_gint_disable_pin(const struct device *dev, uint8_t port, uint8_t pin) +{ + uint32_t reg; + const struct nxp_gint_config *config = dev->config; + struct nxp_gint_data *data = dev->data; + + /* Validate port number */ + if (port >= GINT_PORT_COUNT) { + LOG_ERR("Invalid port number: %d (max: %d)", port, GINT_PORT_COUNT - 1); + return -EINVAL; + } + + /* Validate pin number */ + if (pin > 31) { + LOG_ERR("Invalid pin number: %d (max: 31)", pin); + return -EINVAL; + } + + /* Disable pin */ + K_SPINLOCK(&data->lock) { + reg = gint_read_reg(config, GINT_PORT_ENAN_OFFSET(port)); + reg &= ~BIT(pin); + gint_write_reg(config, GINT_PORT_ENAN_OFFSET(port), reg); + } + + LOG_DBG("Disabled port %d pin %d", port, pin); + + return 0; +} + +bool nxp_gint_is_pending(const struct device *dev) +{ + uint32_t ctrl; + + if (!dev) { + return false; + } + + const struct nxp_gint_config *config = dev->config; + + /* Read control register and check interrupt bit */ + ctrl = gint_read_reg(config, GINT_CTRL_OFFSET); + return (ctrl & GINT_CTRL_INT_BIT) != 0; +} + +int nxp_gint_clear_pending(const struct device *dev) +{ + uint32_t ctrl; + + if (!dev) { + return -EINVAL; + } + + const struct nxp_gint_config *config = dev->config; + + /* Clear interrupt flag by writing 0 to INT bit */ + ctrl = gint_read_reg(config, GINT_CTRL_OFFSET); + ctrl |= GINT_CTRL_INT_BIT; + gint_write_reg(config, GINT_CTRL_OFFSET, ctrl); + + LOG_DBG("Cleared pending interrupt"); + + return 0; +} + +int nxp_gint_register_callback(const struct device *dev, + nxp_gint_callback_t callback, + void *user_data) +{ + if (!dev) { + return -EINVAL; + } + + struct nxp_gint_data *data = dev->data; + + data->callback = callback; + data->user_data = user_data; + + LOG_DBG("Registered callback"); + + return 0; +} + +static void nxp_gint_reset_reg(const struct device *dev) +{ + const struct nxp_gint_config *config = dev->config; + + for (int port = 0; port < GINT_PORT_COUNT; port++) { + gint_write_reg(config, GINT_PORT_ENAN_OFFSET(port), 0U); + } + + gint_write_reg(config, GINT_CTRL_OFFSET, GINT_CTRL_INT_BIT); +} + +static int nxp_gint_init(const struct device *dev) +{ + const struct nxp_gint_config *config = dev->config; + struct nxp_gint_data *data = dev->data; + + /* Initialize data structure */ + data->callback = NULL; + data->user_data = NULL; + + /* Release the GINT controller from reset */ + (void)reset_line_deassert_dt(&config->reset); + + /* Clear the registers */ + nxp_gint_reset_reg(dev); + + /* Init the interrupt */ + config->irq_init_func(); + + return 0; +} + +#define NXP_GINT_IRQ_CONFIG(n) \ + static void nxp_gint_irq_init_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + nxp_gint_isr, \ + DEVICE_DT_INST_GET(n), \ + 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } + +#define NXP_GINT_INIT(n) \ + NXP_GINT_IRQ_CONFIG(n) \ + static const struct nxp_gint_config nxp_gint_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq = DT_INST_IRQN(n), \ + .irq_priority = DT_INST_IRQ(n, priority), \ + .reset = RESET_DT_SPEC_INST_GET(n), \ + .irq_init_func = nxp_gint_irq_init_##n, \ + }; \ + \ + static struct nxp_gint_data nxp_gint_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, nxp_gint_init, NULL, \ + &nxp_gint_data_##n, &nxp_gint_config_##n, \ + POST_KERNEL, CONFIG_INTC_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(NXP_GINT_INIT) diff --git a/dts/bindings/interrupt-controller/nxp,gint.yaml b/dts/bindings/interrupt-controller/nxp,gint.yaml new file mode 100644 index 0000000000000..e1c16dd8746f5 --- /dev/null +++ b/dts/bindings/interrupt-controller/nxp,gint.yaml @@ -0,0 +1,44 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP GINT (Grouped GPIO Input Interrupt) controller + + The GINT module allows multiple GPIO pins to be combined into a single + interrupt source with flexible logic combination and trigger modes. + + Features: + - Support for multiple digital pins in grouped interrupt + - Configurable polarity (active HIGH or active LOW) per pin + - OR or AND logic combination + - Edge or level triggered + + Example usage: + + gint0: gint@40002000 { + compatible = "nxp,gint"; + reg = <0x40002000 0x1000>; + interrupts = <0 2>; + port-num = <2>; + resets = <&reset 0>; + status = "okay"; + }; + +compatible: "nxp,gint" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + description: | + Base address and size of the GINT peripheral register space. + + interrupts: + required: true + description: | + Interrupt line for the GINT controller. + + resets: + description: | + Reset controller phandle and specifier for the GINT peripheral. diff --git a/include/zephyr/drivers/interrupt_controller/intc_nxp_gint.h b/include/zephyr/drivers/interrupt_controller/intc_nxp_gint.h new file mode 100644 index 0000000000000..cf4bddaa1da81 --- /dev/null +++ b/include/zephyr/drivers/interrupt_controller/intc_nxp_gint.h @@ -0,0 +1,121 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_INTERRUPT_CONTROLLER_INTC_NXP_GINT_H_ +#define ZEPHYR_INCLUDE_DRIVERS_INTERRUPT_CONTROLLER_INTC_NXP_GINT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** GINT trigger types */ +typedef enum { + /** Edge triggered */ + NXP_GINT_TRIG_EDGE = 0, + /** Level triggered */ + NXP_GINT_TRIG_LEVEL = 1, +} nxp_gint_trigger_type; + +/** GINT combination logic */ +typedef enum { + /** OR logic - any enabled pin triggers interrupt */ + NXP_GINT_COMB_OR = 0, + /** AND logic - all enabled pins must trigger interrupt */ + NXP_GINT_COMB_AND = 1, +} nxp_gint_combination_type; + +/** GINT pin polarity */ +typedef enum { + /** Active LOW */ + NXP_GINT_POL_LOW = 0, + /** Active HIGH */ + NXP_GINT_POL_HIGH = 1, +} nxp_gint_polarity_type; + +/** GINT group configuration */ +struct nxp_gint_group_config { + /** Trigger type (edge or level) */ + nxp_gint_trigger_type trigger; + /** Combination logic (OR or AND) */ + nxp_gint_combination_type combination; +}; + +/** + * @brief GINT callback function type + * + * @param dev GINT device + * @param user_data User defined data + */ +typedef void (*nxp_gint_callback_t)(const struct device *dev, void *user_data); + +/** + * @brief Configure GINT settings + * + * @param dev GINT device + * @param config Group configuration + * @return 0 on success, negative errno on failure + */ +int nxp_gint_configure_group(const struct device *dev, + const struct nxp_gint_group_config *config); + +/** + * @brief Enable a pin for GINT + * + * @param dev GINT device + * @param port Port number + * @param pin Pin number (0-31) + * @param polarity Pin polarity + * @return 0 on success, negative errno on failure + */ +int nxp_gint_enable_pin(const struct device *dev, uint8_t port, uint8_t pin, + nxp_gint_polarity_type polarity); + +/** + * @brief Disable a pin for GINT + * + * @param dev GINT device + * @param port Port number + * @param pin Pin number (0-31) + * @return 0 on success, negative errno on failure + */ +int nxp_gint_disable_pin(const struct device *dev, uint8_t port, uint8_t pin); + +/** + * @brief Check if GINT interrupt is pending + * + * @param dev GINT device + * @return true if interrupt is pending, false otherwise + */ +bool nxp_gint_is_pending(const struct device *dev); + +/** + * @brief Clear GINT interrupt pending status + * + * @param dev GINT device + * @return 0 on success, negative errno on failure + */ +int nxp_gint_clear_pending(const struct device *dev); + +/** + * @brief Register GINT callback + * + * @param dev GINT device + * @param callback Callback function to register + * @param user_data User defined data to pass to callback + * @return 0 on success, negative errno on failure + */ +int nxp_gint_register_callback(const struct device *dev, + nxp_gint_callback_t callback, + void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_INTERRUPT_CONTROLLER_INTC_NXP_GINT_H_ */ From aa3d45eac8e2ad95f3f9b9997fc9b3ea8ac1f8f2 Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Fri, 28 Nov 2025 23:08:58 +0800 Subject: [PATCH 2/6] drivers: gint: Enable the GINT driver for NXP SOCs Add dts nodes in SOC dts files Signed-off-by: Jason Yu --- dts/arm/nxp/nxp_lpc51u68.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc54xxx.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc55S0x_common.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc55S1x_common.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc55S2x_common.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc55S3x_common.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_lpc55S6x_common.dtsi | 16 ++++++++++++++++ dts/arm/nxp/nxp_mcxw23x_common.dtsi | 8 ++++++++ 8 files changed, 120 insertions(+) diff --git a/dts/arm/nxp/nxp_lpc51u68.dtsi b/dts/arm/nxp/nxp_lpc51u68.dtsi index 047aa427e9e4e..4676bedc8226d 100644 --- a/dts/arm/nxp/nxp_lpc51u68.dtsi +++ b/dts/arm/nxp/nxp_lpc51u68.dtsi @@ -85,6 +85,22 @@ }; }; + gint0: gint@40002000 { + compatible = "nxp,gint"; + reg = <0x40002000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@40003000 { + compatible = "nxp,gint"; + reg = <0x40003000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@40004000 { compatible = "nxp,pint"; reg = <0x40004000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc54xxx.dtsi b/dts/arm/nxp/nxp_lpc54xxx.dtsi index 439e837bed039..377e8356bc183 100644 --- a/dts/arm/nxp/nxp_lpc54xxx.dtsi +++ b/dts/arm/nxp/nxp_lpc54xxx.dtsi @@ -140,6 +140,22 @@ }; }; + gint0: gint@40002000 { + compatible = "nxp,gint"; + reg = <0x40002000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@40003000 { + compatible = "nxp,gint"; + reg = <0x40003000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@40004000 { compatible = "nxp,pint"; reg = <0x40004000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index 97356ebe561d9..64dcd0f505c46 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -147,6 +147,22 @@ }; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@3000 { + compatible = "nxp,gint"; + reg = <0x3000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 61c368f172c3c..95a45513fb3ca 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -150,6 +150,22 @@ }; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@3000 { + compatible = "nxp,gint"; + reg = <0x3000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index 1889513eed11e..8699c24c8eda4 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -162,6 +162,22 @@ }; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@3000 { + compatible = "nxp,gint"; + reg = <0x3000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index f75ae4398017e..a42efd3c4abb6 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -180,6 +180,22 @@ #dma-cells = <1>; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@3000 { + compatible = "nxp,gint"; + reg = <0x3000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index 59ee736098c5d..2572f7832d090 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -189,6 +189,22 @@ }; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + + gint1: gint@3000 { + compatible = "nxp,gint"; + reg = <0x3000 0x1000>; + interrupts = <3 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; diff --git a/dts/arm/nxp/nxp_mcxw23x_common.dtsi b/dts/arm/nxp/nxp_mcxw23x_common.dtsi index 69069e29a4fa4..1a1f104990b0e 100644 --- a/dts/arm/nxp/nxp_mcxw23x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxw23x_common.dtsi @@ -126,6 +126,14 @@ }; }; + gint0: gint@2000 { + compatible = "nxp,gint"; + reg = <0x2000 0x1000>; + interrupts = <2 2>; + resets = <&reset NXP_SYSCON_RESET(0, 19)>; + status = "disabled"; + }; + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; From 083428bc56a1b4a7e9f33619800e7e7fe93e5b8e Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Fri, 28 Nov 2025 23:10:26 +0800 Subject: [PATCH 3/6] drivers: gint: Enable the GINT driver for NXP SOCs Enable GINT clock during SOC init Signed-off-by: Jason Yu --- soc/nxp/lpc/lpc51u68/soc.c | 4 ++++ soc/nxp/lpc/lpc54xxx/soc.c | 4 ++++ soc/nxp/lpc/lpc55xxx/soc.c | 4 ++++ soc/nxp/mcx/mcxw/mcxw2xx/soc.c | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/soc/nxp/lpc/lpc51u68/soc.c b/soc/nxp/lpc/lpc51u68/soc.c index fd8f23800b330..41b07c37bd28f 100644 --- a/soc/nxp/lpc/lpc51u68/soc.c +++ b/soc/nxp/lpc/lpc51u68/soc.c @@ -42,6 +42,10 @@ void soc_early_init_hook(void) POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); POWER_DisablePD(kPDRUNCFG_PD_TEMPS); + + if (IS_ENABLED(CONFIG_NXP_GINT)) { + CLOCK_EnableClock(kCLOCK_Gint); + } } #ifdef CONFIG_SOC_RESET_HOOK diff --git a/soc/nxp/lpc/lpc54xxx/soc.c b/soc/nxp/lpc/lpc54xxx/soc.c index 14f6cd31d0bdb..71f568d630110 100644 --- a/soc/nxp/lpc/lpc54xxx/soc.c +++ b/soc/nxp/lpc/lpc54xxx/soc.c @@ -89,6 +89,10 @@ __weak void clock_init(void) #endif #endif /* CONFIG_SOC_LPC54114_M4 */ + + if (IS_ENABLED(CONFIG_NXP_GINT)) { + CLOCK_EnableClock(kCLOCK_Gint); + } } /** diff --git a/soc/nxp/lpc/lpc55xxx/soc.c b/soc/nxp/lpc/lpc55xxx/soc.c index 100569953286f..472ac2d29b07b 100644 --- a/soc/nxp/lpc/lpc55xxx/soc.c +++ b/soc/nxp/lpc/lpc55xxx/soc.c @@ -444,6 +444,10 @@ DT_FOREACH_STATUS_OKAY(nxp_ctimer_pwm, CTIMER_CLOCK_SETUP) SYSCON->MCLKDIV = SYSCON_MCLKDIV_DIV(0U); SYSCON->MCLKIO = 1U; #endif /* CONFIG_AUDIO_CODEC_WM8904 */ + + if (IS_ENABLED(CONFIG_NXP_GINT)) { + CLOCK_EnableClock(kCLOCK_Gint); + } } /** diff --git a/soc/nxp/mcx/mcxw/mcxw2xx/soc.c b/soc/nxp/mcx/mcxw/mcxw2xx/soc.c index e561ca8d7e78c..ac5935f6353fb 100644 --- a/soc/nxp/mcx/mcxw/mcxw2xx/soc.c +++ b/soc/nxp/mcx/mcxw/mcxw2xx/soc.c @@ -109,6 +109,10 @@ __weak void clock_init(void) */ CLOCK_EnableClock(kCLOCK_Sysctl); #endif + + if (IS_ENABLED(CONFIG_NXP_GINT)) { + CLOCK_EnableClock(kCLOCK_Gint); + } } #ifdef CONFIG_SOC_RESET_HOOK From 90338d5f91c695fd9933773ee4e8c861de549f6c Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Fri, 28 Nov 2025 23:11:03 +0800 Subject: [PATCH 4/6] tests: drivers: gint: Add GINT test case The test cases cover: 1. Pin enable and disable 2. Edge trigger and level trigger for single pin 3. OR combination and AND combination for multiple pins Signed-off-by: Jason Yu --- .../intc_nxp_gint/CMakeLists.txt | 8 + .../intc_nxp_gint/prj.conf | 7 + .../intc_nxp_gint/src/main.c | 391 ++++++++++++++++++ .../intc_nxp_gint/testcase.yaml | 11 + 4 files changed, 417 insertions(+) create mode 100644 tests/drivers/interrupt_controller/intc_nxp_gint/CMakeLists.txt create mode 100644 tests/drivers/interrupt_controller/intc_nxp_gint/prj.conf create mode 100644 tests/drivers/interrupt_controller/intc_nxp_gint/src/main.c create mode 100644 tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/CMakeLists.txt b/tests/drivers/interrupt_controller/intc_nxp_gint/CMakeLists.txt new file mode 100644 index 0000000000000..05d621f69bb33 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_intc_nxp_gint) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/prj.conf b/tests/drivers/interrupt_controller/intc_nxp_gint/prj.conf new file mode 100644 index 0000000000000..153f47dad6434 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/prj.conf @@ -0,0 +1,7 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +CONFIG_GPIO=y +CONFIG_NXP_GINT=y +CONFIG_INTC_LOG_LEVEL_DBG=y diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/src/main.c b/tests/drivers/interrupt_controller/intc_nxp_gint/src/main.c new file mode 100644 index 0000000000000..6f6b2ce3c19d2 --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/src/main.c @@ -0,0 +1,391 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * GINT module is used to monitor the digital function pin + * input signal, no matter the pin is configured as GPIO or not. + * + * Theoretically, external signal should be connected to the + * pins, change the signal level, and check GINT function. + * To make the test easy, this test drives the GPIO pin + * directly, and use GINT to monitor the GPIO pin. When change + * the GPIO level, GINT can monitor the change on the same pin. + * With this method, the externel signal is not necessary. + */ + +#define GINT_NODE DT_NODELABEL(gint0) +#define GPIO_PIN_0_NODE DT_ALIAS(led0) +#define GPIO_PIN_1_NODE DT_ALIAS(led1) + +#define TEST_GPIO_0 DT_GPIO_CTLR(GPIO_PIN_0_NODE, gpios) +#define TEST_PIN_0 DT_GPIO_PIN(GPIO_PIN_0_NODE, gpios) +#define TEST_PORT_0 DT_REG_ADDR(TEST_GPIO_0) + +#define TEST_GPIO_1 DT_GPIO_CTLR(GPIO_PIN_1_NODE, gpios) +#define TEST_PIN_1 DT_GPIO_PIN(GPIO_PIN_1_NODE, gpios) +#define TEST_PORT_1 DT_REG_ADDR(TEST_GPIO_1) + +/* + * For level interrupt testing, we need to disable the pin to prevent + * continuous triggering in callback, and enable the pin again + * after exit callback. Define this as a test loop, this macro + * means how many loops to test. + */ +#define TEST_LEVEL_INT_COUNT 5 + +static const struct device *gint_dev = DEVICE_DT_GET(GINT_NODE); +static const struct gpio_dt_spec gpio_pin0 = GPIO_DT_SPEC_GET(GPIO_PIN_0_NODE, gpios); +static const struct gpio_dt_spec gpio_pin1 = GPIO_DT_SPEC_GET(GPIO_PIN_1_NODE, gpios); + +static atomic_t gint_callback_count; + +static void test_gint_edge_callback(const struct device *dev, void *user_data) +{ + atomic_inc(&gint_callback_count); +} + +static void test_gint_level_callback(const struct device *dev, void *user_data) +{ + atomic_inc(&gint_callback_count); + + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); +} + +static void *test_gint_setup(void) +{ + zassert_true(device_is_ready(gint_dev), "GINT device not ready"); + return NULL; +} + +static void test_gint_before(void *fixture) +{ + ARG_UNUSED(fixture); + + /* Reset callback flags */ + atomic_set(&gint_callback_count, 0); + + /* Clear any pending interrupts */ + nxp_gint_clear_pending(gint_dev); + + /* Disable test pin */ + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); + nxp_gint_disable_pin(gint_dev, TEST_PORT_1, TEST_PIN_1); +} + +ZTEST(intc_nxp_gint, test_enable_disable_pin) +{ + int ret; + + /* Enable pin with HIGH polarity */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_HIGH); + zassert_ok(ret, "Failed to enable pin %d:%d", TEST_PORT_0, TEST_PIN_0); + + /* Disable pin */ + ret = nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); + zassert_ok(ret, "Failed to disable pin %d:%d", TEST_PORT_0, TEST_PIN_0); +} + +ZTEST(intc_nxp_gint, test_invalid_port) +{ + int ret; + + /* Try to enable pin with invalid port number */ + ret = nxp_gint_enable_pin(gint_dev, 255, TEST_PIN_0, NXP_GINT_POL_HIGH); + zassert_equal(ret, -EINVAL, "Should fail with invalid port"); + + /* Try to disable pin with invalid port number */ + ret = nxp_gint_disable_pin(gint_dev, 255, TEST_PIN_0); + zassert_equal(ret, -EINVAL, "Should fail with invalid port"); +} + +ZTEST(intc_nxp_gint, test_invalid_pin) +{ + int ret; + + /* Try to enable pin with invalid pin number */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, 32, NXP_GINT_POL_HIGH); + zassert_equal(ret, -EINVAL, "Should fail with invalid pin"); + + /* Try to disable pin with invalid pin number */ + ret = nxp_gint_disable_pin(gint_dev, TEST_PORT_0, 32); + zassert_equal(ret, -EINVAL, "Should fail with invalid pin"); +} + +ZTEST(intc_nxp_gint, test_gint_single_pin_edge) +{ + int ret; + struct nxp_gint_group_config gint_config = { + .trigger = NXP_GINT_TRIG_EDGE, + .combination = NXP_GINT_COMB_OR, + }; + + /* Configure GPIO pin as output */ + ret = gpio_pin_configure_dt(&gpio_pin0, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO pin as output"); + + /* Set pin LOW initially */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 0); + zassert_ok(ret, "Failed to set pin LOW"); + + /* Register callback */ + ret = nxp_gint_register_callback(gint_dev, test_gint_edge_callback, NULL); + zassert_ok(ret, "Failed to register callback"); + + /* Configure GINT for edge trigger */ + ret = nxp_gint_configure_group(gint_dev, &gint_config); + zassert_ok(ret, "Failed to configure GINT group"); + + /* Clear any pending interrupts */ + nxp_gint_clear_pending(gint_dev); + + /* Enable pin with HIGH polarity (rising edge) */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_HIGH); + zassert_ok(ret, "Failed to enable pin"); + + k_msleep(10); + + /* Reset callback counter */ + atomic_set(&gint_callback_count, 0); + + /* Trigger rising edge: LOW -> HIGH */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 1); + zassert_ok(ret, "Failed to set pin HIGH"); + + /* Wait for interrupt to be processed */ + k_msleep(50); + + /* Verify interrupt was triggered */ + zassert_equal(atomic_get(&gint_callback_count), 1, + "GINT callback should be called once"); + + /* Cleanup */ + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); +} + +ZTEST(intc_nxp_gint, test_gint_single_pin_level) +{ + int ret; + struct nxp_gint_group_config gint_config = { + .trigger = NXP_GINT_TRIG_LEVEL, + .combination = NXP_GINT_COMB_OR, + }; + + /* Configure GPIO pin as output */ + ret = gpio_pin_configure_dt(&gpio_pin0, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO pin as output"); + + /* Set pin LOW initially */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 0); + zassert_ok(ret, "Failed to set pin LOW"); + + /* Register callback */ + ret = nxp_gint_register_callback(gint_dev, test_gint_level_callback, NULL); + zassert_ok(ret, "Failed to register callback"); + + /* Configure GINT for level trigger */ + ret = nxp_gint_configure_group(gint_dev, &gint_config); + zassert_ok(ret, "Failed to configure GINT group"); + + /* Clear any pending interrupts */ + nxp_gint_clear_pending(gint_dev); + + /* Enable pin with HIGH polarity (high level) */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_HIGH); + zassert_ok(ret, "Failed to enable pin"); + + k_msleep(10); + + /* Reset callback counter */ + atomic_set(&gint_callback_count, 0); + + /* Set pin HIGH to trigger level interrupt */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 1); + zassert_ok(ret, "Failed to set pin HIGH"); + + for (int i = 1; i < TEST_LEVEL_INT_COUNT; i++) { + /* Wait for interrupt to be processed */ + k_msleep(50); + + /* + * The pin interrupt is disabled in the callback. + * Enable it here, then the callback will be called again. + */ + nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_HIGH); + } + + /* Verify interrupt was triggered */ + zassert_equal(atomic_get(&gint_callback_count), TEST_LEVEL_INT_COUNT, + "GINT callback should be called desired times"); + + /* Cleanup */ + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); +} + +ZTEST(intc_nxp_gint, test_gint_multi_pin_or_mode) +{ + int ret; + struct nxp_gint_group_config gint_config = { + .trigger = NXP_GINT_TRIG_EDGE, + .combination = NXP_GINT_COMB_OR, + }; + + /* Configure GPIO pin as output */ + ret = gpio_pin_configure_dt(&gpio_pin0, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO 0 pin as output"); + ret = gpio_pin_configure_dt(&gpio_pin1, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO 1 pin as output"); + + /* Set both pins HIGH initially */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 1); + zassert_ok(ret, "Failed to set pin0 HIGH"); + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 1); + zassert_ok(ret, "Failed to set pin1 HIGH"); + + /* Register callback */ + ret = nxp_gint_register_callback(gint_dev, test_gint_edge_callback, NULL); + zassert_ok(ret, "Failed to register callback"); + + /* Configure GINT for OR mode */ + ret = nxp_gint_configure_group(gint_dev, &gint_config); + zassert_ok(ret, "Failed to configure GINT group"); + + /* Clear any pending interrupts */ + nxp_gint_clear_pending(gint_dev); + + /* Enable both pins with falling edge */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_LOW); + zassert_ok(ret, "Failed to enable pin0"); + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_1, TEST_PIN_1, NXP_GINT_POL_LOW); + zassert_ok(ret, "Failed to enable pin1"); + + k_msleep(10); + + /* Reset callback counter */ + atomic_set(&gint_callback_count, 0); + + /* Trigger pin0 - should trigger interrupt in OR mode */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 0); + zassert_ok(ret, "Failed to set pin0 LOW"); + + k_msleep(50); + + zassert_equal(atomic_get(&gint_callback_count), 1, + "GINT interrupt should be triggered by pin0 in OR mode"); + + /* Reset callback counter */ + atomic_set(&gint_callback_count, 0); + /* Reset to the initial state for next test */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 1); + + k_msleep(10); + + /* Trigger pin1 - should also trigger interrupt in OR mode */ + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 0); + zassert_ok(ret, "Failed to set pin1 LOW"); + + k_msleep(50); + + zassert_equal(atomic_get(&gint_callback_count), 1, + "GINT interrupt should be triggered by pin1 in OR mode"); + + /* Cleanup */ + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); + nxp_gint_disable_pin(gint_dev, TEST_PORT_1, TEST_PIN_1); +} + +ZTEST(intc_nxp_gint, test_gint_multi_pin_and_mode) +{ + int ret; + struct nxp_gint_group_config gint_config = { + .trigger = NXP_GINT_TRIG_EDGE, + .combination = NXP_GINT_COMB_AND, + }; + + /* Configure GPIO pin as output */ + ret = gpio_pin_configure_dt(&gpio_pin0, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO 0 pin as output"); + ret = gpio_pin_configure_dt(&gpio_pin1, GPIO_OUTPUT_INACTIVE); + zassert_ok(ret, "Failed to configure GPIO 1 pin as output"); + + /* Set both pins LOW initially */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 0); + zassert_ok(ret, "Failed to set pin0 LOW"); + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 0); + zassert_ok(ret, "Failed to set pin1 LOW"); + + /* Register callback */ + ret = nxp_gint_register_callback(gint_dev, test_gint_edge_callback, NULL); + zassert_ok(ret, "Failed to register callback"); + + /* Configure GINT for AND mode */ + ret = nxp_gint_configure_group(gint_dev, &gint_config); + zassert_ok(ret, "Failed to configure GINT group"); + + /* Clear any pending interrupts */ + nxp_gint_clear_pending(gint_dev); + + /* Enable both pins with HIGH polarity */ + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0, NXP_GINT_POL_HIGH); + zassert_ok(ret, "Failed to enable pin0"); + ret = nxp_gint_enable_pin(gint_dev, TEST_PORT_1, TEST_PIN_1, NXP_GINT_POL_HIGH); + zassert_ok(ret, "Failed to enable pin1"); + + k_msleep(10); + + /* Reset callback counter */ + atomic_set(&gint_callback_count, 0); + + /* Trigger only pin0 - should NOT trigger interrupt in AND mode */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 1); + zassert_ok(ret, "Failed to set pin0 HIGH"); + + k_msleep(50); + + zassert_equal(atomic_get(&gint_callback_count), 0, + "GINT interrupt should NOT be triggered by pin0 alone in AND mode"); + + /* Trigger pin1 as well - now both are HIGH, should trigger interrupt */ + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 1); + zassert_ok(ret, "Failed to set pin1 HIGH"); + + k_msleep(50); + + zassert_equal(atomic_get(&gint_callback_count), 1, + "GINT interrupt should be triggered when both pins are HIGH in AND mode"); + + /* Reset both pins and callback counter */ + ret = gpio_pin_set_raw(gpio_pin0.port, gpio_pin0.pin, 0); + zassert_ok(ret, "Failed to set pin0 LOW"); + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 0); + zassert_ok(ret, "Failed to set pin1 LOW"); + k_msleep(10); + atomic_set(&gint_callback_count, 0); + + /* Trigger only pin1 - should NOT trigger interrupt in AND mode */ + ret = gpio_pin_set_raw(gpio_pin1.port, gpio_pin1.pin, 1); + zassert_ok(ret, "Failed to set pin1 HIGH"); + + k_msleep(50); + + zassert_equal(atomic_get(&gint_callback_count), 0, + "GINT interrupt should NOT be triggered by pin1 alone in AND mode"); + + /* Cleanup */ + nxp_gint_disable_pin(gint_dev, TEST_PORT_0, TEST_PIN_0); + nxp_gint_disable_pin(gint_dev, TEST_PORT_1, TEST_PIN_1); +} + +ZTEST_SUITE(intc_nxp_gint, NULL, test_gint_setup, test_gint_before, NULL, NULL); diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml b/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml new file mode 100644 index 0000000000000..0623eeddf435d --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml @@ -0,0 +1,11 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +common: + tags: + - drivers + - gint + +tests: + drivers.interrupt_controller.intc_nxp_gint: + platform_allow: From 5f7910560a442165ac406bc1642d2b30ca7b3d68 Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Sat, 29 Nov 2025 11:42:47 +0800 Subject: [PATCH 5/6] boards: nxp: gint: Enable GINT for NXP boards Set the DTS node to okay status Signed-off-by: Jason Yu --- boards/nxp/frdm_mcxw23/frdm_mcxw23_common.dtsi | 4 ++++ boards/nxp/lpcxpresso51u68/lpcxpresso51u68.dts | 8 ++++++++ .../nxp/lpcxpresso54114/lpcxpresso54114_lpc54114_m4.dts | 8 ++++++++ boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi | 8 ++++++++ boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi | 8 ++++++++ boards/nxp/lpcxpresso55s28/lpcxpresso55s28_common.dtsi | 8 ++++++++ boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts | 8 ++++++++ .../nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts | 8 ++++++++ .../lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts | 8 ++++++++ .../nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu1.dts | 8 ++++++++ boards/nxp/mcxw23_evk/mcxw23_evk_common.dtsi | 4 ++++ 11 files changed, 80 insertions(+) diff --git a/boards/nxp/frdm_mcxw23/frdm_mcxw23_common.dtsi b/boards/nxp/frdm_mcxw23/frdm_mcxw23_common.dtsi index 205594e59d760..565965a2fe18e 100644 --- a/boards/nxp/frdm_mcxw23/frdm_mcxw23_common.dtsi +++ b/boards/nxp/frdm_mcxw23/frdm_mcxw23_common.dtsi @@ -205,6 +205,10 @@ status = "okay"; }; +&gint0 { + status = "okay"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/nxp/lpcxpresso51u68/lpcxpresso51u68.dts b/boards/nxp/lpcxpresso51u68/lpcxpresso51u68.dts index 120b0565494ae..1bc7927f368a8 100644 --- a/boards/nxp/lpcxpresso51u68/lpcxpresso51u68.dts +++ b/boards/nxp/lpcxpresso51u68/lpcxpresso51u68.dts @@ -73,6 +73,14 @@ }; }; +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; + &flexcomm0 { status = "okay"; compatible = "nxp,lpc-usart"; diff --git a/boards/nxp/lpcxpresso54114/lpcxpresso54114_lpc54114_m4.dts b/boards/nxp/lpcxpresso54114/lpcxpresso54114_lpc54114_m4.dts index 17a45a0f5d585..d547d15c15219 100644 --- a/boards/nxp/lpcxpresso54114/lpcxpresso54114_lpc54114_m4.dts +++ b/boards/nxp/lpcxpresso54114/lpcxpresso54114_lpc54114_m4.dts @@ -116,3 +116,11 @@ }; }; }; + +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; diff --git a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi index a5680e8df8711..c633a804b71fa 100644 --- a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi +++ b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi @@ -171,3 +171,11 @@ max-bitrate = <5000000>; }; }; + +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; diff --git a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi index 29526166613ed..5535cea87516d 100644 --- a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi +++ b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi @@ -219,6 +219,14 @@ }; }; +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; + arduino_i2c: &flexcomm4 {}; arduino_spi: &hs_lspi {}; diff --git a/boards/nxp/lpcxpresso55s28/lpcxpresso55s28_common.dtsi b/boards/nxp/lpcxpresso55s28/lpcxpresso55s28_common.dtsi index 6a2531d23b60f..79b44e7c0174e 100644 --- a/boards/nxp/lpcxpresso55s28/lpcxpresso55s28_common.dtsi +++ b/boards/nxp/lpcxpresso55s28/lpcxpresso55s28_common.dtsi @@ -92,6 +92,14 @@ }; }; +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; + &flexcomm0 { compatible = "nxp,lpc-usart"; current-speed = <115200>; diff --git a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts index 46da74e55e310..f2c65fdb5d0c0 100644 --- a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts +++ b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts @@ -203,6 +203,14 @@ zephyr_udc0: &usbfs { status = "okay"; }; +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; + &dac0 { status = "okay"; pinctrl-0 = <&pinmux_dac0>; diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts index f25e69c574c37..a50a547297be9 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts @@ -240,3 +240,11 @@ i2s1: &flexcomm7 { &counter_rtc { status = "okay"; }; + +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts index 9bad03c71dd22..10a99310ef0e1 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts @@ -137,3 +137,11 @@ zephyr_udc0: &usbhs { &ctimer4 { status = "okay"; }; + +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu1.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu1.dts index 2e8760b9961eb..6315192fd0fd5 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu1.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu1.dts @@ -60,3 +60,11 @@ &mma8652fc { status = "disabled"; }; + +&gint0 { + status = "okay"; +}; + +&gint1 { + status = "okay"; +}; diff --git a/boards/nxp/mcxw23_evk/mcxw23_evk_common.dtsi b/boards/nxp/mcxw23_evk/mcxw23_evk_common.dtsi index c21e8e277696c..9c885180780bf 100644 --- a/boards/nxp/mcxw23_evk/mcxw23_evk_common.dtsi +++ b/boards/nxp/mcxw23_evk/mcxw23_evk_common.dtsi @@ -185,6 +185,10 @@ status = "okay"; }; +&gint0 { + status = "okay"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; From de61a2947bec8ae06700f6cde40aa37d7247066f Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Fri, 28 Nov 2025 23:12:03 +0800 Subject: [PATCH 6/6] tests: drivers: gint: Enable GINT test for NXP boards Enable the test case for NXP boards Signed-off-by: Jason Yu --- .../intc_nxp_gint/boards/mcxw23_evk.overlay | 21 +++++++++++++++++++ .../intc_nxp_gint/testcase.yaml | 10 +++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/drivers/interrupt_controller/intc_nxp_gint/boards/mcxw23_evk.overlay diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/boards/mcxw23_evk.overlay b/tests/drivers/interrupt_controller/intc_nxp_gint/boards/mcxw23_evk.overlay new file mode 100644 index 0000000000000..03e6e1bcb62be --- /dev/null +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/boards/mcxw23_evk.overlay @@ -0,0 +1,21 @@ +/* + * Copyright 2025 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + led1 = &fake_led; + }; + + /* + * This test needs node led0 and led1, only the pins are used, + * the pins are not needed to be real LED. + * This board only has led0, so use a unused pin as led1. + */ + leds { + fake_led: fake-led { + gpios = <&gpio0 1 0>; + }; + }; +}; diff --git a/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml b/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml index 0623eeddf435d..31fc0a740c2f9 100644 --- a/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml +++ b/tests/drivers/interrupt_controller/intc_nxp_gint/testcase.yaml @@ -8,4 +8,14 @@ common: tests: drivers.interrupt_controller.intc_nxp_gint: + extra_args: + - platform:mcxw23_evk:EXTRA_DTC_OVERLAY_FILE="boards/mcxw23_evk.overlay" platform_allow: + - frdm_mcxw23 + - mcxw23_evk + - lpcxpresso55s36 + - lpcxpresso51u68 + - lpcxpresso55s06 + - lpcxpresso55s16 + - lpcxpresso55s28 + - lpcxpresso55s69/lpc55s69/cpu0