ath79: copy patches and kernel config from 5.15 to 6.1
[openwrt/staging/blocktrron.git] / target / linux / ath79 / patches-6.1 / 300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
diff --git a/target/linux/ath79/patches-6.1/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.1/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch
new file mode 100644 (file)
index 0000000..ceda511
--- /dev/null
@@ -0,0 +1,168 @@
+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
+@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQCHIP)                  += irqchip.o
+ obj-$(CONFIG_AL_FIC)                  += irq-al-fic.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);