summaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte/sb1250/smp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:48:03 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:48:03 +1100
commit21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (patch)
tree5d288c1877b1ae9fbe24aa7fabd79565e73d3d2f /arch/mips/sibyte/sb1250/smp.c
parent5ea293a9048d3a58cb0c840fa719d85ad14cba47 (diff)
parenta9d2517c7a5c8028fbc5296d3af3c75597d3d180 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (68 commits) [MIPS] remove Documentation/mips/GT64120.README [MIPS] Malta: remaining bits of the board support code cleanup [MIPS] Malta: make the helper function static [MIPS] Malta: fix braces at single statement blocks [MIPS] Malta, Atlas: move an extern function declaration to the header file [MIPS] Malta: Use C89 style for comments [MIPS] Malta: else should follow close brace in malta_int.c [MIPS] Malta: remove a superfluous comment [MIPS] Malta: include <linux/cpu.h> instead of <asm/cpu.h> [MIPS] Malta, Atlas, Sead: remove an extern from .c files [MIPS] Malta: fix oversized lines in malta_int.c [MIPS] Malta: remove a dead function declaration [MIPS] Malta: use tabs not spaces [MIPS] Malta: set up the screen info in a separate function [MIPS] Malta: check the PCI clock frequency in a separate function [MIPS] Malta: use the KERN_ facility level in printk() [MIPS] Malta: use Linux kernel style for structure initialization [MIPS]: constify function pointer tables [MIPS] compat: handle argument endianess of sys32_(f)truncate64 with merge_64 [MIPS] Cobalt 64-bits kernels can be safely unmarked experimental ...
Diffstat (limited to 'arch/mips/sibyte/sb1250/smp.c')
-rw-r--r--arch/mips/sibyte/sb1250/smp.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index 3f52c95a4eb..0734b933e96 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -24,6 +24,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/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
@@ -55,7 +56,43 @@ void __cpuinit sb1250_smp_init(void)
change_c0_status(ST0_IM, imask);
}
-void __cpuinit sb1250_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 sb1250_send_ipi_single(int cpu, unsigned int action)
+{
+ __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
+}
+
+static inline void sb1250_send_ipi_mask(cpumask_t mask, unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu_mask(i, mask)
+ sb1250_send_ipi_single(i, action);
+}
+
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+static void __cpuinit sb1250_init_secondary(void)
+{
+ extern void sb1250_smp_init(void);
+
+ sb1250_smp_init();
+}
+
+/*
+ * Do any tidying up before marking online and running the idle
+ * loop
+ */
+static void __cpuinit sb1250_smp_finish(void)
{
extern void sb1250_clockevent_init(void);
@@ -64,19 +101,68 @@ void __cpuinit sb1250_smp_finish(void)
}
/*
- * These are routines for dealing with the sb1250 smp capabilities
- * independent of board/firmware
+ * Final cleanup after all secondaries booted
*/
+static void sb1250_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 sb1250_boot_secondary(int cpu, struct task_struct *idle)
{
- __raw_writeq((((u64)action) << 48), mailbox_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 sb1250_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 sb1250_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+struct plat_smp_ops sb_smp_ops = {
+ .send_ipi_single = sb1250_send_ipi_single,
+ .send_ipi_mask = sb1250_send_ipi_mask,
+ .init_secondary = sb1250_init_secondary,
+ .smp_finish = sb1250_smp_finish,
+ .cpus_done = sb1250_cpus_done,
+ .boot_secondary = sb1250_boot_secondary,
+ .smp_setup = sb1250_smp_setup,
+ .prepare_cpus = sb1250_prepare_cpus,
+};
+
void sb1250_mailbox_interrupt(void)
{
int cpu = smp_processor_id();