diff options
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 59e18af..b340297 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 0000000..c95169b --- /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 8e60503..4624eeb 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 9036942..3b9a4bf 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)) { |