diff options
| -rw-r--r-- | arch/arm/mach-bcm/Makefile | 5 | ||||
| -rw-r--r-- | arch/arm/mach-bcm/board_bcm2835.c | 6 | ||||
| -rw-r--r-- | arch/arm/mach-bcm/platsmp.c | 35 | ||||
| -rw-r--r-- | arch/arm/mach-bcm/platsmp.h | 10 | ||||
| -rw-r--r-- | drivers/irqchip/irq-bcm2836.c | 79 | ||||
| -rw-r--r-- | include/linux/irqchip/irq-bcm2836.h | 70 |
6 files changed, 127 insertions, 78 deletions
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 980f5850097c..62a59008c5a8 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile | |||
| @@ -43,6 +43,11 @@ endif | |||
| 43 | 43 | ||
| 44 | # BCM2835 | 44 | # BCM2835 |
| 45 | obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o | 45 | obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o |
| 46 | ifeq ($(CONFIG_ARCH_BCM2835),y) | ||
| 47 | ifeq ($(CONFIG_ARM),y) | ||
| 48 | obj-$(CONFIG_SMP) += platsmp.o | ||
| 49 | endif | ||
| 50 | endif | ||
| 46 | 51 | ||
| 47 | # BCM5301X | 52 | # BCM5301X |
| 48 | obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o | 53 | obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o |
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c index 24af33f91705..8cff865ace04 100644 --- a/arch/arm/mach-bcm/board_bcm2835.c +++ b/arch/arm/mach-bcm/board_bcm2835.c | |||
| @@ -19,16 +19,20 @@ | |||
| 19 | #include <asm/mach/arch.h> | 19 | #include <asm/mach/arch.h> |
| 20 | #include <asm/mach/map.h> | 20 | #include <asm/mach/map.h> |
| 21 | 21 | ||
| 22 | #include "platsmp.h" | ||
| 23 | |||
| 22 | static const char * const bcm2835_compat[] = { | 24 | static const char * const bcm2835_compat[] = { |
| 23 | #ifdef CONFIG_ARCH_MULTI_V6 | 25 | #ifdef CONFIG_ARCH_MULTI_V6 |
| 24 | "brcm,bcm2835", | 26 | "brcm,bcm2835", |
| 25 | #endif | 27 | #endif |
| 26 | #ifdef CONFIG_ARCH_MULTI_V7 | 28 | #ifdef CONFIG_ARCH_MULTI_V7 |
| 27 | "brcm,bcm2836", | 29 | "brcm,bcm2836", |
| 30 | "brcm,bcm2837", | ||
| 28 | #endif | 31 | #endif |
| 29 | NULL | 32 | NULL |
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | DT_MACHINE_START(BCM2835, "BCM2835") | 35 | DT_MACHINE_START(BCM2835, "BCM2835") |
| 33 | .dt_compat = bcm2835_compat | 36 | .dt_compat = bcm2835_compat, |
| 37 | .smp = smp_ops(bcm2836_smp_ops), | ||
| 34 | MACHINE_END | 38 | MACHINE_END |
diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c index 9e3f275934eb..34506a608fea 100644 --- a/arch/arm/mach-bcm/platsmp.c +++ b/arch/arm/mach-bcm/platsmp.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
| 20 | #include <linux/irqchip/irq-bcm2836.h> | ||
| 20 | #include <linux/jiffies.h> | 21 | #include <linux/jiffies.h> |
| 21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 22 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
| @@ -287,6 +288,35 @@ out: | |||
| 287 | return ret; | 288 | return ret; |
| 288 | } | 289 | } |
| 289 | 290 | ||
| 291 | static int bcm2836_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
| 292 | { | ||
| 293 | void __iomem *intc_base; | ||
| 294 | struct device_node *dn; | ||
| 295 | char *name; | ||
| 296 | |||
| 297 | name = "brcm,bcm2836-l1-intc"; | ||
| 298 | dn = of_find_compatible_node(NULL, NULL, name); | ||
| 299 | if (!dn) { | ||
| 300 | pr_err("unable to find intc node\n"); | ||
| 301 | return -ENODEV; | ||
| 302 | } | ||
| 303 | |||
| 304 | intc_base = of_iomap(dn, 0); | ||
| 305 | of_node_put(dn); | ||
| 306 | |||
| 307 | if (!intc_base) { | ||
| 308 | pr_err("unable to remap intc base register\n"); | ||
| 309 | return -ENOMEM; | ||
| 310 | } | ||
| 311 | |||
| 312 | writel(virt_to_phys(secondary_startup), | ||
| 313 | intc_base + LOCAL_MAILBOX3_SET0 + 16 * cpu); | ||
| 314 | |||
| 315 | iounmap(intc_base); | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 290 | static const struct smp_operations kona_smp_ops __initconst = { | 320 | static const struct smp_operations kona_smp_ops __initconst = { |
| 291 | .smp_prepare_cpus = bcm_smp_prepare_cpus, | 321 | .smp_prepare_cpus = bcm_smp_prepare_cpus, |
| 292 | .smp_boot_secondary = kona_boot_secondary, | 322 | .smp_boot_secondary = kona_boot_secondary, |
| @@ -305,3 +335,8 @@ static const struct smp_operations nsp_smp_ops __initconst = { | |||
| 305 | .smp_boot_secondary = nsp_boot_secondary, | 335 | .smp_boot_secondary = nsp_boot_secondary, |
| 306 | }; | 336 | }; |
| 307 | CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); | 337 | CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); |
| 338 | |||
| 339 | const struct smp_operations bcm2836_smp_ops __initconst = { | ||
| 340 | .smp_boot_secondary = bcm2836_boot_secondary, | ||
| 341 | }; | ||
| 342 | CPU_METHOD_OF_DECLARE(bcm_smp_bcm2836, "brcm,bcm2836-smp", &bcm2836_smp_ops); | ||
diff --git a/arch/arm/mach-bcm/platsmp.h b/arch/arm/mach-bcm/platsmp.h new file mode 100644 index 000000000000..b8b8b3fa350d --- /dev/null +++ b/arch/arm/mach-bcm/platsmp.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2017 Stefan Wahren <stefan.wahren@i2se.com> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation version 2. | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | extern const struct smp_operations bcm2836_smp_ops; | ||
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c index dc8c1e3eafe7..667b9e14b032 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c | |||
| @@ -19,62 +19,9 @@ | |||
| 19 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
| 20 | #include <linux/irqchip.h> | 20 | #include <linux/irqchip.h> |
| 21 | #include <linux/irqdomain.h> | 21 | #include <linux/irqdomain.h> |
| 22 | #include <asm/exception.h> | 22 | #include <linux/irqchip/irq-bcm2836.h> |
| 23 | |||
| 24 | #define LOCAL_CONTROL 0x000 | ||
| 25 | #define LOCAL_PRESCALER 0x008 | ||
| 26 | 23 | ||
| 27 | /* | 24 | #include <asm/exception.h> |
| 28 | * The low 2 bits identify the CPU that the GPU IRQ goes to, and the | ||
| 29 | * next 2 bits identify the CPU that the GPU FIQ goes to. | ||
| 30 | */ | ||
| 31 | #define LOCAL_GPU_ROUTING 0x00c | ||
| 32 | /* When setting bits 0-3, enables PMU interrupts on that CPU. */ | ||
| 33 | #define LOCAL_PM_ROUTING_SET 0x010 | ||
| 34 | /* When setting bits 0-3, disables PMU interrupts on that CPU. */ | ||
| 35 | #define LOCAL_PM_ROUTING_CLR 0x014 | ||
| 36 | /* | ||
| 37 | * The low 4 bits of this are the CPU's timer IRQ enables, and the | ||
| 38 | * next 4 bits are the CPU's timer FIQ enables (which override the IRQ | ||
| 39 | * bits). | ||
| 40 | */ | ||
| 41 | #define LOCAL_TIMER_INT_CONTROL0 0x040 | ||
| 42 | /* | ||
| 43 | * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and | ||
| 44 | * the next 4 bits are the CPU's per-mailbox FIQ enables (which | ||
| 45 | * override the IRQ bits). | ||
| 46 | */ | ||
| 47 | #define LOCAL_MAILBOX_INT_CONTROL0 0x050 | ||
| 48 | /* | ||
| 49 | * The CPU's interrupt status register. Bits are defined by the the | ||
| 50 | * LOCAL_IRQ_* bits below. | ||
| 51 | */ | ||
| 52 | #define LOCAL_IRQ_PENDING0 0x060 | ||
| 53 | /* Same status bits as above, but for FIQ. */ | ||
| 54 | #define LOCAL_FIQ_PENDING0 0x070 | ||
| 55 | /* | ||
| 56 | * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and | ||
| 57 | * these bits are organized by mailbox number and then CPU number. We | ||
| 58 | * use mailbox 0 for IPIs. The mailbox's interrupt is raised while | ||
| 59 | * any bit is set. | ||
| 60 | */ | ||
| 61 | #define LOCAL_MAILBOX0_SET0 0x080 | ||
| 62 | #define LOCAL_MAILBOX3_SET0 0x08c | ||
| 63 | /* Mailbox write-to-clear bits. */ | ||
| 64 | #define LOCAL_MAILBOX0_CLR0 0x0c0 | ||
| 65 | #define LOCAL_MAILBOX3_CLR0 0x0cc | ||
| 66 | |||
| 67 | #define LOCAL_IRQ_CNTPSIRQ 0 | ||
| 68 | #define LOCAL_IRQ_CNTPNSIRQ 1 | ||
| 69 | #define LOCAL_IRQ_CNTHPIRQ 2 | ||
| 70 | #define LOCAL_IRQ_CNTVIRQ 3 | ||
| 71 | #define LOCAL_IRQ_MAILBOX0 4 | ||
| 72 | #define LOCAL_IRQ_MAILBOX1 5 | ||
| 73 | #define LOCAL_IRQ_MAILBOX2 6 | ||
| 74 | #define LOCAL_IRQ_MAILBOX3 7 | ||
| 75 | #define LOCAL_IRQ_GPU_FAST 8 | ||
| 76 | #define LOCAL_IRQ_PMU_FAST 9 | ||
| 77 | #define LAST_IRQ LOCAL_IRQ_PMU_FAST | ||
| 78 | 25 | ||
| 79 | struct bcm2836_arm_irqchip_intc { | 26 | struct bcm2836_arm_irqchip_intc { |
| 80 | struct irq_domain *domain; | 27 | struct irq_domain *domain; |
| @@ -215,24 +162,6 @@ static int bcm2836_cpu_dying(unsigned int cpu) | |||
| 215 | cpu); | 162 | cpu); |
| 216 | return 0; | 163 | return 0; |
| 217 | } | 164 | } |
| 218 | |||
| 219 | #ifdef CONFIG_ARM | ||
| 220 | static int __init bcm2836_smp_boot_secondary(unsigned int cpu, | ||
| 221 | struct task_struct *idle) | ||
| 222 | { | ||
| 223 | unsigned long secondary_startup_phys = | ||
| 224 | (unsigned long)virt_to_phys((void *)secondary_startup); | ||
| 225 | |||
| 226 | writel(secondary_startup_phys, | ||
| 227 | intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static const struct smp_operations bcm2836_smp_ops __initconst = { | ||
| 233 | .smp_boot_secondary = bcm2836_smp_boot_secondary, | ||
| 234 | }; | ||
| 235 | #endif | ||
| 236 | #endif | 165 | #endif |
| 237 | 166 | ||
| 238 | static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { | 167 | static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { |
| @@ -249,10 +178,6 @@ bcm2836_arm_irqchip_smp_init(void) | |||
| 249 | bcm2836_cpu_dying); | 178 | bcm2836_cpu_dying); |
| 250 | 179 | ||
| 251 | set_smp_cross_call(bcm2836_arm_irqchip_send_ipi); | 180 | set_smp_cross_call(bcm2836_arm_irqchip_send_ipi); |
| 252 | |||
| 253 | #ifdef CONFIG_ARM | ||
| 254 | smp_set_ops(&bcm2836_smp_ops); | ||
| 255 | #endif | ||
| 256 | #endif | 181 | #endif |
| 257 | } | 182 | } |
| 258 | 183 | ||
diff --git a/include/linux/irqchip/irq-bcm2836.h b/include/linux/irqchip/irq-bcm2836.h new file mode 100644 index 000000000000..218a6e1b18d8 --- /dev/null +++ b/include/linux/irqchip/irq-bcm2836.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * Root interrupt controller for the BCM2836 (Raspberry Pi 2). | ||
| 3 | * | ||
| 4 | * Copyright 2015 Broadcom | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define LOCAL_CONTROL 0x000 | ||
| 18 | #define LOCAL_PRESCALER 0x008 | ||
| 19 | |||
| 20 | /* | ||
| 21 | * The low 2 bits identify the CPU that the GPU IRQ goes to, and the | ||
| 22 | * next 2 bits identify the CPU that the GPU FIQ goes to. | ||
| 23 | */ | ||
| 24 | #define LOCAL_GPU_ROUTING 0x00c | ||
| 25 | /* When setting bits 0-3, enables PMU interrupts on that CPU. */ | ||
| 26 | #define LOCAL_PM_ROUTING_SET 0x010 | ||
| 27 | /* When setting bits 0-3, disables PMU interrupts on that CPU. */ | ||
| 28 | #define LOCAL_PM_ROUTING_CLR 0x014 | ||
| 29 | /* | ||
| 30 | * The low 4 bits of this are the CPU's timer IRQ enables, and the | ||
| 31 | * next 4 bits are the CPU's timer FIQ enables (which override the IRQ | ||
| 32 | * bits). | ||
| 33 | */ | ||
| 34 | #define LOCAL_TIMER_INT_CONTROL0 0x040 | ||
| 35 | /* | ||
| 36 | * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and | ||
| 37 | * the next 4 bits are the CPU's per-mailbox FIQ enables (which | ||
| 38 | * override the IRQ bits). | ||
| 39 | */ | ||
| 40 | #define LOCAL_MAILBOX_INT_CONTROL0 0x050 | ||
| 41 | /* | ||
| 42 | * The CPU's interrupt status register. Bits are defined by the the | ||
| 43 | * LOCAL_IRQ_* bits below. | ||
| 44 | */ | ||
| 45 | #define LOCAL_IRQ_PENDING0 0x060 | ||
| 46 | /* Same status bits as above, but for FIQ. */ | ||
| 47 | #define LOCAL_FIQ_PENDING0 0x070 | ||
| 48 | /* | ||
| 49 | * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and | ||
| 50 | * these bits are organized by mailbox number and then CPU number. We | ||
| 51 | * use mailbox 0 for IPIs. The mailbox's interrupt is raised while | ||
| 52 | * any bit is set. | ||
| 53 | */ | ||
| 54 | #define LOCAL_MAILBOX0_SET0 0x080 | ||
| 55 | #define LOCAL_MAILBOX3_SET0 0x08c | ||
| 56 | /* Mailbox write-to-clear bits. */ | ||
| 57 | #define LOCAL_MAILBOX0_CLR0 0x0c0 | ||
| 58 | #define LOCAL_MAILBOX3_CLR0 0x0cc | ||
| 59 | |||
| 60 | #define LOCAL_IRQ_CNTPSIRQ 0 | ||
| 61 | #define LOCAL_IRQ_CNTPNSIRQ 1 | ||
| 62 | #define LOCAL_IRQ_CNTHPIRQ 2 | ||
| 63 | #define LOCAL_IRQ_CNTVIRQ 3 | ||
| 64 | #define LOCAL_IRQ_MAILBOX0 4 | ||
| 65 | #define LOCAL_IRQ_MAILBOX1 5 | ||
| 66 | #define LOCAL_IRQ_MAILBOX2 6 | ||
| 67 | #define LOCAL_IRQ_MAILBOX3 7 | ||
| 68 | #define LOCAL_IRQ_GPU_FAST 8 | ||
| 69 | #define LOCAL_IRQ_PMU_FAST 9 | ||
| 70 | #define LAST_IRQ LOCAL_IRQ_PMU_FAST | ||
