diff options
Diffstat (limited to 'target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch')
-rw-r--r-- | target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch new file mode 100644 index 0000000..18c9fd4 --- /dev/null +++ b/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -0,0 +1,138 @@ +From cb376159800b9b44be76949c3aee89eb06d29faa Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Tue, 6 Mar 2018 09:55:13 +0100 +Subject: [PATCH 07/27] irqchip/irq-ath79-intc: add irq cascade driver for + QCA9556 SoCs + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-ath79-intc.c | 104 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 105 insertions(+) + create mode 100644 drivers/irqchip/irq-ath79-intc.c + +diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile +index d27e3e3619e0..f63c94a92e25 100644 +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -3,6 +3,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o + + obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o + obj-$(CONFIG_ATH79) += irq-ath79-cpu.o ++obj-$(CONFIG_ATH79) += irq-ath79-intc.o + obj-$(CONFIG_ATH79) += irq-ath79-misc.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o +diff --git a/drivers/irqchip/irq-ath79-intc.c b/drivers/irqchip/irq-ath79-intc.c +new file mode 100644 +index 000000000000..a26d3efe6e10 +--- /dev/null ++++ b/drivers/irqchip/irq-ath79-intc.c +@@ -0,0 +1,104 @@ ++/* ++ * Atheros AR71xx/AR724x/AR913x specific interrupt handling ++ * ++ * Copyright (C) 2018 John Crispin <john@phrozen.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/interrupt.h> ++#include <linux/irqchip.h> ++#include <linux/of.h> ++#include <linux/of_irq.h> ++#include <linux/irqdomain.h> ++ ++#include <asm/irq_cpu.h> ++#include <asm/mach-ath79/ath79.h> ++#include <asm/mach-ath79/ar71xx_regs.h> ++ ++#define ATH79_MAX_INTC_CASCADE 3 ++ ++struct ath79_intc { ++ struct irq_chip chip; ++ u32 irq; ++ u32 pending_mask; ++ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; ++}; ++ ++static void ath79_intc_irq_handler(struct irq_desc *desc) ++{ ++ struct irq_domain *domain = irq_desc_get_handler_data(desc); ++ struct ath79_intc *intc = domain->host_data; ++ u32 pending; ++ ++ pending = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); ++ pending &= intc->pending_mask; ++ ++ if (pending) { ++ int i; ++ ++ for (i = 0; i < domain->hwirq_max; i++) ++ if (pending & intc->irq_mask[i]) ++ generic_handle_irq(irq_find_mapping(domain, i)); ++ } else { ++ spurious_interrupt(); ++ } ++} ++ ++static void ath79_intc_irq_unmask(struct irq_data *d) ++{ ++} ++ ++static void ath79_intc_irq_mask(struct irq_data *d) ++{ ++} ++ ++static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ struct ath79_intc *intc = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops ath79_irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = ath79_intc_map, ++}; ++ ++static int __init qca9556_intc_of_init( ++ struct device_node *node, struct device_node *parent) ++{ ++ struct irq_domain *domain; ++ struct ath79_intc *intc; ++ int cnt, i; ++ ++ cnt = of_property_count_u32_elems(node, "qcom,pending-bits"); ++ if (cnt > ATH79_MAX_INTC_CASCADE) ++ panic("Too many INTC pending bits\n"); ++ ++ intc = kzalloc(sizeof(*intc), GFP_KERNEL); ++ if (!intc) ++ panic("Failed to allocate INTC memory\n"); ++ intc->chip.name = "INTC"; ++ intc->chip.irq_unmask = ath79_intc_irq_unmask, ++ intc->chip.irq_mask = ath79_intc_irq_mask, ++ ++ of_property_read_u32_array(node, "qcom,pending-bits", intc->irq_mask, cnt); ++ for (i = 0; i < cnt; i++) ++ intc->pending_mask |= intc->irq_mask[i]; ++ ++ intc->irq = irq_of_parse_and_map(node, 0); ++ if (!intc->irq) ++ panic("Failed to get INTC IRQ"); ++ ++ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); ++ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); ++ ++ return 0; ++} ++IRQCHIP_DECLARE(qca9556_intc, "qcom,qca9556-intc", ++ qca9556_intc_of_init); +-- +2.11.0 + |