summaryrefslogtreecommitdiff
path: root/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
diff options
context:
space:
mode:
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.patch138
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
+