diff --git a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig index 35a1f47f27a280..05afc38f92fa38 100644 --- a/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig +++ b/boards/nuvoton/npcm400f_evb/npcm400f_evb_defconfig @@ -33,3 +33,6 @@ CONFIG_UART_CONSOLE=y # GPIO Driver CONFIG_GPIO=y CONFIG_GPIO_NPCM=y + +# MIWU Driver +CONFIG_NPCM_MIWU=y diff --git a/drivers/gpio/gpio_npcm.c b/drivers/gpio/gpio_npcm.c index e35520ac073bb0..0a26105a19bf7a 100644 --- a/drivers/gpio/gpio_npcm.c +++ b/drivers/gpio/gpio_npcm.c @@ -66,7 +66,6 @@ const struct device *npcm_get_gpio_dev(int port) return gpio_devs[port]; } -#ifdef CONFIG_NPCM_MIWU void npcm_gpio_enable_io_pads(const struct device *dev, int pin) { const struct gpio_npcm_config *const config = dev->config; @@ -104,14 +103,6 @@ void npcm_gpio_disable_io_pads(const struct device *dev, int pin) npcm_miwu_io_disable(io_wui); } } -#else -void npcm_gpio_enable_io_pads(const struct device *dev, int pin) -{ -} -void npcm_gpio_disable_io_pads(const struct device *dev, int pin) -{ -} -#endif /* GPIO api functions */ static int gpio_npcm_config(const struct device *dev, @@ -277,7 +268,6 @@ static int gpio_npcm_port_toggle_bits(const struct device *dev, return 0; } -#ifdef CONFIG_NPCM_MIWU static int gpio_npcm_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, @@ -337,23 +327,12 @@ static int gpio_npcm_pin_interrupt_configure(const struct device *dev, return 0; } -#else -static int gpio_npcm_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - return -EINVAL; -} -#endif - -#ifdef CONFIG_NPCM_MIWU static int gpio_npcm_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) { const struct gpio_npcm_config *const config = dev->config; - struct miwu_io_callback *miwu_cb = (struct miwu_io_callback *)callback; + struct miwu_callback *miwu_cb = (struct miwu_callback *)callback; int pin = find_lsb_set(callback->pin_mask) - 1; /* pin_mask should not be zero */ @@ -373,15 +352,8 @@ static int gpio_npcm_manage_callback(const struct device *dev, config->port); /* Insert or remove a IO callback which being called in MIWU ISRs */ - return npcm_miwu_manage_gpio_callback(miwu_cb, set); + return npcm_miwu_manage_callback(miwu_cb, set); } -#else -static int gpio_npcm_manage_callback(const struct device *dev, - struct gpio_callback *callback, bool set) -{ - return -EINVAL; -} -#endif /* GPIO driver registration */ static const struct gpio_driver_api gpio_npcm_driver = { diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 9e07386e59eb14..79a93b997ce507 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -21,6 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_LEON_IRQMP intc_irqmp.c) zephyr_library_sources_ifdef(CONFIG_LOAPIC intc_loapic.c intc_system_apic.c) zephyr_library_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR intc_loapic_spurious.S) zephyr_library_sources_ifdef(CONFIG_MCHP_ECIA_XEC intc_mchp_ecia_xec.c) +zephyr_library_sources_ifdef(CONFIG_NPCM_MIWU intc_npcm_miwu.c) zephyr_library_sources_ifdef(CONFIG_NPCX_MIWU intc_miwu.c) zephyr_library_sources_ifdef(CONFIG_PLIC intc_plic.c) zephyr_library_sources_ifdef(CONFIG_RV32M1_INTMUX intc_rv32m1_intmux.c) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index a956afdf1f6024..d99ce17d97674b 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -78,6 +78,8 @@ source "drivers/interrupt_controller/Kconfig.sam0" source "drivers/interrupt_controller/Kconfig.gic" +source "drivers/interrupt_controller/Kconfig.npcm" + source "drivers/interrupt_controller/Kconfig.npcx" source "drivers/interrupt_controller/Kconfig.intel_vtd" diff --git a/drivers/interrupt_controller/Kconfig.npcm b/drivers/interrupt_controller/Kconfig.npcm new file mode 100644 index 00000000000000..bfb549fdde3289 --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.npcm @@ -0,0 +1,13 @@ +# NPCM GPIO driver configuration options + +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config NPCM_MIWU + bool "Nuvoton NPCM embedded controller (EC) miwu driver" + default y + depends on SOC_FAMILY_NPCM + help + This option enables the Multi-Input Wake-Up Unit (MIWU) driver + for NPCM family ofprocessors. + This is required for GPIO, RTC, LPC/eSPI interrupt support. diff --git a/drivers/interrupt_controller/intc_npcm_miwu.c b/drivers/interrupt_controller/intc_npcm_miwu.c new file mode 100644 index 00000000000000..9dd186881163d0 --- /dev/null +++ b/drivers/interrupt_controller/intc_npcm_miwu.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcm_miwu + +/** + * @file + * @brief Nuvoton NPCM MIWU driver + * + * The device Multi-Input Wake-Up Unit (MIWU) supports the Nuvoton embedded + * controller (EC) to exit 'Sleep' or 'Deep Sleep' power state. + * Also, it provides signal conditioning such as + * 'Level' and 'Edge' trigger type and grouping of external interrupt sources + * of NVIC. The NPCM series has three identical MIWU modules: MIWU0, MIWU1, + * MIWU2. Together, they support a total of 143 internal and/or external + * wake-up input (WUI) sources. + * + * This driver uses device tree files to present the relationship bewteen + * MIWU and the other devices in npcm target. + * it include: + * 1. npcm-miwus-wui-map.dtsi: it presents relationship between wake-up inputs + * (WUI) and its source device such as gpio, timer, eSPI VWs and so on. + * 2. npcm-miwus-int-map.dtsi: it presents relationship between MIWU group + * and NVIC interrupt in npcm target. Basically, it's a 1-to-1 mapping. + * There is a group which has 2 interrupts as an exception. + * + * INCLUDE FILES: soc_miwu.h + * + */ + +#include +#include +#include +#include +#include +#include + +#include "soc_miwu.h" +#include "soc_gpio.h" + +#include +#include +LOG_MODULE_REGISTER(intc_npcm_miwu, LOG_LEVEL_ERR); + +/* MIWU module instances */ +#define NPCM_MIWU_DEV(inst) DEVICE_DT_INST_GET(inst), + +static const struct device *miwu_devs[] = { + DT_INST_FOREACH_STATUS_OKAY(NPCM_MIWU_DEV) +}; + +BUILD_ASSERT(ARRAY_SIZE(miwu_devs) == NPCM_MIWU_TABLE_COUNT, + "Size of miwu_devs array must equal to NPCM_MIWU_TABLE_COUNT"); + +/* Driver config */ +struct intc_miwu_config { + /* miwu controller base address */ + uintptr_t base; + /* index of miwu controller */ + uint8_t index; +}; + +/* Driver data */ +struct intc_miwu_data { + /* Callback functions list for each MIWU group */ + sys_slist_t cb_list_grp[8]; +}; + +BUILD_ASSERT(sizeof(struct miwu_io_params) == sizeof(gpio_port_pins_t), + "Size of struct miwu_io_params must equal to struct gpio_port_pins_t"); + +BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params) + + sizeof(struct miwu_io_params) == sizeof(struct gpio_callback), + "Failed in size check of miwu_callback and gpio_callback structures!"); + +BUILD_ASSERT(offsetof(struct miwu_callback, io_cb.params.cb_type) == + offsetof(struct miwu_callback, dev_cb.params.cb_type), + "Failed in offset check of cb_type field of miwu_callback structure"); + +/* MIWU local functions */ +static void intc_miwu_dispatch_isr(sys_slist_t *cb_list, uint8_t mask) +{ + struct miwu_callback *cb, *tmp; + + SYS_SLIST_FOR_EACH_CONTAINER_SAFE(cb_list, cb, tmp, node) { + + if (cb->io_cb.params.cb_type == NPCM_MIWU_CALLBACK_GPIO) { + if (BIT(cb->io_cb.params.wui.bit) & mask) { + __ASSERT(cb->io_cb.handler, "No GPIO callback handler!"); + cb->io_cb.handler( + npcm_get_gpio_dev(cb->io_cb.params.gpio_port), + (struct gpio_callback *)cb, + cb->io_cb.params.pin_mask); + } + } else { + if (BIT(cb->dev_cb.params.wui.bit) & mask) { + __ASSERT(cb->dev_cb.handler, "No device callback handler!"); + + cb->dev_cb.handler(cb->dev_cb.params.source, + &cb->dev_cb.params.wui); + } + } + } +} + +static void intc_miwu_isr_pri(int wui_table, int wui_group) +{ + const struct intc_miwu_config *config = miwu_devs[wui_table]->config; + struct intc_miwu_data *data = miwu_devs[wui_table]->data; + const uint32_t base = config->base; + uint8_t mask = NPCM_WKPND(base, wui_group) & NPCM_WKEN(base, wui_group); + + /* Clear pending bits before dispatch ISR */ + if (mask) { + NPCM_WKPCL(base, wui_group) = mask; + } + + /* Dispatch registered gpio isrs */ + intc_miwu_dispatch_isr(&data->cb_list_grp[wui_group], mask); +} + +/* Platform specific MIWU functions */ +void npcm_miwu_irq_enable(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + + NPCM_WKEN(base, wui->group) |= BIT(wui->bit); +} + +void npcm_miwu_irq_disable(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + + NPCM_WKEN(base, wui->group) &= ~BIT(wui->bit); +} + +void npcm_miwu_io_enable(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + + NPCM_WKINEN(base, wui->group) |= BIT(wui->bit); +} + +void npcm_miwu_io_disable(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + + NPCM_WKINEN(base, wui->group) &= ~BIT(wui->bit); +} + +bool npcm_miwu_irq_get_state(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + + return IS_BIT_SET(NPCM_WKEN(base, wui->group), wui->bit); +} + +bool npcm_miwu_irq_get_and_clear_pending(const struct npcm_wui *wui) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + bool pending = IS_BIT_SET(NPCM_WKPND(base, wui->group), wui->bit); + + if (pending) { + NPCM_WKPCL(base, wui->group) = BIT(wui->bit); + } + + return pending; +} + +int npcm_miwu_interrupt_configure(const struct npcm_wui *wui, + enum miwu_int_mode mode, enum miwu_int_trig trig) +{ + const struct intc_miwu_config *config = miwu_devs[wui->table]->config; + const uint32_t base = config->base; + uint8_t pmask = BIT(wui->bit); + + /* Disable interrupt of wake-up input source before configuring it */ + npcm_miwu_irq_disable(wui); + + /* Handle interrupt for level trigger */ + if (mode == NPCM_MIWU_MODE_LEVEL) { + /* Set detection mode to level */ + NPCM_WKMOD(base, wui->group) |= pmask; + switch (trig) { + /* Enable interrupting on level high */ + case NPCM_MIWU_TRIG_HIGH: + NPCM_WKEDG(base, wui->group) &= ~pmask; + break; + /* Enable interrupting on level low */ + case NPCM_MIWU_TRIG_LOW: + NPCM_WKEDG(base, wui->group) |= pmask; + break; + default: + return -EINVAL; + } + /* Handle interrupt for edge trigger */ + } else { + /* Set detection mode to edge */ + NPCM_WKMOD(base, wui->group) &= ~pmask; + switch (trig) { + /* Handle interrupting on falling edge */ + case NPCM_MIWU_TRIG_LOW: + NPCM_WKAEDG(base, wui->group) &= ~pmask; + NPCM_WKEDG(base, wui->group) |= pmask; + break; + /* Handle interrupting on rising edge */ + case NPCM_MIWU_TRIG_HIGH: + NPCM_WKAEDG(base, wui->group) &= ~pmask; + NPCM_WKEDG(base, wui->group) &= ~pmask; + break; + /* Handle interrupting on both edges */ + case NPCM_MIWU_TRIG_BOTH: + /* Enable any edge */ + NPCM_WKAEDG(base, wui->group) |= pmask; + break; + default: + return -EINVAL; + } + } + + /* Enable wake-up input sources */ + NPCM_WKINEN(base, wui->group) |= pmask; + + /* + * Clear pending bit since it might be set if WKINEN bit is + * changed. + */ + NPCM_WKPCL(base, wui->group) |= pmask; + + return 0; +} + +void npcm_miwu_init_gpio_callback(struct miwu_callback *callback, + const struct npcm_wui *io_wui, int port) +{ + /* Initialize WUI and GPIO settings in unused bits field */ + callback->io_cb.params.wui.table = io_wui->table; + callback->io_cb.params.wui.bit = io_wui->bit; + callback->io_cb.params.gpio_port = port; + callback->io_cb.params.cb_type = NPCM_MIWU_CALLBACK_GPIO; + callback->io_cb.params.wui.group = io_wui->group; +} + +void npcm_miwu_init_dev_callback(struct miwu_callback *callback, + const struct npcm_wui *dev_wui, + miwu_dev_callback_handler_t handler, + const struct device *source) +{ + /* Initialize WUI and input device settings */ + callback->dev_cb.params.wui.table = dev_wui->table; + callback->dev_cb.params.wui.group = dev_wui->group; + callback->dev_cb.params.wui.bit = dev_wui->bit; + callback->dev_cb.params.source = source; + callback->dev_cb.params.cb_type = NPCM_MIWU_CALLBACK_DEV; + callback->dev_cb.handler = handler; +} + +int npcm_miwu_manage_callback(struct miwu_callback *cb, bool set) +{ + struct npcm_wui *wui; + struct intc_miwu_data *data; + sys_slist_t *cb_list; + + if (cb->io_cb.params.cb_type == NPCM_MIWU_CALLBACK_GPIO) { + wui = &cb->io_cb.params.wui; + } else { + wui = &cb->dev_cb.params.wui; + } + + data = miwu_devs[wui->table]->data; + cb_list = &data->cb_list_grp[wui->group]; + if (!sys_slist_is_empty(cb_list)) { + if (!sys_slist_find_and_remove(cb_list, &cb->node)) { + if (!set) { + return -EINVAL; + } + } + } + + if (set) { + sys_slist_prepend(cb_list, &cb->node); + } + + return 0; +} + +/* MIWU driver registration */ +#define NPCM_MIWU_ISR_FUNC(index) _CONCAT(intc_miwu_isr, index) +#define NPCM_MIWU_INIT_FUNC(inst) _CONCAT(intc_miwu_init, inst) +#define NPCM_MIWU_INIT_FUNC_DECL(inst) \ + static int intc_miwu_init##inst(const struct device *dev) + +/* MIWU ISR implementation */ +#define NPCM_MIWU_ISR_FUNC_IMPL(inst) \ + static void intc_miwu_isr##inst(void *arg) \ + { \ + uint8_t grp_mask = (uint32_t)arg; \ + int group = 0; \ + \ + /* Check all MIWU groups belong to the same irq */ \ + do { \ + if (grp_mask & 0x01) \ + intc_miwu_isr_pri(inst, group); \ + group++; \ + grp_mask = grp_mask >> 1; \ + \ + } while (grp_mask != 0); \ + } + +/* MIWU init function implementation */ +#define NPCM_MIWU_INIT_FUNC_IMPL(inst) \ + static int intc_miwu_init##inst(const struct device *dev) \ + { \ + int i; \ + const struct intc_miwu_config *config = dev->config; \ + const uint32_t base = config->base; \ + \ + /* Clear all MIWUs' pending and enable bits of MIWU device */ \ + for (i = 0; i < NPCM_MIWU_GROUP_COUNT; i++) { \ + NPCM_WKEN(base, i) = 0; \ + NPCM_WKPCL(base, i) = 0xFF; \ + } \ + \ + /* Config IRQ and MWIU group directly */ \ + DT_FOREACH_CHILD(NPCM_DT_NODE_FROM_MIWU_MAP(inst), \ + NPCM_DT_MIWU_IRQ_CONNECT_IMPL_CHILD_FUNC) \ + return 0; \ + } \ + +#define NPCM_MIWU_INIT(inst) \ + NPCM_MIWU_INIT_FUNC_DECL(inst); \ + \ + static const struct intc_miwu_config miwu_config_##inst = { \ + .base = DT_REG_ADDR(DT_NODELABEL(miwu##inst)), \ + .index = DT_PROP(DT_NODELABEL(miwu##inst), index), \ + }; \ + struct intc_miwu_data miwu_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + NPCM_MIWU_INIT_FUNC(inst), \ + NULL, \ + &miwu_data_##inst, &miwu_config_##inst, \ + PRE_KERNEL_1, \ + CONFIG_INTC_INIT_PRIORITY, NULL); \ + \ + NPCM_MIWU_ISR_FUNC_IMPL(inst) \ + \ + NPCM_MIWU_INIT_FUNC_IMPL(inst) + +DT_INST_FOREACH_STATUS_OKAY(NPCM_MIWU_INIT) diff --git a/dts/arm/nuvoton/npcm/npcm-miwus-int-map.dtsi b/dts/arm/nuvoton/npcm/npcm-miwus-int-map.dtsi new file mode 100644 index 00000000000000..4dd38058504a71 --- /dev/null +++ b/dts/arm/nuvoton/npcm/npcm-miwus-int-map.dtsi @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* Mapping between MIWU group and interrupts */ + npcm-miwus-int-map { + map_miwu0_groups: map-miwu0-groups { + compatible = "nuvoton,npcm-miwu-int-map"; + parent = <&miwu0>; + + group_a0: group-a0-map { + irq = <40>; + irq-prio = <2>; + group-mask = <0x01>; + }; + group_b0: group-b0-map { + irq = <41>; + irq-prio = <2>; + group-mask = <0x02>; + }; + group_c0: group-c0-map { + irq = <42>; + irq-prio = <2>; + group-mask = <0x04>; + }; + group_d0: group-d0-map { + irq = <43>; + irq-prio = <2>; + group-mask = <0x08>; + }; + group_e0: group-e0-map { + irq = <44>; + irq-prio = <2>; + group-mask = <0x10>; + }; + group_f0: group-f0-map { + irq = <45>; + irq-prio = <2>; + group-mask = <0x20>; + }; + group_g0: group-g0-map { + irq = <46>; + irq-prio = <2>; + group-mask = <0x40>; + }; + group_h0: group-h0-map { + irq = <47>; + irq-prio = <2>; + group-mask = <0x80>; + }; + }; + + map_miwu1_groups: map-miwu1-groups { + compatible = "nuvoton,npcm-miwu-int-map"; + parent = <&miwu1>; + + group_a1: group-a1-map { + irq = <48>; + irq-prio = <2>; + group-mask = <0x01>; + }; + group_b1: group-b1-map { + irq = <49>; + irq-prio = <2>; + group-mask = <0x02>; + }; + group_c1: group-c1-map { + irq = <50>; + irq-prio = <2>; + group-mask = <0x04>; + }; + group_d1: group-d1-map { + irq = <51>; + irq-prio = <2>; + group-mask = <0x08>; + }; + group_e1a: group-e1a-map { + irq = <36>; + irq-prio = <2>; + group-mask = <0x10>; + }; + group_e1b: group-e1b-map { + irq = <12>; + irq-prio = <2>; + group-mask = <0x10>; + }; + group_f1: group-f1-map { + irq = <53>; + irq-prio = <2>; + group-mask = <0x20>; + }; + group_g1: group-g1-map { + irq = <54>; + irq-prio = <2>; + group-mask = <0x40>; + }; + group_h1: group-h1-map { + irq = <55>; + irq-prio = <2>; + group-mask = <0x80>; + }; + }; + + map_miwu2_groups: map-miwu2-groups { + compatible = "nuvoton,npcm-miwu-int-map"; + parent = <&miwu2>; + + group_a2: group-a2-map { + irq = <60>; + irq-prio = <2>; + group-mask = <0x01>; + }; + group_b2: group-b2-map { + irq = <61>; + irq-prio = <2>; + group-mask = <0x02>; + }; + group_c2: group-c2-map { + irq = <62>; + irq-prio = <2>; + group-mask = <0x04>; + }; + group_d2: group-d2-map { + irq = <63>; + irq-prio = <2>; + group-mask = <0x08>; + }; + group_e2: group-e2-map { + irq = <56>; + irq-prio = <2>; + group-mask = <0x10>; + }; + group_f2: group-f2-map { + irq = <57>; + irq-prio = <2>; + group-mask = <0x20>; + }; + group_g2: group-g2-map { + irq = <58>; + irq-prio = <2>; + group-mask = <0x40>; + }; + group_h2: group-h2-map { + irq = <59>; + irq-prio = <2>; + group-mask = <0x80>; + }; + }; + }; +}; diff --git a/dts/arm/nuvoton/npcm/npcm4.dtsi b/dts/arm/nuvoton/npcm/npcm4.dtsi index a7cb004755e272..514df29aea9f40 100644 --- a/dts/arm/nuvoton/npcm/npcm4.dtsi +++ b/dts/arm/nuvoton/npcm/npcm4.dtsi @@ -6,8 +6,10 @@ /* npcm4 series pinmux mapping table */ #include "npcm4/npcm4-alts-map.dtsi" -/* npcm4 series mapping table between MIWU groups and interrupts */ +/* npcm4 series mapping table between MIWU wui bits and source device */ #include "npcm4/npcm4-miwus-wui-map.dtsi" +/* npcm4 series mapping table between MIWU groups and interrupts */ +#include "npcm4/npcm4-miwus-int-map.dtsi" /* Device tree declarations of npcm soc family */ #include "npcm.dtsi" diff --git a/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-int-map.dtsi b/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-int-map.dtsi new file mode 100644 index 00000000000000..6ff1244ed9a125 --- /dev/null +++ b/dts/arm/nuvoton/npcm/npcm4/npcm4-miwus-int-map.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2024 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Common MIWU group-interrupt mapping configurations in npcm family */ +#include diff --git a/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-int-map.yaml b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-int-map.yaml new file mode 100644 index 00000000000000..c038b2d18cac9b --- /dev/null +++ b/dts/bindings/interrupt-controller/nuvoton,npcm-miwu-int-map.yaml @@ -0,0 +1,31 @@ +# Copyright (c) 2024 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: NPCM-MIWU group-interrupt mapping child node + +compatible: "nuvoton,npcm-miwu-int-map" + +properties: + parent: + type: phandle + required: true + description: parent device node of miwu groups + +child-binding: + description: Child node to present the mapping between MIWU group and interrupt + properties: + irq: + type: int + required: true + description: irq for miwu group + irq-prio: + type: int + required: true + description: irq's priority for miwu group. The valid number is from 0 to 7. + group-mask: + type: int + required: true + description: group bit-mask for miwu interrupts + groups: + type: array + description: groups shared the same interrupt diff --git a/soc/nuvoton/npcm/common/soc_miwu.h b/soc/nuvoton/npcm/common/soc_miwu.h index 620f957de14b88..ec20fd5c87e473 100644 --- a/soc/nuvoton/npcm/common/soc_miwu.h +++ b/soc/nuvoton/npcm/common/soc_miwu.h @@ -50,6 +50,12 @@ enum miwu_int_trig { NPCM_MIWU_TRIG_BOTH, /** Both edge rising and failing detection */ }; +/* NPCM miwu driver callback type */ +enum { + NPCM_MIWU_CALLBACK_GPIO, + NPCM_MIWU_CALLBACK_DEV, +}; + /** * @brief NPCM wake-up input source structure * @@ -79,46 +85,50 @@ typedef void (*miwu_dev_callback_handler_t)(const struct device *source, */ struct miwu_io_params { uint8_t pin_mask; /** A mask of pins the callback is interested in. */ - uint8_t reserved; uint8_t gpio_port; /** GPIO device index */ + uint8_t cb_type; /** Callback type */ struct npcm_wui wui; /** Wake-up input source of GPIO */ }; /** - * @brief MIWU callback structure for a GPIO input + * @brief MIWU/generic device information structure * - * Used to register a GPIO callback in the driver instance callback list. - * Beware such structure should not be allocated on stack and its size must - * equal struct gpio_callback. - * - * Note: To help setting it, see npcx_miwu_init_gpio_callback() below + * It contains the information used for MIWU generic device event. Please notice + * the offset of cb_type must be the same as cb_type in struct miwu_io_params. */ -struct miwu_io_callback { - /** Node of single-linked list */ - sys_snode_t node; - /** Callback function being called when GPIO event occurred */ - gpio_callback_handler_t handler; - /** GPIO callback parameters used in MIWU ISR */ - struct miwu_io_params params; +struct miwu_dev_params { + uint8_t reserve1; + uint8_t reserve2; + uint8_t cb_type; /** Callback type */ + struct npcm_wui wui; /** Device instance register callback function */ + const struct device *source; /** Wake-up input source */ }; /** - * @brief MIWU callback structure for a device input + * @brief MIWU callback structure for a gpio or device input * - * Used to register a generic hardware device callback in the driver instance + * Used to register a generic gpio/device callback in the driver instance * callback list. Beware such structure should not be allocated on stack. * - * Note: To help setting it, see npcm_miwu_init_dev_callback() below + * Note: To help setting it, see npcm_miwu_init_dev_callback() and + * npcm_miwu_manage_callback() below */ -struct miwu_dev_callback { +struct miwu_callback { /** Node of single-linked list */ sys_snode_t node; - /** Callback function being called when device event occurred */ - miwu_dev_callback_handler_t handler; - /** Device instance register callback function */ - const struct device *source; - /* Wake-up input source */ - struct npcm_wui wui; + union { + struct { + /** Callback function being called when GPIO event occurred */ + gpio_callback_handler_t handler; + struct miwu_io_params params; + } io_cb; + + struct { + /** Callback function being called when device event occurred */ + miwu_dev_callback_handler_t handler; + struct miwu_dev_params params; + } dev_cb; + }; }; /** @@ -181,50 +191,38 @@ int npcm_miwu_interrupt_configure(const struct npcm_wui *wui, enum miwu_int_mode mode, enum miwu_int_trig trig); /** - * @brief Function to initialize a struct miwu_io_callback properly + * @brief Function to initialize a struct miwu_callback with gpio properly * * @param callback Pointer to io callback structure for initialization * @param io_wui Pointer to wake-up input IO source * @param port GPIO port issued a callback function */ -void npcm_miwu_init_gpio_callback(struct miwu_io_callback *callback, +void npcm_miwu_init_gpio_callback(struct miwu_callback *callback, const struct npcm_wui *io_wui, int port); /** - * @brief Function to initialize a struct miwu_dev_callback properly + * @brief Function to initialize a struct miwu_callback with device properly * * @param callback Pointer to device callback structure for initialization * @param dev_wui Pointer to wake-up input device source * @param handler A function called when its device input event issued * @param source Pointer to device instance issued a callback function */ -void npcm_miwu_init_dev_callback(struct miwu_dev_callback *callback, +void npcm_miwu_init_dev_callback(struct miwu_callback *callback, const struct npcm_wui *dev_wui, miwu_dev_callback_handler_t handler, const struct device *source); /** - * @brief Function to insert or remove a IO callback from a callback list - * - * @param callback Pointer to io callback structure - * @param set A boolean indicating insertion or removal of the callback - * - * @retval 0 If successful. - * @retval -EINVAL Invalid parameters - */ -int npcm_miwu_manage_gpio_callback(struct miwu_io_callback *callback, bool set); - - -/** - * @brief Function to insert or remove a device callback from a callback list + * @brief Function to insert or remove a miwu callback from a callback list * - * @param callback Pointer to device callback structure + * @param callback Pointer to miwu callback structure * @param set A boolean indicating insertion or removal of the callback * * @retval 0 If successful. * @retval -EINVAL Invalid parameters */ -int npcm_miwu_manage_dev_callback(struct miwu_dev_callback *cb, bool set); +int npcm_miwu_manage_callback(struct miwu_callback *cb, bool set); #ifdef __cplusplus }