blob: 59a3fa5ce4e84f6a6a7dc7d78a1cc4ca8e921530 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
4 * Copyright (C) 2001 Ralf Baechle
Deng-Cheng Zhu13361132013-10-30 15:52:10 -05005 * Copyright (C) 2013 Imagination Technologies Ltd.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
7 * This program is free software; you can distribute it and/or modify it
8 * under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * Routines for generic manipulation of the interrupts found on the MIPS
21 * Malta board.
22 * The interrupt controller is located in the South Bridge a PIIX4 device
23 * with two internal 82C95 interrupt controllers.
24 */
25#include <linux/init.h>
26#include <linux/irq.h>
27#include <linux/sched.h>
Ralf Baechle631330f2009-06-19 14:05:26 +010028#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/interrupt.h>
Dmitri Vorobiev54bf0382008-01-24 19:52:49 +030030#include <linux/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/kernel_stat.h>
Ahmed S. Darwish25b8ac32007-02-05 04:42:11 +020032#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/random.h>
34
Ralf Baechle39b8d522008-04-28 17:14:26 +010035#include <asm/traps.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <asm/i8259.h>
Ralf Baechlee01402b2005-07-14 15:57:16 +000037#include <asm/irq_cpu.h>
Ralf Baechleba38cdf2006-10-15 09:17:43 +010038#include <asm/irq_regs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <asm/mips-boards/malta.h>
40#include <asm/mips-boards/maltaint.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <asm/gt64120.h>
42#include <asm/mips-boards/generic.h>
43#include <asm/mips-boards/msc01_pci.h>
Ralf Baechlee01402b2005-07-14 15:57:16 +000044#include <asm/msc01_ic.h>
Ralf Baechle39b8d522008-04-28 17:14:26 +010045#include <asm/gic.h>
46#include <asm/gcmpregs.h>
David Howellsb81947c2012-03-28 18:30:02 +010047#include <asm/setup.h>
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050048#include <asm/rtlx.h>
Ralf Baechle39b8d522008-04-28 17:14:26 +010049
50int gcmp_present = -1;
Ralf Baechle39b8d522008-04-28 17:14:26 +010051static unsigned long _msc01_biu_base;
52static unsigned long _gcmp_base;
53static unsigned int ipi_map[NR_CPUS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Ralf Baechlea963dc72010-02-27 12:53:32 +010055static DEFINE_RAW_SPINLOCK(mips_irq_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57static inline int mips_pcibios_iack(void)
58{
59 int irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61 /*
62 * Determine highest priority pending interrupt by performing
63 * a PCI Interrupt Acknowledge cycle.
64 */
Chris Dearmanb72c0522007-04-27 15:58:41 +010065 switch (mips_revision_sconid) {
66 case MIPS_REVISION_SCON_SOCIT:
67 case MIPS_REVISION_SCON_ROCIT:
68 case MIPS_REVISION_SCON_SOCITSC:
69 case MIPS_REVISION_SCON_SOCITSCP:
Dmitri Vorobievaf825582008-01-24 19:52:45 +030070 MSC_READ(MSC01_PCI_IACK, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 irq &= 0xff;
72 break;
Chris Dearmanb72c0522007-04-27 15:58:41 +010073 case MIPS_REVISION_SCON_GT64120:
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 irq = GT_READ(GT_PCI0_IACK_OFS);
75 irq &= 0xff;
76 break;
Chris Dearmanb72c0522007-04-27 15:58:41 +010077 case MIPS_REVISION_SCON_BONITO:
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 /* The following will generate a PCI IACK cycle on the
79 * Bonito controller. It's a little bit kludgy, but it
80 * was the easiest way to implement it in hardware at
81 * the given time.
82 */
83 BONITO_PCIMAP_CFG = 0x20000;
84
85 /* Flush Bonito register block */
Ralf Baechle6be63bb2011-03-29 11:48:22 +020086 (void) BONITO_PCIMAP_CFG;
Ralf Baechle70342282013-01-22 12:59:30 +010087 iob(); /* sync */
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
Chris Dearmanaccfd352009-07-10 01:53:54 -070089 irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
Ralf Baechle70342282013-01-22 12:59:30 +010090 iob(); /* sync */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 irq &= 0xff;
92 BONITO_PCIMAP_CFG = 0;
93 break;
94 default:
Dmitri Vorobiev8216d342008-01-24 19:52:42 +030095 printk(KERN_WARNING "Unknown system controller.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 return -1;
97 }
98 return irq;
99}
100
Ralf Baechlee01402b2005-07-14 15:57:16 +0000101static inline int get_int(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
103 unsigned long flags;
Ralf Baechlee01402b2005-07-14 15:57:16 +0000104 int irq;
Ralf Baechlea963dc72010-02-27 12:53:32 +0100105 raw_spin_lock_irqsave(&mips_irq_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Ralf Baechlee01402b2005-07-14 15:57:16 +0000107 irq = mips_pcibios_iack();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 /*
Ralf Baechle479a0e32005-08-16 15:44:06 +0000110 * The only way we can decide if an interrupt is spurious
111 * is by checking the 8259 registers. This needs a spinlock
112 * on an SMP system, so leave it up to the generic code...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Ralf Baechlea963dc72010-02-27 12:53:32 +0100115 raw_spin_unlock_irqrestore(&mips_irq_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Ralf Baechlee01402b2005-07-14 15:57:16 +0000117 return irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118}
119
Ralf Baechle937a8012006-10-07 19:44:33 +0100120static void malta_hw0_irqdispatch(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
122 int irq;
123
Ralf Baechlee01402b2005-07-14 15:57:16 +0000124 irq = get_int();
Ralf Baechle41c594a2006-04-05 09:45:45 +0100125 if (irq < 0) {
Dmitri Vorobievcd80d542008-01-24 19:52:54 +0300126 /* interrupt has already been cleared */
127 return;
Ralf Baechle41c594a2006-04-05 09:45:45 +0100128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Ralf Baechle937a8012006-10-07 19:44:33 +0100130 do_IRQ(MALTA_INT_BASE + irq);
Deng-Cheng Zhu13361132013-10-30 15:52:10 -0500131
132#ifdef MIPS_VPE_APSP_API
133 if (aprp_hook)
134 aprp_hook();
135#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136}
137
Ralf Baechle39b8d522008-04-28 17:14:26 +0100138static void malta_ipi_irqdispatch(void)
139{
140 int irq;
141
Raghu Gandham0ab2b7d2013-04-10 16:30:12 -0500142 if (gic_compare_int())
143 do_IRQ(MIPS_GIC_IRQ_BASE);
144
Ralf Baechle39b8d522008-04-28 17:14:26 +0100145 irq = gic_get_int();
146 if (irq < 0)
Ralf Baechle70342282013-01-22 12:59:30 +0100147 return; /* interrupt has already been cleared */
Ralf Baechle39b8d522008-04-28 17:14:26 +0100148
149 do_IRQ(MIPS_GIC_IRQ_BASE + irq);
150}
151
Ralf Baechle937a8012006-10-07 19:44:33 +0100152static void corehi_irqdispatch(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
Ralf Baechle937a8012006-10-07 19:44:33 +0100154 unsigned int intedge, intsteer, pcicmd, pcibadaddr;
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300155 unsigned int pcimstat, intisr, inten, intpol;
Ralf Baechle21a151d2007-10-11 23:46:15 +0100156 unsigned int intrcause, datalo, datahi;
Ralf Baechleba38cdf2006-10-15 09:17:43 +0100157 struct pt_regs *regs = get_irq_regs();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Dmitri Vorobiev8216d342008-01-24 19:52:42 +0300159 printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!\n");
Ralf Baechle70342282013-01-22 12:59:30 +0100160 printk(KERN_EMERG "epc : %08lx\nStatus: %08lx\n"
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300161 "Cause : %08lx\nbadVaddr : %08lx\n",
162 regs->cp0_epc, regs->cp0_status,
163 regs->cp0_cause, regs->cp0_badvaddr);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000164
165 /* Read all the registers and then print them as there is a
166 problem with interspersed printk's upsetting the Bonito controller.
167 Do it for the others too.
168 */
169
Chris Dearmanb72c0522007-04-27 15:58:41 +0100170 switch (mips_revision_sconid) {
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300171 case MIPS_REVISION_SCON_SOCIT:
Chris Dearmanb72c0522007-04-27 15:58:41 +0100172 case MIPS_REVISION_SCON_ROCIT:
173 case MIPS_REVISION_SCON_SOCITSC:
174 case MIPS_REVISION_SCON_SOCITSCP:
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300175 ll_msc_irq();
176 break;
177 case MIPS_REVISION_SCON_GT64120:
178 intrcause = GT_READ(GT_INTRCAUSE_OFS);
179 datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
180 datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
Dmitri Vorobiev8216d342008-01-24 19:52:42 +0300181 printk(KERN_EMERG "GT_INTRCAUSE = %08x\n", intrcause);
182 printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x\n",
183 datahi, datalo);
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300184 break;
185 case MIPS_REVISION_SCON_BONITO:
186 pcibadaddr = BONITO_PCIBADADDR;
187 pcimstat = BONITO_PCIMSTAT;
188 intisr = BONITO_INTISR;
189 inten = BONITO_INTEN;
190 intpol = BONITO_INTPOL;
191 intedge = BONITO_INTEDGE;
192 intsteer = BONITO_INTSTEER;
193 pcicmd = BONITO_PCICMD;
Dmitri Vorobiev8216d342008-01-24 19:52:42 +0300194 printk(KERN_EMERG "BONITO_INTISR = %08x\n", intisr);
195 printk(KERN_EMERG "BONITO_INTEN = %08x\n", inten);
196 printk(KERN_EMERG "BONITO_INTPOL = %08x\n", intpol);
197 printk(KERN_EMERG "BONITO_INTEDGE = %08x\n", intedge);
198 printk(KERN_EMERG "BONITO_INTSTEER = %08x\n", intsteer);
199 printk(KERN_EMERG "BONITO_PCICMD = %08x\n", pcicmd);
200 printk(KERN_EMERG "BONITO_PCIBADADDR = %08x\n", pcibadaddr);
201 printk(KERN_EMERG "BONITO_PCIMSTAT = %08x\n", pcimstat);
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300202 break;
203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300205 die("CoreHi interrupt", regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100208static inline int clz(unsigned long x)
209{
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100210 __asm__(
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100211 " .set push \n"
212 " .set mips32 \n"
213 " clz %0, %1 \n"
214 " .set pop \n"
215 : "=r" (x)
216 : "r" (x));
217
218 return x;
219}
220
221/*
222 * Version of ffs that only looks at bits 12..15.
223 */
224static inline unsigned int irq_ffs(unsigned int pending)
225{
226#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
227 return -clz(pending) + 31 - CAUSEB_IP;
228#else
229 unsigned int a0 = 7;
230 unsigned int t0;
231
Ralf Baechle0118c3c2006-06-05 11:54:41 +0100232 t0 = pending & 0xf000;
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100233 t0 = t0 < 1;
234 t0 = t0 << 2;
235 a0 = a0 - t0;
Ralf Baechle0118c3c2006-06-05 11:54:41 +0100236 pending = pending << t0;
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100237
Ralf Baechle0118c3c2006-06-05 11:54:41 +0100238 t0 = pending & 0xc000;
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100239 t0 = t0 < 1;
240 t0 = t0 << 1;
241 a0 = a0 - t0;
Ralf Baechle0118c3c2006-06-05 11:54:41 +0100242 pending = pending << t0;
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100243
Ralf Baechle0118c3c2006-06-05 11:54:41 +0100244 t0 = pending & 0x8000;
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100245 t0 = t0 < 1;
Dmitri Vorobievae9cef02008-01-24 19:52:52 +0300246 /* t0 = t0 << 2; */
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100247 a0 = a0 - t0;
Dmitri Vorobievae9cef02008-01-24 19:52:52 +0300248 /* pending = pending << t0; */
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100249
250 return a0;
251#endif
252}
253
254/*
255 * IRQs on the Malta board look basically (barring software IRQs which we
256 * don't use at all and all external interrupt sources are combined together
257 * on hardware interrupt 0 (MIPS IRQ 2)) like:
258 *
259 * MIPS IRQ Source
Ralf Baechle70342282013-01-22 12:59:30 +0100260 * -------- ------
261 * 0 Software (ignored)
262 * 1 Software (ignored)
263 * 2 Combined hardware interrupt (hw0)
264 * 3 Hardware (ignored)
265 * 4 Hardware (ignored)
266 * 5 Hardware (ignored)
267 * 6 Hardware (ignored)
268 * 7 R4k timer (what we use)
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100269 *
270 * We handle the IRQ according to _our_ priority which is:
271 *
Ralf Baechle70342282013-01-22 12:59:30 +0100272 * Highest ---- R4k Timer
273 * Lowest ---- Combined hardware interrupt
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100274 *
275 * then we just return, if multiple IRQs are pending then we will just take
276 * another exception, big deal.
277 */
278
Ralf Baechle937a8012006-10-07 19:44:33 +0100279asmlinkage void plat_irq_dispatch(void)
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100280{
281 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
282 int irq;
283
Ralf Baechlee376fdf2012-09-17 01:23:21 +0200284 if (unlikely(!pending)) {
285 spurious_interrupt();
286 return;
287 }
288
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100289 irq = irq_ffs(pending);
290
291 if (irq == MIPSCPU_INT_I8259A)
Ralf Baechle937a8012006-10-07 19:44:33 +0100292 malta_hw0_irqdispatch();
Ralf Baechle39b8d522008-04-28 17:14:26 +0100293 else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
294 malta_ipi_irqdispatch();
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100295 else
Ralf Baechlee376fdf2012-09-17 01:23:21 +0200296 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100297}
298
Ralf Baechle39b8d522008-04-28 17:14:26 +0100299#ifdef CONFIG_MIPS_MT_SMP
300
301
302#define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3
303#define GIC_MIPS_CPU_IPI_CALL_IRQ 4
304
305#define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */
306#define C_RESCHED C_SW0
307#define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */
308#define C_CALL C_SW1
309static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
310
311static void ipi_resched_dispatch(void)
312{
313 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
314}
315
316static void ipi_call_dispatch(void)
317{
318 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
319}
320
321static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
322{
Deng-Cheng Zhu13361132013-10-30 15:52:10 -0500323#ifdef MIPS_VPE_APSP_API
324 if (aprp_hook)
325 aprp_hook();
326#endif
327
Peter Zijlstra184748c2011-04-05 17:23:39 +0200328 scheduler_ipi();
329
Ralf Baechle39b8d522008-04-28 17:14:26 +0100330 return IRQ_HANDLED;
331}
332
333static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
334{
335 smp_call_function_interrupt();
336
337 return IRQ_HANDLED;
338}
339
340static struct irqaction irq_resched = {
341 .handler = ipi_resched_interrupt,
Yong Zhang8b5690f2011-11-22 14:38:03 +0000342 .flags = IRQF_PERCPU,
Ralf Baechle39b8d522008-04-28 17:14:26 +0100343 .name = "IPI_resched"
344};
345
346static struct irqaction irq_call = {
347 .handler = ipi_call_interrupt,
Yong Zhang8b5690f2011-11-22 14:38:03 +0000348 .flags = IRQF_PERCPU,
Ralf Baechle39b8d522008-04-28 17:14:26 +0100349 .name = "IPI_call"
350};
Raghu Gandham008ee962009-07-08 17:00:44 -0700351#endif /* CONFIG_MIPS_MT_SMP */
Tim Andersona214cef2009-06-17 16:22:25 -0700352
353static int gic_resched_int_base;
354static int gic_call_int_base;
355#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
356#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
Tim Anderson03650702009-06-17 16:22:53 -0700357
358unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
359{
360 return GIC_CALL_INT(cpu);
361}
362
363unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
364{
365 return GIC_RESCHED_INT(cpu);
366}
Ralf Baechle39b8d522008-04-28 17:14:26 +0100367
Ralf Baechlee01402b2005-07-14 15:57:16 +0000368static struct irqaction i8259irq = {
369 .handler = no_action,
Wu Zhangjin5a4a4ad2011-07-23 12:41:24 +0000370 .name = "XT-PIC cascade",
371 .flags = IRQF_NO_THREAD,
Ralf Baechlee01402b2005-07-14 15:57:16 +0000372};
373
374static struct irqaction corehi_irqaction = {
375 .handler = no_action,
Wu Zhangjin5a4a4ad2011-07-23 12:41:24 +0000376 .name = "CoreHi",
377 .flags = IRQF_NO_THREAD,
Ralf Baechlee01402b2005-07-14 15:57:16 +0000378};
379
Dmitri Vorobievb57c1912008-04-01 02:03:25 +0400380static msc_irqmap_t __initdata msc_irqmap[] = {
Ralf Baechlee01402b2005-07-14 15:57:16 +0000381 {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0},
382 {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0},
383};
Dmitri Vorobievb57c1912008-04-01 02:03:25 +0400384static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000385
Dmitri Vorobievb57c1912008-04-01 02:03:25 +0400386static msc_irqmap_t __initdata msc_eicirqmap[] = {
Ralf Baechlee01402b2005-07-14 15:57:16 +0000387 {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0},
388 {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0},
389 {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0},
390 {MSC01E_INT_SMI, MSC01_IRQ_LEVEL, 0},
391 {MSC01E_INT_COREHI, MSC01_IRQ_LEVEL, 0},
392 {MSC01E_INT_CORELO, MSC01_IRQ_LEVEL, 0},
393 {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0},
394 {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0},
395 {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0},
396 {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0}
397};
Ralf Baechle39b8d522008-04-28 17:14:26 +0100398
Dmitri Vorobievb57c1912008-04-01 02:03:25 +0400399static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000400
Ralf Baechle39b8d522008-04-28 17:14:26 +0100401/*
402 * This GIC specific tabular array defines the association between External
403 * Interrupts and CPUs/Core Interrupts. The nature of the External
404 * Interrupts is also defined here - polarity/trigger.
405 */
Chris Dearman7098f742009-07-10 01:54:09 -0700406
407#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
Ralf Baechle863cb9b2010-09-17 17:07:48 +0100408#define X GIC_UNUSED
409
Tim Andersona214cef2009-06-17 16:22:25 -0700410static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
Chris Dearman7098f742009-07-10 01:54:09 -0700411 { X, X, X, X, 0 },
Ralf Baechle70342282013-01-22 12:59:30 +0100412 { X, X, X, X, 0 },
Chris Dearman7098f742009-07-10 01:54:09 -0700413 { X, X, X, X, 0 },
414 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
415 { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
416 { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
417 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
418 { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
419 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
420 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
421 { X, X, X, X, 0 },
422 { X, X, X, X, 0 },
423 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
424 { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
425 { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
Ralf Baechle70342282013-01-22 12:59:30 +0100426 { X, X, X, X, 0 },
Chris Dearman7098f742009-07-10 01:54:09 -0700427 /* The remainder of this table is initialised by fill_ipi_map */
Ralf Baechle39b8d522008-04-28 17:14:26 +0100428};
Ralf Baechle863cb9b2010-09-17 17:07:48 +0100429#undef X
Ralf Baechle39b8d522008-04-28 17:14:26 +0100430
431/*
432 * GCMP needs to be detected before any SMP initialisation
433 */
Tim Anderson47b178b2009-06-17 16:25:18 -0700434int __init gcmp_probe(unsigned long addr, unsigned long size)
Ralf Baechle39b8d522008-04-28 17:14:26 +0100435{
Leonid Yegoshin78276202013-06-20 14:36:42 +0000436 if ((mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) &&
437 (mips_revision_sconid != MIPS_REVISION_SCON_GT64120)) {
Jaidev Patwardhan05cf2072009-07-10 01:54:25 -0700438 gcmp_present = 0;
Leonid Yegoshin78276202013-06-20 14:36:42 +0000439 pr_debug("GCMP NOT present\n");
Jaidev Patwardhan05cf2072009-07-10 01:54:25 -0700440 return gcmp_present;
441 }
442
Ralf Baechle39b8d522008-04-28 17:14:26 +0100443 if (gcmp_present >= 0)
444 return gcmp_present;
445
446 _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
447 _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ);
448 gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR;
449
450 if (gcmp_present)
Chris Dearman7098f742009-07-10 01:54:09 -0700451 pr_debug("GCMP present\n");
Ralf Baechle39b8d522008-04-28 17:14:26 +0100452 return gcmp_present;
453}
454
Chris Dearman7098f742009-07-10 01:54:09 -0700455/* Return the number of IOCU's present */
456int __init gcmp_niocu(void)
457{
458 return gcmp_present ?
459 (GCMPGCB(GC) & GCMP_GCB_GC_NUMIOCU_MSK) >> GCMP_GCB_GC_NUMIOCU_SHF :
460 0;
461}
462
463/* Set GCMP region attributes */
464void __init gcmp_setregion(int region, unsigned long base,
465 unsigned long mask, int type)
466{
467 GCMPGCBn(CMxBASE, region) = base;
468 GCMPGCBn(CMxMASK, region) = mask | type;
469}
470
Dmitri Vorobiev7afed6a2008-06-18 10:18:21 +0300471#if defined(CONFIG_MIPS_MT_SMP)
Tim Andersona214cef2009-06-17 16:22:25 -0700472static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
473{
474 int intr = baseintr + cpu;
Tim Andersona214cef2009-06-17 16:22:25 -0700475 gic_intr_map[intr].cpunum = cpu;
476 gic_intr_map[intr].pin = cpupin;
477 gic_intr_map[intr].polarity = GIC_POL_POS;
478 gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
Chris Dearman7098f742009-07-10 01:54:09 -0700479 gic_intr_map[intr].flags = GIC_FLAG_IPI;
Tim Andersona214cef2009-06-17 16:22:25 -0700480 ipi_map[cpu] |= (1 << (cpupin + 2));
481}
482
Dmitri Vorobiev7afed6a2008-06-18 10:18:21 +0300483static void __init fill_ipi_map(void)
Ralf Baechle39b8d522008-04-28 17:14:26 +0100484{
Tim Andersona214cef2009-06-17 16:22:25 -0700485 int cpu;
Ralf Baechle39b8d522008-04-28 17:14:26 +0100486
Markos Chandras13b7ea62013-10-30 14:27:48 +0000487 for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
Tim Andersona214cef2009-06-17 16:22:25 -0700488 fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
489 fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
Ralf Baechle39b8d522008-04-28 17:14:26 +0100490 }
491}
Dmitri Vorobiev7afed6a2008-06-18 10:18:21 +0300492#endif
Ralf Baechle39b8d522008-04-28 17:14:26 +0100493
Chris Dearman7098f742009-07-10 01:54:09 -0700494void __init arch_init_ipiirq(int irq, struct irqaction *action)
495{
496 setup_irq(irq, action);
Thomas Gleixnere4ec7982011-03-27 15:19:28 +0200497 irq_set_handler(irq, handle_percpu_irq);
Chris Dearman7098f742009-07-10 01:54:09 -0700498}
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500void __init arch_init_irq(void)
501{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 init_i8259_irqs();
Ralf Baechlee01402b2005-07-14 15:57:16 +0000503
504 if (!cpu_has_veic)
Atsushi Nemoto97dcb822007-01-08 02:14:29 +0900505 mips_cpu_irq_init();
Ralf Baechlee01402b2005-07-14 15:57:16 +0000506
Ralf Baechle39b8d522008-04-28 17:14:26 +0100507 if (gcmp_present) {
508 GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
509 gic_present = 1;
510 } else {
Jaidev Patwardhan05cf2072009-07-10 01:54:25 -0700511 if (mips_revision_sconid == MIPS_REVISION_SCON_ROCIT) {
512 _msc01_biu_base = (unsigned long)
513 ioremap_nocache(MSC01_BIU_REG_BASE,
514 MSC01_BIU_ADDRSPACE_SZ);
515 gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) &
516 MSC01_SC_CFG_GICPRES_MSK) >>
517 MSC01_SC_CFG_GICPRES_SHF;
518 }
Ralf Baechle39b8d522008-04-28 17:14:26 +0100519 }
520 if (gic_present)
Chris Dearman7098f742009-07-10 01:54:09 -0700521 pr_debug("GIC present\n");
Ralf Baechle39b8d522008-04-28 17:14:26 +0100522
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300523 switch (mips_revision_sconid) {
524 case MIPS_REVISION_SCON_SOCIT:
525 case MIPS_REVISION_SCON_ROCIT:
Ralf Baechlee01402b2005-07-14 15:57:16 +0000526 if (cpu_has_veic)
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300527 init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
528 MSC01E_INT_BASE, msc_eicirqmap,
529 msc_nr_eicirqs);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000530 else
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300531 init_msc_irqs(MIPS_MSC01_IC_REG_BASE,
532 MSC01C_INT_BASE, msc_irqmap,
533 msc_nr_irqs);
Chris Dearmand725cf32007-05-08 14:05:39 +0100534 break;
535
Dmitri Vorobievaf825582008-01-24 19:52:45 +0300536 case MIPS_REVISION_SCON_SOCITSC:
537 case MIPS_REVISION_SCON_SOCITSCP:
Chris Dearmand725cf32007-05-08 14:05:39 +0100538 if (cpu_has_veic)
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300539 init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
540 MSC01E_INT_BASE, msc_eicirqmap,
541 msc_nr_eicirqs);
Chris Dearmand725cf32007-05-08 14:05:39 +0100542 else
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300543 init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE,
544 MSC01C_INT_BASE, msc_irqmap,
545 msc_nr_irqs);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000546 }
547
548 if (cpu_has_veic) {
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100549 set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch);
550 set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
551 setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq);
552 setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction);
Dmitri Vorobiev52b3fc02008-01-24 19:52:51 +0300553 } else if (cpu_has_vint) {
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100554 set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
555 set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch);
Ralf Baechle41c594a2006-04-05 09:45:45 +0100556#ifdef CONFIG_MIPS_MT_SMTC
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100557 setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq,
Ralf Baechle41c594a2006-04-05 09:45:45 +0100558 (0x100 << MIPSCPU_INT_I8259A));
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100559 setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
Ralf Baechle41c594a2006-04-05 09:45:45 +0100560 &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
Kevin D. Kissellc3a005f2007-07-27 18:45:25 +0100561 /*
562 * Temporary hack to ensure that the subsidiary device
563 * interrupts coing in via the i8259A, but associated
564 * with low IRQ numbers, will restore the Status.IM
565 * value associated with the i8259A.
566 */
567 {
568 int i;
569
570 for (i = 0; i < 16; i++)
571 irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A);
572 }
Ralf Baechle41c594a2006-04-05 09:45:45 +0100573#else /* Not SMTC */
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100574 setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300575 setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
576 &corehi_irqaction);
Ralf Baechle41c594a2006-04-05 09:45:45 +0100577#endif /* CONFIG_MIPS_MT_SMTC */
Dmitri Vorobiev52b3fc02008-01-24 19:52:51 +0300578 } else {
Ralf Baechle49a89ef2007-10-11 23:46:15 +0100579 setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
Dmitri Vorobievf8071492008-01-24 19:52:47 +0300580 setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
581 &corehi_irqaction);
Ralf Baechlee01402b2005-07-14 15:57:16 +0000582 }
Ralf Baechle39b8d522008-04-28 17:14:26 +0100583
Ralf Baechle39b8d522008-04-28 17:14:26 +0100584 if (gic_present) {
585 /* FIXME */
586 int i;
Chris Dearman7098f742009-07-10 01:54:09 -0700587#if defined(CONFIG_MIPS_MT_SMP)
Markos Chandras13b7ea62013-10-30 14:27:48 +0000588 gic_call_int_base = GIC_NUM_INTRS -
589 (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids;
590 gic_resched_int_base = gic_call_int_base - nr_cpu_ids;
Ralf Baechle39b8d522008-04-28 17:14:26 +0100591 fill_ipi_map();
Chris Dearman7098f742009-07-10 01:54:09 -0700592#endif
593 gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
594 ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
Ralf Baechle39b8d522008-04-28 17:14:26 +0100595 if (!gcmp_present) {
596 /* Enable the GIC */
597 i = REG(_msc01_biu_base, MSC01_SC_CFG);
598 REG(_msc01_biu_base, MSC01_SC_CFG) =
599 (i | (0x1 << MSC01_SC_CFG_GICENA_SHF));
600 pr_debug("GIC Enabled\n");
601 }
Chris Dearman7098f742009-07-10 01:54:09 -0700602#if defined(CONFIG_MIPS_MT_SMP)
Ralf Baechle39b8d522008-04-28 17:14:26 +0100603 /* set up ipi interrupts */
604 if (cpu_has_vint) {
605 set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch);
606 set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch);
607 }
608 /* Argh.. this really needs sorting out.. */
609 printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status());
610 write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4);
611 printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
612 write_c0_status(0x1100dc00);
613 printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
Markos Chandras13b7ea62013-10-30 14:27:48 +0000614 for (i = 0; i < nr_cpu_ids; i++) {
Chris Dearman7098f742009-07-10 01:54:09 -0700615 arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
616 GIC_RESCHED_INT(i), &irq_resched);
617 arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
618 GIC_CALL_INT(i), &irq_call);
Ralf Baechle39b8d522008-04-28 17:14:26 +0100619 }
Chris Dearman7098f742009-07-10 01:54:09 -0700620#endif
Ralf Baechle39b8d522008-04-28 17:14:26 +0100621 } else {
Chris Dearman7098f742009-07-10 01:54:09 -0700622#if defined(CONFIG_MIPS_MT_SMP)
Ralf Baechle39b8d522008-04-28 17:14:26 +0100623 /* set up ipi interrupts */
624 if (cpu_has_veic) {
625 set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
626 set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
627 cpu_ipi_resched_irq = MSC01E_INT_SW0;
628 cpu_ipi_call_irq = MSC01E_INT_SW1;
629 } else {
630 if (cpu_has_vint) {
631 set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
632 set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
633 }
634 cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
635 cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
636 }
Chris Dearman7098f742009-07-10 01:54:09 -0700637 arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
638 arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
Ralf Baechle39b8d522008-04-28 17:14:26 +0100639#endif
Chris Dearman7098f742009-07-10 01:54:09 -0700640 }
Ralf Baechle39b8d522008-04-28 17:14:26 +0100641}
642
643void malta_be_init(void)
644{
645 if (gcmp_present) {
646 /* Could change CM error mask register */
647 }
648}
649
650
651static char *tr[8] = {
652 "mem", "gcr", "gic", "mmio",
Ralf Baechle70342282013-01-22 12:59:30 +0100653 "0x04", "0x05", "0x06", "0x07"
Ralf Baechle39b8d522008-04-28 17:14:26 +0100654};
655
656static char *mcmd[32] = {
657 [0x00] = "0x00",
658 [0x01] = "Legacy Write",
659 [0x02] = "Legacy Read",
660 [0x03] = "0x03",
661 [0x04] = "0x04",
662 [0x05] = "0x05",
663 [0x06] = "0x06",
664 [0x07] = "0x07",
665 [0x08] = "Coherent Read Own",
666 [0x09] = "Coherent Read Share",
667 [0x0a] = "Coherent Read Discard",
668 [0x0b] = "Coherent Ready Share Always",
669 [0x0c] = "Coherent Upgrade",
670 [0x0d] = "Coherent Writeback",
671 [0x0e] = "0x0e",
672 [0x0f] = "0x0f",
673 [0x10] = "Coherent Copyback",
674 [0x11] = "Coherent Copyback Invalidate",
675 [0x12] = "Coherent Invalidate",
676 [0x13] = "Coherent Write Invalidate",
677 [0x14] = "Coherent Completion Sync",
678 [0x15] = "0x15",
679 [0x16] = "0x16",
680 [0x17] = "0x17",
681 [0x18] = "0x18",
682 [0x19] = "0x19",
683 [0x1a] = "0x1a",
684 [0x1b] = "0x1b",
685 [0x1c] = "0x1c",
686 [0x1d] = "0x1d",
687 [0x1e] = "0x1e",
688 [0x1f] = "0x1f"
689};
690
691static char *core[8] = {
Ralf Baechle70342282013-01-22 12:59:30 +0100692 "Invalid/OK", "Invalid/Data",
Ralf Baechle39b8d522008-04-28 17:14:26 +0100693 "Shared/OK", "Shared/Data",
694 "Modified/OK", "Modified/Data",
Ralf Baechle70342282013-01-22 12:59:30 +0100695 "Exclusive/OK", "Exclusive/Data"
Ralf Baechle39b8d522008-04-28 17:14:26 +0100696};
697
698static char *causes[32] = {
699 "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR",
700 "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
701 "0x08", "0x09", "0x0a", "0x0b",
702 "0x0c", "0x0d", "0x0e", "0x0f",
703 "0x10", "0x11", "0x12", "0x13",
704 "0x14", "0x15", "0x16", "INTVN_WR_ERR",
705 "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
706 "0x1c", "0x1d", "0x1e", "0x1f"
707};
708
709int malta_be_handler(struct pt_regs *regs, int is_fixup)
710{
711 /* This duplicates the handling in do_be which seems wrong */
712 int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
713
714 if (gcmp_present) {
715 unsigned long cm_error = GCMPGCB(GCMEC);
716 unsigned long cm_addr = GCMPGCB(GCMEA);
717 unsigned long cm_other = GCMPGCB(GCMEO);
718 unsigned long cause, ocause;
719 char buf[256];
720
721 cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK);
722 if (cause != 0) {
723 cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF;
724 if (cause < 16) {
725 unsigned long cca_bits = (cm_error >> 15) & 7;
726 unsigned long tr_bits = (cm_error >> 12) & 7;
727 unsigned long mcmd_bits = (cm_error >> 7) & 0x1f;
728 unsigned long stag_bits = (cm_error >> 3) & 15;
729 unsigned long sport_bits = (cm_error >> 0) & 7;
730
731 snprintf(buf, sizeof(buf),
732 "CCA=%lu TR=%s MCmd=%s STag=%lu "
733 "SPort=%lu\n",
734 cca_bits, tr[tr_bits], mcmd[mcmd_bits],
735 stag_bits, sport_bits);
736 } else {
737 /* glob state & sresp together */
738 unsigned long c3_bits = (cm_error >> 18) & 7;
739 unsigned long c2_bits = (cm_error >> 15) & 7;
740 unsigned long c1_bits = (cm_error >> 12) & 7;
741 unsigned long c0_bits = (cm_error >> 9) & 7;
742 unsigned long sc_bit = (cm_error >> 8) & 1;
743 unsigned long mcmd_bits = (cm_error >> 3) & 0x1f;
744 unsigned long sport_bits = (cm_error >> 0) & 7;
745 snprintf(buf, sizeof(buf),
746 "C3=%s C2=%s C1=%s C0=%s SC=%s "
747 "MCmd=%s SPort=%lu\n",
748 core[c3_bits], core[c2_bits],
749 core[c1_bits], core[c0_bits],
750 sc_bit ? "True" : "False",
751 mcmd[mcmd_bits], sport_bits);
752 }
753
754 ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >>
755 GCMP_GCB_GMEO_ERROR_2ND_SHF;
756
757 printk("CM_ERROR=%08lx %s <%s>\n", cm_error,
758 causes[cause], buf);
759 printk("CM_ADDR =%08lx\n", cm_addr);
760 printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]);
761
762 /* reprime cause register */
763 GCMPGCB(GCMEC) = 0;
764 }
765 }
766
767 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
Steven J. Hill0b271f52012-08-31 16:05:37 -0500769
770void gic_enable_interrupt(int irq_vec)
771{
772 GIC_SET_INTR_MASK(irq_vec);
773}
774
775void gic_disable_interrupt(int irq_vec)
776{
777 GIC_CLR_INTR_MASK(irq_vec);
778}
779
780void gic_irq_ack(struct irq_data *d)
781{
782 int irq = (d->irq - gic_irq_base);
783
784 GIC_CLR_INTR_MASK(irq);
785
786 if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
787 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
788}
789
790void gic_finish_irq(struct irq_data *d)
791{
792 /* Enable interrupts. */
793 GIC_SET_INTR_MASK(d->irq - gic_irq_base);
794}
795
796void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
797{
798 int i;
799
800 for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
801 irq_set_chip(i, irq_controller);
802}