brcm63xx: convert to irq domain
authorJonas Gorski <jogo@openwrt.org>
Mon, 1 Dec 2014 00:51:51 +0000 (00:51 +0000)
committerJonas Gorski <jogo@openwrt.org>
Mon, 1 Dec 2014 00:51:51 +0000 (00:51 +0000)
Add irq-domain aware irqchip drivers for the irq controllers of bcm63xx
and switch to use them.

Signed-off-by: Jonas Gorski <jogo@openwrt.org>
SVN-Revision: 43454

21 files changed:
target/linux/brcm63xx/patches-3.14/030-MIPS-Always-use-IRQ-domains-for-CPU-IRQs.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/031-MIPS-Rename-mips_cpu_intc_init-mips_cpu_irq_of_init.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/032-MIPS-Provide-a-generic-plat_irq_dispatch.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/321-irqchip-add-support-for-bcm6345-style-external-inter.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch [new file with mode: 0644]
target/linux/brcm63xx/patches-3.14/328-cfe_simplify_detection.patch [deleted file]
target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch [deleted file]
target/linux/brcm63xx/patches-3.14/339-MIPS-BCM63XX-add-support-for-BCM63268.patch
target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch
target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch
target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch
target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch
target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch
target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch
target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch
target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch

diff --git a/target/linux/brcm63xx/patches-3.14/030-MIPS-Always-use-IRQ-domains-for-CPU-IRQs.patch b/target/linux/brcm63xx/patches-3.14/030-MIPS-Always-use-IRQ-domains-for-CPU-IRQs.patch
new file mode 100644 (file)
index 0000000..e6570ec
--- /dev/null
@@ -0,0 +1,98 @@
+From 0f84c305351c993e4307e1e8c128d44760314e31 Mon Sep 17 00:00:00 2001
+From: Andrew Bresticker <abrestic@chromium.org>
+Date: Thu, 18 Sep 2014 14:47:07 -0700
+Subject: [PATCH 1/3] MIPS: Always use IRQ domains for CPU IRQs
+
+Use an IRQ domain for the 8 CPU IRQs in both the DT and non-DT cases.
+
+Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
+Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
+Tested-by: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Jason Cooper <jason@lakedaemon.net>
+Cc: Andrew Bresticker <abrestic@chromium.org>
+Cc: Jeffrey Deans <jeffrey.deans@imgtec.com>
+Cc: Markos Chandras <markos.chandras@imgtec.com>
+Cc: Paul Burton <paul.burton@imgtec.com>
+Cc: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Jonas Gorski <jogo@openwrt.org>
+Cc: John Crispin <blogic@openwrt.org>
+Cc: David Daney <ddaney.cavm@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: linux-kernel@vger.kernel.org
+Patchwork: https://patchwork.linux-mips.org/patch/7799/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/Kconfig          |    1 +
+ arch/mips/kernel/irq_cpu.c |   36 +++++++++++-------------------------
+ 2 files changed, 12 insertions(+), 25 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -1025,6 +1025,7 @@ config MIPS_HUGE_TLB_SUPPORT
+ config IRQ_CPU
+       bool
++      select IRQ_DOMAIN
+ config IRQ_CPU_RM7K
+       bool
+--- a/arch/mips/kernel/irq_cpu.c
++++ b/arch/mips/kernel/irq_cpu.c
+@@ -94,28 +94,6 @@ static struct irq_chip mips_mt_cpu_irq_c
+       .irq_eoi        = unmask_mips_irq,
+ };
+-void __init mips_cpu_irq_init(void)
+-{
+-      int irq_base = MIPS_CPU_IRQ_BASE;
+-      int i;
+-
+-      /* Mask interrupts. */
+-      clear_c0_status(ST0_IM);
+-      clear_c0_cause(CAUSEF_IP);
+-
+-      /* Software interrupts are used for MT/CMT IPI */
+-      for (i = irq_base; i < irq_base + 2; i++)
+-              irq_set_chip_and_handler(i, cpu_has_mipsmt ?
+-                                       &mips_mt_cpu_irq_controller :
+-                                       &mips_cpu_irq_controller,
+-                                       handle_percpu_irq);
+-
+-      for (i = irq_base + 2; i < irq_base + 8; i++)
+-              irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
+-                                       handle_percpu_irq);
+-}
+-
+-#ifdef CONFIG_IRQ_DOMAIN
+ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
+                            irq_hw_number_t hw)
+ {
+@@ -138,8 +116,7 @@ static const struct irq_domain_ops mips_
+       .xlate = irq_domain_xlate_onecell,
+ };
+-int __init mips_cpu_intc_init(struct device_node *of_node,
+-                            struct device_node *parent)
++static void __init __mips_cpu_irq_init(struct device_node *of_node)
+ {
+       struct irq_domain *domain;
+@@ -151,7 +128,16 @@ int __init mips_cpu_intc_init(struct dev
+                                      &mips_cpu_intc_irq_domain_ops, NULL);
+       if (!domain)
+               panic("Failed to add irqdomain for MIPS CPU");
++}
++void __init mips_cpu_irq_init(void)
++{
++      __mips_cpu_irq_init(NULL);
++}
++
++int __init mips_cpu_intc_init(struct device_node *of_node,
++                            struct device_node *parent)
++{
++      __mips_cpu_irq_init(of_node);
+       return 0;
+ }
+-#endif /* CONFIG_IRQ_DOMAIN */
diff --git a/target/linux/brcm63xx/patches-3.14/031-MIPS-Rename-mips_cpu_intc_init-mips_cpu_irq_of_init.patch b/target/linux/brcm63xx/patches-3.14/031-MIPS-Rename-mips_cpu_intc_init-mips_cpu_irq_of_init.patch
new file mode 100644 (file)
index 0000000..de0f111
--- /dev/null
@@ -0,0 +1,89 @@
+From afe8dc254711b72ba8144295f4a8fcc66d30572d Mon Sep 17 00:00:00 2001
+From: Andrew Bresticker <abrestic@chromium.org>
+Date: Thu, 18 Sep 2014 14:47:08 -0700
+Subject: [PATCH 2/3] MIPS: Rename mips_cpu_intc_init() ->
+ mips_cpu_irq_of_init()
+
+mips_cpu_intc_init() is used for DT-based initialization of the CPU
+IRQ domain.  Give it a more appropriate name.
+
+Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
+Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
+Tested-by: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Jason Cooper <jason@lakedaemon.net>
+Cc: Andrew Bresticker <abrestic@chromium.org>
+Cc: Jeffrey Deans <jeffrey.deans@imgtec.com>
+Cc: Markos Chandras <markos.chandras@imgtec.com>
+Cc: Paul Burton <paul.burton@imgtec.com>
+Cc: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Jonas Gorski <jogo@openwrt.org>
+Cc: John Crispin <blogic@openwrt.org>
+Cc: David Daney <ddaney.cavm@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: linux-kernel@vger.kernel.org
+Patchwork: https://patchwork.linux-mips.org/patch/7800/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ Documentation/devicetree/bindings/mips/cpu_irq.txt |    4 ++--
+ arch/mips/include/asm/irq_cpu.h                    |    4 ++--
+ arch/mips/kernel/irq_cpu.c                         |    4 ++--
+ arch/mips/ralink/irq.c                             |    2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/Documentation/devicetree/bindings/mips/cpu_irq.txt
++++ b/Documentation/devicetree/bindings/mips/cpu_irq.txt
+@@ -1,6 +1,6 @@
+ MIPS CPU interrupt controller
+-On MIPS the mips_cpu_intc_init() helper can be used to initialize the 8 CPU
++On MIPS the mips_cpu_irq_of_init() helper can be used to initialize the 8 CPU
+ IRQs from a devicetree file and create a irq_domain for IRQ controller.
+ With the irq_domain in place we can describe how the 8 IRQs are wired to the
+@@ -36,7 +36,7 @@ Example devicetree:
+ Example platform irq.c:
+ static struct of_device_id __initdata of_irq_ids[] = {
+-      { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
++      { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+       { .compatible = "ralink,rt2880-intc", .data = intc_of_init },
+       {},
+ };
+--- a/arch/mips/include/asm/irq_cpu.h
++++ b/arch/mips/include/asm/irq_cpu.h
+@@ -19,8 +19,8 @@ extern void rm9k_cpu_irq_init(void);
+ #ifdef CONFIG_IRQ_DOMAIN
+ struct device_node;
+-extern int mips_cpu_intc_init(struct device_node *of_node,
+-                            struct device_node *parent);
++extern int mips_cpu_irq_of_init(struct device_node *of_node,
++                              struct device_node *parent);
+ #endif
+ #endif /* _ASM_IRQ_CPU_H */
+--- a/arch/mips/kernel/irq_cpu.c
++++ b/arch/mips/kernel/irq_cpu.c
+@@ -135,8 +135,8 @@ void __init mips_cpu_irq_init(void)
+       __mips_cpu_irq_init(NULL);
+ }
+-int __init mips_cpu_intc_init(struct device_node *of_node,
+-                            struct device_node *parent)
++int __init mips_cpu_irq_of_init(struct device_node *of_node,
++                              struct device_node *parent)
+ {
+       __mips_cpu_irq_init(of_node);
+       return 0;
+--- a/arch/mips/ralink/irq.c
++++ b/arch/mips/ralink/irq.c
+@@ -173,7 +173,7 @@ static int __init intc_of_init(struct de
+ }
+ static struct of_device_id __initdata of_irq_ids[] = {
+-      { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
++      { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+       { .compatible = "ralink,rt2880-intc", .data = intc_of_init },
+       {},
+ };
diff --git a/target/linux/brcm63xx/patches-3.14/032-MIPS-Provide-a-generic-plat_irq_dispatch.patch b/target/linux/brcm63xx/patches-3.14/032-MIPS-Provide-a-generic-plat_irq_dispatch.patch
new file mode 100644 (file)
index 0000000..79a0436
--- /dev/null
@@ -0,0 +1,58 @@
+From 85f7cdacbb81db8c4cc8e474837eab1f0e4ff77b Mon Sep 17 00:00:00 2001
+From: Andrew Bresticker <abrestic@chromium.org>
+Date: Thu, 18 Sep 2014 14:47:09 -0700
+Subject: [PATCH 3/3] MIPS: Provide a generic plat_irq_dispatch
+
+For platforms which boot with device-tree or have correctly chained
+all external interrupt controllers, a generic plat_irq_dispatch() can
+be used.  Implement a plat_irq_dispatch() which simply handles all the
+pending interrupts as reported by C0_Cause.
+
+Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
+Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
+Tested-by: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Jason Cooper <jason@lakedaemon.net>
+Cc: Andrew Bresticker <abrestic@chromium.org>
+Cc: Jeffrey Deans <jeffrey.deans@imgtec.com>
+Cc: Markos Chandras <markos.chandras@imgtec.com>
+Cc: Paul Burton <paul.burton@imgtec.com>
+Cc: Qais Yousef <qais.yousef@imgtec.com>
+Cc: Jonas Gorski <jogo@openwrt.org>
+Cc: John Crispin <blogic@openwrt.org>
+Cc: David Daney <ddaney.cavm@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: linux-kernel@vger.kernel.org
+Patchwork: https://patchwork.linux-mips.org/patch/7801/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/kernel/irq_cpu.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/arch/mips/kernel/irq_cpu.c
++++ b/arch/mips/kernel/irq_cpu.c
+@@ -94,6 +94,24 @@ static struct irq_chip mips_mt_cpu_irq_c
+       .irq_eoi        = unmask_mips_irq,
+ };
++asmlinkage void __weak plat_irq_dispatch(void)
++{
++      unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
++      int irq;
++
++      if (!pending) {
++              spurious_interrupt();
++              return;
++      }
++
++      pending >>= CAUSEB_IP;
++      while (pending) {
++              irq = fls(pending) - 1;
++              do_IRQ(MIPS_CPU_IRQ_BASE + irq);
++              pending &= ~BIT(irq);
++      }
++}
++
+ static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
+                            irq_hw_number_t hw)
+ {
diff --git a/target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch b/target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch
new file mode 100644 (file)
index 0000000..e05c91d
--- /dev/null
@@ -0,0 +1,20 @@
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
+@@ -1,6 +1,8 @@
+ #ifndef BCM63XX_BOARD_H_
+ #define BCM63XX_BOARD_H_
++#include <asm/bootinfo.h>
++
+ const char *board_get_name(void);
+ void board_prom_init(void);
+@@ -9,4 +11,8 @@ void board_setup(void);
+ int board_register_devices(void);
++static inline bool bcm63xx_is_cfe_present(void) {
++      return fw_arg3 == 0x43464531;
++}
++
+ #endif /* ! BCM63XX_BOARD_H_ */
diff --git a/target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch b/target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch
new file mode 100644 (file)
index 0000000..dedd728
--- /dev/null
@@ -0,0 +1,51 @@
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -35,7 +35,7 @@
+ #include <asm/mach-bcm63xx/bcm63xx_nvram.h>
+ #include <linux/bcm963xx_tag.h>
+-#include <asm/mach-bcm63xx/board_bcm963xx.h>
++#include <asm/mach-bcm63xx/bcm63xx_board.h>
+ #define BCM63XX_EXTENDED_SIZE 0xBFC00000      /* Extended flash address */
+@@ -43,30 +43,6 @@
+ #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
+-static int bcm63xx_detect_cfe(struct mtd_info *master)
+-{
+-      char buf[9];
+-      int ret;
+-      size_t retlen;
+-
+-      ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen,
+-                     (void *)buf);
+-      buf[retlen] = 0;
+-
+-      if (ret)
+-              return ret;
+-
+-      if (strncmp("cfe-v", buf, 5) == 0)
+-              return 0;
+-
+-      /* very old CFE's do not have the cfe-v string, so check for magic */
+-      ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
+-                     (void *)buf);
+-      buf[retlen] = 0;
+-
+-      return strncmp("CFE1CFE1", buf, 8);
+-}
+-
+ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
+                                       struct mtd_partition **pparts,
+                                       struct mtd_part_parser_data *data)
+@@ -85,7 +61,7 @@ static int bcm63xx_parse_cfe_partitions(
+       u32 computed_crc;
+       bool rootfs_first = false;
+-      if (bcm63xx_detect_cfe(master))
++      if (!bcm63xx_is_cfe_present())
+               return -EINVAL;
+       cfe_erasesize = max_t(uint32_t, master->erasesize,
diff --git a/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch b/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch
new file mode 100644 (file)
index 0000000..a260a1b
--- /dev/null
@@ -0,0 +1,411 @@
+From 4d3886359d6f6ac475e143d5f3e3b389542a0510 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 30 Nov 2014 14:53:12 +0100
+Subject: [PATCH 17/20] irqchip: add support for bcm6345-style l2 irq
+ controller
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ .../interrupt-controller/brcm,bcm6345-l2-intc.txt  |   25 ++
+ drivers/irqchip/Kconfig                            |    4 +
+ drivers/irqchip/Makefile                           |    1 +
+ drivers/irqchip/irq-bcm6345-l2.c                   |  320 ++++++++++++++++++++
+ include/linux/irqchip/irq-bcm6345-l2-intc.h        |   16 +
+ 5 files changed, 366 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l2-intc.txt
+ create mode 100644 drivers/irqchip/irq-bcm6345-l2.c
+ create mode 100644 include/linux/irqchip/irq-bcm6345-l2-intc.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l2-intc.txt
+@@ -0,0 +1,25 @@
++Broadcom BCM6345 Level 2 interrupt controller
++
++Required properties:
++
++- compatible: should be "brcm,bcm6345-l2-intc"
++- reg: specifies the base physical address and size of the registers;
++  multiple regs may be specified, and must match the amount of parent interrupts
++- interrupt-controller: identifies the node as an interrupt controller
++- #interrupt-cells: specifies the number of cells needed to encode an interrupt
++  source, should be 1
++- interrupt-parent: specifies the phandle to the parent interrupt controller
++  this one is cascaded from
++- interrupts: specifies the interrupt line(s) in the interrupt-parent controller
++  node, valid values depend on the type of parent interrupt controller
++
++Example:
++
++periph_intc: interrupt-controller@f0406800 {
++      compatible = "brcm,bcm6345-l2-intc";
++      interrupt-parent = <&mips_intc>;
++      #interrupt-cells = <1>;
++      reg = <0x10000020 0x10> <0x10000030 0x10>;
++      interrupt-controller;
++      interrupts = <2>, <3>;
++};
+--- a/drivers/irqchip/Kconfig
++++ b/drivers/irqchip/Kconfig
+@@ -30,6 +30,10 @@ config ARM_VIC_NR
+         The maximum number of VICs available in the system, for
+         power management.
++config BCM6345_L2_IRQ
++      bool
++      select IRQ_DOMAIN
++
+ config DW_APB_ICTL
+       bool
+       select IRQ_DOMAIN
+--- a/drivers/irqchip/Makefile
++++ b/drivers/irqchip/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
+ obj-$(CONFIG_ARCH_MVEBU)              += irq-armada-370-xp.o
+ obj-$(CONFIG_ARCH_MXS)                        += irq-mxs.o
+ obj-$(CONFIG_ARCH_S3C24XX)            += irq-s3c24xx.o
++obj-$(CONFIG_BCM6345_L2_IRQ)          += irq-bcm6345-l2.o
+ obj-$(CONFIG_DW_APB_ICTL)             += irq-dw-apb-ictl.o
+ obj-$(CONFIG_METAG)                   += irq-metag-ext.o
+ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)  += irq-metag.o
+--- /dev/null
++++ b/drivers/irqchip/irq-bcm6345-l2.c
+@@ -0,0 +1,320 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
++ */
++
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/irqchip/chained_irq.h>
++#include <linux/irqchip/irq-bcm6345-l2-intc.h>
++#include <linux/kernel.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++
++#ifdef CONFIG_BCM63XX
++#include <asm/mach-bcm63xx/bcm63xx_irq.h>
++
++#define VIRQ_BASE     IRQ_INTERNAL_BASE
++#else
++#define VIRQ_BASE     0
++#endif
++
++#include "irqchip.h"
++
++#define MAX_WORDS     4
++#define MAX_PARENT_IRQS       2
++#define IRQS_PER_WORD 32
++
++struct intc_block {
++      int parent_irq;
++      void __iomem *base;
++      void __iomem *en_reg[MAX_WORDS];
++      void __iomem *status_reg[MAX_WORDS];
++      u32 mask_cache[MAX_WORDS];
++};
++
++struct intc_data {
++      struct irq_chip chip;
++      struct intc_block block[MAX_PARENT_IRQS];
++
++      int num_words;
++
++      struct irq_domain *domain;
++      spinlock_t lock;
++};
++
++static void bcm6345_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
++{
++      struct intc_data *data = irq_desc_get_handler_data(desc);
++      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct intc_block *block;
++      unsigned int idx;
++
++      chained_irq_enter(chip, desc);
++
++      for (idx = 0; idx < MAX_PARENT_IRQS; idx++)
++              if (irq == data->block[idx].parent_irq)
++                      block = &data->block[idx];
++
++      for (idx = 0; idx < data->num_words; idx++) {
++              int base = idx * IRQS_PER_WORD;
++              unsigned long pending;
++              int hw_irq;
++
++              raw_spin_lock(data->lock);
++              pending = __raw_readl(block->en_reg[idx]) &
++                        __raw_readl(block->status_reg[idx]);
++              raw_spin_unlock(data->lock);
++
++              for_each_set_bit(hw_irq, &pending, IRQS_PER_WORD) {
++                      generic_handle_irq(irq_find_mapping(data->domain, base + hw_irq));
++              }
++      }
++
++      chained_irq_exit(chip, desc);
++}
++
++static void bcm6345_l2_intc_irq_mask(struct irq_data *data)
++{
++      unsigned int i, reg, bit;
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++
++      reg = hwirq / IRQS_PER_WORD;
++      bit = hwirq % IRQS_PER_WORD;
++
++      raw_spin_lock(priv->lock);
++      for (i = 0; i < MAX_PARENT_IRQS; i++) {
++              struct intc_block *block = &priv->block[i];
++              u32 val;
++
++              if (!block->parent_irq)
++                      break;
++
++              val = __raw_readl(block->en_reg[reg]);
++              __raw_writel(val & ~BIT(bit), block->en_reg[reg]);
++      }
++      raw_spin_unlock(priv->lock);
++}
++
++static void bcm6345_l2_intc_irq_unmask(struct irq_data *data)
++{
++      unsigned int i, reg, bit;
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++
++      reg = hwirq / IRQS_PER_WORD;
++      bit = hwirq % IRQS_PER_WORD;
++
++      raw_spin_lock(priv->lock);
++      for (i = 0; i < MAX_PARENT_IRQS; i++) {
++              struct intc_block *block = &priv->block[i];
++              u32 val;
++
++              if (!block->parent_irq)
++                      break;
++
++              val = __raw_readl(block->en_reg[reg]);
++
++              if (block->mask_cache[reg] & BIT(bit))
++                      val |= BIT(bit);
++              else
++                      val &= ~BIT(bit);
++
++              __raw_writel(val, block->en_reg[reg]);
++
++      }
++      raw_spin_unlock(priv->lock);
++}
++
++#ifdef CONFIG_SMP
++static int bcm6345_l2_intc_set_affinity(struct irq_data *data,
++                                      const struct cpumask *mask,
++                                      bool force)
++{
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++      struct intc_data *priv = data->domain->host_data;
++      unsigned int i, reg, bit;
++      int cpu;
++
++      reg = hwirq / IRQS_PER_WORD;
++      bit = hwirq % IRQS_PER_WORD;
++
++      /* we could route to more than one cpu, but performance
++         suffers, so fix it to one.
++       */
++      cpu = cpumask_any_and(mask, cpu_online_mask);
++      if (cpu >= nr_cpu_ids)
++              return -EINVAL;
++
++      if (cpu >= MAX_PARENT_IRQS)
++              return -EINVAL;
++
++      if (!priv->block[cpu].parent_irq)
++              return -EINVAL;
++
++      raw_spin_lock(priv->lock);
++      for (i = 0; i < MAX_PARENT_IRQS; i++) {
++              if (i == cpu)
++                      priv->block[i].mask_cache[reg] |= BIT(bit);
++              else
++                      priv->block[i].mask_cache[reg] &= ~BIT(bit);
++      }
++      raw_spin_unlock(priv->lock);
++
++      return 0;
++}
++#endif
++
++static int bcm6345_l2_map(struct irq_domain *d, unsigned int irq,
++                        irq_hw_number_t hw)
++{
++      struct intc_data *priv = d->host_data;
++
++      irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
++
++      return 0;
++}
++
++static const struct irq_domain_ops bcm6345_l2_domain_ops = {
++      .xlate = irq_domain_xlate_onecell,
++      .map = bcm6345_l2_map,
++};
++
++static int __init __bcm6345_l2_intc_init(struct device_node *node,
++                                       int num_blocks, int *irq,
++                                       void __iomem **base, int num_words)
++{
++      struct intc_data *data;
++      unsigned int i, w, status_offset;
++
++      data = kzalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return -ENOMEM;
++
++      status_offset = num_words * sizeof(u32);
++
++      for (i = 0; i < num_blocks; i++) {
++              struct intc_block *block = &data->block[i];
++
++              block->parent_irq = irq[i];
++              block->base = base[i];
++
++              for (w = 0; w < num_words; w++) {
++                      int word_offset = sizeof(u32) * ((num_words - w) - 1);
++
++                      block->en_reg[w] = base[i] + word_offset;
++                      block->status_reg[w] = base[i] + status_offset;
++                      block->status_reg[w] += word_offset;
++
++                      /* route all interrups to line 0 by default */
++                      if (i == 0)
++                              block->mask_cache[w] = 0xffffffff;
++              }
++
++              irq_set_handler_data(block->parent_irq, data);
++              irq_set_chained_handler(block->parent_irq,
++                                      bcm6345_l2_intc_irq_handle);
++      }
++
++      data->num_words = num_words;
++
++      data->chip.name = "bcm6345-l2-intc";
++      data->chip.irq_mask = bcm6345_l2_intc_irq_mask;
++      data->chip.irq_unmask = bcm6345_l2_intc_irq_unmask;
++
++#ifdef CONFIG_SMP
++      if (num_blocks > 1)
++              data->chip.set_affinity = bcm6345_l2_intc_set_affinity;
++#endif
++
++      data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words,
++                                           VIRQ_BASE, &bcm6345_l2_domain_ops,
++                                           data);
++      if (!data->domain) {
++              kfree(data);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++void __init bcm6345_l2_intc_init(int num_blocks, int *irq, void __iomem **base,
++                               int num_words)
++{
++      __bcm6345_l2_intc_init(NULL, num_blocks, irq, base, num_words);
++}
++
++#ifdef CONFIG_OF
++static int __init bcm6345_l2_intc_of_init(struct device_node *node,
++                                        struct device_node *parent)
++{
++      struct resource res;
++      int num_irqs, ret = -EINVAL;
++      int irqs[MAX_PARENT_IRQS] = { 0 };
++      void __iomem *bases[MAX_PARENT_IRQS] = { NULL };
++      int words = 0;
++      int i;
++
++      num_irqs = of_irq_count(node);
++
++      if (num_irqs < 1 || num_irqs > MAX_PARENT_IRQS)
++              return -EINVAL;
++
++      for (i = 0; i < num_irqs; i++) {
++              resource_size_t size;
++
++              irqs[i] = irq_of_parse_and_map(node, i);
++              if (!irqs[i])
++                      goto out_unmap;
++
++              if (of_address_to_resource(node, i, &res)) {
++                      goto out_unmap;
++              }
++
++              size = resource_size(&res);
++              switch (size) {
++                      case 8:
++                      case 16:
++                      case 32:
++                              size = size / 8;
++                              break;
++                      default:
++                              goto out_unmap;
++              }
++
++              if (words && words != size) {
++                      ret = -EINVAL;
++                      goto out_unmap;
++              }
++              words = size;
++
++              bases[i] = of_iomap(node, i);
++              if (!bases[i]) {
++                      ret = -ENOMEM;
++                      goto out_unmap;
++              }
++      }
++
++      ret = __bcm6345_l2_intc_init(node, num_irqs, irqs, bases, words);
++      if (!ret)
++              return 0;
++
++out_unmap:
++      for (i = 0; i < num_irqs; i++) {
++              iounmap(bases[i]);
++              irq_dispose_mapping(irqs[i]);
++      }
++
++      return ret;
++}
++
++IRQCHIP_DECLARE(bcm6345_l2_intc, "brcm,bcm6345-l2-intc",
++              bcm6345_l2_intc_of_init);
++#endif
+--- /dev/null
++++ b/include/linux/irqchip/irq-bcm6345-l2-intc.h
+@@ -0,0 +1,16 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ * Copyright (C) 2008 Nicolas Schichan <nschichan@freebox.fr>
++ */
++
++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_L2_INTC_H
++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_L2_INTC_H
++
++void bcm6345_l2_intc_init(int num_blocks, int *irq, void __iomem **base,
++                        int num_words);
++
++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_L2_INTC_H */
diff --git a/target/linux/brcm63xx/patches-3.14/321-irqchip-add-support-for-bcm6345-style-external-inter.patch b/target/linux/brcm63xx/patches-3.14/321-irqchip-add-support-for-bcm6345-style-external-inter.patch
new file mode 100644 (file)
index 0000000..d53deba
--- /dev/null
@@ -0,0 +1,384 @@
+From 6896b5f0538a7a7cfb7fac2d9ed3c6841c72ed40 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 30 Nov 2014 14:54:27 +0100
+Subject: [PATCH 18/20] irqchip: add support for bcm6345-style external
+ interrupt controller
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ .../interrupt-controller/brcm,bcm6345-ext-intc.txt |   24 ++
+ drivers/irqchip/Kconfig                            |    4 +
+ drivers/irqchip/Makefile                           |    1 +
+ drivers/irqchip/irq-bcm6345-ext.c                  |  296 ++++++++++++++++++++
+ include/linux/irqchip/irq-bcm6345-ext-intc.h       |   14 +
+ 5 files changed, 339 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
+ create mode 100644 drivers/irqchip/irq-bcm6345-ext.c
+ create mode 100644 include/linux/irqchip/irq-bcm6345-ext-intc.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt
+@@ -0,0 +1,24 @@
++Broadcom BCM6345-style external interrupt controller
++
++Required properties:
++
++- compatible: should be "brcm,bcm6345-l2-intc" or "brcm,bcm6345-l2-intc"
++- reg: specifies the base physical addresses and size of the registers.
++- interrupt-controller: identifies the node as an interrupt controller
++- #interrupt-cells: specifies the number of cells needed to encode an interrupt
++  source, should be 2
++- interrupt-parent: specifies the phandle to the parent interrupt controller
++  this one is cascaded from
++- interrupts: specifies the interrupt line(s) in the interrupt-parent controller
++  node, valid values depend on the type of parent interrupt controller
++
++Example:
++
++ext_intc: interrupt-controller@10000018 {
++      compatible = "brcm,bcm6345-l2-intc";
++      interrupt-parent = <&periph_intc>;
++      #interrupt-cells = <2>;
++      reg = <0x10000018 0x4>;
++      interrupt-controller;
++      interrupts = <24>, <25>, <26>, <27>;
++};
+--- a/drivers/irqchip/Kconfig
++++ b/drivers/irqchip/Kconfig
+@@ -30,6 +30,10 @@ config ARM_VIC_NR
+         The maximum number of VICs available in the system, for
+         power management.
++config BCM6345_EXT_IRQ
++      bool
++      select IRQ_DOMAIN
++
+ config BCM6345_L2_IRQ
+       bool
+       select IRQ_DOMAIN
+--- a/drivers/irqchip/Makefile
++++ b/drivers/irqchip/Makefile
+@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
+ obj-$(CONFIG_ARCH_MVEBU)              += irq-armada-370-xp.o
+ obj-$(CONFIG_ARCH_MXS)                        += irq-mxs.o
+ obj-$(CONFIG_ARCH_S3C24XX)            += irq-s3c24xx.o
++obj-$(CONFIG_BCM6345_EXT_IRQ)         += irq-bcm6345-ext.o
+ obj-$(CONFIG_BCM6345_L2_IRQ)          += irq-bcm6345-l2.o
+ obj-$(CONFIG_DW_APB_ICTL)             += irq-dw-apb-ictl.o
+ obj-$(CONFIG_METAG)                   += irq-metag-ext.o
+--- /dev/null
++++ b/drivers/irqchip/irq-bcm6345-ext.c
+@@ -0,0 +1,296 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
++i */
++
++#include <linux/ioport.h>
++#include <linux/irq.h>
++#include <linux/irqchip/chained_irq.h>
++#include <linux/irqchip/irq-bcm6345-ext-intc.h>
++#include <linux/kernel.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++
++#include "irqchip.h"
++
++#ifdef CONFIG_BCM63XX
++#include <asm/mach-bcm63xx/bcm63xx_irq.h>
++
++#define VIRQ_BASE             IRQ_EXTERNAL_BASE
++#else
++#define VIRQ_BASE             0
++#endif
++
++#define MAX_IRQS              4
++
++#define EXTIRQ_CFG_SENSE      0
++#define EXTIRQ_CFG_STAT               1
++#define EXTIRQ_CFG_CLEAR      2
++#define EXTIRQ_CFG_MASK               3
++#define EXTIRQ_CFG_BOTHEDGE   4
++#define EXTIRQ_CFG_LEVELSENSE 5
++
++struct intc_data {
++      struct irq_chip chip;
++      struct irq_domain *domain;
++      spinlock_t lock;
++
++      int parent_irq[MAX_IRQS];
++      void __iomem *reg;
++      int shift;
++};
++
++static void bcm6345_ext_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
++{
++      struct intc_data *data = irq_desc_get_handler_data(desc);
++      struct irq_chip *chip = irq_desc_get_chip(desc);
++      unsigned int idx;
++
++      chained_irq_enter(chip, desc);
++
++      for (idx = 0; idx < MAX_IRQS; idx++) {
++              if (data->parent_irq[idx] != irq)
++                      continue;
++
++              generic_handle_irq(irq_find_mapping(data->domain, idx));
++      }
++
++      chained_irq_exit(chip, desc);
++}
++
++static void bcm6345_ext_intc_irq_ack(struct irq_data *data)
++{
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++      u32 reg;
++
++      raw_spin_lock(priv->lock);
++      reg = __raw_readl(priv->reg);
++      reg |= hwirq << (EXTIRQ_CFG_CLEAR * priv->shift);
++      __raw_writel(reg, priv->reg);
++      raw_spin_unlock(priv->lock);
++}
++
++static void bcm6345_ext_intc_irq_mask(struct irq_data *data)
++{
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++      u32 reg;
++
++      raw_spin_lock(priv->lock);
++      reg = __raw_readl(priv->reg);
++      reg &= ~(hwirq << (EXTIRQ_CFG_MASK * priv->shift));
++      __raw_writel(reg, priv->reg);
++      raw_spin_unlock(priv->lock);
++}
++
++static void bcm6345_ext_intc_irq_unmask(struct irq_data *data)
++{
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++      u32 reg;
++
++      raw_spin_lock(priv->lock);
++      reg = __raw_readl(priv->reg);
++      reg |= hwirq << (EXTIRQ_CFG_MASK * priv->shift);
++      __raw_writel(reg, priv->reg);
++      raw_spin_unlock(priv->lock);
++}
++
++static int bcm6345_ext_intc_set_type(struct irq_data *data,
++                                   unsigned int flow_type)
++{
++      struct intc_data *priv = data->domain->host_data;
++      irq_hw_number_t hwirq = irqd_to_hwirq(data);
++      bool levelsense = 0, sense = 0, bothedge = 0;
++      u32 reg;
++
++      flow_type &= IRQ_TYPE_SENSE_MASK;
++
++      if (flow_type == IRQ_TYPE_NONE)
++              flow_type = IRQ_TYPE_LEVEL_LOW;
++
++      switch (flow_type) {
++      case IRQ_TYPE_EDGE_BOTH:
++              bothedge = 1;
++              break;
++
++      case IRQ_TYPE_EDGE_RISING:
++              break;
++
++      case IRQ_TYPE_EDGE_FALLING:
++              sense = 1;
++              break;
++
++      case IRQ_TYPE_LEVEL_HIGH:
++              levelsense = 1;
++              sense = 1;
++              break;
++
++      case IRQ_TYPE_LEVEL_LOW:
++              levelsense = 1;
++              break;
++
++      default:
++              pr_err("bogus flow type combination given!\n");
++              return -EINVAL;
++      }
++
++      raw_spin_lock(priv->lock);
++      reg = __raw_readl(priv->reg);
++
++      if (levelsense)
++              reg |= hwirq << (EXTIRQ_CFG_LEVELSENSE * priv->shift);
++      else
++              reg &= ~(hwirq << (EXTIRQ_CFG_LEVELSENSE * priv->shift));
++      if (sense)
++              reg |= hwirq << (EXTIRQ_CFG_SENSE * priv->shift);
++      else
++              reg &= ~(hwirq << (EXTIRQ_CFG_SENSE * priv->shift));
++      if (bothedge)
++              reg |= hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift);
++      else
++              reg &= ~(hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift));
++
++      __raw_writel(reg, priv->reg);
++      raw_spin_unlock(priv->lock);
++
++      irqd_set_trigger_type(data, flow_type);
++      if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
++              __irq_set_handler_locked(data->irq, handle_level_irq);
++      else
++              __irq_set_handler_locked(data->irq, handle_edge_irq);
++
++      return 0;
++}
++
++static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq,
++                        irq_hw_number_t hw)
++{
++      struct intc_data *priv = d->host_data;
++
++      irq_set_chip_and_handler(irq, &priv->chip, handle_level_irq);
++
++      return 0;
++}
++
++
++static const struct irq_domain_ops bcm6345_ext_domain_ops = {
++      .xlate = irq_domain_xlate_twocell,
++      .map = bcm6345_ext_intc_map,
++};
++
++static int __init __bcm6345_ext_intc_init(struct device_node *node,
++                                        int num_irqs, int *irqs,
++                                        void __iomem *reg, int shift)
++{
++      struct intc_data *data;
++      unsigned int i;
++      int start = VIRQ_BASE;
++
++      data = kzalloc(sizeof(*data), GFP_KERNEL);
++      if (!data)
++              return -ENOMEM;
++
++      for (i = 0; i < num_irqs; i++) {
++              data->parent_irq[i] = irqs[i];
++
++              irq_set_handler_data(irqs[i], data);
++              irq_set_chained_handler(irqs[i], bcm6345_ext_intc_irq_handle);
++      }
++
++      data->reg = reg;
++
++      data->chip.name = "bcm6345-ext-intc";
++      data->chip.irq_ack = bcm6345_ext_intc_irq_ack;
++      data->chip.irq_mask = bcm6345_ext_intc_irq_mask;
++      data->chip.irq_unmask = bcm6345_ext_intc_irq_unmask;
++      data->chip.irq_set_type = bcm6345_ext_intc_set_type;
++
++      /*
++       * If we have less than 4 irqs, this is the second controller on
++       * bcm63xx. So increase the VIRQ start to not overlap with the first
++       * one, but only do so if we actually use a non-zero start.
++       *
++       * This can be removed when bcm63xx has no legacy users anymore.
++       */
++      if (start && num_irqs < 4)
++              start += 4;
++
++      data->domain = irq_domain_add_simple(node, num_irqs, start,
++                                           &bcm6345_ext_domain_ops, data);
++      if (!data->domain) {
++              kfree(data);
++              return -ENOMEM;
++      }
++
++      return 0;
++}
++
++void __init bcm6345_ext_intc_init(int num_irqs, int *irqs, void __iomem *reg,
++                                int shift)
++{
++      __bcm6345_ext_intc_init(NULL, num_irqs, irqs, reg, shift);
++}
++
++#ifdef CONFIG_OF
++static int __init bcm63xx_ext_intc_of_init(struct device_node *node,
++                                         struct device_node *parent,
++                                         int shift)
++{
++      int num_irqs, ret = -EINVAL;
++      unsigned i;
++      void __iomem *base;
++      int irqs[MAX_IRQS] = { 0 };
++
++      num_irqs = of_irq_count(node);
++
++      if (!num_irqs || num_irqs > MAX_IRQS)
++              return -EINVAL;
++
++      for (i = 0; i < num_irqs; i++) {
++              irqs[i] = irq_of_parse_and_map(node, i);
++              if (!irqs[i]) {
++                      ret = -ENOMEM;
++                      goto out_unmap;
++              }
++      }
++
++      base = of_iomap(node, 0);
++      if (!base)
++              goto out_unmap;
++
++      ret = __bcm6345_ext_intc_init(node, num_irqs, irqs, base, shift);
++      if (!ret)
++              return 0;
++out_unmap:
++      iounmap(base);
++
++      for (i = 0; i < num_irqs; i++)
++              irq_dispose_mapping(irqs[i]);
++
++      return ret;
++}
++
++static int __init bcm6345_ext_intc_of_init(struct device_node *node,
++                                         struct device_node *parent)
++{
++      return bcm63xx_ext_intc_of_init(node, parent, 4);
++}
++static int __init bcm6348_ext_intc_of_init(struct device_node *node,
++                                         struct device_node *parent)
++{
++      return bcm63xx_ext_intc_of_init(node, parent, 5);
++}
++
++IRQCHIP_DECLARE(bcm6345_ext_intc, "brcm,bcm6345-ext-intc",
++              bcm6345_ext_intc_of_init);
++IRQCHIP_DECLARE(bcm6348_ext_intc, "brcm,bcm6348-ext-intc",
++              bcm6348_ext_intc_of_init);
++#endif
+--- /dev/null
++++ b/include/linux/irqchip/irq-bcm6345-ext-intc.h
+@@ -0,0 +1,14 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2014 Jonas Gorski <jogo@openwrt.org>
++ */
++
++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H
++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H
++
++void bcm6345_ext_intc_init(int n_irqs, int *irqs, void __iomem *reg, int shift);
++
++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H */
diff --git a/target/linux/brcm63xx/patches-3.14/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch b/target/linux/brcm63xx/patches-3.14/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch
new file mode 100644 (file)
index 0000000..6338477
--- /dev/null
@@ -0,0 +1,694 @@
+From d93661c9e164ccc41820eeb4f1881e59a34a9e5c Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 30 Nov 2014 14:55:02 +0100
+Subject: [PATCH 19/20] MIPS: BCM63XX: switch to IRQ_DOMAIN
+
+Now that we have working IRQ_DOMAIN drivers for both interrupt controllers,
+switch to using them.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/Kconfig       |    3 +
+ arch/mips/bcm63xx/irq.c |  608 ++++++++---------------------------------------
+ 2 files changed, 108 insertions(+), 503 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -135,6 +135,9 @@ config BCM63XX
+       select SYNC_R4K
+       select DMA_NONCOHERENT
+       select IRQ_CPU
++      select BCM6345_EXT_IRQ
++      select BCM6345_L2_IRQ
++      select IRQ_DOMAIN
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_HAS_EARLY_PRINTK
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -12,7 +12,9 @@
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/irq.h>
+-#include <linux/spinlock.h>
++#include <linux/irqchip.h>
++#include <linux/irqchip/irq-bcm6345-ext-intc.h>
++#include <linux/irqchip/irq-bcm6345-l2-intc.h>
+ #include <asm/irq_cpu.h>
+ #include <asm/mipsregs.h>
+ #include <bcm63xx_cpu.h>
+@@ -20,544 +22,144 @@
+ #include <bcm63xx_io.h>
+ #include <bcm63xx_irq.h>
+-
+-static DEFINE_SPINLOCK(ipic_lock);
+-static DEFINE_SPINLOCK(epic_lock);
+-
+-static u32 irq_stat_addr[2];
+-static u32 irq_mask_addr[2];
+-static void (*dispatch_internal)(int cpu);
+-static int is_ext_irq_cascaded;
+-static unsigned int ext_irq_count;
+-static unsigned int ext_irq_start, ext_irq_end;
+-static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
+-static void (*internal_irq_mask)(struct irq_data *d);
+-static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
+-
+-
+-static inline u32 get_ext_irq_perf_reg(int irq)
+-{
+-      if (irq < 4)
+-              return ext_irq_cfg_reg1;
+-      return ext_irq_cfg_reg2;
+-}
+-
+-static inline void handle_internal(int intbit)
+-{
+-      if (is_ext_irq_cascaded &&
+-          intbit >= ext_irq_start && intbit <= ext_irq_end)
+-              do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE);
+-      else
+-              do_IRQ(intbit + IRQ_INTERNAL_BASE);
+-}
+-
+-static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+-                                   const struct cpumask *m)
+-{
+-      bool enable = cpu_online(cpu);
+-
+-#ifdef CONFIG_SMP
+-      if (m)
+-              enable &= cpu_isset(cpu, *m);
+-      else if (irqd_affinity_was_set(d))
+-              enable &= cpu_isset(cpu, *d->affinity);
+-#endif
+-      return enable;
+-}
+-
+-/*
+- * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
+- * prioritize any interrupt relatively to another. the static counter
+- * will resume the loop where it ended the last time we left this
+- * function.
+- */
+-
+-#define BUILD_IPIC_INTERNAL(width)                                    \
+-void __dispatch_internal_##width(int cpu)                             \
+-{                                                                     \
+-      u32 pending[width / 32];                                        \
+-      unsigned int src, tgt;                                          \
+-      bool irqs_pending = false;                                      \
+-      static unsigned int i[2];                                       \
+-      unsigned int *next = &i[cpu];                                   \
+-      unsigned long flags;                                            \
+-                                                                      \
+-      /* read registers in reverse order */                           \
+-      spin_lock_irqsave(&ipic_lock, flags);                           \
+-      for (src = 0, tgt = (width / 32); src < (width / 32); src++) {  \
+-              u32 val;                                                \
+-                                                                      \
+-              val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
+-              val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
+-              pending[--tgt] = val;                                   \
+-                                                                      \
+-              if (val)                                                \
+-                      irqs_pending = true;                            \
+-      }                                                               \
+-      spin_unlock_irqrestore(&ipic_lock, flags);                      \
+-                                                                      \
+-      if (!irqs_pending)                                              \
+-              return;                                                 \
+-                                                                      \
+-      while (1) {                                                     \
+-              unsigned int to_call = *next;                           \
+-                                                                      \
+-              *next = (*next + 1) & (width - 1);                      \
+-              if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {  \
+-                      handle_internal(to_call);                       \
+-                      break;                                          \
+-              }                                                       \
+-      }                                                               \
+-}                                                                     \
+-                                                                      \
+-static void __internal_irq_mask_##width(struct irq_data *d)           \
+-{                                                                     \
+-      u32 val;                                                        \
+-      unsigned irq = d->irq - IRQ_INTERNAL_BASE;                      \
+-      unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
+-      unsigned bit = irq & 0x1f;                                      \
+-      unsigned long flags;                                            \
+-      int cpu;                                                        \
+-                                                                      \
+-      spin_lock_irqsave(&ipic_lock, flags);                           \
+-      for_each_present_cpu(cpu) {                                     \
+-              if (!irq_mask_addr[cpu])                                \
+-                      break;                                          \
+-                                                                      \
+-              val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+-              val &= ~(1 << bit);                                     \
+-              bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+-      }                                                               \
+-      spin_unlock_irqrestore(&ipic_lock, flags);                      \
+-}                                                                     \
+-                                                                      \
+-static void __internal_irq_unmask_##width(struct irq_data *d,         \
+-                                        const struct cpumask *m)      \
+-{                                                                     \
+-      u32 val;                                                        \
+-      unsigned irq = d->irq - IRQ_INTERNAL_BASE;                      \
+-      unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
+-      unsigned bit = irq & 0x1f;                                      \
+-      unsigned long flags;                                            \
+-      int cpu;                                                        \
+-                                                                      \
+-      spin_lock_irqsave(&ipic_lock, flags);                           \
+-      for_each_present_cpu(cpu) {                                     \
+-              if (!irq_mask_addr[cpu])                                \
+-                      break;                                          \
+-                                                                      \
+-              val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+-              if (enable_irq_for_cpu(cpu, d, m))                      \
+-                      val |= (1 << bit);                              \
+-              else                                                    \
+-                      val &= ~(1 << bit);                             \
+-              bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+-      }                                                               \
+-      spin_unlock_irqrestore(&ipic_lock, flags);                      \
+-}
+-
+-BUILD_IPIC_INTERNAL(32);
+-BUILD_IPIC_INTERNAL(64);
+-
+-asmlinkage void plat_irq_dispatch(void)
+-{
+-      u32 cause;
+-
+-      do {
+-              cause = read_c0_cause() & read_c0_status() & ST0_IM;
+-
+-              if (!cause)
+-                      break;
+-
+-              if (cause & CAUSEF_IP7)
+-                      do_IRQ(7);
+-              if (cause & CAUSEF_IP0)
+-                      do_IRQ(0);
+-              if (cause & CAUSEF_IP1)
+-                      do_IRQ(1);
+-              if (cause & CAUSEF_IP2)
+-                      dispatch_internal(0);
+-              if (is_ext_irq_cascaded) {
+-                      if (cause & CAUSEF_IP3)
+-                              dispatch_internal(1);
+-              } else {
+-                      if (cause & CAUSEF_IP3)
+-                              do_IRQ(IRQ_EXT_0);
+-                      if (cause & CAUSEF_IP4)
+-                              do_IRQ(IRQ_EXT_1);
+-                      if (cause & CAUSEF_IP5)
+-                              do_IRQ(IRQ_EXT_2);
+-                      if (cause & CAUSEF_IP6)
+-                              do_IRQ(IRQ_EXT_3);
+-              }
+-      } while (1);
+-}
+-
+-/*
+- * internal IRQs operations: only mask/unmask on PERF irq mask
+- * register.
+- */
+-static void bcm63xx_internal_irq_mask(struct irq_data *d)
+-{
+-      internal_irq_mask(d);
+-}
+-
+-static void bcm63xx_internal_irq_unmask(struct irq_data *d)
+-{
+-      internal_irq_unmask(d, NULL);
+-}
+-
+-/*
+- * external IRQs operations: mask/unmask and clear on PERF external
+- * irq control register.
+- */
+-static void bcm63xx_external_irq_mask(struct irq_data *d)
+-{
+-      unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+-      u32 reg, regaddr;
+-      unsigned long flags;
+-
+-      regaddr = get_ext_irq_perf_reg(irq);
+-      spin_lock_irqsave(&epic_lock, flags);
+-      reg = bcm_perf_readl(regaddr);
+-
+-      if (BCMCPU_IS_6348())
+-              reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
+-      else
+-              reg &= ~EXTIRQ_CFG_MASK(irq % 4);
+-
+-      bcm_perf_writel(reg, regaddr);
+-      spin_unlock_irqrestore(&epic_lock, flags);
+-
+-      if (is_ext_irq_cascaded)
+-              internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
+-}
+-
+-static void bcm63xx_external_irq_unmask(struct irq_data *d)
+-{
+-      unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+-      u32 reg, regaddr;
+-      unsigned long flags;
+-
+-      regaddr = get_ext_irq_perf_reg(irq);
+-      spin_lock_irqsave(&epic_lock, flags);
+-      reg = bcm_perf_readl(regaddr);
+-
+-      if (BCMCPU_IS_6348())
+-              reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
+-      else
+-              reg |= EXTIRQ_CFG_MASK(irq % 4);
+-
+-      bcm_perf_writel(reg, regaddr);
+-      spin_unlock_irqrestore(&epic_lock, flags);
+-
+-      if (is_ext_irq_cascaded)
+-              internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+-                                  NULL);
+-}
+-
+-static void bcm63xx_external_irq_clear(struct irq_data *d)
+-{
+-      unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+-      u32 reg, regaddr;
+-      unsigned long flags;
+-
+-      regaddr = get_ext_irq_perf_reg(irq);
+-      spin_lock_irqsave(&epic_lock, flags);
+-      reg = bcm_perf_readl(regaddr);
+-
+-      if (BCMCPU_IS_6348())
+-              reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
+-      else
+-              reg |= EXTIRQ_CFG_CLEAR(irq % 4);
+-
+-      bcm_perf_writel(reg, regaddr);
+-      spin_unlock_irqrestore(&epic_lock, flags);
+-}
+-
+-static int bcm63xx_external_irq_set_type(struct irq_data *d,
+-                                       unsigned int flow_type)
+-{
+-      unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+-      u32 reg, regaddr;
+-      int levelsense, sense, bothedge;
+-      unsigned long flags;
+-
+-      flow_type &= IRQ_TYPE_SENSE_MASK;
+-
+-      if (flow_type == IRQ_TYPE_NONE)
+-              flow_type = IRQ_TYPE_LEVEL_LOW;
+-
+-      levelsense = sense = bothedge = 0;
+-      switch (flow_type) {
+-      case IRQ_TYPE_EDGE_BOTH:
+-              bothedge = 1;
+-              break;
+-
+-      case IRQ_TYPE_EDGE_RISING:
+-              sense = 1;
+-              break;
+-
+-      case IRQ_TYPE_EDGE_FALLING:
+-              break;
+-
+-      case IRQ_TYPE_LEVEL_HIGH:
+-              levelsense = 1;
+-              sense = 1;
+-              break;
+-
+-      case IRQ_TYPE_LEVEL_LOW:
+-              levelsense = 1;
+-              break;
+-
+-      default:
+-              printk(KERN_ERR "bogus flow type combination given !\n");
+-              return -EINVAL;
+-      }
+-
+-      regaddr = get_ext_irq_perf_reg(irq);
+-      spin_lock_irqsave(&epic_lock, flags);
+-      reg = bcm_perf_readl(regaddr);
+-      irq %= 4;
+-
+-      switch (bcm63xx_get_cpu_id()) {
+-      case BCM6348_CPU_ID:
+-              if (levelsense)
+-                      reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
+-              if (sense)
+-                      reg |= EXTIRQ_CFG_SENSE_6348(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
+-              if (bothedge)
+-                      reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
+-              break;
+-
+-      case BCM3368_CPU_ID:
+-      case BCM6328_CPU_ID:
+-      case BCM6338_CPU_ID:
+-      case BCM6345_CPU_ID:
+-      case BCM6358_CPU_ID:
+-      case BCM6362_CPU_ID:
+-      case BCM6368_CPU_ID:
+-              if (levelsense)
+-                      reg |= EXTIRQ_CFG_LEVELSENSE(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
+-              if (sense)
+-                      reg |= EXTIRQ_CFG_SENSE(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_SENSE(irq);
+-              if (bothedge)
+-                      reg |= EXTIRQ_CFG_BOTHEDGE(irq);
+-              else
+-                      reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
+-              break;
+-      default:
+-              BUG();
+-      }
+-
+-      bcm_perf_writel(reg, regaddr);
+-      spin_unlock_irqrestore(&epic_lock, flags);
+-
+-      irqd_set_trigger_type(d, flow_type);
+-      if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+-              __irq_set_handler_locked(d->irq, handle_level_irq);
+-      else
+-              __irq_set_handler_locked(d->irq, handle_edge_irq);
+-
+-      return IRQ_SET_MASK_OK_NOCOPY;
+-}
+-
+-#ifdef CONFIG_SMP
+-static int bcm63xx_internal_set_affinity(struct irq_data *data,
+-                                       const struct cpumask *dest,
+-                                       bool force)
+-{
+-      if (!irqd_irq_disabled(data))
+-              internal_irq_unmask(data, dest);
+-
+-      return 0;
+-}
+-#endif
+-
+-static struct irq_chip bcm63xx_internal_irq_chip = {
+-      .name           = "bcm63xx_ipic",
+-      .irq_mask       = bcm63xx_internal_irq_mask,
+-      .irq_unmask     = bcm63xx_internal_irq_unmask,
+-};
+-
+-static struct irq_chip bcm63xx_external_irq_chip = {
+-      .name           = "bcm63xx_epic",
+-      .irq_ack        = bcm63xx_external_irq_clear,
+-
+-      .irq_mask       = bcm63xx_external_irq_mask,
+-      .irq_unmask     = bcm63xx_external_irq_unmask,
+-
+-      .irq_set_type   = bcm63xx_external_irq_set_type,
+-};
+-
+-static struct irqaction cpu_ip2_cascade_action = {
+-      .handler        = no_action,
+-      .name           = "cascade_ip2",
+-      .flags          = IRQF_NO_THREAD,
+-};
+-
+-#ifdef CONFIG_SMP
+-static struct irqaction cpu_ip3_cascade_action = {
+-      .handler        = no_action,
+-      .name           = "cascade_ip3",
+-      .flags          = IRQF_NO_THREAD,
+-};
+-#endif
+-
+-static struct irqaction cpu_ext_cascade_action = {
+-      .handler        = no_action,
+-      .name           = "cascade_extirq",
+-      .flags          = IRQF_NO_THREAD,
+-};
+-
+ static void bcm63xx_init_irq(void)
+ {
+-      int irq_bits;
+-
+-      irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
+-      irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
+-      irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
+-      irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
++      void __iomem *l2_intc_bases[2];
++      void __iomem *ext_intc_bases[2];
++      int l2_irq_count, l2_width, ext_irq_count, ext_shift;
++      int l2_irqs[2] = { 2, 3 };
++      int ext_irqs[6];
++
++      l2_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
++      l2_intc_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
++      ext_intc_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
++      ext_intc_bases[1] = (void __iomem *)bcm63xx_regset_address(RSET_PERF);
+       switch (bcm63xx_get_cpu_id()) {
+       case BCM3368_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
+-              irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
+-              irq_stat_addr[1] = 0;
+-              irq_stat_addr[1] = 0;
+-              irq_bits = 32;
+-              ext_irq_count = 4;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
++              l2_intc_bases[0] += PERF_IRQMASK_3368_REG;
++              l2_irq_count = 1;
++              l2_width = 1;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368;
++              ext_irq_count = 4;
++              ext_irqs[0] = BCM_3368_EXT_IRQ0;
++              ext_irqs[1] = BCM_3368_EXT_IRQ1;
++              ext_irqs[2] = BCM_3368_EXT_IRQ2;
++              ext_irqs[3] = BCM_3368_EXT_IRQ3;
++              ext_shift = 4;
+               break;
+       case BCM6328_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
+-              irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+-              irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
+-              irq_stat_addr[1] += PERF_IRQMASK_6328_REG(1);
+-              irq_bits = 64;
+-              ext_irq_count = 4;
+-              is_ext_irq_cascaded = 1;
+-              ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+-              ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
++              l2_intc_bases[0] += PERF_IRQMASK_6328_REG(0);
++              l2_intc_bases[1] += PERF_IRQMASK_6328_REG(1);
++              l2_irq_count = 2;
++              l2_width = 2;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328;
++              ext_irq_count = 4;
++              ext_irqs[0] = BCM_6328_EXT_IRQ0;
++              ext_irqs[1] = BCM_6328_EXT_IRQ1;
++              ext_irqs[2] = BCM_6328_EXT_IRQ2;
++              ext_irqs[3] = BCM_6328_EXT_IRQ3;
++              ext_shift = 4;
+               break;
+       case BCM6338_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
+-              irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
+-              irq_stat_addr[1] = 0;
+-              irq_mask_addr[1] = 0;
+-              irq_bits = 32;
+-              ext_irq_count = 4;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
++              l2_intc_bases[0] += PERF_IRQMASK_6338_REG;
++              l2_irq_count = 1;
++              l2_width = 1;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338;
++              ext_irq_count = 4;
++              ext_irqs[0] = 3;
++              ext_irqs[1] = 4;
++              ext_irqs[2] = 5;
++              ext_irqs[3] = 6;
++              ext_shift = 4;
+               break;
+       case BCM6345_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
+-              irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
+-              irq_stat_addr[1] = 0;
+-              irq_mask_addr[1] = 0;
+-              irq_bits = 32;
+-              ext_irq_count = 4;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
++              l2_intc_bases[0] += PERF_IRQMASK_6345_REG;
++              l2_irq_count = 1;
++              l2_width = 1;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345;
++              ext_irq_count = 4;
++              ext_irqs[0] = 3;
++              ext_irqs[1] = 4;
++              ext_irqs[2] = 5;
++              ext_irqs[3] = 6;
++              ext_shift = 4;
+               break;
+       case BCM6348_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
+-              irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
+-              irq_stat_addr[1] = 0;
+-              irq_mask_addr[1] = 0;
+-              irq_bits = 32;
+-              ext_irq_count = 4;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
++              l2_intc_bases[0] += PERF_IRQMASK_6348_REG;
++              l2_irq_count = 1;
++              l2_width = 1;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348;
++              ext_irq_count = 4;
++              ext_irqs[0] = 3;
++              ext_irqs[1] = 4;
++              ext_irqs[2] = 5;
++              ext_irqs[3] = 6;
++              ext_shift = 5;
+               break;
+       case BCM6358_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
+-              irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
+-              irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
+-              irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
+-              irq_bits = 32;
+-              ext_irq_count = 4;
+-              is_ext_irq_cascaded = 1;
+-              ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+-              ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
++              l2_intc_bases[0] += PERF_IRQMASK_6358_REG(0);
++              l2_intc_bases[1] += PERF_IRQMASK_6358_REG(1);
++              l2_irq_count = 2;
++              l2_width = 1;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
++              ext_irq_count = 4;
++              ext_irqs[0] = BCM_6358_EXT_IRQ0;
++              ext_irqs[1] = BCM_6358_EXT_IRQ1;
++              ext_irqs[2] = BCM_6358_EXT_IRQ2;
++              ext_irqs[3] = BCM_6358_EXT_IRQ3;
++              ext_shift = 4;
+               break;
+       case BCM6362_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
+-              irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
+-              irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
+-              irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
+-              irq_bits = 64;
+-              ext_irq_count = 4;
+-              is_ext_irq_cascaded = 1;
+-              ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+-              ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
++              l2_intc_bases[0] += PERF_IRQMASK_6362_REG(0);
++              l2_intc_bases[1] += PERF_IRQMASK_6362_REG(1);
++              l2_irq_count = 2;
++              l2_width = 2;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362;
++              ext_irq_count = 4;
++              ext_irqs[0] = BCM_6362_EXT_IRQ0;
++              ext_irqs[1] = BCM_6362_EXT_IRQ1;
++              ext_irqs[2] = BCM_6362_EXT_IRQ2;
++              ext_irqs[3] = BCM_6362_EXT_IRQ3;
++              ext_shift = 4;
+               break;
+       case BCM6368_CPU_ID:
+-              irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
+-              irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
+-              irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
+-              irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
+-              irq_bits = 64;
++              l2_intc_bases[0] += PERF_IRQMASK_6368_REG(0);
++              l2_intc_bases[1] += PERF_IRQMASK_6368_REG(1);
++              l2_irq_count = 2;
++              l2_width = 2;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368;
++              ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368;
+               ext_irq_count = 6;
+-              is_ext_irq_cascaded = 1;
+-              ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+-              ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
+-              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
+-              ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
++              ext_irqs[0] = BCM_6368_EXT_IRQ0;
++              ext_irqs[1] = BCM_6368_EXT_IRQ1;
++              ext_irqs[2] = BCM_6368_EXT_IRQ2;
++              ext_irqs[3] = BCM_6368_EXT_IRQ3;
++              ext_irqs[4] = BCM_6368_EXT_IRQ4;
++              ext_irqs[5] = BCM_6368_EXT_IRQ5;
++              ext_shift = 4;
+               break;
+       default:
+               BUG();
+       }
+-      if (irq_bits == 32) {
+-              dispatch_internal = __dispatch_internal_32;
+-              internal_irq_mask = __internal_irq_mask_32;
+-              internal_irq_unmask = __internal_irq_unmask_32;
+-      } else {
+-              dispatch_internal = __dispatch_internal_64;
+-              internal_irq_mask = __internal_irq_mask_64;
+-              internal_irq_unmask = __internal_irq_unmask_64;
+-      }
++      mips_cpu_irq_init();
++      bcm6345_l2_intc_init(l2_irq_count, l2_irqs, l2_intc_bases, l2_width);
++      bcm6345_ext_intc_init(4, ext_irqs, ext_intc_bases[0], ext_shift);
++      if (ext_irq_count > 4)
++              bcm6345_ext_intc_init(2, &ext_irqs[4], ext_intc_bases[1],
++                                    ext_shift);
+ }
+ void __init arch_init_irq(void)
+ {
+-      int i;
+-
+       bcm63xx_init_irq();
+-      mips_cpu_irq_init();
+-      for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
+-              irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
+-                                       handle_level_irq);
+-
+-      for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
+-              irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
+-                                       handle_edge_irq);
+-
+-      if (!is_ext_irq_cascaded) {
+-              for (i = 3; i < 3 + ext_irq_count; ++i)
+-                      setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
+-      }
+-
+-      setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+-#ifdef CONFIG_SMP
+-      if (is_ext_irq_cascaded) {
+-              setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+-              bcm63xx_internal_irq_chip.irq_set_affinity =
+-                      bcm63xx_internal_set_affinity;
+-
+-              cpumask_clear(irq_default_affinity);
+-              cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+-      }
+-#endif
+ }
diff --git a/target/linux/brcm63xx/patches-3.14/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch b/target/linux/brcm63xx/patches-3.14/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch
new file mode 100644 (file)
index 0000000..fac3d5c
--- /dev/null
@@ -0,0 +1,57 @@
+From e3c68bbba30b212326fb69bf64b2220750dead3e Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 30 Nov 2014 20:20:30 +0100
+Subject: [PATCH 20/20] MIPS: BCM63XX: wire up BCM6358's external interrupts 4
+ and 5
+
+Due to the external interrupts being non consecutive, the previous
+implementation did not support them. Now that we treat both registers
+as separate irq controllers, there is no such limitation anymore and
+we can expose them for drivers to use.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c                           |    5 ++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h  |    2 ++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h |    1 +
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -109,11 +109,14 @@ static void bcm63xx_init_irq(void)
+               l2_width = 1;
+               ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358;
+-              ext_irq_count = 4;
++              ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6358;
++              ext_irq_count = 6;
+               ext_irqs[0] = BCM_6358_EXT_IRQ0;
+               ext_irqs[1] = BCM_6358_EXT_IRQ1;
+               ext_irqs[2] = BCM_6358_EXT_IRQ2;
+               ext_irqs[3] = BCM_6358_EXT_IRQ3;
++              ext_irqs[4] = BCM_6358_EXT_IRQ4;
++              ext_irqs[5] = BCM_6358_EXT_IRQ5;
+               ext_shift = 4;
+               break;
+       case BCM6362_CPU_ID:
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -940,6 +940,8 @@ enum bcm63xx_irq {
+ #define BCM_6358_EXT_IRQ1             (IRQ_INTERNAL_BASE + 26)
+ #define BCM_6358_EXT_IRQ2             (IRQ_INTERNAL_BASE + 27)
+ #define BCM_6358_EXT_IRQ3             (IRQ_INTERNAL_BASE + 28)
++#define BCM_6358_EXT_IRQ4             (IRQ_INTERNAL_BASE + 20)
++#define BCM_6358_EXT_IRQ5             (IRQ_INTERNAL_BASE + 21)
+ /*
+  * 6362 irqs
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -243,6 +243,7 @@
+ #define PERF_EXTIRQ_CFG_REG_6362      0x18
+ #define PERF_EXTIRQ_CFG_REG_6368      0x18
++#define PERF_EXTIRQ_CFG_REG2_6358     0x1c
+ #define PERF_EXTIRQ_CFG_REG2_6368     0x1c
+ /* for 6348 only */
diff --git a/target/linux/brcm63xx/patches-3.14/328-cfe_simplify_detection.patch b/target/linux/brcm63xx/patches-3.14/328-cfe_simplify_detection.patch
deleted file mode 100644 (file)
index e05c91d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
-+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_board.h
-@@ -1,6 +1,8 @@
- #ifndef BCM63XX_BOARD_H_
- #define BCM63XX_BOARD_H_
-+#include <asm/bootinfo.h>
-+
- const char *board_get_name(void);
- void board_prom_init(void);
-@@ -9,4 +11,8 @@ void board_setup(void);
- int board_register_devices(void);
-+static inline bool bcm63xx_is_cfe_present(void) {
-+      return fw_arg3 == 0x43464531;
-+}
-+
- #endif /* ! BCM63XX_BOARD_H_ */
diff --git a/target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch b/target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch
deleted file mode 100644 (file)
index dedd728..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
---- a/drivers/mtd/bcm63xxpart.c
-+++ b/drivers/mtd/bcm63xxpart.c
-@@ -35,7 +35,7 @@
- #include <asm/mach-bcm63xx/bcm63xx_nvram.h>
- #include <linux/bcm963xx_tag.h>
--#include <asm/mach-bcm63xx/board_bcm963xx.h>
-+#include <asm/mach-bcm63xx/bcm63xx_board.h>
- #define BCM63XX_EXTENDED_SIZE 0xBFC00000      /* Extended flash address */
-@@ -43,30 +43,6 @@
- #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
--static int bcm63xx_detect_cfe(struct mtd_info *master)
--{
--      char buf[9];
--      int ret;
--      size_t retlen;
--
--      ret = mtd_read(master, BCM963XX_CFE_VERSION_OFFSET, 5, &retlen,
--                     (void *)buf);
--      buf[retlen] = 0;
--
--      if (ret)
--              return ret;
--
--      if (strncmp("cfe-v", buf, 5) == 0)
--              return 0;
--
--      /* very old CFE's do not have the cfe-v string, so check for magic */
--      ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
--                     (void *)buf);
--      buf[retlen] = 0;
--
--      return strncmp("CFE1CFE1", buf, 8);
--}
--
- static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
-                                       struct mtd_partition **pparts,
-                                       struct mtd_part_parser_data *data)
-@@ -85,7 +61,7 @@ static int bcm63xx_parse_cfe_partitions(
-       u32 computed_crc;
-       bool rootfs_first = false;
--      if (bcm63xx_detect_cfe(master))
-+      if (!bcm63xx_is_cfe_present())
-               return -EINVAL;
-       cfe_erasesize = max_t(uint32_t, master->erasesize,
index 797e853baff0becf66bfe20e48c1316e351d4856..7dd5e083d881bf0dc27a2c213d053fd188019590 100644 (file)
@@ -284,57 +284,27 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
                spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
 --- a/arch/mips/bcm63xx/irq.c
 +++ b/arch/mips/bcm63xx/irq.c
-@@ -158,6 +158,7 @@ static void __internal_irq_unmask_##widt
- BUILD_IPIC_INTERNAL(32);
- BUILD_IPIC_INTERNAL(64);
-+BUILD_IPIC_INTERNAL(128);
- asmlinkage void plat_irq_dispatch(void)
- {
-@@ -343,6 +344,7 @@ static int bcm63xx_external_irq_set_type
-       case BCM6358_CPU_ID:
-       case BCM6362_CPU_ID:
-       case BCM6368_CPU_ID:
-+      case BCM63268_CPU_ID:
-               if (levelsense)
-                       reg |= EXTIRQ_CFG_LEVELSENSE(irq);
-               else
-@@ -515,6 +517,18 @@ static void bcm63xx_init_irq(void)
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
-               ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+@@ -150,6 +150,20 @@ static void bcm63xx_init_irq(void)
+               ext_irqs[5] = BCM_6368_EXT_IRQ5;
+               ext_shift = 4;
                break;
 +      case BCM63268_CPU_ID:
-+              irq_stat_addr[0] += PERF_IRQSTAT_63268_REG(0);
-+              irq_mask_addr[0] += PERF_IRQMASK_63268_REG(0);
-+              irq_stat_addr[1] += PERF_IRQSTAT_63268_REG(1);
-+              irq_mask_addr[1] += PERF_IRQMASK_63268_REG(1);
-+              irq_bits = 128;
++              l2_intc_bases[0] += PERF_IRQSTAT_63268_REG(0);
++              l2_intc_bases[1] += PERF_IRQSTAT_63268_REG(1);
++              l2_irq_count = 2;
++              l2_width = 4;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_63268;
 +              ext_irq_count = 4;
-+              is_ext_irq_cascaded = 1;
-+              ext_irq_start = BCM_63268_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-+              ext_irq_end = BCM_63268_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-+              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_63268;
++              ext_irqs[0] = BCM_63268_EXT_IRQ0;
++              ext_irqs[1] = BCM_63268_EXT_IRQ1;
++              ext_irqs[2] = BCM_63268_EXT_IRQ2;
++              ext_irqs[3] = BCM_63268_EXT_IRQ3;
++              ext_shift = 4;
 +              break;
        default:
                BUG();
        }
-@@ -523,10 +537,14 @@ static void bcm63xx_init_irq(void)
-               dispatch_internal = __dispatch_internal_32;
-               internal_irq_mask = __internal_irq_mask_32;
-               internal_irq_unmask = __internal_irq_unmask_32;
--      } else {
-+      } else if (irq_bits == 64) {
-               dispatch_internal = __dispatch_internal_64;
-               internal_irq_mask = __internal_irq_mask_64;
-               internal_irq_unmask = __internal_irq_unmask_64;
-+      } else {
-+              dispatch_internal = __dispatch_internal_128;
-+              internal_irq_mask = __internal_irq_mask_128;
-+              internal_irq_unmask = __internal_irq_unmask_128;
-       }
- }
 --- a/arch/mips/bcm63xx/reset.c
 +++ b/arch/mips/bcm63xx/reset.c
 @@ -125,6 +125,20 @@
@@ -479,7 +449,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
  
  extern const unsigned long *bcm63xx_regs_base;
  
-@@ -1084,6 +1147,73 @@ enum bcm63xx_irq {
+@@ -1086,6 +1149,73 @@ enum bcm63xx_irq {
  #define BCM_6368_EXT_IRQ4             (IRQ_INTERNAL_BASE + 24)
  #define BCM_6368_EXT_IRQ5             (IRQ_INTERNAL_BASE + 25)
  
@@ -650,9 +620,9 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
  #define PERF_EXTIRQ_CFG_REG_6368      0x18
 +#define PERF_EXTIRQ_CFG_REG_63268     0x18
  
+ #define PERF_EXTIRQ_CFG_REG2_6358     0x1c
  #define PERF_EXTIRQ_CFG_REG2_6368     0x1c
-@@ -273,6 +324,7 @@
+@@ -274,6 +325,7 @@
  #define PERF_SOFTRESET_6358_REG               0x34
  #define PERF_SOFTRESET_6362_REG               0x10
  #define PERF_SOFTRESET_6368_REG               0x10
@@ -660,7 +630,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
  
  #define SOFTRESET_3368_SPI_MASK               (1 << 0)
  #define SOFTRESET_3368_ENET_MASK      (1 << 2)
-@@ -366,6 +418,26 @@
+@@ -367,6 +419,26 @@
  #define SOFTRESET_6368_USBH_MASK      (1 << 12)
  #define SOFTRESET_6368_PCM_MASK               (1 << 13)
  
@@ -687,7 +657,7 @@ Signed-off-by: Jonas Gorski <jogo@openwrt.org>
  /* MIPS PLL control register */
  #define PERF_MIPSPLLCTL_REG           0x34
  #define MIPSPLLCTL_N1_SHIFT           20
-@@ -1379,6 +1451,13 @@
+@@ -1380,6 +1452,13 @@
  #define STRAPBUS_6362_BOOT_SEL_SERIAL (1 << 15)
  #define STRAPBUS_6362_BOOT_SEL_NAND   (0 << 15)
  
index 46b5f5c6855daa0533974a0878f746e988c62773..be7264c3cbd61e38367c7cccc4d1aed9458b72bb 100644 (file)
@@ -194,23 +194,26 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
        spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
 --- a/arch/mips/bcm63xx/irq.c
 +++ b/arch/mips/bcm63xx/irq.c
-@@ -441,6 +441,16 @@ static void bcm63xx_init_irq(void)
-               ext_irq_count = 4;
-               ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+@@ -49,6 +49,19 @@ static void bcm63xx_init_irq(void)
+               ext_irqs[3] = BCM_3368_EXT_IRQ3;
+               ext_shift = 4;
                break;
 +      case BCM6318_CPU_ID:
-+              irq_stat_addr[0] += PERF_IRQSTAT_6318_REG;
-+              irq_mask_addr[0] += PERF_IRQMASK_6318_REG;
-+              irq_bits = 128;
++              l2_intc_bases[0] += PERF_IRQMASK_6318_REG;
++              l2_irq_count = 1;
++              l2_width = 4;
++
++              ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6318;
 +              ext_irq_count = 4;
-+              is_ext_irq_cascaded = 1;
-+              ext_irq_start = BCM_6318_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-+              ext_irq_end = BCM_6318_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-+              ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6318;
++              ext_irqs[0] = BCM_6318_EXT_IRQ0;
++              ext_irqs[1] = BCM_6318_EXT_IRQ0;
++              ext_irqs[2] = BCM_6318_EXT_IRQ0;
++              ext_irqs[3] = BCM_6318_EXT_IRQ0;
++              ext_shift = 4;
 +              break;
        case BCM6328_CPU_ID:
-               irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
-               irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+               l2_intc_bases[0] += PERF_IRQMASK_6328_REG(0);
+               l2_intc_bases[1] += PERF_IRQMASK_6328_REG(1);
 --- a/arch/mips/bcm63xx/prom.c
 +++ b/arch/mips/bcm63xx/prom.c
 @@ -72,7 +72,7 @@ void __init prom_init(void)
@@ -527,7 +530,7 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
  #define PERF_EXTIRQ_CFG_REG_6328      0x18
  #define PERF_EXTIRQ_CFG_REG_6338      0x14
  #define PERF_EXTIRQ_CFG_REG_6345      0x14
-@@ -320,6 +370,7 @@
+@@ -321,6 +371,7 @@
  
  /* Soft Reset register */
  #define PERF_SOFTRESET_REG            0x28
@@ -535,7 +538,7 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
  #define PERF_SOFTRESET_6328_REG               0x10
  #define PERF_SOFTRESET_6358_REG               0x34
  #define PERF_SOFTRESET_6362_REG               0x10
-@@ -333,6 +384,18 @@
+@@ -334,6 +385,18 @@
  #define SOFTRESET_3368_USBS_MASK      (1 << 11)
  #define SOFTRESET_3368_PCM_MASK               (1 << 13)
  
@@ -554,7 +557,7 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
  #define SOFTRESET_6328_SPI_MASK               (1 << 0)
  #define SOFTRESET_6328_EPHY_MASK      (1 << 1)
  #define SOFTRESET_6328_SAR_MASK               (1 << 2)
-@@ -504,8 +567,17 @@
+@@ -505,8 +568,17 @@
  #define TIMER_IRQSTAT_TIMER1_IR_EN    (1 << 9)
  #define TIMER_IRQSTAT_TIMER2_IR_EN    (1 << 10)
  
@@ -572,7 +575,7 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318
  #define TIMER_CTL0_REG                        0x4
  #define TIMER_CTL1_REG                        0x8
  #define TIMER_CTL2_REG                        0xC
-@@ -1252,6 +1324,8 @@
+@@ -1253,6 +1325,8 @@
  #define SDRAM_CFG_32B_MASK            (1 << SDRAM_CFG_32B_SHIFT)
  #define SDRAM_CFG_BANK_SHIFT          13
  #define SDRAM_CFG_BANK_MASK           (1 << SDRAM_CFG_BANK_SHIFT)
index 3ba33576fddf6b42e510af8adf586134bfb94d1a..3ac08b471e3ef9c14bfeea699d959564ff69f5bd 100644 (file)
@@ -79,7 +79,7 @@ Subject: [PATCH 53/53] MIPS: BCM63XX: add PCIe support for BCM6318
  #define BCM_PCIE_MEM_END_PA_6328      (BCM_PCIE_MEM_BASE_PA_6328 +    \
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -1542,6 +1542,17 @@
+@@ -1543,6 +1543,17 @@
   * _REG relative to RSET_PCIE
   *************************************************************************/
  
@@ -97,7 +97,7 @@ Subject: [PATCH 53/53] MIPS: BCM63XX: add PCIe support for BCM6318
  #define PCIE_CONFIG2_REG              0x408
  #define CONFIG2_BAR1_SIZE_EN          1
  #define CONFIG2_BAR1_SIZE_MASK                0xf
-@@ -1587,7 +1598,54 @@
+@@ -1588,7 +1599,54 @@
  #define PCIE_RC_INT_C                 (1 << 2)
  #define PCIE_RC_INT_D                 (1 << 3)
  
index c59d4f74663fe598f977165dd7b55c24ff638f7e..904d0b7ab054a5723069eb40accdb48329663e4f 100644 (file)
@@ -58,7 +58,7 @@
        spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -680,6 +680,12 @@
+@@ -681,6 +681,12 @@
  #define GPIO_MODE_6368_SPI_SSN4               (1 << 30)
  #define GPIO_MODE_6368_SPI_SSN5               (1 << 31)
  
@@ -71,7 +71,7 @@
  
  #define GPIO_PINMUX_OTHR_REG          0x24
  #define GPIO_PINMUX_OTHR_6328_USB_SHIFT 12
-@@ -998,6 +1004,7 @@
+@@ -999,6 +1005,7 @@
  
  #define USBH_PRIV_SWAP_6358_REG               0x0
  #define USBH_PRIV_SWAP_6368_REG               0x1c
@@ -79,7 +79,7 @@
  
  #define USBH_PRIV_SWAP_USBD_SHIFT     6
  #define USBH_PRIV_SWAP_USBD_MASK      (1 << USBH_PRIV_SWAP_USBD_SHIFT)
-@@ -1023,6 +1030,13 @@
+@@ -1024,6 +1031,13 @@
  #define USBH_PRIV_SETUP_IOC_SHIFT     4
  #define USBH_PRIV_SETUP_IOC_MASK      (1 << USBH_PRIV_SETUP_IOC_SHIFT)
  
index 2489c21e2b3e6538bda56dda3b64f67c295deabe..c758163956020922c9fc61f75ecca3e18a40c9d2 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -585,6 +585,9 @@
+@@ -586,6 +586,9 @@
  #define TIMER_CTL_MONOTONIC_MASK      (1 << 30)
  #define TIMER_CTL_ENABLE_MASK         (1 << 31)
  
@@ -10,7 +10,7 @@
  
  /*************************************************************************
   * _REG relative to RSET_WDT
-@@ -1546,6 +1549,11 @@
+@@ -1547,6 +1550,11 @@
  #define STRAPBUS_63268_FCVO_SHIFT     21
  #define STRAPBUS_63268_FCVO_MASK      (0xf << STRAPBUS_63268_FCVO_SHIFT)
  
index 1dff9bfdc2f569d387766f25ac2ea5888ef5fbba..0b709915a7484e7934938abb219c457580f32d13 100644 (file)
@@ -1,6 +1,6 @@
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -1032,11 +1032,18 @@
+@@ -1033,11 +1033,18 @@
  #define USBH_PRIV_SETUP_6368_REG      0x28
  #define USBH_PRIV_SETUP_IOC_SHIFT     4
  #define USBH_PRIV_SETUP_IOC_MASK      (1 << USBH_PRIV_SETUP_IOC_SHIFT)
index 344e78b5b41e03bff5f3d1f9cce1e8e2cb1a9368..900116ff45d2ceabd9fe55a6470c38e8045ca787 100644 (file)
@@ -43,7 +43,7 @@ Completely untested on anything except MIPS32 / big endian.
 
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -2519,6 +2519,24 @@ config RAPIDIO
+@@ -2523,6 +2523,24 @@ config RAPIDIO
  
  source "drivers/rapidio/Kconfig"
  
index f3484b692e8e0bce8be55bee06d5af9b0b3c50e7..0745c3cc8f6ed8ff2b86847d9ff363031176e2be 100644 (file)
@@ -11,7 +11,7 @@
        bcm_gpio_writel(val, GPIO_MODE_REG);
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -650,6 +650,8 @@
+@@ -651,6 +651,8 @@
  #define GPIO_MODE_6358_EXTRA_SPI_SS   (1 << 7)
  #define GPIO_MODE_6358_SERIAL_LED     (1 << 10)
  #define GPIO_MODE_6358_UTOPIA         (1 << 12)
index 52c75a81c7261adf87329930707a51a5c99ab8af..a6f35c5b5e6a1dc86669e60f6040222902fa9f38 100644 (file)
@@ -10,7 +10,7 @@ Subject: [PATCH 54/81] bcm63xx_enet: enable rgmii clock on external ports
 
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -966,6 +966,19 @@
+@@ -967,6 +967,19 @@
  #define ENETSW_PORTOV_FDX_MASK                (1 << 1)
  #define ENETSW_PORTOV_LINKUP_MASK     (1 << 0)
  
index 5fe20784662b1859764188eeceefb2153d1b5f01..24a5888ef5d974b55c1876e4b08f23b6dce1afa7 100644 (file)
@@ -115,7 +115,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
                return -ENODEV;
 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
 +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
-@@ -707,6 +707,7 @@
+@@ -708,6 +708,7 @@
  #define GPIO_STRAPBUS_REG             0x40
  #define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
  #define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
@@ -123,7 +123,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
  #define STRAPBUS_6368_BOOT_SEL_MASK   0x3
  #define STRAPBUS_6368_BOOT_SEL_NAND   0
  #define STRAPBUS_6368_BOOT_SEL_SERIAL 1
-@@ -1577,6 +1578,7 @@
+@@ -1578,6 +1579,7 @@
  #define IDDQ_CTRL_63268_USBH          (1 << 4)
  
  #define MISC_STRAPBUS_6328_REG                0x240