summaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/saturn/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/saturn/smp.c')
-rw-r--r--arch/sh/boards/saturn/smp.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/arch/sh/boards/saturn/smp.c b/arch/sh/boards/saturn/smp.c
new file mode 100644
index 000000000000..76460918c9cd
--- /dev/null
+++ b/arch/sh/boards/saturn/smp.c
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/boards/saturn/smp.c
+ *
+ * SMP support for the Sega Saturn.
+ *
+ * Copyright (c) 2002 Paul Mundt
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/saturn/smpc.h>
+
+extern void start_secondary(void);
+
+void __smp_send_ipi(unsigned int cpu, unsigned int action)
+{
+ /* Nothing here yet .. */
+}
+
+unsigned int __smp_probe_cpus(void)
+{
+ /*
+ * This is just a straightforward master/slave configuration,
+ * and probing isn't really supported..
+ */
+ return 2;
+}
+
+/*
+ * We're only allowed to do byte-access to SMPC registers. In
+ * addition to which, we treat them as write-only, since
+ * reading from them will return undefined data.
+ */
+static inline void smpc_slave_stop(unsigned int cpu)
+{
+ smpc_barrier();
+ ctrl_outb(1, SMPC_STATUS);
+
+ ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
+ smpc_barrier();
+}
+
+static inline void smpc_slave_start(unsigned int cpu)
+{
+ ctrl_outb(1, SMPC_STATUS);
+ ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
+
+ smpc_barrier();
+}
+
+void __smp_slave_init(unsigned int cpu)
+{
+ register unsigned long vbr;
+ void **entry;
+
+ __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
+ entry = (void **)(vbr + 0x310 + 0x94);
+
+ smpc_slave_stop(cpu);
+
+ *(void **)entry = (void *)start_secondary;
+
+ smpc_slave_start(cpu);
+}
+