1#include <linux/linkage.h>
2#include <linux/sched.h>
3
4#include <asm/pmon.h>
5#include <asm/titan_dep.h>
6#include <asm/time.h>
7
8#define LAUNCHSTACK_SIZE 256
9
10static __cpuinitdata DEFINE_SPINLOCK(launch_lock);
11
12static unsigned long secondary_sp __cpuinitdata;
13static unsigned long secondary_gp __cpuinitdata;
14
15static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
16 __attribute__((aligned(2 * sizeof(long))));
17
18static void __init prom_smp_bootstrap(void)
19{
20 local_irq_disable();
21
22 while (spin_is_locked(&launch_lock));
23
24 __asm__ __volatile__(
25 " move $sp, %0 \n"
26 " move $gp, %1 \n"
27 " j smp_bootstrap \n"
28 :
29 : "r" (secondary_sp), "r" (secondary_gp));
30}
31
32
33
34
35
36
37void __init prom_grab_secondary(void)
38{
39 spin_lock(&launch_lock);
40
41 pmon_cpustart(1, &prom_smp_bootstrap,
42 launchstack + LAUNCHSTACK_SIZE, 0);
43}
44
45void titan_mailbox_irq(void)
46{
47 int cpu = smp_processor_id();
48 unsigned long status;
49
50 switch (cpu) {
51 case 0:
52 status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
53 OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
54
55 if (status & 0x2)
56 smp_call_function_interrupt();
57 break;
58
59 case 1:
60 status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
61 OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
62
63 if (status & 0x2)
64 smp_call_function_interrupt();
65 break;
66 }
67}
68
69
70
71
72static void yos_send_ipi_single(int cpu, unsigned int action)
73{
74
75
76
77
78
79
80
81
82 switch (action) {
83 case SMP_RESCHEDULE_YOURSELF:
84 if (cpu == 1)
85 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
86 else
87 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
88 break;
89
90 case SMP_CALL_FUNCTION:
91 if (cpu == 1)
92 OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
93 else
94 OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
95 break;
96 }
97}
98
99static void yos_send_ipi_mask(cpumask_t mask, unsigned int action)
100{
101 unsigned int i;
102
103 for_each_cpu_mask(i, mask)
104 yos_send_ipi_single(i, action);
105}
106
107
108
109
110
111static void __cpuinit yos_init_secondary(void)
112{
113 set_c0_status(ST0_CO | ST0_IE | ST0_IM);
114}
115
116static void __cpuinit yos_smp_finish(void)
117{
118}
119
120
121static void yos_cpus_done(void)
122{
123}
124
125
126
127
128
129
130
131
132static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
133{
134 unsigned long gp = (unsigned long) task_thread_info(idle);
135 unsigned long sp = __KSTK_TOS(idle);
136
137 secondary_sp = sp;
138 secondary_gp = gp;
139
140 spin_unlock(&launch_lock);
141}
142
143
144
145
146
147
148
149static void __init yos_smp_setup(void)
150{
151 int i;
152
153 cpus_clear(phys_cpu_present_map);
154
155 for (i = 0; i < 2; i++) {
156 cpu_set(i, phys_cpu_present_map);
157 __cpu_number_map[i] = i;
158 __cpu_logical_map[i] = i;
159 }
160}
161
162static void __init yos_prepare_cpus(unsigned int max_cpus)
163{
164
165
166
167 if (cpus_weight(cpu_possible_map))
168 set_c0_status(STATUSF_IP5);
169}
170
171struct plat_smp_ops yos_smp_ops = {
172 .send_ipi_single = yos_send_ipi_single,
173 .send_ipi_mask = yos_send_ipi_mask,
174 .init_secondary = yos_init_secondary,
175 .smp_finish = yos_smp_finish,
176 .cpus_done = yos_cpus_done,
177 .boot_secondary = yos_boot_secondary,
178 .smp_setup = yos_smp_setup,
179 .prepare_cpus = yos_prepare_cpus,
180};
181