aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Gorski <jogo@openwrt.org>2014-12-01 00:51:51 +0000
committerJonas Gorski <jogo@openwrt.org>2014-12-01 00:51:51 +0000
commit29b06c76c3c91635b5d82ca9f20ed8062b94ebf0 (patch)
treef7d3454fc9f6488d9a525185b9779d22f4154b3a
parent69df57900e7885a54eb77b56035b2d824f78c926 (diff)
downloadupstream-29b06c76c3c91635b5d82ca9f20ed8062b94ebf0.tar.gz
upstream-29b06c76c3c91635b5d82ca9f20ed8062b94ebf0.tar.bz2
upstream-29b06c76c3c91635b5d82ca9f20ed8062b94ebf0.zip
brcm63xx: convert to irq domain
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> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43454 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--target/linux/brcm63xx/patches-3.14/030-MIPS-Always-use-IRQ-domains-for-CPU-IRQs.patch98
-rw-r--r--target/linux/brcm63xx/patches-3.14/031-MIPS-Rename-mips_cpu_intc_init-mips_cpu_irq_of_init.patch89
-rw-r--r--target/linux/brcm63xx/patches-3.14/032-MIPS-Provide-a-generic-plat_irq_dispatch.patch58
-rw-r--r--target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch (renamed from target/linux/brcm63xx/patches-3.14/328-cfe_simplify_detection.patch)0
-rw-r--r--target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch (renamed from target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch)0
-rw-r--r--target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch411
-rw-r--r--target/linux/brcm63xx/patches-3.14/321-irqchip-add-support-for-bcm6345-style-external-inter.patch384
-rw-r--r--target/linux/brcm63xx/patches-3.14/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch694
-rw-r--r--target/linux/brcm63xx/patches-3.14/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch57
-rw-r--r--target/linux/brcm63xx/patches-3.14/339-MIPS-BCM63XX-add-support-for-BCM63268.patch68
-rw-r--r--target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch35
-rw-r--r--target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch4
-rw-r--r--target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch6
-rw-r--r--target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch4
-rw-r--r--target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch2
-rw-r--r--target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch2
-rw-r--r--target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch2
-rw-r--r--target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch2
-rw-r--r--target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch4
19 files changed, 1842 insertions, 78 deletions
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
index 0000000000..e6570ecdc6
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/030-MIPS-Always-use-IRQ-domains-for-CPU-IRQs.patch
@@ -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
index 0000000000..de0f111e28
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/031-MIPS-Rename-mips_cpu_intc_init-mips_cpu_irq_of_init.patch
@@ -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
index 0000000000..79a0436dc6
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/032-MIPS-Provide-a-generic-plat_irq_dispatch.patch
@@ -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/328-cfe_simplify_detection.patch b/target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch
index e05c91d931..e05c91d931 100644
--- a/target/linux/brcm63xx/patches-3.14/328-cfe_simplify_detection.patch
+++ b/target/linux/brcm63xx/patches-3.14/310-cfe_simplify_detection.patch
diff --git a/target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch b/target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch
index dedd728ce9..dedd728ce9 100644
--- a/target/linux/brcm63xx/patches-3.14/329-bcm63xxpart_use_cfedetection.patch
+++ b/target/linux/brcm63xx/patches-3.14/311-bcm63xxpart_use_cfedetection.patch
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
index 0000000000..a260a1b0fe
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch
@@ -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
index 0000000000..d53deba0ca
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/321-irqchip-add-support-for-bcm6345-style-external-inter.patch
@@ -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
index 0000000000..63384773ea
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch
@@ -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
index 0000000000..fac3d5c764
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.14/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch
@@ -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/339-MIPS-BCM63XX-add-support-for-BCM63268.patch b/target/linux/brcm63xx/patches-3.14/339-MIPS-BCM63XX-add-support-for-BCM63268.patch
index 797e853baf..7dd5e083d8 100644
--- a/target/linux/brcm63xx/patches-3.14/339-MIPS-BCM63XX-add-support-for-BCM63268.patch
+++ b/target/linux/brcm63xx/patches-3.14/339-MIPS-BCM63XX-add-support-for-BCM63268.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch b/target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch
index 46b5f5c685..be7264c3cb 100644
--- a/target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch
+++ b/target/linux/brcm63xx/patches-3.14/341-MIPS-BCM63XX-add-support-for-BCM6318.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch b/target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch
index 3ba33576fd..3ac08b471e 100644
--- a/target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch
+++ b/target/linux/brcm63xx/patches-3.14/343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch b/target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch
index c59d4f7466..904d0b7ab0 100644
--- a/target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch
+++ b/target/linux/brcm63xx/patches-3.14/347-MIPS-BCM6318-USB-support.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch b/target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch
index 2489c21e2b..c758163956 100644
--- a/target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch
+++ b/target/linux/brcm63xx/patches-3.14/348-MIPS-BCM63XX-fix-BCM63268-USB-clock.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch b/target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch
index 1dff9bfdc2..0b709915a7 100644
--- a/target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch
+++ b/target/linux/brcm63xx/patches-3.14/349-MIPS-BCM63XX-add-BCM63268-USB-support.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch b/target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch
index 344e78b5b4..900116ff45 100644
--- a/target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch
+++ b/target/linux/brcm63xx/patches-3.14/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch
@@ -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"
diff --git a/target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch b/target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch
index f3484b692e..0745c3cc8f 100644
--- a/target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch
+++ b/target/linux/brcm63xx/patches-3.14/403-6358-enet1-external-mii-clk.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch b/target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
index 52c75a81c7..a6f35c5b5e 100644
--- a/target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
+++ b/target/linux/brcm63xx/patches-3.14/408-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
@@ -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)
diff --git a/target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch b/target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch
index 5fe2078466..24a5888ef5 100644
--- a/target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch
+++ b/target/linux/brcm63xx/patches-3.14/411-MIPS-BCM63XX-Register-SPI-flash-if-present.patch
@@ -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