Blame view

arch/mips/mti-malta/malta-int.c 20.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  /*
   * Carsten Langgaard, carstenl@mips.com
   * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
   * Copyright (C) 2001 Ralf Baechle
   *
   *  This program is free software; you can distribute it and/or modify it
   *  under the terms of the GNU General Public License (Version 2) as
   *  published by the Free Software Foundation.
   *
   *  This program is distributed in the hope it will be useful, but WITHOUT
   *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   *  for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
   *
   * Routines for generic manipulation of the interrupts found on the MIPS
   * Malta board.
   * The interrupt controller is located in the South Bridge a PIIX4 device
   * with two internal 82C95 interrupt controllers.
   */
  #include <linux/init.h>
  #include <linux/irq.h>
  #include <linux/sched.h>
631330f58   Ralf Baechle   MIPS: Build fix -...
27
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/interrupt.h>
54bf038e2   Dmitri Vorobiev   [MIPS] Malta: inc...
29
  #include <linux/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/kernel_stat.h>
25b8ac3ba   Ahmed S. Darwish   [MIPS] Use ARRAY_...
31
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include <linux/random.h>
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
33
  #include <asm/traps.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <asm/i8259.h>
e01402b11   Ralf Baechle   More AP / SP bits...
35
  #include <asm/irq_cpu.h>
ba38cdf94   Ralf Baechle   [MIPS] Malta: Fix...
36
  #include <asm/irq_regs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
  #include <asm/mips-boards/malta.h>
  #include <asm/mips-boards/maltaint.h>
  #include <asm/mips-boards/piix4.h>
  #include <asm/gt64120.h>
  #include <asm/mips-boards/generic.h>
  #include <asm/mips-boards/msc01_pci.h>
e01402b11   Ralf Baechle   More AP / SP bits...
43
  #include <asm/msc01_ic.h>
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
44
45
46
47
48
49
50
51
  #include <asm/gic.h>
  #include <asm/gcmpregs.h>
  
  int gcmp_present = -1;
  int gic_present;
  static unsigned long _msc01_biu_base;
  static unsigned long _gcmp_base;
  static unsigned int ipi_map[NR_CPUS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

a963dc70a   Ralf Baechle   MIPS: Malta: Conv...
53
  static DEFINE_RAW_SPINLOCK(mips_irq_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
  
  static inline int mips_pcibios_iack(void)
  {
  	int irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
  
  	/*
  	 * Determine highest priority pending interrupt by performing
  	 * a PCI Interrupt Acknowledge cycle.
  	 */
b72c05262   Chris Dearman   [MIPS] Malta: Fix...
63
64
65
66
67
  	switch (mips_revision_sconid) {
  	case MIPS_REVISION_SCON_SOCIT:
  	case MIPS_REVISION_SCON_ROCIT:
  	case MIPS_REVISION_SCON_SOCITSC:
  	case MIPS_REVISION_SCON_SOCITSCP:
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
68
  		MSC_READ(MSC01_PCI_IACK, irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  		irq &= 0xff;
  		break;
b72c05262   Chris Dearman   [MIPS] Malta: Fix...
71
  	case MIPS_REVISION_SCON_GT64120:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
  		irq = GT_READ(GT_PCI0_IACK_OFS);
  		irq &= 0xff;
  		break;
b72c05262   Chris Dearman   [MIPS] Malta: Fix...
75
  	case MIPS_REVISION_SCON_BONITO:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
82
83
  		/* The following will generate a PCI IACK cycle on the
  		 * Bonito controller. It's a little bit kludgy, but it
  		 * was the easiest way to implement it in hardware at
  		 * the given time.
  		 */
  		BONITO_PCIMAP_CFG = 0x20000;
  
  		/* Flush Bonito register block */
6be63bbbd   Ralf Baechle   MIPS: Malta: Fix ...
84
  		(void) BONITO_PCIMAP_CFG;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  		iob();    /* sync */
accfd35a4   Chris Dearman   MIPS: MTI: Fix ac...
86
  		irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
90
91
  		iob();    /* sync */
  		irq &= 0xff;
  		BONITO_PCIMAP_CFG = 0;
  		break;
  	default:
8216d348e   Dmitri Vorobiev   [MIPS] Malta: use...
92
93
  		printk(KERN_WARNING "Unknown system controller.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
  		return -1;
  	}
  	return irq;
  }
e01402b11   Ralf Baechle   More AP / SP bits...
98
  static inline int get_int(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  {
  	unsigned long flags;
e01402b11   Ralf Baechle   More AP / SP bits...
101
  	int irq;
a963dc70a   Ralf Baechle   MIPS: Malta: Conv...
102
  	raw_spin_lock_irqsave(&mips_irq_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103

e01402b11   Ralf Baechle   More AP / SP bits...
104
  	irq = mips_pcibios_iack();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  
  	/*
479a0e3e0   Ralf Baechle   Support for CoreF...
107
108
109
  	 * The only way we can decide if an interrupt is spurious
  	 * is by checking the 8259 registers.  This needs a spinlock
  	 * on an SMP system,  so leave it up to the generic code...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111

a963dc70a   Ralf Baechle   MIPS: Malta: Conv...
112
  	raw_spin_unlock_irqrestore(&mips_irq_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

e01402b11   Ralf Baechle   More AP / SP bits...
114
  	return irq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  }
937a80157   Ralf Baechle   [MIPS] Complete f...
116
  static void malta_hw0_irqdispatch(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
  {
  	int irq;
e01402b11   Ralf Baechle   More AP / SP bits...
119
  	irq = get_int();
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
120
  	if (irq < 0) {
cd80d5485   Dmitri Vorobiev   [MIPS] Malta: fix...
121
122
  		/* interrupt has already been cleared */
  		return;
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
123
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

937a80157   Ralf Baechle   [MIPS] Complete f...
125
  	do_IRQ(MALTA_INT_BASE + irq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  }
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
127
128
129
130
131
132
133
134
135
136
  static void malta_ipi_irqdispatch(void)
  {
  	int irq;
  
  	irq = gic_get_int();
  	if (irq < 0)
  		return;  /* interrupt has already been cleared */
  
  	do_IRQ(MIPS_GIC_IRQ_BASE + irq);
  }
937a80157   Ralf Baechle   [MIPS] Complete f...
137
  static void corehi_irqdispatch(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  {
937a80157   Ralf Baechle   [MIPS] Complete f...
139
  	unsigned int intedge, intsteer, pcicmd, pcibadaddr;
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
140
  	unsigned int pcimstat, intisr, inten, intpol;
21a151d8c   Ralf Baechle   [MIPS] checkfiles...
141
  	unsigned int intrcause, datalo, datahi;
ba38cdf94   Ralf Baechle   [MIPS] Malta: Fix...
142
  	struct pt_regs *regs = get_irq_regs();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

8216d348e   Dmitri Vorobiev   [MIPS] Malta: use...
144
145
146
147
148
  	printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!
  ");
  	printk(KERN_EMERG "epc   : %08lx
  Status: %08lx
  "
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
149
150
151
152
153
  			"Cause : %08lx
  badVaddr : %08lx
  ",
  			regs->cp0_epc, regs->cp0_status,
  			regs->cp0_cause, regs->cp0_badvaddr);
e01402b11   Ralf Baechle   More AP / SP bits...
154
155
156
157
158
  
  	/* Read all the registers and then print them as there is a
  	   problem with interspersed printk's upsetting the Bonito controller.
  	   Do it for the others too.
  	*/
b72c05262   Chris Dearman   [MIPS] Malta: Fix...
159
  	switch (mips_revision_sconid) {
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
160
  	case MIPS_REVISION_SCON_SOCIT:
b72c05262   Chris Dearman   [MIPS] Malta: Fix...
161
162
163
  	case MIPS_REVISION_SCON_ROCIT:
  	case MIPS_REVISION_SCON_SOCITSC:
  	case MIPS_REVISION_SCON_SOCITSCP:
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
164
165
166
167
168
169
  		ll_msc_irq();
  		break;
  	case MIPS_REVISION_SCON_GT64120:
  		intrcause = GT_READ(GT_INTRCAUSE_OFS);
  		datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
  		datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
8216d348e   Dmitri Vorobiev   [MIPS] Malta: use...
170
171
172
173
174
  		printk(KERN_EMERG "GT_INTRCAUSE = %08x
  ", intrcause);
  		printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x
  ",
  				datahi, datalo);
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
175
176
177
178
179
180
181
182
183
184
  		break;
  	case MIPS_REVISION_SCON_BONITO:
  		pcibadaddr = BONITO_PCIBADADDR;
  		pcimstat = BONITO_PCIMSTAT;
  		intisr = BONITO_INTISR;
  		inten = BONITO_INTEN;
  		intpol = BONITO_INTPOL;
  		intedge = BONITO_INTEDGE;
  		intsteer = BONITO_INTSTEER;
  		pcicmd = BONITO_PCICMD;
8216d348e   Dmitri Vorobiev   [MIPS] Malta: use...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  		printk(KERN_EMERG "BONITO_INTISR = %08x
  ", intisr);
  		printk(KERN_EMERG "BONITO_INTEN = %08x
  ", inten);
  		printk(KERN_EMERG "BONITO_INTPOL = %08x
  ", intpol);
  		printk(KERN_EMERG "BONITO_INTEDGE = %08x
  ", intedge);
  		printk(KERN_EMERG "BONITO_INTSTEER = %08x
  ", intsteer);
  		printk(KERN_EMERG "BONITO_PCICMD = %08x
  ", pcicmd);
  		printk(KERN_EMERG "BONITO_PCIBADADDR = %08x
  ", pcibadaddr);
  		printk(KERN_EMERG "BONITO_PCIMSTAT = %08x
  ", pcimstat);
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
201
202
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203

af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
204
  	die("CoreHi interrupt", regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  }
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
206
207
  static inline int clz(unsigned long x)
  {
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
208
  	__asm__(
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	"	.set	push					
  "
  	"	.set	mips32					
  "
  	"	clz	%0, %1					
  "
  	"	.set	pop					
  "
  	: "=r" (x)
  	: "r" (x));
  
  	return x;
  }
  
  /*
   * Version of ffs that only looks at bits 12..15.
   */
  static inline unsigned int irq_ffs(unsigned int pending)
  {
  #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
  	return -clz(pending) + 31 - CAUSEB_IP;
  #else
  	unsigned int a0 = 7;
  	unsigned int t0;
0118c3ca9   Ralf Baechle   [MIPS] Malta: Fix...
233
  	t0 = pending & 0xf000;
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
234
235
236
  	t0 = t0 < 1;
  	t0 = t0 << 2;
  	a0 = a0 - t0;
0118c3ca9   Ralf Baechle   [MIPS] Malta: Fix...
237
  	pending = pending << t0;
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
238

0118c3ca9   Ralf Baechle   [MIPS] Malta: Fix...
239
  	t0 = pending & 0xc000;
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
240
241
242
  	t0 = t0 < 1;
  	t0 = t0 << 1;
  	a0 = a0 - t0;
0118c3ca9   Ralf Baechle   [MIPS] Malta: Fix...
243
  	pending = pending << t0;
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
244

0118c3ca9   Ralf Baechle   [MIPS] Malta: Fix...
245
  	t0 = pending & 0x8000;
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
246
  	t0 = t0 < 1;
ae9cef0b7   Dmitri Vorobiev   [MIPS] Malta: Use...
247
  	/* t0 = t0 << 2; */
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
248
  	a0 = a0 - t0;
ae9cef0b7   Dmitri Vorobiev   [MIPS] Malta: Use...
249
  	/* pending = pending << t0; */
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  
  	return a0;
  #endif
  }
  
  /*
   * IRQs on the Malta board look basically (barring software IRQs which we
   * don't use at all and all external interrupt sources are combined together
   * on hardware interrupt 0 (MIPS IRQ 2)) like:
   *
   *	MIPS IRQ	Source
   *      --------        ------
   *             0	Software (ignored)
   *             1        Software (ignored)
   *             2        Combined hardware interrupt (hw0)
   *             3        Hardware (ignored)
   *             4        Hardware (ignored)
   *             5        Hardware (ignored)
   *             6        Hardware (ignored)
   *             7        R4k timer (what we use)
   *
   * We handle the IRQ according to _our_ priority which is:
   *
   * Highest ----     R4k Timer
   * Lowest  ----     Combined hardware interrupt
   *
   * then we just return, if multiple IRQs are pending then we will just take
   * another exception, big deal.
   */
937a80157   Ralf Baechle   [MIPS] Complete f...
279
  asmlinkage void plat_irq_dispatch(void)
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
280
281
282
283
284
285
286
  {
  	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
  	int irq;
  
  	irq = irq_ffs(pending);
  
  	if (irq == MIPSCPU_INT_I8259A)
937a80157   Ralf Baechle   [MIPS] Complete f...
287
  		malta_hw0_irqdispatch();
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
288
289
  	else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
  		malta_ipi_irqdispatch();
48d480b0b   Ralf Baechle   [MIPS] Malta: Fix...
290
  	else if (irq >= 0)
3b1d4ed53   Ralf Baechle   [MIPS] Don't drag...
291
  		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
292
  	else
937a80157   Ralf Baechle   [MIPS] Complete f...
293
  		spurious_interrupt();
e4ac58afd   Ralf Baechle   [MIPS] Rewrite al...
294
  }
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  #ifdef CONFIG_MIPS_MT_SMP
  
  
  #define GIC_MIPS_CPU_IPI_RESCHED_IRQ	3
  #define GIC_MIPS_CPU_IPI_CALL_IRQ	4
  
  #define MIPS_CPU_IPI_RESCHED_IRQ 0	/* SW int 0 for resched */
  #define C_RESCHED C_SW0
  #define MIPS_CPU_IPI_CALL_IRQ 1		/* SW int 1 for resched */
  #define C_CALL C_SW1
  static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
  
  static void ipi_resched_dispatch(void)
  {
  	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
  }
  
  static void ipi_call_dispatch(void)
  {
  	do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
  }
  
  static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
  {
184748cc5   Peter Zijlstra   sched: Provide sc...
319
  	scheduler_ipi();
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
320
321
322
323
324
325
326
327
328
329
330
331
  	return IRQ_HANDLED;
  }
  
  static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
  {
  	smp_call_function_interrupt();
  
  	return IRQ_HANDLED;
  }
  
  static struct irqaction irq_resched = {
  	.handler	= ipi_resched_interrupt,
8b5690f88   Yong Zhang   MIPS: irq: Remove...
332
  	.flags		= IRQF_PERCPU,
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
333
334
335
336
337
  	.name		= "IPI_resched"
  };
  
  static struct irqaction irq_call = {
  	.handler	= ipi_call_interrupt,
8b5690f88   Yong Zhang   MIPS: irq: Remove...
338
  	.flags		= IRQF_PERCPU,
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
339
340
  	.name		= "IPI_call"
  };
008ee96f1   Raghu Gandham   [PATCH] MIPS: SMT...
341
  #endif /* CONFIG_MIPS_MT_SMP */
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
342
343
344
345
346
  
  static int gic_resched_int_base;
  static int gic_call_int_base;
  #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
  #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
0365070f0   Tim Anderson   MIPS: CMP: activa...
347
348
349
350
351
352
353
354
355
356
  
  unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
  {
  	return GIC_CALL_INT(cpu);
  }
  
  unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
  {
  	return GIC_RESCHED_INT(cpu);
  }
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
357

e01402b11   Ralf Baechle   More AP / SP bits...
358
359
  static struct irqaction i8259irq = {
  	.handler = no_action,
5a4a4ad85   Wu Zhangjin   MIPS: Mark cascad...
360
361
  	.name = "XT-PIC cascade",
  	.flags = IRQF_NO_THREAD,
e01402b11   Ralf Baechle   More AP / SP bits...
362
363
364
365
  };
  
  static struct irqaction corehi_irqaction = {
  	.handler = no_action,
5a4a4ad85   Wu Zhangjin   MIPS: Mark cascad...
366
367
  	.name = "CoreHi",
  	.flags = IRQF_NO_THREAD,
e01402b11   Ralf Baechle   More AP / SP bits...
368
  };
b57c1913b   Dmitri Vorobiev   [MIPS] malta_int....
369
  static msc_irqmap_t __initdata msc_irqmap[] = {
e01402b11   Ralf Baechle   More AP / SP bits...
370
371
372
  	{MSC01C_INT_TMR,		MSC01_IRQ_EDGE, 0},
  	{MSC01C_INT_PCI,		MSC01_IRQ_LEVEL, 0},
  };
b57c1913b   Dmitri Vorobiev   [MIPS] malta_int....
373
  static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
e01402b11   Ralf Baechle   More AP / SP bits...
374

b57c1913b   Dmitri Vorobiev   [MIPS] malta_int....
375
  static msc_irqmap_t __initdata msc_eicirqmap[] = {
e01402b11   Ralf Baechle   More AP / SP bits...
376
377
378
379
380
381
382
383
384
385
386
  	{MSC01E_INT_SW0,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_SW1,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_I8259A,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_SMI,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_COREHI,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_CORELO,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_TMR,		MSC01_IRQ_EDGE, 0},
  	{MSC01E_INT_PCI,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_PERFCTR,		MSC01_IRQ_LEVEL, 0},
  	{MSC01E_INT_CPUCTR,		MSC01_IRQ_LEVEL, 0}
  };
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
387

b57c1913b   Dmitri Vorobiev   [MIPS] malta_int....
388
  static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
e01402b11   Ralf Baechle   More AP / SP bits...
389

39b8d5254   Ralf Baechle   [MIPS] Add suppor...
390
391
392
393
394
  /*
   * This GIC specific tabular array defines the association between External
   * Interrupts and CPUs/Core Interrupts. The nature of the External
   * Interrupts is also defined here - polarity/trigger.
   */
7098f7482   Chris Dearman   MIPS: GIC: Random...
395
396
  
  #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
863cb9bad   Ralf Baechle   MIPS: GIC: Remove...
397
  #define X GIC_UNUSED
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
398
  static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
7098f7482   Chris Dearman   MIPS: GIC: Random...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  	{ X, X,		   X,		X,		0 },
  	{ X, X,		   X,	 	X,		0 },
  	{ X, X,		   X,		X,		0 },
  	{ 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ X, X,		   X,		X,		0 },
  	{ X, X,		   X,		X,		0 },
  	{ 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ 0, GIC_CPU_NMI,  GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
  	{ X, X,		   X,		X,	        0 },
  	/* The remainder of this table is initialised by fill_ipi_map */
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
416
  };
863cb9bad   Ralf Baechle   MIPS: GIC: Remove...
417
  #undef X
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
418
419
420
421
  
  /*
   * GCMP needs to be detected before any SMP initialisation
   */
47b178bb6   Tim Anderson   MIPS: CMP: Move g...
422
  int __init gcmp_probe(unsigned long addr, unsigned long size)
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
423
  {
05cf20790   Jaidev Patwardhan   MIPS: GCMP: Avoid...
424
425
426
427
  	if (mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) {
  		gcmp_present = 0;
  		return gcmp_present;
  	}
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
428
429
430
431
432
433
434
435
  	if (gcmp_present >= 0)
  		return gcmp_present;
  
  	_gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
  	_msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
  	gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
  
  	if (gcmp_present)
7098f7482   Chris Dearman   MIPS: GIC: Random...
436
437
  		pr_debug("GCMP present
  ");
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
438
439
  	return gcmp_present;
  }
7098f7482   Chris Dearman   MIPS: GIC: Random...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  /* Return the number of IOCU's present */
  int __init gcmp_niocu(void)
  {
    return gcmp_present ?
      (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
      0;
  }
  
  /* Set GCMP region attributes */
  void __init gcmp_setregion(int region, unsigned long base,
  			   unsigned long mask, int type)
  {
  	GCMPGCBn(CMxBASE, region) = base;
  	GCMPGCBn(CMxMASK, region) = mask | type;
  }
7afed6a6c   Dmitri Vorobiev   [MIPS] A few clea...
455
  #if defined(CONFIG_MIPS_MT_SMP)
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
456
457
458
  static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
  {
  	int intr = baseintr + cpu;
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
459
460
461
462
  	gic_intr_map[intr].cpunum = cpu;
  	gic_intr_map[intr].pin = cpupin;
  	gic_intr_map[intr].polarity = GIC_POL_POS;
  	gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
7098f7482   Chris Dearman   MIPS: GIC: Random...
463
  	gic_intr_map[intr].flags = GIC_FLAG_IPI;
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
464
465
  	ipi_map[cpu] |= (1 << (cpupin + 2));
  }
7afed6a6c   Dmitri Vorobiev   [MIPS] A few clea...
466
  static void __init fill_ipi_map(void)
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
467
  {
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
468
  	int cpu;
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
469

a214cef9a   Tim Anderson   MIPS: CMP: Extend...
470
471
472
  	for (cpu = 0; cpu < NR_CPUS; cpu++) {
  		fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
  		fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
473
474
  	}
  }
7afed6a6c   Dmitri Vorobiev   [MIPS] A few clea...
475
  #endif
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
476

7098f7482   Chris Dearman   MIPS: GIC: Random...
477
478
479
  void __init arch_init_ipiirq(int irq, struct irqaction *action)
  {
  	setup_irq(irq, action);
e4ec7989b   Thomas Gleixner   MIPS: Convert the...
480
  	irq_set_handler(irq, handle_percpu_irq);
7098f7482   Chris Dearman   MIPS: GIC: Random...
481
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  void __init arch_init_irq(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  	init_i8259_irqs();
e01402b11   Ralf Baechle   More AP / SP bits...
485
486
  
  	if (!cpu_has_veic)
97dcb82de   Atsushi Nemoto   [MIPS] Define MIP...
487
  		mips_cpu_irq_init();
e01402b11   Ralf Baechle   More AP / SP bits...
488

39b8d5254   Ralf Baechle   [MIPS] Add suppor...
489
490
491
492
  	if (gcmp_present)  {
  		GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
  		gic_present = 1;
  	} else {
05cf20790   Jaidev Patwardhan   MIPS: GCMP: Avoid...
493
494
495
496
497
498
499
500
  		if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
  			_msc01_biu_base = (unsigned long)
  					ioremap_nocache(MSC01_BIU_REG_BASE,
  						MSC01_BIU_ADDRSPACE_SZ);
  			gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
  					MSC01_SC_CFG_GICPRES_MSK) >>
  					MSC01_SC_CFG_GICPRES_SHF;
  		}
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
501
502
  	}
  	if (gic_present)
7098f7482   Chris Dearman   MIPS: GIC: Random...
503
504
  		pr_debug("GIC present
  ");
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
505

af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
506
507
508
  	switch (mips_revision_sconid) {
  	case MIPS_REVISION_SCON_SOCIT:
  	case MIPS_REVISION_SCON_ROCIT:
d725cf381   Chris Dearman   [MIPS] MT: Reenab...
509
  		if (cpu_has_veic)
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
510
511
512
  			init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
  					MSC01E_INT_BASE, msc_eicirqmap,
  					msc_nr_eicirqs);
d725cf381   Chris Dearman   [MIPS] MT: Reenab...
513
  		else
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
514
515
516
  			init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
  					MSC01C_INT_BASE, msc_irqmap,
  					msc_nr_irqs);
d725cf381   Chris Dearman   [MIPS] MT: Reenab...
517
  		break;
af825586c   Dmitri Vorobiev   [MIPS] Malta: use...
518
519
  	case MIPS_REVISION_SCON_SOCITSC:
  	case MIPS_REVISION_SCON_SOCITSCP:
e01402b11   Ralf Baechle   More AP / SP bits...
520
  		if (cpu_has_veic)
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
521
522
523
  			init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
  					MSC01E_INT_BASE, msc_eicirqmap,
  					msc_nr_eicirqs);
e01402b11   Ralf Baechle   More AP / SP bits...
524
  		else
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
525
526
527
  			init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
  					MSC01C_INT_BASE, msc_irqmap,
  					msc_nr_irqs);
e01402b11   Ralf Baechle   More AP / SP bits...
528
529
530
  	}
  
  	if (cpu_has_veic) {
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
531
532
533
534
  		set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch);
  		set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
  		setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq);
  		setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction);
52b3fc04b   Dmitri Vorobiev   [MIPS] Malta: els...
535
  	} else if (cpu_has_vint) {
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
536
537
  		set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
  		set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch);
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
538
  #ifdef CONFIG_MIPS_MT_SMTC
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
539
  		setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq,
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
540
  			(0x100 << MIPSCPU_INT_I8259A));
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
541
  		setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
542
  			&corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
c3a005f4b   Kevin D. Kissell   [MIPS] SMTC: Safe...
543
544
545
546
547
548
549
550
551
552
553
554
  		/*
  		 * Temporary hack to ensure that the subsidiary device
  		 * interrupts coing in via the i8259A, but associated
  		 * with low IRQ numbers, will restore the Status.IM
  		 * value associated with the i8259A.
  		 */
  		{
  			int i;
  
  			for (i = 0; i < 16; i++)
  				irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A);
  		}
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
555
  #else /* Not SMTC */
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
556
  		setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
557
558
  		setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
  						&corehi_irqaction);
41c594ab6   Ralf Baechle   [MIPS] MT: Improv...
559
  #endif /* CONFIG_MIPS_MT_SMTC */
52b3fc04b   Dmitri Vorobiev   [MIPS] Malta: els...
560
  	} else {
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
561
  		setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
f80714966   Dmitri Vorobiev   [MIPS] Malta: fix...
562
563
  		setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
  						&corehi_irqaction);
e01402b11   Ralf Baechle   More AP / SP bits...
564
  	}
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
565

39b8d5254   Ralf Baechle   [MIPS] Add suppor...
566
567
568
  	if (gic_present) {
  		/* FIXME */
  		int i;
7098f7482   Chris Dearman   MIPS: GIC: Random...
569
  #if defined(CONFIG_MIPS_MT_SMP)
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
570
571
  		gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
  		gic_resched_int_base = gic_call_int_base - NR_CPUS;
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
572
  		fill_ipi_map();
7098f7482   Chris Dearman   MIPS: GIC: Random...
573
574
575
  #endif
  		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
  				ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
576
577
578
579
580
581
582
583
  		if (!gcmp_present) {
  			/* Enable the GIC */
  			i = REG(_msc01_biu_base, MSC01_SC_CFG);
  			REG(_msc01_biu_base, MSC01_SC_CFG) =
  				(i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
  			pr_debug("GIC Enabled
  ");
  		}
7098f7482   Chris Dearman   MIPS: GIC: Random...
584
  #if defined(CONFIG_MIPS_MT_SMP)
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
  		/* set up ipi interrupts */
  		if (cpu_has_vint) {
  			set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
  			set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
  		}
  		/* Argh.. this really needs sorting out.. */
  		printk("CPU%d: status register was %08x
  ", smp_processor_id(), read_c0_status());
  		write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
  		printk("CPU%d: status register now %08x
  ", smp_processor_id(), read_c0_status());
  		write_c0_status(0x1100dc00);
  		printk("CPU%d: status register frc %08x
  ", smp_processor_id(), read_c0_status());
a214cef9a   Tim Anderson   MIPS: CMP: Extend...
599
  		for (i = 0; i < NR_CPUS; i++) {
7098f7482   Chris Dearman   MIPS: GIC: Random...
600
601
602
603
  			arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
  					 GIC_RESCHED_INT(i), &irq_resched);
  			arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
  					 GIC_CALL_INT(i), &irq_call);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
604
  		}
7098f7482   Chris Dearman   MIPS: GIC: Random...
605
  #endif
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
606
  	} else {
7098f7482   Chris Dearman   MIPS: GIC: Random...
607
  #if defined(CONFIG_MIPS_MT_SMP)
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  		/* set up ipi interrupts */
  		if (cpu_has_veic) {
  			set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
  			set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
  			cpu_ipi_resched_irq = MSC01E_INT_SW0;
  			cpu_ipi_call_irq = MSC01E_INT_SW1;
  		} else {
  			if (cpu_has_vint) {
  				set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
  				set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
  			}
  			cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
  			cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
  		}
7098f7482   Chris Dearman   MIPS: GIC: Random...
622
623
  		arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
  		arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
624
  #endif
7098f7482   Chris Dearman   MIPS: GIC: Random...
625
  	}
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
  }
  
  void malta_be_init(void)
  {
  	if (gcmp_present) {
  		/* Could change CM error mask register */
  	}
  }
  
  
  static char *tr[8] = {
  	"mem",	"gcr",	"gic",	"mmio",
  	"0x04",	"0x05",	"0x06",	"0x07"
  };
  
  static char *mcmd[32] = {
  	[0x00] = "0x00",
  	[0x01] = "Legacy Write",
  	[0x02] = "Legacy Read",
  	[0x03] = "0x03",
  	[0x04] = "0x04",
  	[0x05] = "0x05",
  	[0x06] = "0x06",
  	[0x07] = "0x07",
  	[0x08] = "Coherent Read Own",
  	[0x09] = "Coherent Read Share",
  	[0x0a] = "Coherent Read Discard",
  	[0x0b] = "Coherent Ready Share Always",
  	[0x0c] = "Coherent Upgrade",
  	[0x0d] = "Coherent Writeback",
  	[0x0e] = "0x0e",
  	[0x0f] = "0x0f",
  	[0x10] = "Coherent Copyback",
  	[0x11] = "Coherent Copyback Invalidate",
  	[0x12] = "Coherent Invalidate",
  	[0x13] = "Coherent Write Invalidate",
  	[0x14] = "Coherent Completion Sync",
  	[0x15] = "0x15",
  	[0x16] = "0x16",
  	[0x17] = "0x17",
  	[0x18] = "0x18",
  	[0x19] = "0x19",
  	[0x1a] = "0x1a",
  	[0x1b] = "0x1b",
  	[0x1c] = "0x1c",
  	[0x1d] = "0x1d",
  	[0x1e] = "0x1e",
  	[0x1f] = "0x1f"
  };
  
  static char *core[8] = {
  	"Invalid/OK", 	"Invalid/Data",
  	"Shared/OK",	"Shared/Data",
  	"Modified/OK",	"Modified/Data",
  	"Exclusive/OK",	"Exclusive/Data"
  };
  
  static char *causes[32] = {
  	"None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
  	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
  	"0x08", "0x09", "0x0a", "0x0b",
  	"0x0c", "0x0d", "0x0e", "0x0f",
  	"0x10", "0x11", "0x12", "0x13",
  	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
  	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
  	"0x1c", "0x1d", "0x1e", "0x1f"
  };
  
  int malta_be_handler(struct pt_regs *regs, int is_fixup)
  {
  	/* This duplicates the handling in do_be which seems wrong */
  	int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
  
  	if (gcmp_present) {
  		unsigned long cm_error = GCMPGCB(GCMEC);
  		unsigned long cm_addr = GCMPGCB(GCMEA);
  		unsigned long cm_other = GCMPGCB(GCMEO);
  		unsigned long cause, ocause;
  		char buf[256];
  
  		cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
  		if (cause != 0) {
  			cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
  			if (cause < 16) {
  				unsigned long cca_bits = (cm_error >> 15) & 7;
  				unsigned long tr_bits = (cm_error >> 12) & 7;
  				unsigned long mcmd_bits = (cm_error >> 7) & 0x1f;
  				unsigned long stag_bits = (cm_error >> 3) & 15;
  				unsigned long sport_bits = (cm_error >> 0) & 7;
  
  				snprintf(buf, sizeof(buf),
  					 "CCA=%lu TR=%s MCmd=%s STag=%lu "
  					 "SPort=%lu
  ",
  					 cca_bits, tr[tr_bits], mcmd[mcmd_bits],
  					 stag_bits, sport_bits);
  			} else {
  				/* glob state & sresp together */
  				unsigned long c3_bits = (cm_error >> 18) & 7;
  				unsigned long c2_bits = (cm_error >> 15) & 7;
  				unsigned long c1_bits = (cm_error >> 12) & 7;
  				unsigned long c0_bits = (cm_error >> 9) & 7;
  				unsigned long sc_bit = (cm_error >> 8) & 1;
  				unsigned long mcmd_bits = (cm_error >> 3) & 0x1f;
  				unsigned long sport_bits = (cm_error >> 0) & 7;
  				snprintf(buf, sizeof(buf),
  					 "C3=%s C2=%s C1=%s C0=%s SC=%s "
  					 "MCmd=%s SPort=%lu
  ",
  					 core[c3_bits], core[c2_bits],
  					 core[c1_bits], core[c0_bits],
  					 sc_bit ? "True" : "False",
  					 mcmd[mcmd_bits], sport_bits);
  			}
  
  			ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
  				 GCMP_GCB_GMEO_ERROR_2ND_SHF;
  
  			printk("CM_ERROR=%08lx %s <%s>
  ", cm_error,
  			       causes[cause], buf);
  			printk("CM_ADDR =%08lx
  ", cm_addr);
  			printk("CM_OTHER=%08lx %s
  ", cm_other, causes[ocause]);
  
  			/* reprime cause register */
  			GCMPGCB(GCMEC) = 0;
  		}
  	}
  
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
  }