1/*
2 * arch/sh/boards/saturn/smp.c
3 *
4 * SMP support for the Sega Saturn.
5 *
6 * Copyright (c) 2002 Paul Mundt
7 *
8 * Released under the terms of the GNU GPL v2.0.
9 */
10#include <linux/kernel.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13
14#include <asm/saturn/smpc.h>
15
16extern void start_secondary(void);
17
18void __smp_send_ipi(unsigned int cpu, unsigned int action)
19{
20	/* Nothing here yet .. */
21}
22
23unsigned int __smp_probe_cpus(void)
24{
25	/*
26	 * This is just a straightforward master/slave configuration,
27	 * and probing isn't really supported..
28	 */
29	return 2;
30}
31
32/*
33 * We're only allowed to do byte-access to SMPC registers. In
34 * addition to which, we treat them as write-only, since
35 * reading from them will return undefined data.
36 */
37static inline void smpc_slave_stop(unsigned int cpu)
38{
39	smpc_barrier();
40	ctrl_outb(1, SMPC_STATUS);
41
42	ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND);
43	smpc_barrier();
44}
45
46static inline void smpc_slave_start(unsigned int cpu)
47{
48	ctrl_outb(1, SMPC_STATUS);
49	ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND);
50
51	smpc_barrier();
52}
53
54void __smp_slave_init(unsigned int cpu)
55{
56	register unsigned long vbr;
57	void **entry;
58
59	__asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr));
60	entry = (void **)(vbr + 0x310 + 0x94);
61
62	smpc_slave_stop(cpu);
63
64	*(void **)entry = (void *)start_secondary;
65
66	smpc_slave_start(cpu);
67}
68