summaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/saturn/smp.c
blob: 76460918c9cd9b2d916c20eb8b5a6158a969d61f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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);
}