initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / mips / pmc-sierra / yosemite / smp.c
blob08064f24b12bb16317315cae8d9b9fd415100f2a
1 /*
2 * Copyright 2003 PMC-Sierra
3 * Author: Manish Lachwani (lachwani@pmc-sierra.com)
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <linux/init.h>
21 #include <linux/delay.h>
22 #include <linux/smp.h>
23 #include <linux/kernel_stat.h>
25 #include <asm/mmu_context.h>
26 #include <asm/trace.h>
28 extern void asmlinkage smp_bootstrap(void);
31 * Send inter-processor interrupt
33 void core_send_ipi(int cpu, unsigned int action)
36 * Generate and INTMSG so that it can be sent over to the destination CPU
37 * The INTMSG will put the STATUS bits based on the action desired
39 switch(action) {
40 case SMP_RESCHEDULE_YOURSELF:
41 /* Do nothing */
42 break;
43 case SMP_CALL_FUNCTION:
44 if (cpu == 1)
45 *(volatile uint32_t *)(0xbb000a00) = 0x00610002;
46 else
47 *(volatile uint32_t *)(0xbb000a00) = 0x00610001;
48 break;
50 default:
51 panic("core_send_ipi \n");
56 * Mailbox interrupt to handle IPI
58 void jaguar_mailbox_irq(struct pt_regs *regs)
60 int cpu = smp_processor_id();
62 /* SMP_CALL_FUNCTION */
63 smp_call_function_interrupt();
66 extern atomic_t cpus_booted;
68 void __init start_secondary(void)
70 unsigned int cpu = smp_processor_id();
71 extern atomic_t smp_commenced;
73 if (current->processor != 1) {
74 printk("Impossible CPU %d \n", cpu);
75 current->processor = 1;
76 current->cpus_runnable = 1 << 1;
77 cpu = current->processor;
80 if (current->mm)
81 current->mm = NULL;
83 prom_init_secondary();
84 per_cpu_trap_init();
87 * XXX parity protection should be folded in here when it's converted
88 * to an option instead of something based on .cputype
90 pgd_current[cpu] = init_mm.pgd;
91 cpu_data[cpu].udelay_val = loops_per_jiffy;
92 prom_smp_finish();
93 CPUMASK_SETB(cpu_online_map, cpu);
94 atomic_inc(&cpus_booted);
95 __flush_cache_all();
97 printk("Slave cpu booted successfully \n");
98 *(volatile uint32_t *)(0xbb000a68) = 0x00000000;
99 *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
101 while (*(volatile uint32_t *)(0xbb000a68) != 0x00000000);
103 return cpu_idle();
106 void __init smp_boot_cpus(void)
108 int i;
109 int cur_cpu = 0;
111 smp_num_cpus = prom_setup_smp();
112 printk("Detected %d available CPUs \n", smp_num_cpus);
114 init_new_context(current, &init_mm);
115 current->processor = 0;
116 cpu_data[0].udelay_val = loops_per_jiffy;
117 cpu_data[0].asid_cache = ASID_FIRST_VERSION;
118 CPUMASK_CLRALL(cpu_online_map);
119 CPUMASK_SETB(cpu_online_map, 0);
120 atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */
121 init_idle();
123 __cpu_number_map[0] = 0;
124 __cpu_logical_map[0] = 0;
127 * This loop attempts to compensate for "holes" in the CPU
128 * numbering. It's overkill, but general.
130 for (i = 1; i < smp_num_cpus; ) {
131 struct task_struct *p;
132 struct pt_regs regs;
133 int retval;
134 printk("Starting CPU %d... \n", i);
136 /* Spawn a new process normally. Grab a pointer to
137 its task struct so we can mess with it */
138 do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
140 p = init_task.prev_task;
141 if (!p)
142 panic("failed fork for CPU %d", i);
144 /* This is current for the second processor */
145 p->processor = i;
146 p->cpus_runnable = 1 << i; /* we schedule the first task manually */
147 p->thread.reg31 = (unsigned long) start_secondary;
149 del_from_runqueue(p);
150 unhash_process(p);
151 init_tasks[i] = p;
153 __flush_cache_all();
155 do {
156 /* Iterate until we find a CPU that comes up */
157 cur_cpu++;
158 retval = prom_boot_secondary(cur_cpu,
159 (unsigned long)p + KERNEL_STACK_SIZE - 32,
160 (unsigned long)p);
162 } while (!retval && (cur_cpu < NR_CPUS));
163 if (retval) {
164 __cpu_number_map[cur_cpu] = i;
165 __cpu_logical_map[i] = cur_cpu;
166 i++;
167 } else {
168 panic("CPU discovery disaster");
172 /* Local semaphore to both the CPUs */
174 *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
175 while (*(volatile uint32_t *)(0xbb000a68) != 0x00000000);
177 smp_threads_ready = 1;