diff options
author | Graf Yang <graf.yang@analog.com> | 2009-12-28 06:13:51 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-03-09 00:30:48 -0500 |
commit | 0b39db28b953945232719e7ff6fb802aa8a2be5f (patch) | |
tree | c35193b07e9413ed6b5436aa79e24b0f22627082 /arch/blackfin/mach-bf561 | |
parent | 0d152c27e336b5fd777da7dd3e814617e7305afd (diff) |
Blackfin: SMP: add PM/CPU hotplug support
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/mach-bf561')
-rw-r--r-- | arch/blackfin/mach-bf561/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/mach-bf561/hotplug.c | 32 | ||||
-rw-r--r-- | arch/blackfin/mach-bf561/secondary.S | 50 | ||||
-rw-r--r-- | arch/blackfin/mach-bf561/smp.c | 17 |
4 files changed, 91 insertions, 9 deletions
diff --git a/arch/blackfin/mach-bf561/Makefile b/arch/blackfin/mach-bf561/Makefile index 59e18afe28c6..b34029718318 100644 --- a/arch/blackfin/mach-bf561/Makefile +++ b/arch/blackfin/mach-bf561/Makefile | |||
@@ -6,3 +6,4 @@ obj-y := ints-priority.o dma.o | |||
6 | 6 | ||
7 | obj-$(CONFIG_BF561_COREB) += coreb.o | 7 | obj-$(CONFIG_BF561_COREB) += coreb.o |
8 | obj-$(CONFIG_SMP) += smp.o secondary.o atomic.o | 8 | obj-$(CONFIG_SMP) += smp.o secondary.o atomic.o |
9 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
diff --git a/arch/blackfin/mach-bf561/hotplug.c b/arch/blackfin/mach-bf561/hotplug.c new file mode 100644 index 000000000000..c95169b612dc --- /dev/null +++ b/arch/blackfin/mach-bf561/hotplug.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright 2007-2009 Analog Devices Inc. | ||
3 | * Graff Yang <graf.yang@analog.com> | ||
4 | * | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <asm/blackfin.h> | ||
9 | #include <asm/smp.h> | ||
10 | #define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) | ||
11 | |||
12 | int hotplug_coreb; | ||
13 | |||
14 | void platform_cpu_die(void) | ||
15 | { | ||
16 | unsigned long iwr[2] = {0, 0}; | ||
17 | unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32; | ||
18 | unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32); | ||
19 | |||
20 | hotplug_coreb = 1; | ||
21 | |||
22 | iwr[bank] = bit; | ||
23 | |||
24 | /* disable core timer */ | ||
25 | bfin_write_TCNTL(0); | ||
26 | |||
27 | /* clear ipi interrupt IRQ_SUPPLE_0 */ | ||
28 | bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1))); | ||
29 | SSYNC(); | ||
30 | |||
31 | coreb_sleep(iwr[0], iwr[1], 0); | ||
32 | } | ||
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S index 8e6050369c06..4624eebbf9c4 100644 --- a/arch/blackfin/mach-bf561/secondary.S +++ b/arch/blackfin/mach-bf561/secondary.S | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <asm/blackfin.h> | 12 | #include <asm/blackfin.h> |
13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
14 | #include <asm/trace.h> | ||
14 | 15 | ||
15 | __INIT | 16 | __INIT |
16 | 17 | ||
@@ -62,6 +63,8 @@ ENTRY(_coreb_trampoline_start) | |||
62 | M2 = r0; | 63 | M2 = r0; |
63 | M3 = r0; | 64 | M3 = r0; |
64 | 65 | ||
66 | trace_buffer_init(p0,r0); | ||
67 | |||
65 | /* Turn off the icache */ | 68 | /* Turn off the icache */ |
66 | p0.l = LO(IMEM_CONTROL); | 69 | p0.l = LO(IMEM_CONTROL); |
67 | p0.h = HI(IMEM_CONTROL); | 70 | p0.h = HI(IMEM_CONTROL); |
@@ -159,6 +162,41 @@ ENTRY(_coreb_trampoline_start) | |||
159 | ENDPROC(_coreb_trampoline_start) | 162 | ENDPROC(_coreb_trampoline_start) |
160 | ENTRY(_coreb_trampoline_end) | 163 | ENTRY(_coreb_trampoline_end) |
161 | 164 | ||
165 | .section ".text" | ||
166 | ENTRY(_set_sicb_iwr) | ||
167 | P0.H = hi(SICB_IWR0); | ||
168 | P0.L = lo(SICB_IWR0); | ||
169 | P1.H = hi(SICB_IWR1); | ||
170 | P1.L = lo(SICB_IWR1); | ||
171 | [P0] = R0; | ||
172 | [P1] = R1; | ||
173 | SSYNC; | ||
174 | RTS; | ||
175 | ENDPROC(_set_sicb_iwr) | ||
176 | |||
177 | ENTRY(_coreb_sleep) | ||
178 | sp.l = lo(INITIAL_STACK); | ||
179 | sp.h = hi(INITIAL_STACK); | ||
180 | fp = sp; | ||
181 | usp = sp; | ||
182 | |||
183 | call _set_sicb_iwr; | ||
184 | |||
185 | CLI R2; | ||
186 | SSYNC; | ||
187 | IDLE; | ||
188 | STI R2; | ||
189 | |||
190 | R0 = IWR_DISABLE_ALL; | ||
191 | R1 = IWR_DISABLE_ALL; | ||
192 | call _set_sicb_iwr; | ||
193 | |||
194 | p0.h = hi(COREB_L1_CODE_START); | ||
195 | p0.l = lo(COREB_L1_CODE_START); | ||
196 | jump (p0); | ||
197 | ENDPROC(_coreb_sleep) | ||
198 | |||
199 | __CPUINIT | ||
162 | ENTRY(_coreb_start) | 200 | ENTRY(_coreb_start) |
163 | [--sp] = reti; | 201 | [--sp] = reti; |
164 | 202 | ||
@@ -176,12 +214,20 @@ ENTRY(_coreb_start) | |||
176 | sp = [p0]; | 214 | sp = [p0]; |
177 | usp = sp; | 215 | usp = sp; |
178 | fp = sp; | 216 | fp = sp; |
217 | #ifdef CONFIG_HOTPLUG_CPU | ||
218 | p0.l = _hotplug_coreb; | ||
219 | p0.h = _hotplug_coreb; | ||
220 | r0 = [p0]; | ||
221 | cc = BITTST(r0, 0); | ||
222 | if cc jump 3f; | ||
223 | #endif | ||
179 | sp += -12; | 224 | sp += -12; |
180 | call _init_pda | 225 | call _init_pda |
181 | sp += 12; | 226 | sp += 12; |
227 | #ifdef CONFIG_HOTPLUG_CPU | ||
228 | 3: | ||
229 | #endif | ||
182 | call _secondary_start_kernel; | 230 | call _secondary_start_kernel; |
183 | .L_exit: | 231 | .L_exit: |
184 | jump.s .L_exit; | 232 | jump.s .L_exit; |
185 | ENDPROC(_coreb_start) | 233 | ENDPROC(_coreb_start) |
186 | |||
187 | __FINIT | ||
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 90369429ee66..3b9a4bf7dacc 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c | |||
@@ -65,6 +65,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
65 | bfin_write_SICB_IAR5(bfin_read_SICA_IAR5()); | 65 | bfin_write_SICB_IAR5(bfin_read_SICA_IAR5()); |
66 | bfin_write_SICB_IAR6(bfin_read_SICA_IAR6()); | 66 | bfin_write_SICB_IAR6(bfin_read_SICA_IAR6()); |
67 | bfin_write_SICB_IAR7(bfin_read_SICA_IAR7()); | 67 | bfin_write_SICB_IAR7(bfin_read_SICA_IAR7()); |
68 | bfin_write_SICB_IWR0(IWR_DISABLE_ALL); | ||
69 | bfin_write_SICB_IWR1(IWR_DISABLE_ALL); | ||
68 | SSYNC(); | 70 | SSYNC(); |
69 | 71 | ||
70 | /* Store CPU-private information to the cpu_data array. */ | 72 | /* Store CPU-private information to the cpu_data array. */ |
@@ -80,17 +82,18 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle | |||
80 | { | 82 | { |
81 | unsigned long timeout; | 83 | unsigned long timeout; |
82 | 84 | ||
83 | /* CoreB already running?! */ | ||
84 | BUG_ON((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0); | ||
85 | |||
86 | printk(KERN_INFO "Booting Core B.\n"); | 85 | printk(KERN_INFO "Booting Core B.\n"); |
87 | 86 | ||
88 | spin_lock(&boot_lock); | 87 | spin_lock(&boot_lock); |
89 | 88 | ||
90 | /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */ | 89 | if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) { |
91 | SSYNC(); | 90 | /* CoreB already running, sending ipi to wakeup it */ |
92 | bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT); | 91 | platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0); |
93 | SSYNC(); | 92 | } else { |
93 | /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */ | ||
94 | bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT); | ||
95 | SSYNC(); | ||
96 | } | ||
94 | 97 | ||
95 | timeout = jiffies + 1 * HZ; | 98 | timeout = jiffies + 1 * HZ; |
96 | while (time_before(jiffies, timeout)) { | 99 | while (time_before(jiffies, timeout)) { |