ath79: fix irq-ath79-intc driver and add support for other ath79 SoCs
authorJohann Neuhauser <johann@it-neuhauser.de>
Mon, 18 Jun 2018 17:15:21 +0000 (19:15 +0200)
committerJohn Crispin <john@phrozen.org>
Wed, 20 Jun 2018 09:12:00 +0000 (11:12 +0200)
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>
target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch

index 72a7a5ee2960ee7bbc51be26d315effba6627150..ae3e6c068da1d9614218a723cec6ac2ddea7c735 100644 (file)
@@ -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);