diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-11-19 12:23:51 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-01-29 10:14:57 +0000 |
commit | 87353d8ac39c52784da605ecbe965ecdfad609ad (patch) | |
tree | c95ce7cbe9b099c21cab71a195621801b04bc05a /arch/mips/sibyte/bcm1480/smp.c | |
parent | 19388fb092d89e179575bd0b44f51b57e175edf5 (diff) |
[MIPS] SMP: Call platform methods via ops structure.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sibyte/bcm1480/smp.c')
-rw-r--r-- | arch/mips/sibyte/bcm1480/smp.c | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 436ba78359a..183c460b9ca 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -23,6 +23,7 @@ #include <asm/mmu_context.h> #include <asm/io.h> +#include <asm/fw/cfe/cfe_api.h> #include <asm/sibyte/sb1250.h> #include <asm/sibyte/bcm1480_regs.h> #include <asm/sibyte/bcm1480_int.h> @@ -67,28 +68,114 @@ void __cpuinit bcm1480_smp_init(void) change_c0_status(ST0_IM, imask); } -void __cpuinit bcm1480_smp_finish(void) +/* + * These are routines for dealing with the sb1250 smp capabilities + * independent of board/firmware + */ + +/* + * Simple enough; everything is set up, so just poke the appropriate mailbox + * register, and we should be set + */ +static void bcm1480_send_ipi_single(int cpu, unsigned int action) +{ + __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); +} + +static void bcm1480_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + + for_each_cpu_mask(i, mask) + bcm1480_send_ipi_single(i, action); +} + +/* + * Code to run on secondary just after probing the CPU + */ +static void __cpuinit bcm1480_init_secondary(void) +{ + extern void bcm1480_smp_init(void); + + bcm1480_smp_init(); +} + +/* + * Do any tidying up before marking online and running the idle + * loop + */ +static void __cpuinit bcm1480_smp_finish(void) { extern void sb1480_clockevent_init(void); sb1480_clockevent_init(); local_irq_enable(); + bcm1480_smp_finish(); } /* - * These are routines for dealing with the sb1250 smp capabilities - * independent of board/firmware + * Final cleanup after all secondaries booted */ +static void bcm1480_cpus_done(void) +{ +} /* - * Simple enough; everything is set up, so just poke the appropriate mailbox - * register, and we should be set + * Setup the PC, SP, and GP of a secondary processor and start it + * running! */ -void core_send_ipi(int cpu, unsigned int action) +static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle) { - __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); + int retval; + + retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, + __KSTK_TOS(idle), + (unsigned long)task_thread_info(idle), 0); + if (retval != 0) + printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); } +/* + * Use CFE to find out how many CPUs are available, setting up + * phys_cpu_present_map and the logical/physical mappings. + * XXXKW will the boot CPU ever not be physical 0? + * + * Common setup before any secondaries are started + */ +static void __init bcm1480_smp_setup(void) +{ + int i, num; + + cpus_clear(phys_cpu_present_map); + cpu_set(0, phys_cpu_present_map); + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + + for (i = 1, num = 0; i < NR_CPUS; i++) { + if (cfe_cpu_stop(i) == 0) { + cpu_set(i, phys_cpu_present_map); + __cpu_number_map[i] = ++num; + __cpu_logical_map[num] = i; + } + } + printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); +} + +static void __init bcm1480_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops bcm1480_smp_ops = { + .send_ipi_single = bcm1480_send_ipi_single, + .send_ipi_mask = bcm1480_send_ipi_mask, + .init_secondary = bcm1480_init_secondary, + .smp_finish = bcm1480_smp_finish, + .cpus_done = bcm1480_cpus_done, + .boot_secondary = bcm1480_boot_secondary, + .smp_setup = bcm1480_smp_setup, + .prepare_cpus = bcm1480_prepare_cpus, +}; + void bcm1480_mailbox_interrupt(void) { int cpu = smp_processor_id(); |