diff options
author | Graf Yang <graf.yang@analog.com> | 2009-12-28 11:13:51 +0000 |
---|---|---|
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 59e18afe28c..b3402971831 100644 --- a/arch/blackfin/mach-bf561/Makefile +++ b/arch/blackfin/mach-bf561/Makefile @@ -6,3 +6,4 @@ obj-y := ints-priority.o dma.o obj-$(CONFIG_BF561_COREB) += coreb.o obj-$(CONFIG_SMP) += smp.o secondary.o atomic.o +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 00000000000..c95169b612d --- /dev/null +++ b/arch/blackfin/mach-bf561/hotplug.c @@ -0,0 +1,32 @@ +/* + * Copyright 2007-2009 Analog Devices Inc. + * Graff Yang <graf.yang@analog.com> + * + * Licensed under the GPL-2 or later. + */ + +#include <asm/blackfin.h> +#include <asm/smp.h> +#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1)) + +int hotplug_coreb; + +void platform_cpu_die(void) +{ + unsigned long iwr[2] = {0, 0}; + unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32; + unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32); + + hotplug_coreb = 1; + + iwr[bank] = bit; + + /* disable core timer */ + bfin_write_TCNTL(0); + + /* clear ipi interrupt IRQ_SUPPLE_0 */ + bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1))); + SSYNC(); + + coreb_sleep(iwr[0], iwr[1], 0); +} diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S index 8e6050369c0..4624eebbf9c 100644 --- a/arch/blackfin/mach-bf561/secondary.S +++ b/arch/blackfin/mach-bf561/secondary.S @@ -11,6 +11,7 @@ #include <linux/init.h> #include <asm/blackfin.h> #include <asm/asm-offsets.h> +#include <asm/trace.h> __INIT @@ -62,6 +63,8 @@ ENTRY(_coreb_trampoline_start) M2 = r0; M3 = r0; + trace_buffer_init(p0,r0); + /* Turn off the icache */ p0.l = LO(IMEM_CONTROL); p0.h = HI(IMEM_CONTROL); @@ -159,6 +162,41 @@ ENTRY(_coreb_trampoline_start) ENDPROC(_coreb_trampoline_start) ENTRY(_coreb_trampoline_end) +.section ".text" +ENTRY(_set_sicb_iwr) + P0.H = hi(SICB_IWR0); + P0.L = lo(SICB_IWR0); + P1.H = hi(SICB_IWR1); + P1.L = lo(SICB_IWR1); + [P0] = R0; + [P1] = R1; + SSYNC; + RTS; +ENDPROC(_set_sicb_iwr) + +ENTRY(_coreb_sleep) + sp.l = lo(INITIAL_STACK); + sp.h = hi(INITIAL_STACK); + fp = sp; + usp = sp; + + call _set_sicb_iwr; + + CLI R2; + SSYNC; + IDLE; + STI R2; + + R0 = IWR_DISABLE_ALL; + R1 = IWR_DISABLE_ALL; + call _set_sicb_iwr; + + p0.h = hi(COREB_L1_CODE_START); + p0.l = lo(COREB_L1_CODE_START); + jump (p0); +ENDPROC(_coreb_sleep) + +__CPUINIT ENTRY(_coreb_start) [--sp] = reti; @@ -176,12 +214,20 @@ ENTRY(_coreb_start) sp = [p0]; usp = sp; fp = sp; +#ifdef CONFIG_HOTPLUG_CPU + p0.l = _hotplug_coreb; + p0.h = _hotplug_coreb; + r0 = [p0]; + cc = BITTST(r0, 0); + if cc jump 3f; +#endif sp += -12; call _init_pda sp += 12; +#ifdef CONFIG_HOTPLUG_CPU +3: +#endif call _secondary_start_kernel; .L_exit: jump.s .L_exit; ENDPROC(_coreb_start) - -__FINIT diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index 90369429ee6..3b9a4bf7dac 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) bfin_write_SICB_IAR5(bfin_read_SICA_IAR5()); bfin_write_SICB_IAR6(bfin_read_SICA_IAR6()); bfin_write_SICB_IAR7(bfin_read_SICA_IAR7()); + bfin_write_SICB_IWR0(IWR_DISABLE_ALL); + bfin_write_SICB_IWR1(IWR_DISABLE_ALL); SSYNC(); /* 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 { unsigned long timeout; - /* CoreB already running?! */ - BUG_ON((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0); - printk(KERN_INFO "Booting Core B.\n"); spin_lock(&boot_lock); - /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */ - SSYNC(); - bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT); - SSYNC(); + if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) { + /* CoreB already running, sending ipi to wakeup it */ + platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0); + } else { + /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */ + bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT); + SSYNC(); + } timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { |