aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig2
-rw-r--r--arch/mips/Makefile14
-rw-r--r--arch/mips/sibyte/Kconfig10
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile5
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c476
-rw-r--r--arch/mips/sibyte/bcm1480/irq_handler.S165
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c136
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c110
-rw-r--r--arch/mips/sibyte/bcm1480/time.c138
-rw-r--r--arch/mips/sibyte/cfe/smp.c14
-rw-r--r--arch/mips/sibyte/swarm/setup.c28
11 files changed, 1093 insertions, 5 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index bafd7755380d..fdeffc81e17a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1429,7 +1429,7 @@ source "mm/Kconfig"
1429 1429
1430config SMP 1430config SMP
1431 bool "Multi-Processing support" 1431 bool "Multi-Processing support"
1432 depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP 1432 depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
1433 ---help--- 1433 ---help---
1434 This enables support for systems with more than one CPU. If you have 1434 This enables support for systems with more than one CPU. If you have
1435 a system with only one CPU, like most personal computers, say N. If 1435 a system with only one CPU, like most personal computers, say N. If
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 4d0645cb5725..92e16157734c 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -650,10 +650,20 @@ load-$(CONFIG_SGI_IP32) += 0xffffffff80004000
650# removed (as happens, even if they have __initcall/module_init) 650# removed (as happens, even if they have __initcall/module_init)
651# 651#
652core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ 652core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/
653cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte 653cflags-$(CONFIG_SIBYTE_BCM112X) += -Iinclude/asm-mips/mach-sibyte \
654 -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
654 655
655core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ 656core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/
656cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte 657cflags-$(CONFIG_SIBYTE_SB1250) += -Iinclude/asm-mips/mach-sibyte \
658 -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
659
660core-$(CONFIG_SIBYTE_BCM1x55) += arch/mips/sibyte/bcm1480/
661cflags-$(CONFIG_SIBYTE_BCM1x55) += -Iinclude/asm-mips/mach-sibyte \
662 -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
663
664core-$(CONFIG_SIBYTE_BCM1x80) += arch/mips/sibyte/bcm1480/
665cflags-$(CONFIG_SIBYTE_BCM1x80) += -Iinclude/asm-mips/mach-sibyte \
666 -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
657 667
658# 668#
659# Sibyte BCM91120x (Carmel) board 669# Sibyte BCM91120x (Carmel) board
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index 3618d61f004a..6a5a08f5e212 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -26,6 +26,16 @@ config SIBYTE_BCM112X
26 bool 26 bool
27 select SIBYTE_SB1xxx_SOC 27 select SIBYTE_SB1xxx_SOC
28 28
29config SIBYTE_BCM1x80
30 bool
31 select HW_HAS_PCI
32 select SIBYTE_SB1xxx_SOC
33
34config SIBYTE_BCM1x55
35 bool
36 select HW_HAS_PCI
37 select SIBYTE_SB1xxx_SOC
38
29config SIBYTE_SB1xxx_SOC 39config SIBYTE_SB1xxx_SOC
30 bool 40 bool
31 depends on EXPERIMENTAL 41 depends on EXPERIMENTAL
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
new file mode 100644
index 000000000000..538d5a51ae94
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -0,0 +1,5 @@
1obj-y := setup.o irq.o irq_handler.o time.o
2
3obj-$(CONFIG_SMP) += smp.o
4
5EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
new file mode 100644
index 000000000000..b2a1ba5d23df
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -0,0 +1,476 @@
1/*
2 * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18#include <linux/config.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/linkage.h>
22#include <linux/interrupt.h>
23#include <linux/spinlock.h>
24#include <linux/mm.h>
25#include <linux/slab.h>
26#include <linux/kernel_stat.h>
27
28#include <asm/errno.h>
29#include <asm/signal.h>
30#include <asm/system.h>
31#include <asm/ptrace.h>
32#include <asm/io.h>
33
34#include <asm/sibyte/bcm1480_regs.h>
35#include <asm/sibyte/bcm1480_int.h>
36#include <asm/sibyte/bcm1480_scd.h>
37
38#include <asm/sibyte/sb1250_uart.h>
39#include <asm/sibyte/sb1250.h>
40
41/*
42 * These are the routines that handle all the low level interrupt stuff.
43 * Actions handled here are: initialization of the interrupt map, requesting of
44 * interrupt lines by handlers, dispatching if interrupts to handlers, probing
45 * for interrupt lines
46 */
47
48
49#define shutdown_bcm1480_irq disable_bcm1480_irq
50static void end_bcm1480_irq(unsigned int irq);
51static void enable_bcm1480_irq(unsigned int irq);
52static void disable_bcm1480_irq(unsigned int irq);
53static unsigned int startup_bcm1480_irq(unsigned int irq);
54static void ack_bcm1480_irq(unsigned int irq);
55#ifdef CONFIG_SMP
56static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask);
57#endif
58
59#ifdef CONFIG_PCI
60extern unsigned long ht_eoi_space;
61#endif
62
63#ifdef CONFIG_KGDB
64#include <asm/gdb-stub.h>
65extern void breakpoint(void);
66static int kgdb_irq;
67#ifdef CONFIG_GDB_CONSOLE
68extern void register_gdb_console(void);
69#endif
70
71/* kgdb is on when configured. Pass "nokgdb" kernel arg to turn it off */
72static int kgdb_flag = 1;
73static int __init nokgdb(char *str)
74{
75 kgdb_flag = 0;
76 return 1;
77}
78__setup("nokgdb", nokgdb);
79
80/* Default to UART1 */
81int kgdb_port = 1;
82#ifdef CONFIG_SIBYTE_SB1250_DUART
83extern char sb1250_duart_present[];
84#endif
85#endif
86
87static struct hw_interrupt_type bcm1480_irq_type = {
88 .typename = "BCM1480-IMR",
89 .startup = startup_bcm1480_irq,
90 .shutdown = shutdown_bcm1480_irq,
91 .enable = enable_bcm1480_irq,
92 .disable = disable_bcm1480_irq,
93 .ack = ack_bcm1480_irq,
94 .end = end_bcm1480_irq,
95#ifdef CONFIG_SMP
96 .set_affinity = bcm1480_set_affinity
97#endif
98};
99
100/* Store the CPU id (not the logical number) */
101int bcm1480_irq_owner[BCM1480_NR_IRQS];
102
103DEFINE_SPINLOCK(bcm1480_imr_lock);
104
105void bcm1480_mask_irq(int cpu, int irq)
106{
107 unsigned long flags;
108 u64 cur_ints,hl_spacing;
109
110 spin_lock_irqsave(&bcm1480_imr_lock, flags);
111 hl_spacing = 0;
112 if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
113 hl_spacing = BCM1480_IMR_HL_SPACING;
114 irq -= BCM1480_NR_IRQS_HALF;
115 }
116 cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
117 cur_ints |= (((u64) 1) << irq);
118 ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
119 spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
120}
121
122void bcm1480_unmask_irq(int cpu, int irq)
123{
124 unsigned long flags;
125 u64 cur_ints,hl_spacing;
126
127 spin_lock_irqsave(&bcm1480_imr_lock, flags);
128 hl_spacing = 0;
129 if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
130 hl_spacing = BCM1480_IMR_HL_SPACING;
131 irq -= BCM1480_NR_IRQS_HALF;
132 }
133 cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
134 cur_ints &= ~(((u64) 1) << irq);
135 ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
136 spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
137}
138
139#ifdef CONFIG_SMP
140static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
141{
142 int i = 0, old_cpu, cpu, int_on;
143 u64 cur_ints;
144 irq_desc_t *desc = irq_desc + irq;
145 unsigned long flags;
146 unsigned int irq_dirty;
147
148 i = first_cpu(mask);
149 if (next_cpu(i, mask) <= NR_CPUS) {
150 printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
151 return;
152 }
153
154 /* Convert logical CPU to physical CPU */
155 cpu = cpu_logical_map(i);
156
157 /* Protect against other affinity changers and IMR manipulation */
158 spin_lock_irqsave(&desc->lock, flags);
159 spin_lock(&bcm1480_imr_lock);
160
161 /* Swizzle each CPU's IMR (but leave the IP selection alone) */
162 old_cpu = bcm1480_irq_owner[irq];
163 irq_dirty = irq;
164 if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
165 irq_dirty -= BCM1480_NR_IRQS_HALF;
166 }
167
168 int k;
169 for (k=0; k<2; k++) { /* Loop through high and low interrupt mask register */
170 cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
171 int_on = !(cur_ints & (((u64) 1) << irq_dirty));
172 if (int_on) {
173 /* If it was on, mask it */
174 cur_ints |= (((u64) 1) << irq_dirty);
175 ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
176 }
177 bcm1480_irq_owner[irq] = cpu;
178 if (int_on) {
179 /* unmask for the new CPU */
180 cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
181 cur_ints &= ~(((u64) 1) << irq_dirty);
182 ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
183 }
184 }
185 spin_unlock(&bcm1480_imr_lock);
186 spin_unlock_irqrestore(&desc->lock, flags);
187}
188#endif
189
190
191/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
192extern void bcm1480_irq_handler(void);
193
194/*****************************************************************************/
195
196static unsigned int startup_bcm1480_irq(unsigned int irq)
197{
198 bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
199
200 return 0; /* never anything pending */
201}
202
203
204static void disable_bcm1480_irq(unsigned int irq)
205{
206 bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
207}
208
209static void enable_bcm1480_irq(unsigned int irq)
210{
211 bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
212}
213
214
215static void ack_bcm1480_irq(unsigned int irq)
216{
217 u64 pending;
218 unsigned int irq_dirty;
219
220 /*
221 * If the interrupt was an HT interrupt, now is the time to
222 * clear it. NOTE: we assume the HT bridge was set up to
223 * deliver the interrupts to all CPUs (which makes affinity
224 * changing easier for us)
225 */
226 irq_dirty = irq;
227 if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
228 irq_dirty -= BCM1480_NR_IRQS_HALF;
229 }
230 int k;
231 for (k=0; k<2; k++) { /* Loop through high and low LDT interrupts */
232 pending = __raw_readq(IOADDR(A_BCM1480_IMR_REGISTER(bcm1480_irq_owner[irq],
233 R_BCM1480_IMR_LDT_INTERRUPT_H + (k*BCM1480_IMR_HL_SPACING))));
234 pending &= ((u64)1 << (irq_dirty));
235 if (pending) {
236#ifdef CONFIG_SMP
237 int i;
238 for (i=0; i<NR_CPUS; i++) {
239 /*
240 * Clear for all CPUs so an affinity switch
241 * doesn't find an old status
242 */
243 __raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(cpu_logical_map(i),
244 R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
245 }
246#else
247 __raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
248#endif
249
250 /*
251 * Generate EOI. For Pass 1 parts, EOI is a nop. For
252 * Pass 2, the LDT world may be edge-triggered, but
253 * this EOI shouldn't hurt. If they are
254 * level-sensitive, the EOI is required.
255 */
256#ifdef CONFIG_PCI
257 if (ht_eoi_space)
258 *(uint32_t *)(ht_eoi_space+(irq<<16)+(7<<2)) = 0;
259#endif
260 }
261 }
262 bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
263}
264
265
266static void end_bcm1480_irq(unsigned int irq)
267{
268 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
269 bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
270 }
271}
272
273
274void __init init_bcm1480_irqs(void)
275{
276 int i;
277
278 for (i = 0; i < NR_IRQS; i++) {
279 irq_desc[i].status = IRQ_DISABLED;
280 irq_desc[i].action = 0;
281 irq_desc[i].depth = 1;
282 if (i < BCM1480_NR_IRQS) {
283 irq_desc[i].handler = &bcm1480_irq_type;
284 bcm1480_irq_owner[i] = 0;
285 } else {
286 irq_desc[i].handler = &no_irq_type;
287 }
288 }
289}
290
291
292static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id,
293 struct pt_regs *regs)
294{
295 return IRQ_NONE;
296}
297
298static struct irqaction bcm1480_dummy_action = {
299 .handler = bcm1480_dummy_handler,
300 .flags = 0,
301 .mask = CPU_MASK_NONE,
302 .name = "bcm1480-private",
303 .next = NULL,
304 .dev_id = 0
305};
306
307int bcm1480_steal_irq(int irq)
308{
309 irq_desc_t *desc = irq_desc + irq;
310 unsigned long flags;
311 int retval = 0;
312
313 if (irq >= BCM1480_NR_IRQS)
314 return -EINVAL;
315
316 spin_lock_irqsave(&desc->lock,flags);
317 /* Don't allow sharing at all for these */
318 if (desc->action != NULL)
319 retval = -EBUSY;
320 else {
321 desc->action = &bcm1480_dummy_action;
322 desc->depth = 0;
323 }
324 spin_unlock_irqrestore(&desc->lock,flags);
325 return 0;
326}
327
328/*
329 * init_IRQ is called early in the boot sequence from init/main.c. It
330 * is responsible for setting up the interrupt mapper and installing the
331 * handler that will be responsible for dispatching interrupts to the
332 * "right" place.
333 */
334/*
335 * For now, map all interrupts to IP[2]. We could save
336 * some cycles by parceling out system interrupts to different
337 * IP lines, but keep it simple for bringup. We'll also direct
338 * all interrupts to a single CPU; we should probably route
339 * PCI and LDT to one cpu and everything else to the other
340 * to balance the load a bit.
341 *
342 * On the second cpu, everything is set to IP5, which is
343 * ignored, EXCEPT the mailbox interrupt. That one is
344 * set to IP[2] so it is handled. This is needed so we
345 * can do cross-cpu function calls, as requred by SMP
346 */
347
348#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
349#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
350#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
351#define IMR_IP5_VAL K_BCM1480_INT_MAP_I3
352#define IMR_IP6_VAL K_BCM1480_INT_MAP_I4
353
354void __init arch_init_irq(void)
355{
356
357 unsigned int i, cpu;
358 u64 tmp;
359 unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
360 STATUSF_IP1 | STATUSF_IP0;
361
362 /* Default everything to IP2 */
363 /* Start with _high registers which has no bit 0 interrupt source */
364 for (i = 1; i < BCM1480_NR_IRQS_HALF; i++) { /* was I0 */
365 for (cpu = 0; cpu < 4; cpu++) {
366 __raw_writeq(IMR_IP2_VAL,
367 IOADDR(A_BCM1480_IMR_REGISTER(cpu,
368 R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (i << 3)));
369 }
370 }
371
372 /* Now do _low registers */
373 for (i = 0; i < BCM1480_NR_IRQS_HALF; i++) {
374 for (cpu = 0; cpu < 4; cpu++) {
375 __raw_writeq(IMR_IP2_VAL,
376 IOADDR(A_BCM1480_IMR_REGISTER(cpu,
377 R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) + (i << 3)));
378 }
379 }
380
381 init_bcm1480_irqs();
382
383 /*
384 * Map the high 16 bits of mailbox_0 registers to IP[3], for
385 * inter-cpu messages
386 */
387 /* Was I1 */
388 for (cpu = 0; cpu < 4; cpu++) {
389 __raw_writeq(IMR_IP3_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
390 (K_BCM1480_INT_MBOX_0_0 << 3)));
391 }
392
393
394 /* Clear the mailboxes. The firmware may leave them dirty */
395 for (cpu = 0; cpu < 4; cpu++) {
396 __raw_writeq(0xffffffffffffffffULL,
397 IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_0_CLR_CPU)));
398 __raw_writeq(0xffffffffffffffffULL,
399 IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_1_CLR_CPU)));
400 }
401
402
403 /* Mask everything except the high 16 bit of mailbox_0 registers for all cpus */
404 tmp = ~((u64) 0) ^ ( (((u64) 1) << K_BCM1480_INT_MBOX_0_0));
405 for (cpu = 0; cpu < 4; cpu++) {
406 __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_H)));
407 }
408 tmp = ~((u64) 0);
409 for (cpu = 0; cpu < 4; cpu++) {
410 __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L)));
411 }
412
413 bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0);
414
415 /*
416 * Note that the timer interrupts are also mapped, but this is
417 * done in bcm1480_time_init(). Also, the profiling driver
418 * does its own management of IP7.
419 */
420
421#ifdef CONFIG_KGDB
422 imask |= STATUSF_IP6;
423#endif
424 /* Enable necessary IPs, disable the rest */
425 change_c0_status(ST0_IM, imask);
426 set_except_vector(0, bcm1480_irq_handler);
427
428#ifdef CONFIG_KGDB
429 if (kgdb_flag) {
430 kgdb_irq = K_BCM1480_INT_UART_0 + kgdb_port;
431
432#ifdef CONFIG_SIBYTE_SB1250_DUART
433 sb1250_duart_present[kgdb_port] = 0;
434#endif
435 /* Setup uart 1 settings, mapper */
436 /* QQQ FIXME */
437 __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
438
439 bcm1480_steal_irq(kgdb_irq);
440 __raw_writeq(IMR_IP6_VAL,
441 IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
442 (kgdb_irq<<3));
443 bcm1480_unmask_irq(0, kgdb_irq);
444
445#ifdef CONFIG_GDB_CONSOLE
446 register_gdb_console();
447#endif
448 prom_printf("Waiting for GDB on UART port %d\n", kgdb_port);
449 set_debug_traps();
450 breakpoint();
451 }
452#endif
453}
454
455#ifdef CONFIG_KGDB
456
457#include <linux/delay.h>
458
459#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
460#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
461
462void bcm1480_kgdb_interrupt(struct pt_regs *regs)
463{
464 /*
465 * Clear break-change status (allow some time for the remote
466 * host to stop the break, since we would see another
467 * interrupt on the end-of-break too)
468 */
469 kstat.irqs[smp_processor_id()][kgdb_irq]++;
470 mdelay(500);
471 duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
472 M_DUART_RX_EN | M_DUART_TX_EN);
473 set_async_breakpoint(&regs->cp0_epc);
474}
475
476#endif /* CONFIG_KGDB */
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
new file mode 100644
index 000000000000..408db88d050f
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq_handler.S
@@ -0,0 +1,165 @@
1/*
2 * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19/*
20 * bcm1480_irq_handler() is the routine that is actually called when an
21 * interrupt occurs. It is installed as the exception vector handler in
22 * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
23 *
24 * In the handle we figure out which interrupts need handling, and use that
25 * to call the dispatcher, which will take care of actually calling
26 * registered handlers
27 *
28 * Note that we take care of all raised interrupts in one go at the handler.
29 * This is more BSDish than the Indy code, and also, IMHO, more sane.
30 */
31#include <linux/config.h>
32
33#include <asm/addrspace.h>
34#include <asm/asm.h>
35#include <asm/mipsregs.h>
36#include <asm/regdef.h>
37#include <asm/stackframe.h>
38#include <asm/sibyte/sb1250_defs.h>
39#include <asm/sibyte/bcm1480_regs.h>
40#include <asm/sibyte/bcm1480_int.h>
41
42/*
43 * What a pain. We have to be really careful saving the upper 32 bits of any
44 * register across function calls if we don't want them trashed--since were
45 * running in -o32, the calling routing never saves the full 64 bits of a
46 * register across a function call. Being the interrupt handler, we're
47 * guaranteed that interrupts are disabled during this code so we don't have
48 * to worry about random interrupts blasting the high 32 bits.
49 */
50
51 .text
52 .set push
53 .set noreorder
54 .set noat
55 .set mips64
56 #.set mips4
57 .align 5
58 NESTED(bcm1480_irq_handler, PT_SIZE, sp)
59 SAVE_ALL
60 CLI
61
62#ifdef CONFIG_SIBYTE_BCM1480_PROF
63 /* Set compare to count to silence count/compare timer interrupts */
64 mfc0 t1, CP0_COUNT
65 mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
66#endif
67 /* Read cause */
68 mfc0 s0, CP0_CAUSE
69
70#ifdef CONFIG_SIBYTE_BCM1480_PROF
71 /* Cpu performance counter interrupt is routed to IP[7] */
72 andi t1, s0, CAUSEF_IP7
73 beqz t1, 0f
74 srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
75 and t1, t1, 0x4 /* mask to get just BD bit */
76#ifdef CONFIG_MIPS64
77 dmfc0 a0, CP0_EPC
78 daddu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
79#else
80 mfc0 a0, CP0_EPC
81 addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
82#endif
83 jal sbprof_cpu_intr
84 nop
85 j ret_from_irq
86 nop
870:
88#endif
89
90 /* Timer interrupt is routed to IP[4] */
91 andi t1, s0, CAUSEF_IP4
92 beqz t1, 1f
93 nop
94 jal bcm1480_timer_interrupt
95 move a0, sp /* Pass the registers along */
96 j ret_from_irq
97 nop /* delay slot */
981:
99
100#ifdef CONFIG_SMP
101 /* Mailbox interrupt is routed to IP[3] */
102 andi t1, s0, CAUSEF_IP3
103 beqz t1, 2f
104 nop
105 jal bcm1480_mailbox_interrupt
106 move a0, sp
107 j ret_from_irq
108 nop /* delay slot */
1092:
110#endif
111
112#ifdef CONFIG_KGDB
113 /* KGDB (uart 1) interrupt is routed to IP[6] */
114 andi t1, s0, CAUSEF_IP6
115 beqz t1, 3f
116 nop /* delay slot */
117 jal bcm1480_kgdb_interrupt
118 move a0, sp
119 j ret_from_irq
120 nop /* delay slot */
1213:
122#endif
123
124 and t1, s0, CAUSEF_IP2
125 beqz t1, 9f
126 nop
127
128 /*
129 * Default...we've hit an IP[2] interrupt, which means we've got
130 * to check the 1480 interrupt registers to figure out what to do
131 * Need to detect which CPU we're on, now that smp_affinity is
132 * supported.
133 */
134 PTR_LA v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
135#ifdef CONFIG_SMP
136 lw t1, TI_CPU($28)
137 sll t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
138 addu v0, v0, t1
139#endif
140
141 /* Read IP[2] status (get both high and low halves of status) */
142 ld s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
143 ld s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
144
145 move s2, zero /* intr number */
146 li s3, 64
147
148 beqz s0, 9f /* No interrupts. Return. */
149 move a1, sp
150
151 xori s4, s0, 1 /* if s0 (_H) == 1, it's a low intr, so... */
152 movz s2, s3, s4 /* start the intr number at 64, and */
153 movz s0, s1, s4 /* look at the low status value. */
154
155 dclz s1, s0 /* Find the next interrupt. */
156 dsubu a0, zero, s1
157 daddiu a0, a0, 63
158 jal do_IRQ
159 daddu a0, a0, s2
160
1619: j ret_from_irq
162 nop
163
164 .set pop
165 END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
new file mode 100644
index 000000000000..d90a0b87874c
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18#include <linux/config.h>
19#include <linux/kernel.h>
20#include <linux/reboot.h>
21#include <linux/string.h>
22
23#include <asm/bootinfo.h>
24#include <asm/mipsregs.h>
25#include <asm/io.h>
26#include <asm/sibyte/sb1250.h>
27
28#include <asm/sibyte/bcm1480_regs.h>
29#include <asm/sibyte/bcm1480_scd.h>
30#include <asm/sibyte/sb1250_scd.h>
31
32unsigned int sb1_pass;
33unsigned int soc_pass;
34unsigned int soc_type;
35unsigned int periph_rev;
36unsigned int zbbus_mhz;
37
38static unsigned int part_type;
39
40static char *soc_str;
41static char *pass_str;
42
43static inline int setup_bcm1x80_bcm1x55(void);
44
45/* Setup code likely to be common to all SiByte platforms */
46
47static inline int sys_rev_decode(void)
48{
49 int ret = 0;
50
51 switch (soc_type) {
52 case K_SYS_SOC_TYPE_BCM1x80:
53 if (part_type == K_SYS_PART_BCM1480)
54 soc_str = "BCM1480";
55 else if (part_type == K_SYS_PART_BCM1280)
56 soc_str = "BCM1280";
57 else
58 soc_str = "BCM1x80";
59 ret = setup_bcm1x80_bcm1x55();
60 break;
61
62 case K_SYS_SOC_TYPE_BCM1x55:
63 if (part_type == K_SYS_PART_BCM1455)
64 soc_str = "BCM1455";
65 else if (part_type == K_SYS_PART_BCM1255)
66 soc_str = "BCM1255";
67 else
68 soc_str = "BCM1x55";
69 ret = setup_bcm1x80_bcm1x55();
70 break;
71
72 default:
73 prom_printf("Unknown part type %x\n", part_type);
74 ret = 1;
75 break;
76 }
77 return ret;
78}
79
80static inline int setup_bcm1x80_bcm1x55(void)
81{
82 int ret = 0;
83
84 switch (soc_pass) {
85 case K_SYS_REVISION_BCM1480_S0:
86 periph_rev = 1;
87 pass_str = "S0 (pass1)";
88 break;
89 case K_SYS_REVISION_BCM1480_A1:
90 periph_rev = 1;
91 pass_str = "A1 (pass1)";
92 break;
93 case K_SYS_REVISION_BCM1480_A2:
94 periph_rev = 1;
95 pass_str = "A2 (pass1)";
96 break;
97 case K_SYS_REVISION_BCM1480_A3:
98 periph_rev = 1;
99 pass_str = "A3 (pass1)";
100 break;
101 case K_SYS_REVISION_BCM1480_B0:
102 periph_rev = 1;
103 pass_str = "B0 (pass2)";
104 break;
105 default:
106 prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
107 periph_rev = 1;
108 pass_str = "Unknown Revision";
109 break;
110 }
111 return ret;
112}
113
114void bcm1480_setup(void)
115{
116 uint64_t sys_rev;
117 int plldiv;
118
119 sb1_pass = read_c0_prid() & 0xff;
120 sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
121 soc_type = SYS_SOC_TYPE(sys_rev);
122 part_type = G_SYS_PART(sys_rev);
123 soc_pass = G_SYS_REVISION(sys_rev);
124
125 if (sys_rev_decode()) {
126 prom_printf("Restart after failure to identify SiByte chip\n");
127 machine_restart(NULL);
128 }
129
130 plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
131 zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
132
133 prom_printf("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
134 soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
135 prom_printf("Board type: %s\n", get_system_type());
136}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
new file mode 100644
index 000000000000..584a4b33faac
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2001,2002,2004 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#include <linux/init.h>
20#include <linux/delay.h>
21#include <linux/smp.h>
22#include <linux/kernel_stat.h>
23
24#include <asm/mmu_context.h>
25#include <asm/io.h>
26#include <asm/sibyte/sb1250.h>
27#include <asm/sibyte/bcm1480_regs.h>
28#include <asm/sibyte/bcm1480_int.h>
29
30extern void smp_call_function_interrupt(void);
31
32/*
33 * These are routines for dealing with the bcm1480 smp capabilities
34 * independent of board/firmware
35 */
36
37static void *mailbox_0_set_regs[] = {
38 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
39 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
40 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
41 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
42};
43
44static void *mailbox_0_clear_regs[] = {
45 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
46 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
47 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
48 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
49};
50
51static void *mailbox_0_regs[] = {
52 IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
53 IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
54 IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
55 IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
56};
57
58/*
59 * SMP init and finish on secondary CPUs
60 */
61void bcm1480_smp_init(void)
62{
63 unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
64 STATUSF_IP1 | STATUSF_IP0;
65
66 /* Set interrupt mask, but don't enable */
67 change_c0_status(ST0_IM, imask);
68}
69
70void bcm1480_smp_finish(void)
71{
72 extern void bcm1480_time_init(void);
73 bcm1480_time_init();
74 local_irq_enable();
75}
76
77/*
78 * These are routines for dealing with the sb1250 smp capabilities
79 * independent of board/firmware
80 */
81
82/*
83 * Simple enough; everything is set up, so just poke the appropriate mailbox
84 * register, and we should be set
85 */
86void core_send_ipi(int cpu, unsigned int action)
87{
88 __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
89}
90
91void bcm1480_mailbox_interrupt(struct pt_regs *regs)
92{
93 int cpu = smp_processor_id();
94 unsigned int action;
95
96 kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
97 /* Load the mailbox register to figure out what we're supposed to do */
98 action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
99
100 /* Clear the mailbox to clear the interrupt */
101 __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
102
103 /*
104 * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
105 * interrupt will do the reschedule for us
106 */
107
108 if (action & SMP_CALL_FUNCTION)
109 smp_call_function_interrupt();
110}
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
new file mode 100644
index 000000000000..e545752695a1
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -0,0 +1,138 @@
1/*
2 * Copyright (C) 2000,2001,2004 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19/*
20 * These are routines to set up and handle interrupts from the
21 * bcm1480 general purpose timer 0. We're using the timer as a
22 * system clock, so we set it up to run at 100 Hz. On every
23 * interrupt, we update our idea of what the time of day is,
24 * then call do_timer() in the architecture-independent kernel
25 * code to do general bookkeeping (e.g. update jiffies, run
26 * bottom halves, etc.)
27 */
28#include <linux/config.h>
29#include <linux/interrupt.h>
30#include <linux/sched.h>
31#include <linux/spinlock.h>
32#include <linux/kernel_stat.h>
33
34#include <asm/irq.h>
35#include <asm/ptrace.h>
36#include <asm/addrspace.h>
37#include <asm/time.h>
38#include <asm/io.h>
39
40#include <asm/sibyte/bcm1480_regs.h>
41#include <asm/sibyte/sb1250_regs.h>
42#include <asm/sibyte/bcm1480_int.h>
43#include <asm/sibyte/bcm1480_scd.h>
44
45#include <asm/sibyte/sb1250.h>
46
47
48#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
49#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
50#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
51
52extern int bcm1480_steal_irq(int irq);
53
54void bcm1480_time_init(void)
55{
56 int cpu = smp_processor_id();
57 int irq = K_BCM1480_INT_TIMER_0+cpu;
58
59 /* Only have 4 general purpose timers */
60 if (cpu > 3) {
61 BUG();
62 }
63
64 if (!cpu) {
65 /* Use our own gettimeoffset() routine */
66 do_gettimeoffset = bcm1480_gettimeoffset;
67 }
68
69 bcm1480_mask_irq(cpu, irq);
70
71 /* Map the timer interrupt to ip[4] of this cpu */
72 __raw_writeq(IMR_IP4_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H)
73 + (irq<<3)));
74
75 /* the general purpose timer ticks at 1 Mhz independent of the rest of the system */
76 /* Disable the timer and set up the count */
77 __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
78 __raw_writeq(
79#ifndef CONFIG_SIMULATION
80 1000000/HZ
81#else
82 50000/HZ
83#endif
84 , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
85
86 /* Set the timer running */
87 __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
88 IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
89
90 bcm1480_unmask_irq(cpu, irq);
91 bcm1480_steal_irq(irq);
92 /*
93 * This interrupt is "special" in that it doesn't use the request_irq
94 * way to hook the irq line. The timer interrupt is initialized early
95 * enough to make this a major pain, and it's also firing enough to
96 * warrant a bit of special case code. bcm1480_timer_interrupt is
97 * called directly from irq_handler.S when IP[4] is set during an
98 * interrupt
99 */
100}
101
102#include <asm/sibyte/sb1250.h>
103
104void bcm1480_timer_interrupt(struct pt_regs *regs)
105{
106 int cpu = smp_processor_id();
107 int irq = K_BCM1480_INT_TIMER_0+cpu;
108
109 /* Reset the timer */
110 __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
111 IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
112
113 /*
114 * CPU 0 handles the global timer interrupt job
115 */
116 if (cpu == 0) {
117 ll_timer_interrupt(irq, regs);
118 }
119
120 /*
121 * every CPU should do profiling and process accouting
122 */
123 ll_local_timer_interrupt(irq, regs);
124}
125
126/*
127 * We use our own do_gettimeoffset() instead of the generic one,
128 * because the generic one does not work for SMP case.
129 * In addition, since we use general timer 0 for system time,
130 * we can get accurate intra-jiffy offset without calibration.
131 */
132unsigned long bcm1480_gettimeoffset(void)
133{
134 unsigned long count =
135 __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
136
137 return 1000000/HZ - count;
138}
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
index e44ce1a9eea9..e8485124b8fc 100644
--- a/arch/mips/sibyte/cfe/smp.c
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -70,8 +70,15 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
70 */ 70 */
71void prom_init_secondary(void) 71void prom_init_secondary(void)
72{ 72{
73#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
74 extern void bcm1480_smp_init(void);
75 bcm1480_smp_init();
76#elif defined(CONFIG_SIBYTE_SB1250)
73 extern void sb1250_smp_init(void); 77 extern void sb1250_smp_init(void);
74 sb1250_smp_init(); 78 sb1250_smp_init();
79#else
80#error invalid SMP configuration
81#endif
75} 82}
76 83
77/* 84/*
@@ -80,8 +87,15 @@ void prom_init_secondary(void)
80 */ 87 */
81void prom_smp_finish(void) 88void prom_smp_finish(void)
82{ 89{
90#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
91 extern void bcm1480_smp_finish(void);
92 bcm1480_smp_finish();
93#elif defined(CONFIG_SIBYTE_SB1250)
83 extern void sb1250_smp_finish(void); 94 extern void sb1250_smp_finish(void);
84 sb1250_smp_finish(); 95 sb1250_smp_finish();
96#else
97#error invalid SMP configuration
98#endif
85} 99}
86 100
87/* 101/*
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index f8963de1bbf4..b614ca0ddb69 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation 2 * Copyright (C) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
3 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 3 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -39,11 +39,23 @@
39#include <asm/time.h> 39#include <asm/time.h>
40#include <asm/traps.h> 40#include <asm/traps.h>
41#include <asm/sibyte/sb1250.h> 41#include <asm/sibyte/sb1250.h>
42#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
43#include <asm/sibyte/bcm1480_regs.h>
44#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
42#include <asm/sibyte/sb1250_regs.h> 45#include <asm/sibyte/sb1250_regs.h>
46#else
47#error invalid SiByte board configuation
48#endif
43#include <asm/sibyte/sb1250_genbus.h> 49#include <asm/sibyte/sb1250_genbus.h>
44#include <asm/sibyte/board.h> 50#include <asm/sibyte/board.h>
45 51
52#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
53extern void bcm1480_setup(void);
54#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
46extern void sb1250_setup(void); 55extern void sb1250_setup(void);
56#else
57#error invalid SiByte board configuation
58#endif
47 59
48extern int xicor_probe(void); 60extern int xicor_probe(void);
49extern int xicor_set_time(unsigned long); 61extern int xicor_set_time(unsigned long);
@@ -66,7 +78,13 @@ void __init swarm_timer_setup(struct irqaction *irq)
66 */ 78 */
67 79
68 /* We only need to setup the generic timer */ 80 /* We only need to setup the generic timer */
69 sb1250_time_init(); 81#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
82 bcm1480_time_init();
83#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
84 sb1250_time_init();
85#else
86#error invalid SiByte board configuation
87#endif
70} 88}
71 89
72int swarm_be_handler(struct pt_regs *regs, int is_fixup) 90int swarm_be_handler(struct pt_regs *regs, int is_fixup)
@@ -81,7 +99,13 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
81 99
82void __init plat_setup(void) 100void __init plat_setup(void)
83{ 101{
102#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
103 bcm1480_setup();
104#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
84 sb1250_setup(); 105 sb1250_setup();
106#else
107#error invalid SiByte board configuation
108#endif
85 109
86 panic_timeout = 5; /* For debug. */ 110 panic_timeout = 5; /* For debug. */
87 111