aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohann Neuhauser <johann@it-neuhauser.de>2018-06-18 19:15:21 +0200
committerJohn Crispin <john@phrozen.org>2018-06-20 11:12:00 +0200
commitc7efc93509cbdf1471b06d20439dc23bcaa875d5 (patch)
treed98454a665b97b4fcdc2dedf1aa2383c8ff8b95d
parent189815462cda469f6bba2609d65a4591f83418e1 (diff)
downloadupstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.tar.gz
upstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.tar.bz2
upstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.zip
ath79: fix irq-ath79-intc driver and add support for other ath79 SoCs
Add the missing enable and disable function. Remove dummy mask and unmask function and use the one provided by irq_dummy_chip. Allow interrupt status register being defined from dts. Add ddr_wb_flush for ar934x/qca953x. Rename controller name to qca,ar9340-intc because this design was first introduced in AR934x. Signed-off-by: Chuanhong Guo <gch981213@gmail.com> Signed-off-by: Johann Neuhauser <johann@it-neuhauser.de>
-rw-r--r--target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch66
1 files changed, 52 insertions, 14 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
index 72a7a5ee29..ae3e6c068d 100644
--- 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
@@ -23,7 +23,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
--- /dev/null
+++ b/drivers/irqchip/irq-ath79-intc.c
-@@ -0,0 +1,104 @@
+@@ -0,0 +1,142 @@
+/*
+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling
+ *
@@ -50,7 +50,9 @@ Signed-off-by: John Crispin <john@phrozen.org>
+ 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)
@@ -59,26 +61,33 @@ Signed-off-by: John Crispin <john@phrozen.org>
+ struct ath79_intc *intc = domain->host_data;
+ u32 pending;
+
-+ pending = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
++ 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 (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_unmask(struct irq_data *d)
++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_mask(struct irq_data *d)
++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)
@@ -95,27 +104,56 @@ Signed-off-by: John Crispin <john@phrozen.org>
+ .map = ath79_intc_map,
+};
+
-+static int __init qca9556_intc_of_init(
++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, i;
++ int cnt, cntwb, i, err;
+
-+ cnt = of_property_count_u32_elems(node, "qcom,pending-bits");
++ 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_unmask = ath79_intc_irq_unmask,
-+ intc->chip.irq_mask = ath79_intc_irq_mask,
++ intc->chip.irq_disable = ath79_intc_irq_disable;
++ intc->chip.irq_enable = ath79_intc_irq_enable;
+
-+ of_property_read_u32_array(node, "qcom,pending-bits", intc->irq_mask, cnt);
-+ for (i = 0; i < cnt; i++)
++ 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)
@@ -126,5 +164,5 @@ Signed-off-by: John Crispin <john@phrozen.org>
+
+ return 0;
+}
-+IRQCHIP_DECLARE(qca9556_intc, "qcom,qca9556-intc",
-+ qca9556_intc_of_init);
++IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc",
++ ath79_intc_of_init);