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