diff --git a/MAINTAINERS b/MAINTAINERS index 6161a4507e4ec..b1a81b684f504 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17699,6 +17699,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next F: drivers/mtd/nand/ F: include/linux/mtd/*nand*.h +NATIONAL INSTRUMENTS DEVICETREE IRQ RESOLVER +M: Alison Montag +S: Maintained +F: drivers/misc/niirqresolver.c +F: include/linux/niirqresolver.h + NATIONAL INSTRUMENTS SERIAL DRIVER M: Chaitanya Vadrevu L: linux-serial@vger.kernel.org diff --git a/arch/arm/configs/nati_bluefin_defconfig b/arch/arm/configs/nati_bluefin_defconfig index 5cb1e0e1b40d4..d93765d777db9 100644 --- a/arch/arm/configs/nati_bluefin_defconfig +++ b/arch/arm/configs/nati_bluefin_defconfig @@ -82,6 +82,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SRAM=y +CONFIG_NI_IRQ_RESOLVER=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y CONFIG_SCSI=y diff --git a/arch/arm/configs/nati_slsc_defconfig b/arch/arm/configs/nati_slsc_defconfig index 4546c323117d8..1aa2a20e48601 100644 --- a/arch/arm/configs/nati_slsc_defconfig +++ b/arch/arm/configs/nati_slsc_defconfig @@ -71,6 +71,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SRAM=y +CONFIG_NI_IRQ_RESOLVER=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y CONFIG_EEPROM_93CX6=m diff --git a/arch/arm/configs/nati_zynq_defconfig b/arch/arm/configs/nati_zynq_defconfig index 8b849b1760254..eafc0445dc284 100644 --- a/arch/arm/configs/nati_zynq_defconfig +++ b/arch/arm/configs/nati_zynq_defconfig @@ -179,6 +179,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_FPGA_PERIPHERAL=y CONFIG_NIZYNQ_CPLD=y CONFIG_SRAM=y +CONFIG_NI_IRQ_RESOLVER=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y CONFIG_SCSI=y diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7f369157c4609..b25f99b0e82dc 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -694,6 +694,16 @@ config NI_WATCHDOG If unsure, say N (but it's safe to say "Y"). +config NI_IRQ_RESOLVER + bool "NI interrupt resolver" + depends on ARCH_ZYNQ + help + Resolves the Linux virtual IRQ for the HW interrupts. + Required for NI-RIO Zynq HW on kernels where the + GIC allocates virtual IRQs dynamically. + + If unsure, say Y on NI-RIO Zynq targets. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 0ca142eee19bf..f93bfc2dc288f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -79,3 +79,4 @@ obj-$(CONFIG_MISC_RP1) += rp1/ obj-$(CONFIG_NI_RT_FEATURES) += nirtfeatures.o obj-$(CONFIG_NI_WATCHDOG) += niwatchdog.o obj-$(CONFIG_FPGA_PERIPHERAL) += fpgaperipheral.o +obj-$(CONFIG_NI_IRQ_RESOLVER) += niirqresolver.o diff --git a/drivers/misc/niirqresolver.c b/drivers/misc/niirqresolver.c new file mode 100644 index 0000000000000..f1d2b6704af9b --- /dev/null +++ b/drivers/misc/niirqresolver.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic devicetree interrupt specifier -> Linux virq resolver. + * + * This file has no knowledge of any specific device, board, or interrupt + * controller: the caller supplies the controller's devicetree "compatible" + * string and its raw, controller-specific interrupt specifier cells (for + * example for an ARM GIC). + */ + +#include +#include +#include +#include +#include + +/** + * ni_of_resolve_irq - resolve a Linux virq from a devicetree interrupt specifier + * @compatible: devicetree "compatible" string of the interrupt controller node + * @args: raw interrupt specifier cells, controller-specific + * @args_count: number of valid entries in @args (must not exceed MAX_PHANDLE_ARGS) + * + * Finds the first devicetree node matching @compatible and asks its + * irqdomain to map @args to a Linux virq. Repeated calls with the same + * arguments return the same virq. + * + * Return: the Linux virtual IRQ number, or 0 if it could not be resolved + * (no matching node, args_count out of range, or the domain couldn't map it). + */ +unsigned int ni_of_resolve_irq(const char *compatible, const unsigned int *args, + unsigned int args_count) +{ + struct device_node *node; + struct of_phandle_args irq_spec; + unsigned int virq; + unsigned int i; + + if (args_count > MAX_PHANDLE_ARGS) + return 0; + + node = of_find_compatible_node(NULL, NULL, compatible); + if (!node) + return 0; + + irq_spec.np = node; + irq_spec.args_count = args_count; + for (i = 0; i < args_count; i++) + irq_spec.args[i] = args[i]; + + virq = irq_create_of_mapping(&irq_spec); + + of_node_put(node); + + return virq; +} +EXPORT_SYMBOL(ni_of_resolve_irq); diff --git a/include/linux/niirqresolver.h b/include/linux/niirqresolver.h new file mode 100644 index 0000000000000..cd2dee268a7a3 --- /dev/null +++ b/include/linux/niirqresolver.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Generic devicetree interrupt specifier -> Linux virq resolver. + * + * Public declaration for the NI IRQ resolver implemented in + * drivers/misc/niirqresolver.c. + */ + +#ifndef _LINUX_NIIRQRESOLVER_H_ +#define _LINUX_NIIRQRESOLVER_H_ + +/** + * ni_of_resolve_irq - resolve a Linux virq from a devicetree interrupt specifier + * @compatible: devicetree "compatible" string of the interrupt controller node + * @args: raw interrupt specifier cells, controller-specific + * @args_count: number of valid entries in @args (must not exceed MAX_PHANDLE_ARGS) + * + * Return: the Linux virtual IRQ number, or 0 if it could not be resolved. + */ +unsigned int ni_of_resolve_irq(const char *compatible, const unsigned int *args, + unsigned int args_count); + +#endif /* _LINUX_NIIRQRESOLVER_H_ */