replace our downstream version of the patches with the ones that were sent upstream. Signed-off-by: John Crispin <john@phrozen.org>
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From f3eacff2310a60348a755c50a8da6fc251fc8587 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/33] 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 | 142 +++++++++++++++++++++++++++++++++++++++
 | 
						|
 2 files changed, 143 insertions(+)
 | 
						|
 create mode 100644 drivers/irqchip/irq-ath79-intc.c
 | 
						|
 | 
						|
--- 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
 | 
						|
--- /dev/null
 | 
						|
+++ b/drivers/irqchip/irq-ath79-intc.c
 | 
						|
@@ -0,0 +1,142 @@
 | 
						|
+/*
 | 
						|
+ *  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 int_status;
 | 
						|
+	u32 irq_mask[ATH79_MAX_INTC_CASCADE];
 | 
						|
+	u32 irq_wb_chan[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(intc->int_status);
 | 
						|
+	pending &= intc->pending_mask;
 | 
						|
+
 | 
						|
+	if (pending) {
 | 
						|
+		int i;
 | 
						|
+
 | 
						|
+		for (i = 0; i < domain->hwirq_max; i++)
 | 
						|
+			if (pending & intc->irq_mask[i]) {
 | 
						|
+				if (intc->irq_wb_chan[i] != 0xffffffff)
 | 
						|
+					ath79_ddr_wb_flush(intc->irq_wb_chan[i]);
 | 
						|
+				generic_handle_irq(irq_find_mapping(domain, i));
 | 
						|
+			}
 | 
						|
+	} else {
 | 
						|
+		spurious_interrupt();
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void ath79_intc_irq_enable(struct irq_data *d)
 | 
						|
+{
 | 
						|
+	struct ath79_intc *intc = d->domain->host_data;
 | 
						|
+	enable_irq(intc->irq);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static void ath79_intc_irq_disable(struct irq_data *d)
 | 
						|
+{
 | 
						|
+	struct ath79_intc *intc = d->domain->host_data;
 | 
						|
+	disable_irq(intc->irq);
 | 
						|
+}
 | 
						|
+
 | 
						|
+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 ath79_intc_of_init(
 | 
						|
+	struct device_node *node, struct device_node *parent)
 | 
						|
+{
 | 
						|
+	struct irq_domain *domain;
 | 
						|
+	struct ath79_intc *intc;
 | 
						|
+	int cnt, cntwb, i, err;
 | 
						|
+
 | 
						|
+	cnt = of_property_count_u32_elems(node, "qca,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 = dummy_irq_chip;
 | 
						|
+	intc->chip.name = "INTC";
 | 
						|
+	intc->chip.irq_disable = ath79_intc_irq_disable;
 | 
						|
+	intc->chip.irq_enable = ath79_intc_irq_enable;
 | 
						|
+
 | 
						|
+	if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) {
 | 
						|
+		panic("Missing address of interrupt status register\n");
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt);
 | 
						|
+	for (i = 0; i < cnt; i++) {
 | 
						|
+		intc->pending_mask |= intc->irq_mask[i];
 | 
						|
+		intc->irq_wb_chan[i] = 0xffffffff;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	cntwb = of_count_phandle_with_args(
 | 
						|
+		node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
 | 
						|
+
 | 
						|
+	for (i = 0; i < cntwb; i++) {
 | 
						|
+		struct of_phandle_args args;
 | 
						|
+		u32 irq = i;
 | 
						|
+
 | 
						|
+		of_property_read_u32_index(
 | 
						|
+			node, "qca,ddr-wb-channel-interrupts", i, &irq);
 | 
						|
+		if (irq >= ATH79_MAX_INTC_CASCADE)
 | 
						|
+			continue;
 | 
						|
+
 | 
						|
+		err = of_parse_phandle_with_args(
 | 
						|
+			node, "qca,ddr-wb-channels",
 | 
						|
+			"#qca,ddr-wb-channel-cells",
 | 
						|
+			i, &args);
 | 
						|
+		if (err)
 | 
						|
+			return err;
 | 
						|
+
 | 
						|
+		intc->irq_wb_chan[irq] = args.args[0];
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	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(ath79_intc, "qca,ar9340-intc",
 | 
						|
+		ath79_intc_of_init);
 |