• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/mips/mti-sead3/
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
4 * Copyright (C) 2001 Ralf Baechle
5 *
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.
9 *
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
13 *  for more details.
14 *
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.
18 *
19 * Routines for generic manipulation of the interrupts found on the MIPS
20 * Malta board.
21 * The interrupt controller is located in the South Bridge a PIIX4 device
22 * with two internal 82C95 interrupt controllers.
23 */
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>
29#include <linux/io.h>
30#include <linux/kernel_stat.h>
31#include <linux/kernel.h>
32#include <linux/random.h>
33
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>
39#include <asm/gic.h>
40
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)
45
46int gic_present;    /* global var => auto initialized to 0 */
47static unsigned long sead3_config_reg;
48
49/*
50 * This table defines the setup for each external GIC interrupt
51 * It is indexed by interrupt number
52 */
53#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
54static 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 },
64	{ X, X,            X,           X,              0 },
65	{ X, X,            X,           X,              0 },
66	{ X, X,            X,           X,              0 },
67	{ X, X,            X,           X,              0 },
68	{ X, X,            X,           X,              0 },
69	{ X, X,            X,           X,              0 },
70	{ X, X,            X,           X,              0 },
71	/* The remainder of this table is initialised by fill_ipi_map */
72};
73
74/*
75 * Version of ffs that only looks at bits 8..15
76 */
77static inline unsigned int irq_ffs(unsigned int pending)
78{
79#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
80	return fls(pending) - CAUSEB_IP - 1;
81#else
82	unsigned int a0 = 7;
83	unsigned int t0;
84
85	t0 = pending & 0xf000;
86	t0 = t0 < 1;
87	t0 = t0 << 2;
88	a0 = a0 - t0;
89	pending = pending << t0;
90
91	t0 = pending & 0xc000;
92	t0 = t0 < 1;
93	t0 = t0 << 1;
94	a0 = a0 - t0;
95	pending = pending << t0;
96
97	t0 = pending & 0x8000;
98	t0 = t0 < 1;
99	/* t0 = t0 << 2; */
100	a0 = a0 - t0;
101	/* pending = pending << t0; */
102
103	return a0;
104#endif
105}
106
107asmlinkage void plat_irq_dispatch(void)
108{
109	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
110	int irq;
111
112	irq = irq_ffs(pending);
113
114	if (irq >= 0)
115		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
116	else
117		spurious_interrupt();
118}
119
120void __init arch_init_irq(void)
121{
122	int i;
123
124	if (!cpu_has_veic) {
125		mips_cpu_irq_init();
126
127		if (cpu_has_vint) {
128			/* install generic handler */
129			for (i = 0; i < 8; i++)
130				set_vi_handler(i, plat_irq_dispatch);
131		}
132	}
133
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");
139
140	if (gic_present) {
141		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
142				ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
143	}
144}
145