diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2014-09-10 09:35:38 -0400 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2015-06-22 04:36:56 -0400 |
commit | 82fea5a1bbbe8c3b56d5f3efbf8880c7b25b1758 (patch) | |
tree | 736061a26f019af1912dd6824f8ab4eb5a20eb33 | |
parent | 173eaafaed284fc95209902f68f011d01d1eda02 (diff) |
ARCv2: SMP: Support ARConnect (MCIP) for Inter-Core-Interrupts et al
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r-- | arch/arc/Kconfig | 21 | ||||
-rw-r--r-- | arch/arc/include/asm/irq.h | 1 | ||||
-rw-r--r-- | arch/arc/include/asm/mcip.h | 91 | ||||
-rw-r--r-- | arch/arc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arc/kernel/intc-arcv2.c | 2 | ||||
-rw-r--r-- | arch/arc/kernel/mcip.c | 117 | ||||
-rw-r--r-- | arch/arc/plat-sim/platform.c | 5 |
7 files changed, 230 insertions, 8 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index f09e03a0d604..301525020af7 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -160,12 +160,12 @@ config CPU_BIG_ENDIAN | |||
160 | Build kernel for Big Endian Mode of ARC CPU | 160 | Build kernel for Big Endian Mode of ARC CPU |
161 | 161 | ||
162 | config SMP | 162 | config SMP |
163 | bool "Symmetric Multi-Processing (Incomplete)" | 163 | bool "Symmetric Multi-Processing" |
164 | default n | 164 | default n |
165 | select ARC_HAS_COH_CACHES if ISA_ARCV2 | ||
166 | select ARC_MCIP if ISA_ARCV2 | ||
165 | help | 167 | help |
166 | This enables support for systems with more than one CPU. If you have | 168 | This enables support for systems with more than one CPU. |
167 | a system with only one CPU, say N. If you have a system with more | ||
168 | than one CPU, say Y. | ||
169 | 169 | ||
170 | if SMP | 170 | if SMP |
171 | 171 | ||
@@ -175,13 +175,20 @@ config ARC_HAS_COH_CACHES | |||
175 | config ARC_HAS_REENTRANT_IRQ_LV2 | 175 | config ARC_HAS_REENTRANT_IRQ_LV2 |
176 | def_bool n | 176 | def_bool n |
177 | 177 | ||
178 | endif #SMP | 178 | config ARC_MCIP |
179 | bool "ARConnect Multicore IP (MCIP) Support " | ||
180 | depends on ISA_ARCV2 | ||
181 | help | ||
182 | This IP block enables SMP in ARC-HS38 cores. | ||
183 | It provides for cross-core interrupts, multi-core debug | ||
184 | hardware semaphores, shared memory,.... | ||
179 | 185 | ||
180 | config NR_CPUS | 186 | config NR_CPUS |
181 | int "Maximum number of CPUs (2-4096)" | 187 | int "Maximum number of CPUs (2-4096)" |
182 | range 2 4096 | 188 | range 2 4096 |
183 | depends on SMP | 189 | default "4" |
184 | default "2" | 190 | |
191 | endif #SMP | ||
185 | 192 | ||
186 | menuconfig ARC_CACHE | 193 | menuconfig ARC_CACHE |
187 | bool "Enable Cache Support" | 194 | bool "Enable Cache Support" |
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 49014f0ef36d..bc5103637326 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #else | 19 | #else |
20 | #define TIMER0_IRQ 16 | 20 | #define TIMER0_IRQ 16 |
21 | #define TIMER1_IRQ 17 | 21 | #define TIMER1_IRQ 17 |
22 | #define IPI_IRQ 19 | ||
22 | #endif | 23 | #endif |
23 | 24 | ||
24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
diff --git a/arch/arc/include/asm/mcip.h b/arch/arc/include/asm/mcip.h new file mode 100644 index 000000000000..31f9bac77a27 --- /dev/null +++ b/arch/arc/include/asm/mcip.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * ARConnect IP Support (Multi core enabler: Cross core IPI, RTC ...) | ||
3 | * | ||
4 | * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef __ASM_MCIP_H | ||
12 | #define __ASM_MCIP_H | ||
13 | |||
14 | #ifdef CONFIG_ISA_ARCV2 | ||
15 | |||
16 | #include <asm/arcregs.h> | ||
17 | |||
18 | #define ARC_REG_MCIP_BCR 0x0d0 | ||
19 | #define ARC_REG_MCIP_CMD 0x600 | ||
20 | #define ARC_REG_MCIP_WDATA 0x601 | ||
21 | #define ARC_REG_MCIP_READBACK 0x602 | ||
22 | |||
23 | struct mcip_cmd { | ||
24 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
25 | unsigned int pad:8, param:16, cmd:8; | ||
26 | #else | ||
27 | unsigned int cmd:8, param:16, pad:8; | ||
28 | #endif | ||
29 | |||
30 | #define CMD_INTRPT_GENERATE_IRQ 0x01 | ||
31 | #define CMD_INTRPT_GENERATE_ACK 0x02 | ||
32 | #define CMD_INTRPT_READ_STATUS 0x03 | ||
33 | #define CMD_INTRPT_CHECK_SOURCE 0x04 | ||
34 | |||
35 | /* Semaphore Commands */ | ||
36 | #define CMD_SEMA_CLAIM_AND_READ 0x11 | ||
37 | #define CMD_SEMA_RELEASE 0x12 | ||
38 | |||
39 | #define CMD_DEBUG_SET_MASK 0x34 | ||
40 | #define CMD_DEBUG_SET_SELECT 0x36 | ||
41 | |||
42 | #define CMD_IDU_ENABLE 0x71 | ||
43 | #define CMD_IDU_DISABLE 0x72 | ||
44 | #define CMD_IDU_SET_MODE 0x74 | ||
45 | #define CMD_IDU_SET_DEST 0x76 | ||
46 | #define CMD_IDU_SET_MASK 0x7C | ||
47 | |||
48 | #define IDU_M_TRIG_LEVEL 0x0 | ||
49 | #define IDU_M_TRIG_EDGE 0x1 | ||
50 | |||
51 | #define IDU_M_DISTRI_RR 0x0 | ||
52 | #define IDU_M_DISTRI_DEST 0x2 | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * MCIP programming model | ||
57 | * | ||
58 | * - Simple commands write {cmd:8,param:16} to MCIP_CMD aux reg | ||
59 | * (param could be irq, common_irq, core_id ...) | ||
60 | * - More involved commands setup MCIP_WDATA with cmd specific data | ||
61 | * before invoking the simple command | ||
62 | */ | ||
63 | static inline void __mcip_cmd(unsigned int cmd, unsigned int param) | ||
64 | { | ||
65 | struct mcip_cmd buf; | ||
66 | |||
67 | buf.pad = 0; | ||
68 | buf.cmd = cmd; | ||
69 | buf.param = param; | ||
70 | |||
71 | WRITE_AUX(ARC_REG_MCIP_CMD, buf); | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Setup additional data for a cmd | ||
76 | * Callers need to lock to ensure atomicity | ||
77 | */ | ||
78 | static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param, | ||
79 | unsigned int data) | ||
80 | { | ||
81 | write_aux_reg(ARC_REG_MCIP_WDATA, data); | ||
82 | |||
83 | __mcip_cmd(cmd, param); | ||
84 | } | ||
85 | |||
86 | extern void mcip_init_early_smp(void); | ||
87 | extern void mcip_init_smp(unsigned int cpu); | ||
88 | |||
89 | #endif | ||
90 | |||
91 | #endif | ||
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 0be7ba087260..e7f3625a19b5 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o | |||
15 | 15 | ||
16 | obj-$(CONFIG_MODULES) += arcksyms.o module.o | 16 | obj-$(CONFIG_MODULES) += arcksyms.o module.o |
17 | obj-$(CONFIG_SMP) += smp.o | 17 | obj-$(CONFIG_SMP) += smp.o |
18 | obj-$(CONFIG_ARC_MCIP) += mcip.o | ||
18 | obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o | 19 | obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o |
19 | obj-$(CONFIG_KPROBES) += kprobes.o | 20 | obj-$(CONFIG_KPROBES) += kprobes.o |
20 | obj-$(CONFIG_ARC_EMUL_UNALIGNED) += unaligned.o | 21 | obj-$(CONFIG_ARC_EMUL_UNALIGNED) += unaligned.o |
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index c5c64dc47655..6208c630abed 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c | |||
@@ -107,7 +107,7 @@ static struct irq_chip arcv2_irq_chip = { | |||
107 | static int arcv2_irq_map(struct irq_domain *d, unsigned int irq, | 107 | static int arcv2_irq_map(struct irq_domain *d, unsigned int irq, |
108 | irq_hw_number_t hw) | 108 | irq_hw_number_t hw) |
109 | { | 109 | { |
110 | if (irq == TIMER0_IRQ) | 110 | if (irq == TIMER0_IRQ || irq == IPI_IRQ) |
111 | irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_percpu_irq); | 111 | irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_percpu_irq); |
112 | else | 112 | else |
113 | irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_level_irq); | 113 | irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_level_irq); |
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c new file mode 100644 index 000000000000..e6ad6e64440a --- /dev/null +++ b/arch/arc/kernel/mcip.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * ARC ARConnect (MultiCore IP) support (formerly known as MCIP) | ||
3 | * | ||
4 | * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/smp.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <asm/mcip.h> | ||
15 | |||
16 | static char smp_cpuinfo_buf[128]; | ||
17 | |||
18 | static DEFINE_RAW_SPINLOCK(mcip_lock); | ||
19 | |||
20 | |||
21 | /* | ||
22 | * Any SMP specific init any CPU does when it comes up. | ||
23 | * Here we setup the CPU to enable Inter-Processor-Interrupts | ||
24 | * Called for each CPU | ||
25 | * -Master : init_IRQ() | ||
26 | * -Other(s) : start_kernel_secondary() | ||
27 | */ | ||
28 | void mcip_init_smp(unsigned int cpu) | ||
29 | { | ||
30 | smp_ipi_irq_setup(cpu, IPI_IRQ); | ||
31 | } | ||
32 | |||
33 | static void mcip_ipi_send(int cpu) | ||
34 | { | ||
35 | unsigned long flags; | ||
36 | |||
37 | raw_spin_lock_irqsave(&mcip_lock, flags); | ||
38 | __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu); | ||
39 | raw_spin_unlock_irqrestore(&mcip_lock, flags); | ||
40 | } | ||
41 | |||
42 | static void mcip_ipi_clear(int irq) | ||
43 | { | ||
44 | unsigned int cpu; | ||
45 | unsigned long flags; | ||
46 | |||
47 | raw_spin_lock_irqsave(&mcip_lock, flags); | ||
48 | |||
49 | /* Who sent the IPI */ | ||
50 | __mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0); | ||
51 | |||
52 | cpu = read_aux_reg(ARC_REG_MCIP_READBACK); /* 1,2,4,8... */ | ||
53 | |||
54 | __mcip_cmd(CMD_INTRPT_GENERATE_ACK, __ffs(cpu)); /* 0,1,2,3... */ | ||
55 | |||
56 | raw_spin_unlock_irqrestore(&mcip_lock, flags); | ||
57 | } | ||
58 | |||
59 | volatile int wake_flag; | ||
60 | |||
61 | static void mcip_wakeup_cpu(int cpu, unsigned long pc) | ||
62 | { | ||
63 | BUG_ON(cpu == 0); | ||
64 | wake_flag = cpu; | ||
65 | } | ||
66 | |||
67 | void arc_platform_smp_wait_to_boot(int cpu) | ||
68 | { | ||
69 | while (wake_flag != cpu) | ||
70 | ; | ||
71 | |||
72 | wake_flag = 0; | ||
73 | __asm__ __volatile__("j @first_lines_of_secondary \n"); | ||
74 | } | ||
75 | |||
76 | struct plat_smp_ops plat_smp_ops = { | ||
77 | .info = smp_cpuinfo_buf, | ||
78 | .cpu_kick = mcip_wakeup_cpu, | ||
79 | .ipi_send = mcip_ipi_send, | ||
80 | .ipi_clear = mcip_ipi_clear, | ||
81 | }; | ||
82 | |||
83 | void mcip_init_early_smp(void) | ||
84 | { | ||
85 | #define IS_AVAIL1(var, str) ((var) ? str : "") | ||
86 | |||
87 | struct mcip_bcr { | ||
88 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
89 | unsigned int pad3:8, | ||
90 | idu:1, llm:1, num_cores:6, | ||
91 | iocoh:1, grtc:1, dbg:1, pad2:1, | ||
92 | msg:1, sem:1, ipi:1, pad:1, | ||
93 | ver:8; | ||
94 | #else | ||
95 | unsigned int ver:8, | ||
96 | pad:1, ipi:1, sem:1, msg:1, | ||
97 | pad2:1, dbg:1, grtc:1, iocoh:1, | ||
98 | num_cores:6, llm:1, idu:1, | ||
99 | pad3:8; | ||
100 | #endif | ||
101 | } mp; | ||
102 | |||
103 | READ_BCR(ARC_REG_MCIP_BCR, mp); | ||
104 | |||
105 | sprintf(smp_cpuinfo_buf, | ||
106 | "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n", | ||
107 | mp.ver, mp.num_cores, | ||
108 | IS_AVAIL1(mp.ipi, "IPI "), | ||
109 | IS_AVAIL1(mp.idu, "IDU "), | ||
110 | IS_AVAIL1(mp.dbg, "DEBUG "), | ||
111 | IS_AVAIL1(mp.grtc, "GRTC")); | ||
112 | |||
113 | if (mp.dbg) { | ||
114 | __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf); | ||
115 | __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf); | ||
116 | } | ||
117 | } | ||
diff --git a/arch/arc/plat-sim/platform.c b/arch/arc/plat-sim/platform.c index 114fdc30941c..8795ae2ef48a 100644 --- a/arch/arc/plat-sim/platform.c +++ b/arch/arc/plat-sim/platform.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <asm/mach_desc.h> | 12 | #include <asm/mach_desc.h> |
13 | #include <asm/mcip.h> | ||
13 | 14 | ||
14 | /*----------------------- Machine Descriptions ------------------------------ | 15 | /*----------------------- Machine Descriptions ------------------------------ |
15 | * | 16 | * |
@@ -27,4 +28,8 @@ static const char *simulation_compat[] __initconst = { | |||
27 | 28 | ||
28 | MACHINE_START(SIMULATION, "simulation") | 29 | MACHINE_START(SIMULATION, "simulation") |
29 | .dt_compat = simulation_compat, | 30 | .dt_compat = simulation_compat, |
31 | #ifdef CONFIG_ARC_MCIP | ||
32 | .init_early = mcip_init_early_smp, | ||
33 | .init_smp = mcip_init_smp, | ||
34 | #endif | ||
30 | MACHINE_END | 35 | MACHINE_END |