2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
4 * Copyright (C) 2001 Ralf Baechle
6 * This program is free software; you can distribute it and/or modify it
7 * under the terms of the GNU General Public License (Version 2) as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 * Routines for generic manipulation of the interrupts found on the MIPS
21 * The interrupt controller is located in the South Bridge a PIIX4 device
22 * with two internal 82C95 interrupt controllers.
24 #include <linux/init.h>
25 #include <linux/irq.h>
26 #include <linux/sched.h>
27 #include <linux/slab.h>
28 #include <linux/interrupt.h>
30 #include <linux/kernel_stat.h>
31 #include <linux/kernel.h>
32 #include <linux/random.h>
34 #include <asm/traps.h>
35 #include <asm/irq_cpu.h>
36 #include <asm/irq_regs.h>
37 #include <asm/mips-boards/generic.h>
38 #include <asm/mips-boards/sead3int.h>
41 #define SEAD_CONFIG_GIC_PRESENT_SHF (1)
42 #define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF)
43 #define SEAD_CONFIG_BASE (0x1B100110)
44 #define SEAD_CONFIG_SIZE (4)
46 int gic_present
; /* global var => auto initialized to 0 */
47 static unsigned long sead3_config_reg
;
50 * This table defines the setup for each external GIC interrupt
51 * It is indexed by interrupt number
53 #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
54 static struct gic_intr_map gic_intr_map
[GIC_NUM_INTRS
] = {
55 { 0, GIC_CPU_INT4
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
56 { 0, GIC_CPU_INT3
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
57 { 0, GIC_CPU_INT2
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
58 { 0, GIC_CPU_INT2
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
59 { 0, GIC_CPU_INT1
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
60 { 0, GIC_CPU_INT0
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
61 { 0, GIC_CPU_INT0
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
62 { 0, GIC_CPU_INT0
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
63 { 0, GIC_CPU_INT0
, GIC_POL_POS
, GIC_TRIG_LEVEL
, GIC_FLAG_TRANSPARENT
},
71 /* The remainder of this table is initialised by fill_ipi_map */
75 * Version of ffs that only looks at bits 8..15
77 static inline unsigned int irq_ffs(unsigned int pending
)
79 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
80 return fls(pending
) - CAUSEB_IP
- 1;
85 t0
= pending
& 0xf000;
89 pending
= pending
<< t0
;
91 t0
= pending
& 0xc000;
95 pending
= pending
<< t0
;
97 t0
= pending
& 0x8000;
101 /* pending = pending << t0; */
107 asmlinkage
void plat_irq_dispatch(void)
109 unsigned int pending
= read_c0_cause() & read_c0_status() & ST0_IM
;
112 irq
= irq_ffs(pending
);
115 do_IRQ(MIPS_CPU_IRQ_BASE
+ irq
);
117 spurious_interrupt();
120 void __init
arch_init_irq(void)
128 /* install generic handler */
129 for (i
= 0; i
< 8; i
++)
130 set_vi_handler(i
, plat_irq_dispatch
);
134 sead3_config_reg
= (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE
, SEAD_CONFIG_SIZE
);
135 gic_present
= (REG32(sead3_config_reg
) & SEAD_CONFIG_GIC_PRESENT_MSK
) >>
136 SEAD_CONFIG_GIC_PRESENT_SHF
;
137 printk("GIC: %spresent\n", (gic_present
) ? "" : "not ");
138 printk("EIC: %s\n", (current_cpu_data
.options
& MIPS_CPU_VEIC
) ? "on" : "off");
141 gic_init(GIC_BASE_ADDR
, GIC_ADDRSPACE_SZ
, gic_intr_map
,
142 ARRAY_SIZE(gic_intr_map
), MIPS_GIC_IRQ_BASE
);