From: Jonas Gorski Date: Mon, 8 Dec 2014 16:11:52 +0000 (+0000) Subject: brcm63xx: fix a few issues in irq chip drivers X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=bdb1ee51f85607632893564dc332f1469c0970d4;p=openwrt%2Fstaging%2Fjow.git brcm63xx: fix a few issues in irq chip drivers Fix locking and lock usage, making it compile for SMP. Signed-off-by: Jonas Gorski SVN-Revision: 43578 --- diff --git a/target/linux/brcm63xx/config-3.14 b/target/linux/brcm63xx/config-3.14 index 1fee6392bd..dd27f473bb 100644 --- a/target/linux/brcm63xx/config-3.14 +++ b/target/linux/brcm63xx/config-3.14 @@ -14,6 +14,8 @@ CONFIG_B53_PHY_DRIVER=y CONFIG_B53_PHY_FIXUP=y CONFIG_B53_SPI_DRIVER=y # CONFIG_B53_SRAB_DRIVER is not set +CONFIG_BCM6345_EXT_IRQ=y +CONFIG_BCM6345_PERIPH_IRQ=y CONFIG_BCM63XX=y CONFIG_BCM63XX_CPU_3368=y CONFIG_BCM63XX_CPU_6318=y @@ -71,7 +73,6 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_NET_UTILS=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GPIOLIB=y diff --git a/target/linux/brcm63xx/config-3.18 b/target/linux/brcm63xx/config-3.18 index b323da40ca..e3cf020a99 100644 --- a/target/linux/brcm63xx/config-3.18 +++ b/target/linux/brcm63xx/config-3.18 @@ -18,7 +18,7 @@ CONFIG_B53_PHY_FIXUP=y CONFIG_B53_SPI_DRIVER=y # CONFIG_B53_SRAB_DRIVER is not set CONFIG_BCM6345_EXT_IRQ=y -CONFIG_BCM6345_L2_IRQ=y +CONFIG_BCM6345_PERIPH_IRQ=y CONFIG_BCM63XX=y CONFIG_BCM63XX_CPU_3368=y CONFIG_BCM63XX_CPU_6318=y @@ -61,6 +61,7 @@ CONFIG_CPU_GENERIC_DUMP_TLB=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_MIPS32=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y CONFIG_CPU_R4K_CACHE_TLB=y CONFIG_CPU_R4K_FPU=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y diff --git a/target/linux/brcm63xx/dts/bcm6318.dtsi b/target/linux/brcm63xx/dts/bcm6318.dtsi index 723c488f20..97bdea7b5b 100644 --- a/target/linux/brcm63xx/dts/bcm6318.dtsi +++ b/target/linux/brcm63xx/dts/bcm6318.dtsi @@ -42,7 +42,7 @@ }; periph_intc: interrupt-controller@10000020 { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0x10000020 0x20>; interrupt-controller; diff --git a/target/linux/brcm63xx/dts/bcm63268.dtsi b/target/linux/brcm63xx/dts/bcm63268.dtsi index 214cd6266c..bc80d70575 100644 --- a/target/linux/brcm63xx/dts/bcm63268.dtsi +++ b/target/linux/brcm63xx/dts/bcm63268.dtsi @@ -48,7 +48,7 @@ }; periph_intc: interrupt-controller@10000020 { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0x10000020 0x20>, <0x10000040 0x20>; diff --git a/target/linux/brcm63xx/dts/bcm6328.dtsi b/target/linux/brcm63xx/dts/bcm6328.dtsi index 0ed186e185..53f96ff009 100644 --- a/target/linux/brcm63xx/dts/bcm6328.dtsi +++ b/target/linux/brcm63xx/dts/bcm6328.dtsi @@ -42,7 +42,7 @@ }; periph_intc: interrupt-controller@10000020 { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0x10000020 0x10>; interrupt-controller; diff --git a/target/linux/brcm63xx/dts/bcm6338.dtsi b/target/linux/brcm63xx/dts/bcm6338.dtsi index b527781060..c1980f4036 100644 --- a/target/linux/brcm63xx/dts/bcm6338.dtsi +++ b/target/linux/brcm63xx/dts/bcm6338.dtsi @@ -45,7 +45,7 @@ compatible = "simple-bus"; periph_intc: interrupt-controller@fffe000c { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0xfffe000c 0x8>; interrupt-controller; diff --git a/target/linux/brcm63xx/dts/bcm6345.dtsi b/target/linux/brcm63xx/dts/bcm6345.dtsi index 16ba8bd6c0..e8e7016ff7 100644 --- a/target/linux/brcm63xx/dts/bcm6345.dtsi +++ b/target/linux/brcm63xx/dts/bcm6345.dtsi @@ -45,7 +45,7 @@ compatible = "simple-bus"; periph_intc: interrupt-controller@fffe000c { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0xfffe000c 0x9>; interrupt-controller; diff --git a/target/linux/brcm63xx/dts/bcm6348.dtsi b/target/linux/brcm63xx/dts/bcm6348.dtsi index 06ecbaa1f9..7dd423b9ca 100644 --- a/target/linux/brcm63xx/dts/bcm6348.dtsi +++ b/target/linux/brcm63xx/dts/bcm6348.dtsi @@ -45,7 +45,7 @@ compatible = "simple-bus"; periph_intc: interrupt-controller@fffe000c { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0xfffe000c 0x8>; interrupt-controller; @@ -64,6 +64,8 @@ interrupt-parent = <&cpu_intc>; interrupts = <3>, <4>, <5>, <6>; + + brcm,field-width = <5>; }; }; }; diff --git a/target/linux/brcm63xx/dts/bcm6358.dtsi b/target/linux/brcm63xx/dts/bcm6358.dtsi index a4af2144a8..7217b8db6e 100644 --- a/target/linux/brcm63xx/dts/bcm6358.dtsi +++ b/target/linux/brcm63xx/dts/bcm6358.dtsi @@ -51,7 +51,7 @@ compatible = "simple-bus"; periph_intc: interrupt-controller@fffe000c { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0xfffe000c 0x8>, <0xfffe0038 0x8>; diff --git a/target/linux/brcm63xx/dts/bcm6362.dtsi b/target/linux/brcm63xx/dts/bcm6362.dtsi index 36765b0eba..4e2e41d5d4 100644 --- a/target/linux/brcm63xx/dts/bcm6362.dtsi +++ b/target/linux/brcm63xx/dts/bcm6362.dtsi @@ -48,7 +48,7 @@ }; periph_intc: interrupt-controller@10000020 { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0x10000020 0x10>, <0x10000030 0x10>; diff --git a/target/linux/brcm63xx/dts/bcm6368.dtsi b/target/linux/brcm63xx/dts/bcm6368.dtsi index dcbbdbfe81..27b9f62b69 100644 --- a/target/linux/brcm63xx/dts/bcm6368.dtsi +++ b/target/linux/brcm63xx/dts/bcm6368.dtsi @@ -63,7 +63,7 @@ }; periph_intc: interrupt-controller@10000020 { - compatible = "brcm,bcm6345-l2-intc"; + compatible = "brcm,bcm6345-periph-intc"; reg = <0x10000020 0x10>, <0x10000030 0x10>; 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 deleted file mode 100644 index a260a1b0fe..0000000000 --- a/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch +++ /dev/null @@ -1,411 +0,0 @@ -From 4d3886359d6f6ac475e143d5f3e3b389542a0510 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -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 ---- - .../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 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_BCM63XX -+#include -+ -+#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 -+ * Copyright (C) 2008 Nicolas Schichan -+ */ -+ -+#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/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch b/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch new file mode 100644 index 0000000000..2fd1568e27 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.14/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch @@ -0,0 +1,486 @@ +From 7aaa70416d87434792b73077beb328202975e541 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 30 Nov 2014 14:53:12 +0100 +Subject: [PATCH 1/5] irqchip: add support for bcm6345-style periphery irq + controller + +Signed-off-by: Jonas Gorski +--- + .../brcm,bcm6345-periph-intc.txt | 50 +++ + drivers/irqchip/Kconfig | 4 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-bcm6345-periph.c | 325 ++++++++++++++++++++ + include/linux/irqchip/irq-bcm6345-periph.h | 16 + + 5 files changed, 396 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt + create mode 100644 drivers/irqchip/irq-bcm6345-periph.c + create mode 100644 include/linux/irqchip/irq-bcm6345-periph.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt +@@ -0,0 +1,50 @@ ++Broadcom BCM6345 Level 1 periphery interrupt controller ++ ++This block is a interrupt controller that is typically connected directly ++to one of the HW INT lines on each CPU. Every BCM63XX xDSL chip since ++BCM6345 has contained this hardware. ++ ++Key elements of the hardware design include: ++ ++- 32, 64, or 128 incoming level IRQ lines ++ ++- All onchip peripherals are wired directly to an L2 input ++ ++- A separate instance of the register set for each CPU, allowing individual ++ peripheral IRQs to be routed to any CPU ++ ++- No atomic mask/unmask operations ++ ++- No polarity/level/edge settings ++ ++- No FIFO or priority encoder logic; software is expected to read all ++ 1-4 status words to determine which IRQs are pending ++ ++Required properties: ++ ++- compatible: Should be "brcm,bcm6345-periph-intc". ++- reg: Specifies the base physical address and size of the registers. ++ Multiple register addresses 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. ++ Multiple lines are used to route interrupts to different cpus, with the first ++ assumed to be for the boot CPU. ++ ++Example: ++ ++periph_intc: interrupt-controller@f0406800 { ++ compatible = "brcm,bcm6345-periph-intc"; ++ reg = <0x10000020 0x10>, <0x10000030 0x10>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpu_intc>; ++ 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_PERIPH_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_PERIPH_IRQ) += irq-bcm6345-periph.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-periph.c +@@ -0,0 +1,340 @@ ++/* ++ * 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_BCM63XX ++#include ++ ++#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; ++ raw_spinlock_t lock; ++}; ++ ++static void bcm6345_periph_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) { ++ int virq; ++ ++ virq = irq_find_mapping(data->domain, base + hw_irq); ++ generic_handle_irq(virq); ++ } ++ } ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static void __bcm6345_periph_enable(struct intc_block *block, int reg, int bit, ++ bool enable) ++{ ++ u32 val; ++ ++ val = __raw_readl(block->en_reg[reg]); ++ if (enable) ++ val |= BIT(bit); ++ else ++ val &= ~BIT(bit); ++ __raw_writel(val, block->en_reg[reg]); ++} ++ ++static void bcm6345_periph_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]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ __bcm6345_periph_enable(block, reg, bit, false); ++ } ++ raw_spin_unlock(&priv->lock); ++} ++ ++static void bcm6345_periph_irq_unmask(struct irq_data *data) ++{ ++ struct intc_data *priv = data->domain->host_data; ++ irq_hw_number_t hwirq = irqd_to_hwirq(data); ++ unsigned int i, reg, bit; ++ ++ 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]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ if (block->mask_cache[reg] & BIT(bit)) ++ __bcm6345_periph_enable(block, reg, bit, true); ++ else ++ __bcm6345_periph_enable(block, reg, bit, false); ++ ++ } ++ raw_spin_unlock(&priv->lock); ++} ++ ++#ifdef CONFIG_SMP ++static int bcm6345_periph_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; ++ bool enabled; ++ 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); ++ enabled = !irqd_irq_masked(data); ++ for (i = 0; i < MAX_PARENT_IRQS; i++) { ++ struct intc_block *block = &priv->block[i]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ if (i == cpu) { ++ block->mask_cache[reg] |= BIT(bit); ++ __bcm6345_periph_enable(block, reg, bit, enabled); ++ } else { ++ block->mask_cache[reg] &= ~BIT(bit); ++ __bcm6345_periph_enable(block, reg, bit, false); ++ } ++ } ++ raw_spin_unlock(&priv->lock); ++ ++ return 0; ++} ++#endif ++ ++static int bcm6345_periph_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_periph_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = bcm6345_periph_map, ++}; ++ ++static int __init __bcm6345_periph_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; ++ ++ raw_spin_lock_init(&data->lock); ++ ++ 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_periph_irq_handle); ++ } ++ ++ data->num_words = num_words; ++ ++ data->chip.name = "bcm6345-periph-intc"; ++ data->chip.irq_mask = bcm6345_periph_irq_mask; ++ data->chip.irq_unmask = bcm6345_periph_irq_unmask; ++ ++#ifdef CONFIG_SMP ++ if (num_blocks > 1) ++ data->chip.irq_set_affinity = bcm6345_periph_set_affinity; ++#endif ++ ++ data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words, ++ VIRQ_BASE, ++ &bcm6345_periph_domain_ops, data); ++ if (!data->domain) { ++ kfree(data); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void __init bcm6345_periph_intc_init(int num_blocks, int *irq, ++ void __iomem **base, int num_words) ++{ ++ __bcm6345_periph_intc_init(NULL, num_blocks, irq, base, num_words); ++} ++ ++#ifdef CONFIG_OF ++static int __init bcm6345_periph_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_periph_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_periph_intc, "brcm,bcm6345-periph-intc", ++ bcm6345_periph_of_init); ++#endif +--- /dev/null ++++ b/include/linux/irqchip/irq-bcm6345-periph.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 ++ * Copyright (C) 2008 Nicolas Schichan ++ */ ++ ++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H ++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H ++ ++void bcm6345_periph_intc_init(int num_blocks, int *irq, void __iomem **base, ++ int num_words); ++ ++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H */ +diff --git a/drivers/irqchip/irq-bcm6345-periph.c b/drivers/irqchip/irq-bcm6345-periph.c +index dfab88e..b280164 100644 +--- a/drivers/irqchip/irq-bcm6345-periph.c ++++ b/drivers/irqchip/irq-bcm6345-periph.c +@@ -149,6 +149,7 @@ static int bcm6345_periph_set_affinity(struct irq_data *data, + irq_hw_number_t hwirq = irqd_to_hwirq(data); + struct intc_data *priv = data->domain->host_data; + unsigned int i, reg, bit; ++ unsigned long flags; + bool enabled; + int cpu; + +@@ -168,7 +169,7 @@ static int bcm6345_periph_set_affinity(struct irq_data *data, + if (!priv->block[cpu].parent_irq) + return -EINVAL; + +- raw_spin_lock(&priv->lock); ++ raw_spin_lock_irqsave(&priv->lock, flags); + enabled = !irqd_irq_masked(data); + for (i = 0; i < MAX_PARENT_IRQS; i++) { + struct intc_block *block = &priv->block[i]; +@@ -184,7 +185,7 @@ static int bcm6345_periph_set_affinity(struct irq_data *data, + __bcm6345_periph_enable(block, reg, bit, false); + } + } +- raw_spin_unlock(&priv->lock); ++ raw_spin_unlock_irqrestore(&priv->lock, flags); + + return 0; + } 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 index d53deba0ca..964d9fc60f 100644 --- 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 @@ -1,37 +1,42 @@ -From 6896b5f0538a7a7cfb7fac2d9ed3c6841c72ed40 Mon Sep 17 00:00:00 2001 +From ac60253478d58fc73b4c0a390eb6229222460e8a Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 30 Nov 2014 14:54:27 +0100 -Subject: [PATCH 18/20] irqchip: add support for bcm6345-style external +Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external interrupt controller Signed-off-by: Jonas Gorski --- - .../interrupt-controller/brcm,bcm6345-ext-intc.txt | 24 ++ + .../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++ 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(+) + drivers/irqchip/irq-bcm6345-ext.c | 286 ++++++++++++++++++++ + include/linux/irqchip/irq-bcm6345-ext.h | 14 + + 5 files changed, 334 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 + create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt -@@ -0,0 +1,24 @@ +@@ -0,0 +1,29 @@ +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 ++- compatible: Should be "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. ++ ++Optional properties: ++ ++- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the ++ register. Defaults to 4. + +Example: + @@ -53,7 +58,7 @@ Signed-off-by: Jonas Gorski + bool + select IRQ_DOMAIN + - config BCM6345_L2_IRQ + config BCM6345_PERIPH_IRQ bool select IRQ_DOMAIN --- a/drivers/irqchip/Makefile @@ -63,12 +68,12 @@ Signed-off-by: Jonas Gorski 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_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.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 @@ +@@ -0,0 +1,288 @@ +/* + * 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 @@ -80,7 +85,7 @@ Signed-off-by: Jonas Gorski +#include +#include +#include -+#include ++#include +#include +#include +#include @@ -110,7 +115,7 @@ Signed-off-by: Jonas Gorski +struct intc_data { + struct irq_chip chip; + struct irq_domain *domain; -+ spinlock_t lock; ++ raw_spinlock_t lock; + + int parent_irq[MAX_IRQS]; + void __iomem *reg; @@ -141,11 +146,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static void bcm6345_ext_intc_irq_mask(struct irq_data *data) @@ -154,11 +159,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static void bcm6345_ext_intc_irq_unmask(struct irq_data *data) @@ -167,11 +172,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static int bcm6345_ext_intc_set_type(struct irq_data *data, @@ -213,7 +218,7 @@ Signed-off-by: Jonas Gorski + return -EINVAL; + } + -+ raw_spin_lock(priv->lock); ++ raw_spin_lock(&priv->lock); + reg = __raw_readl(priv->reg); + + if (levelsense) @@ -230,7 +235,7 @@ Signed-off-by: Jonas Gorski + reg &= ~(hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift)); + + __raw_writel(reg, priv->reg); -+ raw_spin_unlock(priv->lock); ++ raw_spin_unlock(&priv->lock); + + irqd_set_trigger_type(data, flow_type); + if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) @@ -269,6 +274,8 @@ Signed-off-by: Jonas Gorski + if (!data) + return -ENOMEM; + ++ raw_spin_lock_init(&data->lock); ++ + for (i = 0; i < num_irqs; i++) { + data->parent_irq[i] = irqs[i]; + @@ -311,20 +318,23 @@ Signed-off-by: Jonas Gorski +} + +#ifdef CONFIG_OF -+static int __init bcm63xx_ext_intc_of_init(struct device_node *node, -+ struct device_node *parent, -+ int shift) ++static int __init bcm6345_ext_intc_of_init(struct device_node *node, ++ struct device_node *parent) +{ + int num_irqs, ret = -EINVAL; + unsigned i; + void __iomem *base; + int irqs[MAX_IRQS] = { 0 }; ++ u32 shift; + + num_irqs = of_irq_count(node); + + if (!num_irqs || num_irqs > MAX_IRQS) + return -EINVAL; + ++ if (of_property_read_u32(node, "brcm,field-width", &shift)) ++ shift = 4; ++ + for (i = 0; i < num_irqs; i++) { + irqs[i] = irq_of_parse_and_map(node, i); + if (!irqs[i]) { @@ -349,24 +359,11 @@ Signed-off-by: Jonas Gorski + 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 ++++ b/include/linux/irqchip/irq-bcm6345-ext.h @@ -0,0 +1,14 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -376,9 +373,9 @@ Signed-off-by: Jonas Gorski + * Copyright (C) 2014 Jonas Gorski + */ + -+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H -+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H ++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H ++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_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 */ ++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_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 index 63384773ea..7f3682c417 100644 --- 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 @@ -19,7 +19,7 @@ Signed-off-by: Jonas Gorski select DMA_NONCOHERENT select IRQ_CPU + select BCM6345_EXT_IRQ -+ select BCM6345_L2_IRQ ++ select BCM6345_PERIPH_IRQ + select IRQ_DOMAIN select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN @@ -32,8 +32,8 @@ Signed-off-by: Jonas Gorski #include -#include +#include -+#include -+#include ++#include ++#include #include #include #include @@ -449,14 +449,14 @@ Signed-off-by: Jonas Gorski - 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 *periph_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 periph_irq_count, periph_width, ext_irq_count, ext_shift; ++ int periph_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); ++ periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF); ++ periph_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); @@ -469,9 +469,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_3368_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368; + ext_irq_count = 4; @@ -492,10 +492,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6328_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6328_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328; + ext_irq_count = 4; @@ -513,9 +513,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6338_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338; + ext_irq_count = 4; @@ -533,9 +533,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6345_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345; + ext_irq_count = 4; @@ -553,9 +553,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6348_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348; + ext_irq_count = 4; @@ -576,10 +576,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6358_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6358_REG(1); ++ periph_irq_count = 2; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358; + ext_irq_count = 4; @@ -600,10 +600,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6362_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6362_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362; + ext_irq_count = 4; @@ -619,10 +619,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6368_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6368_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368; + ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368; @@ -654,7 +654,7 @@ Signed-off-by: Jonas Gorski - 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_periph_intc_init(periph_irq_count, periph_irqs, periph_bases, periph_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], 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 index fac3d5c764..5d7371ccf9 100644 --- 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 @@ -1,7 +1,7 @@ -From e3c68bbba30b212326fb69bf64b2220750dead3e Mon Sep 17 00:00:00 2001 +From fc8b863c38be9b2ccf805dd5ae17dbffb6bfbe87 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 30 Nov 2014 20:20:30 +0100 -Subject: [PATCH 20/20] MIPS: BCM63XX: wire up BCM6358's external interrupts 4 +Subject: [PATCH 4/5] MIPS: BCM63XX: wire up BCM6358's external interrupts 4 and 5 Due to the external interrupts being non consecutive, the previous @@ -19,7 +19,7 @@ Signed-off-by: Jonas Gorski --- 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; + periph_width = 1; ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358; - ext_irq_count = 4; 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 7dd5e083d8..4d29f6f2d3 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 @@ -289,10 +289,10 @@ Signed-off-by: Jonas Gorski ext_shift = 4; break; + case BCM63268_CPU_ID: -+ 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; ++ periph_bases[0] += PERF_IRQSTAT_63268_REG(0); ++ periph_bases[1] += PERF_IRQSTAT_63268_REG(1); ++ periph_irq_count = 2; ++ periph_width = 4; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_63268; + ext_irq_count = 4; 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 be7264c3cb..7d9578bfcb 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 @@ -199,9 +199,9 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318 ext_shift = 4; break; + case BCM6318_CPU_ID: -+ l2_intc_bases[0] += PERF_IRQMASK_6318_REG; -+ l2_irq_count = 1; -+ l2_width = 4; ++ periph_bases[0] += PERF_IRQMASK_6318_REG; ++ periph_irq_count = 1; ++ periph_width = 4; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6318; + ext_irq_count = 4; @@ -212,8 +212,8 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318 + ext_shift = 4; + break; case BCM6328_CPU_ID: - l2_intc_bases[0] += PERF_IRQMASK_6328_REG(0); - l2_intc_bases[1] += PERF_IRQMASK_6328_REG(1); + periph_bases[0] += PERF_IRQMASK_6328_REG(0); + periph_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) diff --git a/target/linux/brcm63xx/patches-3.14/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch b/target/linux/brcm63xx/patches-3.14/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch index 5a74ddb839..c8c212b08f 100644 --- a/target/linux/brcm63xx/patches-3.14/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch +++ b/target/linux/brcm63xx/patches-3.14/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch @@ -1,25 +1,25 @@ -From 7c22b08baba941a8c83072047b0d2b55a6b952aa Mon Sep 17 00:00:00 2001 +From 40c0e6e4f68ce0c759eb216b44cdfbe18de328b0 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 1 Dec 2014 00:20:07 +0100 -Subject: [PATCH] MIPS: BCM63XX: register interrupt controllers through DT +Subject: [PATCH 5/5] MIPS: BCM63XX: register interrupt controllers through DT Signed-off-by: Jonas Gorski --- - arch/mips/bcm63xx/irq.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) + arch/mips/bcm63xx/irq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -15,6 +15,8 @@ #include - #include - #include + #include + #include +#include +#include #include #include #include -@@ -189,7 +191,15 @@ static void bcm63xx_init_irq(void) +@@ -189,7 +191,17 @@ static void bcm63xx_init_irq(void) ext_shift); } @@ -31,8 +31,10 @@ Signed-off-by: Jonas Gorski void __init arch_init_irq(void) { - bcm63xx_init_irq(); ++#ifdef CONFIG_OF + if (initial_boot_params) + irqchip_init(); + else ++#endif + bcm63xx_init_irq(); } diff --git a/target/linux/brcm63xx/patches-3.18/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch b/target/linux/brcm63xx/patches-3.18/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch deleted file mode 100644 index c709394b35..0000000000 --- a/target/linux/brcm63xx/patches-3.18/320-irqchip-add-support-for-bcm6345-style-l2-irq-control.patch +++ /dev/null @@ -1,411 +0,0 @@ -From 4d3886359d6f6ac475e143d5f3e3b389542a0510 Mon Sep 17 00:00:00 2001 -From: Jonas Gorski -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 ---- - .../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 -@@ -54,6 +54,10 @@ config BRCMSTB_L2_IRQ - select GENERIC_IRQ_CHIP - select IRQ_DOMAIN - -+config BCM6345_L2_IRQ -+ bool -+ select IRQ_DOMAIN -+ - config DW_APB_ICTL - bool - select IRQ_DOMAIN ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -7,6 +7,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 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_BCM63XX -+#include -+ -+#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 -+ * Copyright (C) 2008 Nicolas Schichan -+ */ -+ -+#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.18/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch b/target/linux/brcm63xx/patches-3.18/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch new file mode 100644 index 0000000000..11eedf9b93 --- /dev/null +++ b/target/linux/brcm63xx/patches-3.18/320-irqchip-add-support-for-bcm6345-style-periphery-irq-.patch @@ -0,0 +1,455 @@ +From 301744ecbeece89ab3a9d6beef7802fa22598f00 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Sun, 30 Nov 2014 14:53:12 +0100 +Subject: [PATCH 1/5] irqchip: add support for bcm6345-style periphery irq + controller + +Signed-off-by: Jonas Gorski +--- + .../brcm,bcm6345-periph-intc.txt | 50 +++ + drivers/irqchip/Kconfig | 4 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-bcm6345-periph.c | 339 ++++++++++++++++++++ + include/linux/irqchip/irq-bcm6345-periph.h | 16 + + 5 files changed, 410 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt + create mode 100644 drivers/irqchip/irq-bcm6345-periph.c + create mode 100644 include/linux/irqchip/irq-bcm6345-periph.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-periph-intc.txt +@@ -0,0 +1,50 @@ ++Broadcom BCM6345 Level 1 periphery interrupt controller ++ ++This block is a interrupt controller that is typically connected directly ++to one of the HW INT lines on each CPU. Every BCM63XX xDSL chip since ++BCM6345 has contained this hardware. ++ ++Key elements of the hardware design include: ++ ++- 32, 64, or 128 incoming level IRQ lines ++ ++- All onchip peripherals are wired directly to an L2 input ++ ++- A separate instance of the register set for each CPU, allowing individual ++ peripheral IRQs to be routed to any CPU ++ ++- No atomic mask/unmask operations ++ ++- No polarity/level/edge settings ++ ++- No FIFO or priority encoder logic; software is expected to read all ++ 1-4 status words to determine which IRQs are pending ++ ++Required properties: ++ ++- compatible: Should be "brcm,bcm6345-periph-intc". ++- reg: Specifies the base physical address and size of the registers. ++ Multiple register addresses 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. ++ Multiple lines are used to route interrupts to different cpus, with the first ++ assumed to be for the boot CPU. ++ ++Example: ++ ++periph_intc: interrupt-controller@f0406800 { ++ compatible = "brcm,bcm6345-periph-intc"; ++ reg = <0x10000020 0x10>, <0x10000030 0x10>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpu_intc>; ++ interrupts = <2>, <3>; ++}; +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -54,6 +54,10 @@ config BRCMSTB_L2_IRQ + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + ++config BCM6345_PERIPH_IRQ ++ bool ++ select IRQ_DOMAIN ++ + config DW_APB_ICTL + bool + select IRQ_DOMAIN +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -7,6 +7,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_PERIPH_IRQ) += irq-bcm6345-periph.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-periph.c +@@ -0,0 +1,339 @@ ++/* ++ * 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_BCM63XX ++#include ++ ++#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; ++ raw_spinlock_t lock; ++}; ++ ++static void bcm6345_periph_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) { ++ int virq; ++ ++ virq = irq_find_mapping(data->domain, base + hw_irq); ++ generic_handle_irq(virq); ++ } ++ } ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static void __bcm6345_periph_enable(struct intc_block *block, int reg, int bit, ++ bool enable) ++{ ++ u32 val; ++ ++ val = __raw_readl(block->en_reg[reg]); ++ if (enable) ++ val |= BIT(bit); ++ else ++ val &= ~BIT(bit); ++ __raw_writel(val, block->en_reg[reg]); ++} ++ ++static void bcm6345_periph_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]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ __bcm6345_periph_enable(block, reg, bit, false); ++ } ++ raw_spin_unlock(&priv->lock); ++} ++ ++static void bcm6345_periph_irq_unmask(struct irq_data *data) ++{ ++ struct intc_data *priv = data->domain->host_data; ++ irq_hw_number_t hwirq = irqd_to_hwirq(data); ++ unsigned int i, reg, bit; ++ ++ 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]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ if (block->mask_cache[reg] & BIT(bit)) ++ __bcm6345_periph_enable(block, reg, bit, true); ++ else ++ __bcm6345_periph_enable(block, reg, bit, false); ++ } ++ raw_spin_unlock(&priv->lock); ++} ++ ++#ifdef CONFIG_SMP ++static int bcm6345_periph_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; ++ unsigned long flags; ++ bool enabled; ++ 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_irqsave(&priv->lock, flags); ++ enabled = !irqd_irq_masked(data); ++ for (i = 0; i < MAX_PARENT_IRQS; i++) { ++ struct intc_block *block = &priv->block[i]; ++ ++ if (!block->parent_irq) ++ break; ++ ++ if (i == cpu) { ++ block->mask_cache[reg] |= BIT(bit); ++ __bcm6345_periph_enable(block, reg, bit, enabled); ++ } else { ++ block->mask_cache[reg] &= ~BIT(bit); ++ __bcm6345_periph_enable(block, reg, bit, false); ++ } ++ } ++ raw_spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return 0; ++} ++#endif ++ ++static int bcm6345_periph_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_periph_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = bcm6345_periph_map, ++}; ++ ++static int __init __bcm6345_periph_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; ++ ++ raw_spin_lock_init(&data->lock); ++ ++ 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 interrupts 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_periph_irq_handle); ++ } ++ ++ data->num_words = num_words; ++ ++ data->chip.name = "bcm6345-periph-intc"; ++ data->chip.irq_mask = bcm6345_periph_irq_mask; ++ data->chip.irq_unmask = bcm6345_periph_irq_unmask; ++ ++#ifdef CONFIG_SMP ++ if (num_blocks > 1) ++ data->chip.irq_set_affinity = bcm6345_periph_set_affinity; ++#endif ++ ++ data->domain = irq_domain_add_simple(node, IRQS_PER_WORD * num_words, ++ VIRQ_BASE, ++ &bcm6345_periph_domain_ops, data); ++ if (!data->domain) { ++ kfree(data); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void __init bcm6345_periph_intc_init(int num_blocks, int *irq, ++ void __iomem **base, int num_words) ++{ ++ __bcm6345_periph_intc_init(NULL, num_blocks, irq, base, num_words); ++} ++ ++#ifdef CONFIG_OF ++static int __init bcm6345_periph_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_periph_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_periph_intc, "brcm,bcm6345-periph-intc", ++ bcm6345_periph_of_init); ++#endif +--- /dev/null ++++ b/include/linux/irqchip/irq-bcm6345-periph.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 ++ * Copyright (C) 2008 Nicolas Schichan ++ */ ++ ++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H ++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H ++ ++void bcm6345_periph_intc_init(int num_blocks, int *irq, void __iomem **base, ++ int num_words); ++ ++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_PERIPH_H */ diff --git a/target/linux/brcm63xx/patches-3.18/321-irqchip-add-support-for-bcm6345-style-external-inter.patch b/target/linux/brcm63xx/patches-3.18/321-irqchip-add-support-for-bcm6345-style-external-inter.patch index 8189e7e807..547b2f1a84 100644 --- a/target/linux/brcm63xx/patches-3.18/321-irqchip-add-support-for-bcm6345-style-external-inter.patch +++ b/target/linux/brcm63xx/patches-3.18/321-irqchip-add-support-for-bcm6345-style-external-inter.patch @@ -1,37 +1,42 @@ -From 6896b5f0538a7a7cfb7fac2d9ed3c6841c72ed40 Mon Sep 17 00:00:00 2001 +From cf908990d4a8ccdb73ee4484aa8cadad379ca314 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 30 Nov 2014 14:54:27 +0100 -Subject: [PATCH 18/20] irqchip: add support for bcm6345-style external +Subject: [PATCH 2/5] irqchip: add support for bcm6345-style external interrupt controller Signed-off-by: Jonas Gorski --- - .../interrupt-controller/brcm,bcm6345-ext-intc.txt | 24 ++ + .../interrupt-controller/brcm,bcm6345-ext-intc.txt | 29 ++ 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(+) + drivers/irqchip/irq-bcm6345-ext.c | 287 ++++++++++++++++++++ + include/linux/irqchip/irq-bcm6345-ext.h | 14 + + 5 files changed, 335 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 + create mode 100644 include/linux/irqchip/irq-bcm6345-ext.h --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-ext-intc.txt -@@ -0,0 +1,24 @@ +@@ -0,0 +1,29 @@ +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 ++- compatible: Should be "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. ++ ++Optional properties: ++ ++- brcm,field-width: Size of each field (mask, clear, sense, ...) in bits in the ++ register. Defaults to 4. + +Example: + @@ -53,7 +58,7 @@ Signed-off-by: Jonas Gorski + bool + select IRQ_DOMAIN + - config BCM6345_L2_IRQ + config BCM6345_PERIPH_IRQ bool select IRQ_DOMAIN --- a/drivers/irqchip/Makefile @@ -63,24 +68,24 @@ Signed-off-by: Jonas Gorski 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_BCM6345_PERIPH_IRQ) += irq-bcm6345-periph.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 @@ +@@ -0,0 +1,287 @@ +/* + * 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 -+i */ ++ */ + +#include +#include +#include -+#include ++#include +#include +#include +#include @@ -110,7 +115,7 @@ Signed-off-by: Jonas Gorski +struct intc_data { + struct irq_chip chip; + struct irq_domain *domain; -+ spinlock_t lock; ++ raw_spinlock_t lock; + + int parent_irq[MAX_IRQS]; + void __iomem *reg; @@ -141,11 +146,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static void bcm6345_ext_intc_irq_mask(struct irq_data *data) @@ -154,11 +159,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static void bcm6345_ext_intc_irq_unmask(struct irq_data *data) @@ -167,11 +172,11 @@ Signed-off-by: Jonas Gorski + irq_hw_number_t hwirq = irqd_to_hwirq(data); + u32 reg; + -+ raw_spin_lock(priv->lock); ++ 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); ++ raw_spin_unlock(&priv->lock); +} + +static int bcm6345_ext_intc_set_type(struct irq_data *data, @@ -213,7 +218,7 @@ Signed-off-by: Jonas Gorski + return -EINVAL; + } + -+ raw_spin_lock(priv->lock); ++ raw_spin_lock(&priv->lock); + reg = __raw_readl(priv->reg); + + if (levelsense) @@ -230,7 +235,7 @@ Signed-off-by: Jonas Gorski + reg &= ~(hwirq << (EXTIRQ_CFG_BOTHEDGE * priv->shift)); + + __raw_writel(reg, priv->reg); -+ raw_spin_unlock(priv->lock); ++ raw_spin_unlock(&priv->lock); + + irqd_set_trigger_type(data, flow_type); + if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) @@ -242,7 +247,7 @@ Signed-off-by: Jonas Gorski +} + +static int bcm6345_ext_intc_map(struct irq_domain *d, unsigned int irq, -+ irq_hw_number_t hw) ++ irq_hw_number_t hw) +{ + struct intc_data *priv = d->host_data; + @@ -251,7 +256,6 @@ Signed-off-by: Jonas Gorski + return 0; +} + -+ +static const struct irq_domain_ops bcm6345_ext_domain_ops = { + .xlate = irq_domain_xlate_twocell, + .map = bcm6345_ext_intc_map, @@ -269,6 +273,8 @@ Signed-off-by: Jonas Gorski + if (!data) + return -ENOMEM; + ++ raw_spin_lock_init(&data->lock); ++ + for (i = 0; i < num_irqs; i++) { + data->parent_irq[i] = irqs[i]; + @@ -311,20 +317,23 @@ Signed-off-by: Jonas Gorski +} + +#ifdef CONFIG_OF -+static int __init bcm63xx_ext_intc_of_init(struct device_node *node, -+ struct device_node *parent, -+ int shift) ++static int __init bcm6345_ext_intc_of_init(struct device_node *node, ++ struct device_node *parent) +{ + int num_irqs, ret = -EINVAL; + unsigned i; + void __iomem *base; + int irqs[MAX_IRQS] = { 0 }; ++ u32 shift; + + num_irqs = of_irq_count(node); + + if (!num_irqs || num_irqs > MAX_IRQS) + return -EINVAL; + ++ if (of_property_read_u32(node, "brcm,field-width", &shift)) ++ shift = 4; ++ + for (i = 0; i < num_irqs; i++) { + irqs[i] = irq_of_parse_and_map(node, i); + if (!irqs[i]) { @@ -349,24 +358,11 @@ Signed-off-by: Jonas Gorski + 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 ++++ b/include/linux/irqchip/irq-bcm6345-ext.h @@ -0,0 +1,14 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -376,9 +372,9 @@ Signed-off-by: Jonas Gorski + * Copyright (C) 2014 Jonas Gorski + */ + -+#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H -+#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_INTC_H ++#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H ++#define __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_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 */ ++#endif /* __INCLUDE_LINUX_IRQCHIP_IRQ_BCM6345_EXT_H */ diff --git a/target/linux/brcm63xx/patches-3.18/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch b/target/linux/brcm63xx/patches-3.18/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch index 49c5bccb21..54d9094064 100644 --- a/target/linux/brcm63xx/patches-3.18/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch +++ b/target/linux/brcm63xx/patches-3.18/322-MIPS-BCM63XX-switch-to-IRQ_DOMAIN.patch @@ -1,7 +1,7 @@ -From d93661c9e164ccc41820eeb4f1881e59a34a9e5c Mon Sep 17 00:00:00 2001 +From cfe7647c2a4decf874dff8abb60704e9917f76fe Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 30 Nov 2014 14:55:02 +0100 -Subject: [PATCH 19/20] MIPS: BCM63XX: switch to IRQ_DOMAIN +Subject: [PATCH 3/5] MIPS: BCM63XX: switch to IRQ_DOMAIN Now that we have working IRQ_DOMAIN drivers for both interrupt controllers, switch to using them. @@ -9,8 +9,8 @@ switch to using them. Signed-off-by: Jonas Gorski --- arch/mips/Kconfig | 3 + - arch/mips/bcm63xx/irq.c | 608 ++++++++--------------------------------------- - 2 files changed, 108 insertions(+), 503 deletions(-) + arch/mips/bcm63xx/irq.c | 609 +++++++++-------------------------------------- + 2 files changed, 109 insertions(+), 503 deletions(-) --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -19,7 +19,7 @@ Signed-off-by: Jonas Gorski select DMA_NONCOHERENT select IRQ_CPU + select BCM6345_EXT_IRQ -+ select BCM6345_L2_IRQ ++ select BCM6345_PERIPH_IRQ + select IRQ_DOMAIN select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN @@ -32,12 +32,12 @@ Signed-off-by: Jonas Gorski #include -#include +#include -+#include -+#include ++#include ++#include #include #include #include -@@ -20,544 +22,144 @@ +@@ -20,544 +22,145 @@ #include #include @@ -449,14 +449,14 @@ Signed-off-by: Jonas Gorski - 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 *periph_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 periph_irq_count, periph_width, ext_irq_count, ext_shift; ++ int periph_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); ++ periph_bases[0] = (void __iomem *)bcm63xx_regset_address(RSET_PERF); ++ periph_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); @@ -469,9 +469,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_3368_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_3368; + ext_irq_count = 4; @@ -492,10 +492,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6328_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6328_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6328; + ext_irq_count = 4; @@ -513,9 +513,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6338_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6338; + ext_irq_count = 4; @@ -533,9 +533,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6345_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6345; + ext_irq_count = 4; @@ -553,9 +553,9 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6348_REG; ++ periph_irq_count = 1; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6348; + ext_irq_count = 4; @@ -576,10 +576,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6358_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6358_REG(1); ++ periph_irq_count = 2; ++ periph_width = 1; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358; + ext_irq_count = 4; @@ -600,10 +600,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6362_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6362_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6362; + ext_irq_count = 4; @@ -619,10 +619,10 @@ Signed-off-by: Jonas Gorski - 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; ++ periph_bases[0] += PERF_IRQMASK_6368_REG(0); ++ periph_bases[1] += PERF_IRQMASK_6368_REG(1); ++ periph_irq_count = 2; ++ periph_width = 2; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6368; + ext_intc_bases[1] += PERF_EXTIRQ_CFG_REG2_6368; @@ -654,7 +654,8 @@ Signed-off-by: Jonas Gorski - 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_periph_intc_init(periph_irq_count, periph_irqs, periph_bases, ++ periph_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], diff --git a/target/linux/brcm63xx/patches-3.18/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch b/target/linux/brcm63xx/patches-3.18/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch index 3e718772ca..a2ee1b67fe 100644 --- a/target/linux/brcm63xx/patches-3.18/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch +++ b/target/linux/brcm63xx/patches-3.18/323-MIPS-BCM63XX-wire-up-BCM6358-s-external-interrupts-4.patch @@ -1,7 +1,7 @@ -From e3c68bbba30b212326fb69bf64b2220750dead3e Mon Sep 17 00:00:00 2001 +From 4fd286c3e5a5bebab0391cf1937695b3ed6721a3 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sun, 30 Nov 2014 20:20:30 +0100 -Subject: [PATCH 20/20] MIPS: BCM63XX: wire up BCM6358's external interrupts 4 +Subject: [PATCH 4/5] MIPS: BCM63XX: wire up BCM6358's external interrupts 4 and 5 Due to the external interrupts being non consecutive, the previous @@ -19,7 +19,7 @@ Signed-off-by: Jonas Gorski --- 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; + periph_width = 1; ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6358; - ext_irq_count = 4; diff --git a/target/linux/brcm63xx/patches-3.18/339-MIPS-BCM63XX-add-support-for-BCM63268.patch b/target/linux/brcm63xx/patches-3.18/339-MIPS-BCM63XX-add-support-for-BCM63268.patch index 5abdd9d09f..ba0df35251 100644 --- a/target/linux/brcm63xx/patches-3.18/339-MIPS-BCM63XX-add-support-for-BCM63268.patch +++ b/target/linux/brcm63xx/patches-3.18/339-MIPS-BCM63XX-add-support-for-BCM63268.patch @@ -289,10 +289,10 @@ Signed-off-by: Jonas Gorski ext_shift = 4; break; + case BCM63268_CPU_ID: -+ 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; ++ periph_bases[0] += PERF_IRQSTAT_63268_REG(0); ++ periph_bases[1] += PERF_IRQSTAT_63268_REG(1); ++ periph_irq_count = 2; ++ periph_width = 4; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_63268; + ext_irq_count = 4; diff --git a/target/linux/brcm63xx/patches-3.18/341-MIPS-BCM63XX-add-support-for-BCM6318.patch b/target/linux/brcm63xx/patches-3.18/341-MIPS-BCM63XX-add-support-for-BCM6318.patch index 440a30ead7..0e4df97731 100644 --- a/target/linux/brcm63xx/patches-3.18/341-MIPS-BCM63XX-add-support-for-BCM6318.patch +++ b/target/linux/brcm63xx/patches-3.18/341-MIPS-BCM63XX-add-support-for-BCM6318.patch @@ -199,9 +199,9 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318 ext_shift = 4; break; + case BCM6318_CPU_ID: -+ l2_intc_bases[0] += PERF_IRQMASK_6318_REG; -+ l2_irq_count = 1; -+ l2_width = 4; ++ periph_bases[0] += PERF_IRQMASK_6318_REG; ++ periph_irq_count = 1; ++ periph_width = 4; + + ext_intc_bases[0] += PERF_EXTIRQ_CFG_REG_6318; + ext_irq_count = 4; @@ -212,8 +212,8 @@ Subject: [PATCH 51/53] MIPS: BCM63XX: add support for BCM6318 + ext_shift = 4; + break; case BCM6328_CPU_ID: - l2_intc_bases[0] += PERF_IRQMASK_6328_REG(0); - l2_intc_bases[1] += PERF_IRQMASK_6328_REG(1); + periph_bases[0] += PERF_IRQMASK_6328_REG(0); + periph_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) diff --git a/target/linux/brcm63xx/patches-3.18/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch b/target/linux/brcm63xx/patches-3.18/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch index 7c19ee590d..ff455dddc9 100644 --- a/target/linux/brcm63xx/patches-3.18/366-MIPS-add-support-for-vmlinux.bin-appended-DTB.patch +++ b/target/linux/brcm63xx/patches-3.18/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 -@@ -2645,6 +2645,24 @@ config RAPIDIO +@@ -2655,6 +2655,24 @@ config RAPIDIO source "drivers/rapidio/Kconfig" diff --git a/target/linux/brcm63xx/patches-3.18/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch b/target/linux/brcm63xx/patches-3.18/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch index 3b15589baa..edc05d95fb 100644 --- a/target/linux/brcm63xx/patches-3.18/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch +++ b/target/linux/brcm63xx/patches-3.18/373-MIPS-BCM63XX-register-interrupt-controllers-through-.patch @@ -1,25 +1,25 @@ -From 7c22b08baba941a8c83072047b0d2b55a6b952aa Mon Sep 17 00:00:00 2001 +From 8a0803979163c647736cb234ee1620c049c4915c Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 1 Dec 2014 00:20:07 +0100 -Subject: [PATCH] MIPS: BCM63XX: register interrupt controllers through DT +Subject: [PATCH 5/5] MIPS: BCM63XX: register interrupt controllers through DT Signed-off-by: Jonas Gorski --- - arch/mips/bcm63xx/irq.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) + arch/mips/bcm63xx/irq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -15,6 +15,8 @@ #include - #include - #include + #include + #include +#include +#include #include #include #include -@@ -189,7 +191,13 @@ static void bcm63xx_init_irq(void) +@@ -190,7 +192,15 @@ static void bcm63xx_init_irq(void) ext_shift); } @@ -29,8 +29,10 @@ Signed-off-by: Jonas Gorski void __init arch_init_irq(void) { - bcm63xx_init_irq(); ++#ifdef CONFIG_OF + if (initial_boot_params) + irqchip_init(); + else ++#endif + bcm63xx_init_irq(); } diff --git a/target/linux/generic/patches-3.18/132-mips_inline_dma_ops.patch b/target/linux/generic/patches-3.18/132-mips_inline_dma_ops.patch index 49d44574b9..8795bde0bd 100644 --- a/target/linux/generic/patches-3.18/132-mips_inline_dma_ops.patch +++ b/target/linux/generic/patches-3.18/132-mips_inline_dma_ops.patch @@ -519,7 +519,7 @@ Signed-off-by: Felix Fietkau void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -@@ -167,8 +145,8 @@ void dma_free_noncoherent(struct device +@@ -167,8 +145,8 @@ void dma_free_noncoherent(struct device } EXPORT_SYMBOL(dma_free_noncoherent); @@ -659,7 +659,7 @@ Signed-off-by: Felix Fietkau void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) -@@ -360,23 +238,10 @@ void dma_cache_sync(struct device *dev, +@@ -360,23 +238,10 @@ void dma_cache_sync(struct device *dev, EXPORT_SYMBOL(dma_cache_sync); diff --git a/target/linux/generic/patches-3.18/203-kallsyms_uncompressed.patch b/target/linux/generic/patches-3.18/203-kallsyms_uncompressed.patch index 4888dd5c02..b9d82207a0 100644 --- a/target/linux/generic/patches-3.18/203-kallsyms_uncompressed.patch +++ b/target/linux/generic/patches-3.18/203-kallsyms_uncompressed.patch @@ -1,6 +1,6 @@ --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c -@@ -58,6 +58,7 @@ static struct addr_range percpu_range = +@@ -58,6 +58,7 @@ static struct addr_range percpu_range = static struct sym_entry *table; static unsigned int table_size, table_cnt; static int all_symbols = 0; diff --git a/target/linux/generic/patches-3.18/204-module_strip.patch b/target/linux/generic/patches-3.18/204-module_strip.patch index c46f5f99dd..ed95eafd0d 100644 --- a/target/linux/generic/patches-3.18/204-module_strip.patch +++ b/target/linux/generic/patches-3.18/204-module_strip.patch @@ -72,7 +72,7 @@ Signed-off-by: Felix Fietkau #ifdef MODULE #define __MODULE_INFO(tag, name, info) \ static const char __UNIQUE_ID(name)[] \ -@@ -23,8 +33,7 @@ static const char __UNIQUE_ID(name)[] +@@ -23,8 +33,7 @@ static const char __UNIQUE_ID(name)[] = __stringify(tag) "=" info #else /* !MODULE */ /* This struct is here for syntactic coherency, it is not used */ @@ -82,7 +82,7 @@ Signed-off-by: Felix Fietkau #endif #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type) -@@ -32,7 +41,7 @@ static const char __UNIQUE_ID(name)[] +@@ -32,7 +41,7 @@ static const char __UNIQUE_ID(name)[] /* One for each parameter, describing how to use it. Some files do multiple of these per line, so can't just use MODULE_INFO. */ #define MODULE_PARM_DESC(_parm, desc) \ diff --git a/target/linux/generic/patches-3.18/230-openwrt_lzma_options.patch b/target/linux/generic/patches-3.18/230-openwrt_lzma_options.patch index 1f9f0d0161..e59fdcd2e0 100644 --- a/target/linux/generic/patches-3.18/230-openwrt_lzma_options.patch +++ b/target/linux/generic/patches-3.18/230-openwrt_lzma_options.patch @@ -1,6 +1,6 @@ --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -325,7 +325,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) +@@ -325,7 +325,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^) quiet_cmd_lzma = LZMA $@ cmd_lzma = (cat $(filter-out FORCE,$^) | \ diff --git a/target/linux/generic/patches-3.18/306-mips_mem_functions_performance.patch b/target/linux/generic/patches-3.18/306-mips_mem_functions_performance.patch index e6056fa5c4..9818677425 100644 --- a/target/linux/generic/patches-3.18/306-mips_mem_functions_performance.patch +++ b/target/linux/generic/patches-3.18/306-mips_mem_functions_performance.patch @@ -1,6 +1,6 @@ --- a/arch/mips/include/asm/string.h +++ b/arch/mips/include/asm/string.h -@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ +@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__ #define __HAVE_ARCH_MEMSET extern void *memset(void *__s, int __c, size_t __count); diff --git a/target/linux/generic/patches-3.18/408-mtd-old-rootfs-squashfs-splitter.patch b/target/linux/generic/patches-3.18/408-mtd-old-rootfs-squashfs-splitter.patch index 540e2bd0c8..07d4f7d824 100644 --- a/target/linux/generic/patches-3.18/408-mtd-old-rootfs-squashfs-splitter.patch +++ b/target/linux/generic/patches-3.18/408-mtd-old-rootfs-squashfs-splitter.patch @@ -14,7 +14,7 @@ default y --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c -@@ -681,6 +681,47 @@ mtd_pad_erasesize(struct mtd_info *mtd, +@@ -681,6 +681,47 @@ mtd_pad_erasesize(struct mtd_info *mtd, return len; } diff --git a/target/linux/generic/patches-3.18/431-mtd-bcm47xxpart-support-TRX-data-partition-being-UBI.patch b/target/linux/generic/patches-3.18/431-mtd-bcm47xxpart-support-TRX-data-partition-being-UBI.patch index 46881fca2c..4c4720341e 100644 --- a/target/linux/generic/patches-3.18/431-mtd-bcm47xxpart-support-TRX-data-partition-being-UBI.patch +++ b/target/linux/generic/patches-3.18/431-mtd-bcm47xxpart-support-TRX-data-partition-being-UBI.patch @@ -17,7 +17,7 @@ u64 offset, uint32_t mask_flags) { part->name = name; -@@ -58,6 +59,26 @@ static void bcm47xxpart_add_part(struct +@@ -58,6 +59,26 @@ static void bcm47xxpart_add_part(struct part->mask_flags = mask_flags; } diff --git a/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch b/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch index 5345678c56..5b73d3898b 100644 --- a/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch +++ b/target/linux/generic/patches-3.18/502-yaffs-3.10-disable-proc-entry.patch @@ -8,7 +8,7 @@ static struct proc_dir_entry *my_proc_entry; static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) -@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file +@@ -3398,6 +3399,7 @@ static int yaffs_proc_write(struct file return yaffs_proc_debug_write(file, buf, count, data); return yaffs_proc_write_trace_options(file, buf, count, data); } diff --git a/target/linux/generic/patches-3.18/600-netfilter_layer7_2.22.patch b/target/linux/generic/patches-3.18/600-netfilter_layer7_2.22.patch index eb38e3078f..4b0a364c3f 100644 --- a/target/linux/generic/patches-3.18/600-netfilter_layer7_2.22.patch +++ b/target/linux/generic/patches-3.18/600-netfilter_layer7_2.22.patch @@ -30,7 +30,7 @@ depends on NETFILTER_ADVANCED --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile -@@ -162,6 +162,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) +@@ -162,6 +162,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o diff --git a/target/linux/generic/patches-3.18/604-netfilter_conntrack_flush.patch b/target/linux/generic/patches-3.18/604-netfilter_conntrack_flush.patch index 88adb01955..83cd04ac8b 100644 --- a/target/linux/generic/patches-3.18/604-netfilter_conntrack_flush.patch +++ b/target/linux/generic/patches-3.18/604-netfilter_conntrack_flush.patch @@ -8,7 +8,7 @@ #include #ifdef CONFIG_SYSCTL #include -@@ -268,10 +269,66 @@ static int ct_open(struct inode *inode, +@@ -268,10 +269,66 @@ static int ct_open(struct inode *inode, sizeof(struct ct_iter_state)); } diff --git a/target/linux/generic/patches-3.18/615-netfilter_add_xt_id_match.patch b/target/linux/generic/patches-3.18/615-netfilter_add_xt_id_match.patch index b95c7218c3..265ff207b6 100644 --- a/target/linux/generic/patches-3.18/615-netfilter_add_xt_id_match.patch +++ b/target/linux/generic/patches-3.18/615-netfilter_add_xt_id_match.patch @@ -37,7 +37,7 @@ depends on NETFILTER_ADVANCED --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile -@@ -140,6 +140,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += +@@ -140,6 +140,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o obj-$(CONFIG_NETFILTER_XT_MATCH_HL) += xt_hl.o diff --git a/target/linux/generic/patches-3.18/643-bridge_remove_ipv6_dependency.patch b/target/linux/generic/patches-3.18/643-bridge_remove_ipv6_dependency.patch index 05df907f6a..e8b21e5060 100644 --- a/target/linux/generic/patches-3.18/643-bridge_remove_ipv6_dependency.patch +++ b/target/linux/generic/patches-3.18/643-bridge_remove_ipv6_dependency.patch @@ -25,7 +25,7 @@ Ethernet bridge, which means that the different Ethernet segments it --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile -@@ -45,6 +45,7 @@ obj-y += addrconf_core.o exthdrs_core.o +@@ -45,6 +45,7 @@ obj-y += addrconf_core.o exthdrs_core.o obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o diff --git a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch index a8a6017c9a..8d0da3c6e5 100644 --- a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch +++ b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch @@ -195,7 +195,7 @@ } #endif -@@ -1556,6 +1581,7 @@ static int br_multicast_ipv4_rcv(struct +@@ -1556,6 +1581,7 @@ static int br_multicast_ipv4_rcv(struct struct sk_buff *skb, u16 vid) { @@ -203,7 +203,7 @@ struct sk_buff *skb2 = skb; const struct iphdr *iph; struct igmphdr *ih; -@@ -1629,7 +1655,7 @@ static int br_multicast_ipv4_rcv(struct +@@ -1629,7 +1655,7 @@ static int br_multicast_ipv4_rcv(struct case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: BR_INPUT_SKB_CB(skb)->mrouters_only = 1; @@ -212,7 +212,7 @@ break; case IGMPV3_HOST_MEMBERSHIP_REPORT: err = br_ip4_multicast_igmp3_report(br, port, skb2, vid); -@@ -1638,7 +1664,7 @@ static int br_multicast_ipv4_rcv(struct +@@ -1638,7 +1664,7 @@ static int br_multicast_ipv4_rcv(struct err = br_ip4_multicast_query(br, port, skb2, vid); break; case IGMP_HOST_LEAVE_MESSAGE: @@ -221,7 +221,7 @@ break; } -@@ -1656,6 +1682,7 @@ static int br_multicast_ipv6_rcv(struct +@@ -1656,6 +1682,7 @@ static int br_multicast_ipv6_rcv(struct struct sk_buff *skb, u16 vid) { @@ -229,7 +229,7 @@ struct sk_buff *skb2; const struct ipv6hdr *ip6h; u8 icmp6_type; -@@ -1765,7 +1792,8 @@ static int br_multicast_ipv6_rcv(struct +@@ -1765,7 +1792,8 @@ static int br_multicast_ipv6_rcv(struct } mld = (struct mld_msg *)skb_transport_header(skb2); BR_INPUT_SKB_CB(skb)->mrouters_only = 1; @@ -239,7 +239,7 @@ break; } case ICMPV6_MLD2_REPORT: -@@ -1782,7 +1810,7 @@ static int br_multicast_ipv6_rcv(struct +@@ -1782,7 +1810,7 @@ static int br_multicast_ipv6_rcv(struct goto out; } mld = (struct mld_msg *)skb_transport_header(skb2); diff --git a/target/linux/generic/patches-3.18/653-disable_netlink_trim.patch b/target/linux/generic/patches-3.18/653-disable_netlink_trim.patch index 5462388feb..6b25a2e8f5 100644 --- a/target/linux/generic/patches-3.18/653-disable_netlink_trim.patch +++ b/target/linux/generic/patches-3.18/653-disable_netlink_trim.patch @@ -1,6 +1,6 @@ --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c -@@ -1715,27 +1715,7 @@ void netlink_detachskb(struct sock *sk, +@@ -1715,27 +1715,7 @@ void netlink_detachskb(struct sock *sk, static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation) { diff --git a/target/linux/generic/patches-3.18/657-qdisc_reduce_truesize.patch b/target/linux/generic/patches-3.18/657-qdisc_reduce_truesize.patch index 72b3dfc04d..6777eecf5a 100644 --- a/target/linux/generic/patches-3.18/657-qdisc_reduce_truesize.patch +++ b/target/linux/generic/patches-3.18/657-qdisc_reduce_truesize.patch @@ -24,7 +24,7 @@ commont qdiscs. } --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c -@@ -29,17 +29,21 @@ static int bfifo_enqueue(struct sk_buff +@@ -29,17 +29,21 @@ static int bfifo_enqueue(struct sk_buff static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch) { diff --git a/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch b/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch index 8bf4b3b294..000665f047 100644 --- a/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch +++ b/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch @@ -308,7 +308,7 @@ Signed-off-by: Steven Barth err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); if (err != 0) { /* XXX: send ICMP error even if DF is not set. */ -@@ -1263,6 +1413,14 @@ ip6_tnl_change(struct ip6_tnl *t, const +@@ -1263,6 +1413,14 @@ ip6_tnl_change(struct ip6_tnl *t, const t->parms.flowinfo = p->flowinfo; t->parms.link = p->link; t->parms.proto = p->proto; diff --git a/target/linux/generic/patches-3.18/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/patches-3.18/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index 63e5ab4bde..d76375efa6 100644 --- a/target/linux/generic/patches-3.18/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/patches-3.18/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -55,7 +55,7 @@ Signed-off-by: Jonas Gorski --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c -@@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX +@@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX .error = -EINVAL, .scope = RT_SCOPE_NOWHERE, }, diff --git a/target/linux/generic/patches-3.18/750-hostap_txpower.patch b/target/linux/generic/patches-3.18/750-hostap_txpower.patch index fc032a93c9..768c80f73b 100644 --- a/target/linux/generic/patches-3.18/750-hostap_txpower.patch +++ b/target/linux/generic/patches-3.18/750-hostap_txpower.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c -@@ -2403,13 +2403,13 @@ int prism2_ap_get_sta_qual(local_info_t +@@ -2403,13 +2403,13 @@ int prism2_ap_get_sta_qual(local_info_t addr[count].sa_family = ARPHRD_ETHER; memcpy(addr[count].sa_data, sta->addr, ETH_ALEN); if (sta->last_rx_silence == 0) diff --git a/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch b/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch index c2eef69924..fe52ccc33e 100644 --- a/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch +++ b/target/linux/generic/patches-3.18/773-bgmac-add-srab-switch.patch @@ -12,7 +12,7 @@ Signed-off-by: Hauke Mehrtens #include static const struct bcma_device_id bgmac_bcma_tbl[] = { -@@ -1405,6 +1406,17 @@ static void bgmac_mii_unregister(struct +@@ -1405,6 +1406,17 @@ static void bgmac_mii_unregister(struct mdiobus_free(mii_bus); } diff --git a/target/linux/generic/patches-3.18/810-pci_disable_common_quirks.patch b/target/linux/generic/patches-3.18/810-pci_disable_common_quirks.patch index 63cc20109e..ef811c6fdf 100644 --- a/target/linux/generic/patches-3.18/810-pci_disable_common_quirks.patch +++ b/target/linux/generic/patches-3.18/810-pci_disable_common_quirks.patch @@ -15,7 +15,7 @@ default y --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c -@@ -41,6 +41,7 @@ static void quirk_mmio_always_on(struct +@@ -41,6 +41,7 @@ static void quirk_mmio_always_on(struct DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); diff --git a/target/linux/generic/patches-3.18/902-debloat_proc.patch b/target/linux/generic/patches-3.18/902-debloat_proc.patch index 08c06486a0..1134b83d49 100644 --- a/target/linux/generic/patches-3.18/902-debloat_proc.patch +++ b/target/linux/generic/patches-3.18/902-debloat_proc.patch @@ -199,7 +199,7 @@ &fib_triestat_fops)) goto out2; -@@ -2594,17 +2596,21 @@ int __net_init fib_proc_init(struct net +@@ -2594,17 +2596,21 @@ int __net_init fib_proc_init(struct net return 0; out3: diff --git a/target/linux/generic/patches-3.18/941-ocf_20120127.patch b/target/linux/generic/patches-3.18/941-ocf_20120127.patch index 4e3e99d925..cc512f8359 100644 --- a/target/linux/generic/patches-3.18/941-ocf_20120127.patch +++ b/target/linux/generic/patches-3.18/941-ocf_20120127.patch @@ -24,7 +24,7 @@ * All of these routines try to estimate how many bits of randomness a * particular randomness source. They do this by keeping track of the * first and second order deltas of the event timings. -@@ -938,6 +948,63 @@ void add_disk_randomness(struct gendisk +@@ -938,6 +948,63 @@ void add_disk_randomness(struct gendisk EXPORT_SYMBOL_GPL(add_disk_randomness); #endif