aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorManuel Lauss <mano@roarinelk.homelinux.net>2008-12-21 03:26:17 -0500
committerRalf Baechle <ralf@linux-mips.org>2009-01-11 04:57:26 -0500
commit785e3268e2951d4c0c21417c8e5d8004b2ab2480 (patch)
tree3e7e98dbaf2592f22f65090325a823d36caa13f7 /arch
parent7179380ee9bdeb5fa2ff07581f512fe0f5382e5b (diff)
MIPS: Alchemy: update core interrupt code.
This patch attempts to modernize core Alchemy interrupt handling code. - add irq_chips for irq controllers instead of irq type, - add a set_type() hook to change irq trigger type during runtime, - add a set_wake() hook to control GPIO0..7 based wakeup, - use linux' IRQF_TRIGGER_ constants instead of homebrew ones, - enable GENERIC_HARDIRQS_NO__DO_IRQ. - simplify plat_irq_dispatch - merge au1xxx_irqmap into irq.c file, the only place where its contents are referenced. - board_init_irq() is now mandatory for every board; use it to register the remaining (gpio-based) interrupt sources; update all boards accordingly. Run-tested on Db1200 and other Au1200 based platforms. Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> delete mode 100644 arch/mips/alchemy/common/au1xxx_irqmap.c
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/alchemy/Kconfig1
-rw-r--r--arch/mips/alchemy/common/Makefile2
-rw-r--r--arch/mips/alchemy/common/au1xxx_irqmap.c205
-rw-r--r--arch/mips/alchemy/common/irq.c785
-rw-r--r--arch/mips/alchemy/common/power.c6
-rw-r--r--arch/mips/alchemy/devboards/db1x00/irqmap.c24
-rw-r--r--arch/mips/alchemy/devboards/pb1000/board_setup.c9
-rw-r--r--arch/mips/alchemy/devboards/pb1100/board_setup.c16
-rw-r--r--arch/mips/alchemy/devboards/pb1200/board_setup.c5
-rw-r--r--arch/mips/alchemy/devboards/pb1200/irqmap.c7
-rw-r--r--arch/mips/alchemy/devboards/pb1500/board_setup.c18
-rw-r--r--arch/mips/alchemy/devboards/pb1550/board_setup.c13
-rw-r--r--arch/mips/alchemy/mtx-1/irqmap.c18
-rw-r--r--arch/mips/alchemy/xxs1500/irqmap.c31
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h18
15 files changed, 514 insertions, 644 deletions
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig
index e4a057d80ab6..4397d94f327a 100644
--- a/arch/mips/alchemy/Kconfig
+++ b/arch/mips/alchemy/Kconfig
@@ -134,3 +134,4 @@ config SOC_AU1X00
134 select SYS_HAS_CPU_MIPS32_R1 134 select SYS_HAS_CPU_MIPS32_R1
135 select SYS_SUPPORTS_32BIT_KERNEL 135 select SYS_SUPPORTS_32BIT_KERNEL
136 select SYS_SUPPORTS_APM_EMULATION 136 select SYS_SUPPORTS_APM_EMULATION
137 select GENERIC_HARDIRQS_NO__DO_IRQ
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index df48fd65bbf3..28b8aebb35ea 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -6,7 +6,7 @@
6# 6#
7 7
8obj-y += prom.o irq.o puts.o time.o reset.o \ 8obj-y += prom.o irq.o puts.o time.o reset.o \
9 au1xxx_irqmap.o clocks.o platform.o power.o setup.o \ 9 clocks.o platform.o power.o setup.o \
10 sleeper.o cputable.o dma.o dbdma.o gpio.o 10 sleeper.o cputable.o dma.o dbdma.o gpio.o
11 11
12obj-$(CONFIG_PCI) += pci.o 12obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/alchemy/common/au1xxx_irqmap.c b/arch/mips/alchemy/common/au1xxx_irqmap.c
deleted file mode 100644
index c7ca1596394c..000000000000
--- a/arch/mips/alchemy/common/au1xxx_irqmap.c
+++ /dev/null
@@ -1,205 +0,0 @@
1/*
2 * BRIEF MODULE DESCRIPTION
3 * Au1xxx processor specific IRQ tables
4 *
5 * Copyright 2004 Embedded Edge, LLC
6 * dan@embeddededge.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28#include <linux/init.h>
29#include <linux/kernel.h>
30
31#include <au1000.h>
32
33/* The IC0 interrupt table. This is processor, rather than
34 * board dependent, so no reason to keep this info in the board
35 * dependent files.
36 *
37 * Careful if you change match 2 request!
38 * The interrupt handler is called directly from the low level dispatch code.
39 */
40struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = {
41
42#if defined(CONFIG_SOC_AU1000)
43 { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
44 { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
45 { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 },
46 { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
47 { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
48 { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
49 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
50 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
51 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
52 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
53 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
54 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
55 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
56 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
57 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
58 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
59 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
60 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
61 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
62 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
63 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
64 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
65 { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
66 { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
67 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
68 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
69 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
70 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
71 { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
72 { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
73 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
74
75#elif defined(CONFIG_SOC_AU1500)
76
77 { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
78 { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
79 { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
80 { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
81 { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
82 { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
83 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
84 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
85 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
86 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
87 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
88 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
89 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
90 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
91 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
92 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
93 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
94 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
95 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
96 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
97 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
98 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
99 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
100 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
101 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
102 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
103 { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
104 { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
105 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
106
107#elif defined(CONFIG_SOC_AU1100)
108
109 { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
110 { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
111 { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
112 { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
113 { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
114 { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
115 { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
116 { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
117 { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
118 { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
119 { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
120 { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
121 { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
122 { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
123 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
124 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
125 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
126 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
127 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
128 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
129 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
130 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
131 { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
132 { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
133 { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
134 { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
135 { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
136 { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
137 { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
138 /* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */
139 { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
140 { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
141
142#elif defined(CONFIG_SOC_AU1550)
143
144 { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
145 { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
146 { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
147 { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
148 { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 },
149 { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
150 { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
151 { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
152 { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
153 { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
154 { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
155 { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
156 { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 },
157 { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 },
158 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
159 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
160 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
161 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
162 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
163 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
164 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
165 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
166 { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 },
167 { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
168 { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
169 { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
170 { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
171 { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
172
173#elif defined(CONFIG_SOC_AU1200)
174
175 { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
176 { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
177 { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
178 { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
179 { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
180 { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
181 { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
182 { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
183 { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
184 { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 },
185 { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 },
186 { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
187 { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
188 { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
189 { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
190 { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
191 { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
192 { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
193 { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
194 { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 },
195 { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
196 { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
197 { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 },
198
199#else
200#error "Error: Unknown Alchemy SOC"
201#endif
202
203};
204
205int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c
index 40c6ceceb5f9..c54384779fb9 100644
--- a/arch/mips/alchemy/common/irq.c
+++ b/arch/mips/alchemy/common/irq.c
@@ -24,6 +24,7 @@
24 * with this program; if not, write to the Free Software Foundation, Inc., 24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 675 Mass Ave, Cambridge, MA 02139, USA. 25 * 675 Mass Ave, Cambridge, MA 02139, USA.
26 */ 26 */
27
27#include <linux/bitops.h> 28#include <linux/bitops.h>
28#include <linux/init.h> 29#include <linux/init.h>
29#include <linux/interrupt.h> 30#include <linux/interrupt.h>
@@ -36,15 +37,174 @@
36#include <asm/mach-pb1x00/pb1000.h> 37#include <asm/mach-pb1x00/pb1000.h>
37#endif 38#endif
38 39
39#define EXT_INTC0_REQ0 2 /* IP 2 */ 40static DEFINE_SPINLOCK(irq_lock);
40#define EXT_INTC0_REQ1 3 /* IP 3 */
41#define EXT_INTC1_REQ0 4 /* IP 4 */
42#define EXT_INTC1_REQ1 5 /* IP 5 */
43#define MIPS_TIMER_IP 7 /* IP 7 */
44 41
45void (*board_init_irq)(void) __initdata = NULL; 42static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
43
44/* per-processor fixed function irqs */
45struct au1xxx_irqmap au1xxx_ic0_map[] __initdata = {
46
47#if defined(CONFIG_SOC_AU1000)
48 { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
49 { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
50 { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
51 { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
52 { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
53 { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
54 { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
55 { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
56 { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
57 { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
58 { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
59 { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
60 { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
61 { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
62 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
63 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
64 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
65 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
66 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
67 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
68 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
69 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
70 { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
71 { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
72 { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
73 { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
74 { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
75 { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
76 { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
77 { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
78 { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
79
80#elif defined(CONFIG_SOC_AU1500)
81
82 { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
83 { AU1000_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
84 { AU1000_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
85 { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
86 { AU1000_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
87 { AU1000_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
88 { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
89 { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
90 { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
91 { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
92 { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
93 { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
94 { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
95 { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
96 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
97 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
98 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
99 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
100 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
101 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
102 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
103 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
104 { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
105 { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
106 { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
107 { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
108 { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
109 { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
110 { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
111
112#elif defined(CONFIG_SOC_AU1100)
113
114 { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
115 { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
116 { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
117 { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
118 { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
119 { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
120 { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
121 { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
122 { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
123 { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
124 { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
125 { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
126 { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
127 { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
128 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
129 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
130 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
131 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
132 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
133 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
134 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
135 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
136 { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
137 { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
138 { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
139 { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
140 { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
141 { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
142 { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
143 { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
144 { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
145
146#elif defined(CONFIG_SOC_AU1550)
147
148 { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
149 { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
150 { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
151 { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
152 { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
153 { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
154 { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
155 { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
156 { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
157 { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
158 { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
159 { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
160 { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
161 { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
162 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
163 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
164 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
165 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
166 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
167 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
168 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
169 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
170 { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
171 { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
172 { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
173 { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
174 { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
175 { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
176
177#elif defined(CONFIG_SOC_AU1200)
178
179 { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
180 { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 },
181 { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
182 { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
183 { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
184 { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
185 { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
186 { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
187 { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
188 { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
189 { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
190 { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
191 { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
192 { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
193 { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
194 { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
195 { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
196 { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
197 { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
198 { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
199 { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
200 { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
201 { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
202
203#else
204#error "Error: Unknown Alchemy SOC"
205#endif
206};
46 207
47static DEFINE_SPINLOCK(irq_lock);
48 208
49#ifdef CONFIG_PM 209#ifdef CONFIG_PM
50 210
@@ -130,67 +290,47 @@ void restore_au1xxx_intctl(void)
130#endif /* CONFIG_PM */ 290#endif /* CONFIG_PM */
131 291
132 292
133inline void local_enable_irq(unsigned int irq_nr) 293static void au1x_ic0_unmask(unsigned int irq_nr)
134{ 294{
135 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 295 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
136 296 au_writel(1 << bit, IC0_MASKSET);
137 if (bit >= 32) { 297 au_writel(1 << bit, IC0_WAKESET);
138 au_writel(1 << (bit - 32), IC1_MASKSET);
139 au_writel(1 << (bit - 32), IC1_WAKESET);
140 } else {
141 au_writel(1 << bit, IC0_MASKSET);
142 au_writel(1 << bit, IC0_WAKESET);
143 }
144 au_sync(); 298 au_sync();
145} 299}
146 300
147 301static void au1x_ic1_unmask(unsigned int irq_nr)
148inline void local_disable_irq(unsigned int irq_nr)
149{ 302{
150 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 303 unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
304 au_writel(1 << bit, IC1_MASKSET);
305 au_writel(1 << bit, IC1_WAKESET);
151 306
152 if (bit >= 32) { 307/* very hacky. does the pb1000 cpld auto-disable this int?
153 au_writel(1 << (bit - 32), IC1_MASKCLR); 308 * nowhere in the current kernel sources is it disabled. --mlau
154 au_writel(1 << (bit - 32), IC1_WAKECLR); 309 */
155 } else { 310#if defined(CONFIG_MIPS_PB1000)
156 au_writel(1 << bit, IC0_MASKCLR); 311 if (irq_nr == AU1000_GPIO_15)
157 au_writel(1 << bit, IC0_WAKECLR); 312 au_writel(0x4000, PB1000_MDR); /* enable int */
158 } 313#endif
159 au_sync(); 314 au_sync();
160} 315}
161 316
162 317static void au1x_ic0_mask(unsigned int irq_nr)
163static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
164{ 318{
165 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 319 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
166 320 au_writel(1 << bit, IC0_MASKCLR);
167 if (bit >= 32) { 321 au_writel(1 << bit, IC0_WAKECLR);
168 au_writel(1 << (bit - 32), IC1_RISINGCLR);
169 au_writel(1 << (bit - 32), IC1_MASKCLR);
170 } else {
171 au_writel(1 << bit, IC0_RISINGCLR);
172 au_writel(1 << bit, IC0_MASKCLR);
173 }
174 au_sync(); 322 au_sync();
175} 323}
176 324
177 325static void au1x_ic1_mask(unsigned int irq_nr)
178static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
179{ 326{
180 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 327 unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
181 328 au_writel(1 << bit, IC1_MASKCLR);
182 if (bit >= 32) { 329 au_writel(1 << bit, IC1_WAKECLR);
183 au_writel(1 << (bit - 32), IC1_FALLINGCLR);
184 au_writel(1 << (bit - 32), IC1_MASKCLR);
185 } else {
186 au_writel(1 << bit, IC0_FALLINGCLR);
187 au_writel(1 << bit, IC0_MASKCLR);
188 }
189 au_sync(); 330 au_sync();
190} 331}
191 332
192 333static void au1x_ic0_ack(unsigned int irq_nr)
193static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
194{ 334{
195 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 335 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
196 336
@@ -198,349 +338,229 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
198 * This may assume that we don't get interrupts from 338 * This may assume that we don't get interrupts from
199 * both edges at once, or if we do, that we don't care. 339 * both edges at once, or if we do, that we don't care.
200 */ 340 */
201 if (bit >= 32) { 341 au_writel(1 << bit, IC0_FALLINGCLR);
202 au_writel(1 << (bit - 32), IC1_FALLINGCLR); 342 au_writel(1 << bit, IC0_RISINGCLR);
203 au_writel(1 << (bit - 32), IC1_RISINGCLR);
204 au_writel(1 << (bit - 32), IC1_MASKCLR);
205 } else {
206 au_writel(1 << bit, IC0_FALLINGCLR);
207 au_writel(1 << bit, IC0_RISINGCLR);
208 au_writel(1 << bit, IC0_MASKCLR);
209 }
210 au_sync(); 343 au_sync();
211} 344}
212 345
213static inline void mask_and_ack_level_irq(unsigned int irq_nr) 346static void au1x_ic1_ack(unsigned int irq_nr)
214{
215 local_disable_irq(irq_nr);
216 au_sync();
217#if defined(CONFIG_MIPS_PB1000)
218 if (irq_nr == AU1000_GPIO_15) {
219 au_writel(0x8000, PB1000_MDR); /* ack int */
220 au_sync();
221 }
222#endif
223}
224
225static void end_irq(unsigned int irq_nr)
226{ 347{
227 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 348 unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
228 local_enable_irq(irq_nr);
229
230#if defined(CONFIG_MIPS_PB1000)
231 if (irq_nr == AU1000_GPIO_15) {
232 au_writel(0x4000, PB1000_MDR); /* enable int */
233 au_sync();
234 }
235#endif
236}
237
238unsigned long save_local_and_disable(int controller)
239{
240 int i;
241 unsigned long flags, mask;
242
243 spin_lock_irqsave(&irq_lock, flags);
244 if (controller) {
245 mask = au_readl(IC1_MASKSET);
246 for (i = 32; i < 64; i++)
247 local_disable_irq(i);
248 } else {
249 mask = au_readl(IC0_MASKSET);
250 for (i = 0; i < 32; i++)
251 local_disable_irq(i);
252 }
253 spin_unlock_irqrestore(&irq_lock, flags);
254 349
255 return mask; 350 /*
351 * This may assume that we don't get interrupts from
352 * both edges at once, or if we do, that we don't care.
353 */
354 au_writel(1 << bit, IC1_FALLINGCLR);
355 au_writel(1 << bit, IC1_RISINGCLR);
356 au_sync();
256} 357}
257 358
258void restore_local_and_enable(int controller, unsigned long mask) 359static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
259{ 360{
260 int i; 361 unsigned int bit = irq - AU1000_INTC1_INT_BASE;
261 unsigned long flags, new_mask; 362 unsigned long wakemsk, flags;
262 363
263 spin_lock_irqsave(&irq_lock, flags); 364 /* only GPIO 0-7 can act as wakeup source: */
264 for (i = 0; i < 32; i++) 365 if ((irq < AU1000_GPIO_0) || (irq > AU1000_GPIO_7))
265 if (mask & (1 << i)) { 366 return -EINVAL;
266 if (controller)
267 local_enable_irq(i + 32);
268 else
269 local_enable_irq(i);
270 }
271 367
272 if (controller) 368 local_irq_save(flags);
273 new_mask = au_readl(IC1_MASKSET); 369 wakemsk = au_readl(SYS_WAKEMSK);
370 if (on)
371 wakemsk |= 1 << bit;
274 else 372 else
275 new_mask = au_readl(IC0_MASKSET); 373 wakemsk &= ~(1 << bit);
374 au_writel(wakemsk, SYS_WAKEMSK);
375 au_sync();
376 local_irq_restore(flags);
276 377
277 spin_unlock_irqrestore(&irq_lock, flags); 378 return 0;
278} 379}
279 380
280 381/*
281static struct irq_chip rise_edge_irq_type = { 382 * irq_chips for both ICs; this way the mask handlers can be
282 .name = "Au1000 Rise Edge", 383 * as short as possible.
283 .ack = mask_and_ack_rise_edge_irq, 384 *
284 .mask = local_disable_irq, 385 * NOTE: the ->ack() callback is used by the handle_edge_irq
285 .mask_ack = mask_and_ack_rise_edge_irq, 386 * flowhandler only, the ->mask_ack() one by handle_level_irq,
286 .unmask = local_enable_irq, 387 * so no need for an irq_chip for each type of irq (level/edge).
287 .end = end_irq, 388 */
288}; 389static struct irq_chip au1x_ic0_chip = {
289 390 .name = "Alchemy-IC0",
290static struct irq_chip fall_edge_irq_type = { 391 .ack = au1x_ic0_ack, /* edge */
291 .name = "Au1000 Fall Edge", 392 .mask = au1x_ic0_mask,
292 .ack = mask_and_ack_fall_edge_irq, 393 .mask_ack = au1x_ic0_mask, /* level */
293 .mask = local_disable_irq, 394 .unmask = au1x_ic0_unmask,
294 .mask_ack = mask_and_ack_fall_edge_irq, 395 .set_type = au1x_ic_settype,
295 .unmask = local_enable_irq,
296 .end = end_irq,
297};
298
299static struct irq_chip either_edge_irq_type = {
300 .name = "Au1000 Rise or Fall Edge",
301 .ack = mask_and_ack_either_edge_irq,
302 .mask = local_disable_irq,
303 .mask_ack = mask_and_ack_either_edge_irq,
304 .unmask = local_enable_irq,
305 .end = end_irq,
306}; 396};
307 397
308static struct irq_chip level_irq_type = { 398static struct irq_chip au1x_ic1_chip = {
309 .name = "Au1000 Level", 399 .name = "Alchemy-IC1",
310 .ack = mask_and_ack_level_irq, 400 .ack = au1x_ic1_ack, /* edge */
311 .mask = local_disable_irq, 401 .mask = au1x_ic1_mask,
312 .mask_ack = mask_and_ack_level_irq, 402 .mask_ack = au1x_ic1_mask, /* level */
313 .unmask = local_enable_irq, 403 .unmask = au1x_ic1_unmask,
314 .end = end_irq, 404 .set_type = au1x_ic_settype,
405 .set_wake = au1x_ic1_setwake,
315}; 406};
316 407
317static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) 408static int au1x_ic_settype(unsigned int irq, unsigned int flow_type)
318{ 409{
319 unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 410 struct irq_chip *chip;
320 411 unsigned long icr[6];
321 if (irq_nr > AU1000_MAX_INTR) 412 unsigned int bit, ic;
322 return; 413 int ret;
323 414
324 /* Config2[n], Config1[n], Config0[n] */ 415 if (irq >= AU1000_INTC1_INT_BASE) {
325 if (bit >= 32) { 416 bit = irq - AU1000_INTC1_INT_BASE;
326 switch (type) { 417 chip = &au1x_ic1_chip;
327 case INTC_INT_RISE_EDGE: /* 0:0:1 */ 418 ic = 1;
328 au_writel(1 << (bit - 32), IC1_CFG2CLR);
329 au_writel(1 << (bit - 32), IC1_CFG1CLR);
330 au_writel(1 << (bit - 32), IC1_CFG0SET);
331 set_irq_chip(irq_nr, &rise_edge_irq_type);
332 break;
333 case INTC_INT_FALL_EDGE: /* 0:1:0 */
334 au_writel(1 << (bit - 32), IC1_CFG2CLR);
335 au_writel(1 << (bit - 32), IC1_CFG1SET);
336 au_writel(1 << (bit - 32), IC1_CFG0CLR);
337 set_irq_chip(irq_nr, &fall_edge_irq_type);
338 break;
339 case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
340 au_writel(1 << (bit - 32), IC1_CFG2CLR);
341 au_writel(1 << (bit - 32), IC1_CFG1SET);
342 au_writel(1 << (bit - 32), IC1_CFG0SET);
343 set_irq_chip(irq_nr, &either_edge_irq_type);
344 break;
345 case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
346 au_writel(1 << (bit - 32), IC1_CFG2SET);
347 au_writel(1 << (bit - 32), IC1_CFG1CLR);
348 au_writel(1 << (bit - 32), IC1_CFG0SET);
349 set_irq_chip(irq_nr, &level_irq_type);
350 break;
351 case INTC_INT_LOW_LEVEL: /* 1:1:0 */
352 au_writel(1 << (bit - 32), IC1_CFG2SET);
353 au_writel(1 << (bit - 32), IC1_CFG1SET);
354 au_writel(1 << (bit - 32), IC1_CFG0CLR);
355 set_irq_chip(irq_nr, &level_irq_type);
356 break;
357 case INTC_INT_DISABLED: /* 0:0:0 */
358 au_writel(1 << (bit - 32), IC1_CFG0CLR);
359 au_writel(1 << (bit - 32), IC1_CFG1CLR);
360 au_writel(1 << (bit - 32), IC1_CFG2CLR);
361 break;
362 default: /* disable the interrupt */
363 printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
364 type, irq_nr);
365 au_writel(1 << (bit - 32), IC1_CFG0CLR);
366 au_writel(1 << (bit - 32), IC1_CFG1CLR);
367 au_writel(1 << (bit - 32), IC1_CFG2CLR);
368 return;
369 }
370 if (int_req) /* assign to interrupt request 1 */
371 au_writel(1 << (bit - 32), IC1_ASSIGNCLR);
372 else /* assign to interrupt request 0 */
373 au_writel(1 << (bit - 32), IC1_ASSIGNSET);
374 au_writel(1 << (bit - 32), IC1_SRCSET);
375 au_writel(1 << (bit - 32), IC1_MASKCLR);
376 au_writel(1 << (bit - 32), IC1_WAKECLR);
377 } else { 419 } else {
378 switch (type) { 420 bit = irq - AU1000_INTC0_INT_BASE;
379 case INTC_INT_RISE_EDGE: /* 0:0:1 */ 421 chip = &au1x_ic0_chip;
380 au_writel(1 << bit, IC0_CFG2CLR); 422 ic = 0;
381 au_writel(1 << bit, IC0_CFG1CLR); 423 }
382 au_writel(1 << bit, IC0_CFG0SET); 424
383 set_irq_chip(irq_nr, &rise_edge_irq_type); 425 if (bit > 31)
384 break; 426 return -EINVAL;
385 case INTC_INT_FALL_EDGE: /* 0:1:0 */ 427
386 au_writel(1 << bit, IC0_CFG2CLR); 428 icr[0] = ic ? IC1_CFG0SET : IC0_CFG0SET;
387 au_writel(1 << bit, IC0_CFG1SET); 429 icr[1] = ic ? IC1_CFG1SET : IC0_CFG1SET;
388 au_writel(1 << bit, IC0_CFG0CLR); 430 icr[2] = ic ? IC1_CFG2SET : IC0_CFG2SET;
389 set_irq_chip(irq_nr, &fall_edge_irq_type); 431 icr[3] = ic ? IC1_CFG0CLR : IC0_CFG0CLR;
390 break; 432 icr[4] = ic ? IC1_CFG1CLR : IC0_CFG1CLR;
391 case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ 433 icr[5] = ic ? IC1_CFG2CLR : IC0_CFG2CLR;
392 au_writel(1 << bit, IC0_CFG2CLR); 434
393 au_writel(1 << bit, IC0_CFG1SET); 435 ret = 0;
394 au_writel(1 << bit, IC0_CFG0SET); 436
395 set_irq_chip(irq_nr, &either_edge_irq_type); 437 switch (flow_type) { /* cfgregs 2:1:0 */
396 break; 438 case IRQ_TYPE_EDGE_RISING: /* 0:0:1 */
397 case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ 439 au_writel(1 << bit, icr[5]);
398 au_writel(1 << bit, IC0_CFG2SET); 440 au_writel(1 << bit, icr[4]);
399 au_writel(1 << bit, IC0_CFG1CLR); 441 au_writel(1 << bit, icr[0]);
400 au_writel(1 << bit, IC0_CFG0SET); 442 set_irq_chip_and_handler_name(irq, chip,
401 set_irq_chip(irq_nr, &level_irq_type); 443 handle_edge_irq, "riseedge");
402 break; 444 break;
403 case INTC_INT_LOW_LEVEL: /* 1:1:0 */ 445 case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */
404 au_writel(1 << bit, IC0_CFG2SET); 446 au_writel(1 << bit, icr[5]);
405 au_writel(1 << bit, IC0_CFG1SET); 447 au_writel(1 << bit, icr[1]);
406 au_writel(1 << bit, IC0_CFG0CLR); 448 au_writel(1 << bit, icr[3]);
407 set_irq_chip(irq_nr, &level_irq_type); 449 set_irq_chip_and_handler_name(irq, chip,
408 break; 450 handle_edge_irq, "falledge");
409 case INTC_INT_DISABLED: /* 0:0:0 */ 451 break;
410 au_writel(1 << bit, IC0_CFG0CLR); 452 case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */
411 au_writel(1 << bit, IC0_CFG1CLR); 453 au_writel(1 << bit, icr[5]);
412 au_writel(1 << bit, IC0_CFG2CLR); 454 au_writel(1 << bit, icr[1]);
413 break; 455 au_writel(1 << bit, icr[0]);
414 default: /* disable the interrupt */ 456 set_irq_chip_and_handler_name(irq, chip,
415 printk(KERN_WARNING "unexpected int type %d (irq %d)\n", 457 handle_edge_irq, "bothedge");
416 type, irq_nr); 458 break;
417 au_writel(1 << bit, IC0_CFG0CLR); 459 case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */
418 au_writel(1 << bit, IC0_CFG1CLR); 460 au_writel(1 << bit, icr[2]);
419 au_writel(1 << bit, IC0_CFG2CLR); 461 au_writel(1 << bit, icr[4]);
420 return; 462 au_writel(1 << bit, icr[0]);
421 } 463 set_irq_chip_and_handler_name(irq, chip,
422 if (int_req) /* assign to interrupt request 1 */ 464 handle_level_irq, "hilevel");
423 au_writel(1 << bit, IC0_ASSIGNCLR); 465 break;
424 else /* assign to interrupt request 0 */ 466 case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */
425 au_writel(1 << bit, IC0_ASSIGNSET); 467 au_writel(1 << bit, icr[2]);
426 au_writel(1 << bit, IC0_SRCSET); 468 au_writel(1 << bit, icr[1]);
427 au_writel(1 << bit, IC0_MASKCLR); 469 au_writel(1 << bit, icr[3]);
428 au_writel(1 << bit, IC0_WAKECLR); 470 set_irq_chip_and_handler_name(irq, chip,
471 handle_level_irq, "lowlevel");
472 break;
473 case IRQ_TYPE_NONE: /* 0:0:0 */
474 au_writel(1 << bit, icr[5]);
475 au_writel(1 << bit, icr[4]);
476 au_writel(1 << bit, icr[3]);
477 /* set at least chip so we can call set_irq_type() on it */
478 set_irq_chip(irq, chip);
479 break;
480 default:
481 ret = -EINVAL;
429 } 482 }
430 au_sync(); 483 au_sync();
431}
432 484
433/* 485 return ret;
434 * Interrupts are nested. Even if an interrupt handler is registered 486}
435 * as "fast", we might get another interrupt before we return from
436 * intcX_reqX_irqdispatch().
437 */
438 487
439static void intc0_req0_irqdispatch(void) 488asmlinkage void plat_irq_dispatch(void)
440{ 489{
441 static unsigned long intc0_req0; 490 unsigned int pending = read_c0_status() & read_c0_cause();
442 unsigned int bit; 491 unsigned long s, off, bit;
443
444 intc0_req0 |= au_readl(IC0_REQ0INT);
445 492
446 if (!intc0_req0) 493 if (pending & CAUSEF_IP7) {
494 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
447 return; 495 return;
448 496 } else if (pending & CAUSEF_IP2) {
497 s = IC0_REQ0INT;
498 off = AU1000_INTC0_INT_BASE;
499 } else if (pending & CAUSEF_IP3) {
500 s = IC0_REQ1INT;
501 off = AU1000_INTC0_INT_BASE;
502 } else if (pending & CAUSEF_IP4) {
503 s = IC1_REQ0INT;
504 off = AU1000_INTC1_INT_BASE;
505 } else if (pending & CAUSEF_IP5) {
506 s = IC1_REQ1INT;
507 off = AU1000_INTC1_INT_BASE;
508 } else
509 goto spurious;
510
511 bit = 0;
512 s = au_readl(s);
513 if (unlikely(!s)) {
514spurious:
515 spurious_interrupt();
516 return;
517 }
449#ifdef AU1000_USB_DEV_REQ_INT 518#ifdef AU1000_USB_DEV_REQ_INT
450 /* 519 /*
451 * Because of the tight timing of SETUP token to reply 520 * Because of the tight timing of SETUP token to reply
452 * transactions, the USB devices-side packet complete 521 * transactions, the USB devices-side packet complete
453 * interrupt needs the highest priority. 522 * interrupt needs the highest priority.
454 */ 523 */
455 if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { 524 bit = 1 << (AU1000_USB_DEV_REQ_INT - AU1000_INTC0_INT_BASE);
456 intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); 525 if ((pending & CAUSEF_IP2) && (s & bit)) {
457 do_IRQ(AU1000_USB_DEV_REQ_INT); 526 do_IRQ(AU1000_USB_DEV_REQ_INT);
458 return; 527 return;
459 } 528 }
460#endif 529#endif
461 bit = __ffs(intc0_req0); 530 do_IRQ(__ffs(s) + off);
462 intc0_req0 &= ~(1 << bit);
463 do_IRQ(AU1000_INTC0_INT_BASE + bit);
464} 531}
465 532
466 533/* setup edge/level and assign request 0/1 */
467static void intc0_req1_irqdispatch(void) 534void __init au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count)
468{ 535{
469 static unsigned long intc0_req1; 536 unsigned int bit, irq_nr;
470 unsigned int bit; 537
471 538 while (count--) {
472 intc0_req1 |= au_readl(IC0_REQ1INT); 539 irq_nr = map[count].im_irq;
473 540
474 if (!intc0_req1) 541 if (((irq_nr < AU1000_INTC0_INT_BASE) ||
475 return; 542 (irq_nr >= AU1000_INTC0_INT_BASE + 32)) &&
476 543 ((irq_nr < AU1000_INTC1_INT_BASE) ||
477 bit = __ffs(intc0_req1); 544 (irq_nr >= AU1000_INTC1_INT_BASE + 32)))
478 intc0_req1 &= ~(1 << bit); 545 continue;
479 do_IRQ(AU1000_INTC0_INT_BASE + bit); 546
480} 547 if (irq_nr >= AU1000_INTC1_INT_BASE) {
481 548 bit = irq_nr - AU1000_INTC1_INT_BASE;
482 549 if (map[count].im_request)
483/* 550 au_writel(1 << bit, IC1_ASSIGNCLR);
484 * Interrupt Controller 1: 551 } else {
485 * interrupts 32 - 63 552 bit = irq_nr - AU1000_INTC0_INT_BASE;
486 */ 553 if (map[count].im_request)
487static void intc1_req0_irqdispatch(void) 554 au_writel(1 << bit, IC0_ASSIGNCLR);
488{ 555 }
489 static unsigned long intc1_req0;
490 unsigned int bit;
491
492 intc1_req0 |= au_readl(IC1_REQ0INT);
493
494 if (!intc1_req0)
495 return;
496
497 bit = __ffs(intc1_req0);
498 intc1_req0 &= ~(1 << bit);
499 do_IRQ(AU1000_INTC1_INT_BASE + bit);
500}
501
502
503static void intc1_req1_irqdispatch(void)
504{
505 static unsigned long intc1_req1;
506 unsigned int bit;
507
508 intc1_req1 |= au_readl(IC1_REQ1INT);
509
510 if (!intc1_req1)
511 return;
512
513 bit = __ffs(intc1_req1);
514 intc1_req1 &= ~(1 << bit);
515 do_IRQ(AU1000_INTC1_INT_BASE + bit);
516}
517
518asmlinkage void plat_irq_dispatch(void)
519{
520 unsigned int pending = read_c0_status() & read_c0_cause();
521 556
522 if (pending & CAUSEF_IP7) 557 au1x_ic_settype(irq_nr, map[count].im_type);
523 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 558 }
524 else if (pending & CAUSEF_IP2)
525 intc0_req0_irqdispatch();
526 else if (pending & CAUSEF_IP3)
527 intc0_req1_irqdispatch();
528 else if (pending & CAUSEF_IP4)
529 intc1_req0_irqdispatch();
530 else if (pending & CAUSEF_IP5)
531 intc1_req1_irqdispatch();
532 else
533 spurious_interrupt();
534} 559}
535 560
536void __init arch_init_irq(void) 561void __init arch_init_irq(void)
537{ 562{
538 int i; 563 int i;
539 struct au1xxx_irqmap *imp;
540 extern struct au1xxx_irqmap au1xxx_irq_map[];
541 extern struct au1xxx_irqmap au1xxx_ic0_map[];
542 extern int au1xxx_nr_irqs;
543 extern int au1xxx_ic0_nr_irqs;
544 564
545 /* 565 /*
546 * Initialize interrupt controllers to a safe state. 566 * Initialize interrupt controllers to a safe state.
@@ -569,28 +589,67 @@ void __init arch_init_irq(void)
569 589
570 mips_cpu_irq_init(); 590 mips_cpu_irq_init();
571 591
572 /* 592 /* register all 64 possible IC0+IC1 irq sources as type "none".
573 * Initialize IC0, which is fixed per processor. 593 * Use set_irq_type() to set edge/level behaviour at runtime.
574 */ 594 */
575 imp = au1xxx_ic0_map; 595 for (i = AU1000_INTC0_INT_BASE;
576 for (i = 0; i < au1xxx_ic0_nr_irqs; i++) { 596 (i < AU1000_INTC0_INT_BASE + 32); i++)
577 setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); 597 au1x_ic_settype(i, IRQ_TYPE_NONE);
578 imp++; 598
579 } 599 for (i = AU1000_INTC1_INT_BASE;
600 (i < AU1000_INTC1_INT_BASE + 32); i++)
601 au1x_ic_settype(i, IRQ_TYPE_NONE);
580 602
581 /* 603 /*
582 * Now set up the irq mapping for the board. 604 * Initialize IC0, which is fixed per processor.
583 */ 605 */
584 imp = au1xxx_irq_map; 606 au1xxx_setup_irqmap(au1xxx_ic0_map, ARRAY_SIZE(au1xxx_ic0_map));
585 for (i = 0; i < au1xxx_nr_irqs; i++) { 607
586 setup_local_irq(imp->im_irq, imp->im_type, imp->im_request); 608 /* Boards can register additional (GPIO-based) IRQs.
587 imp++; 609 */
610 board_init_irq();
611
612 set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
613}
614
615unsigned long save_local_and_disable(int controller)
616{
617 int i;
618 unsigned long flags, mask;
619
620 spin_lock_irqsave(&irq_lock, flags);
621 if (controller) {
622 mask = au_readl(IC1_MASKSET);
623 for (i = 0; i < 32; i++)
624 au1x_ic1_mask(i + AU1000_INTC1_INT_BASE);
625 } else {
626 mask = au_readl(IC0_MASKSET);
627 for (i = 0; i < 32; i++)
628 au1x_ic0_mask(i + AU1000_INTC0_INT_BASE);
588 } 629 }
630 spin_unlock_irqrestore(&irq_lock, flags);
589 631
590 set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); 632 return mask;
633}
591 634
592 /* Board specific IRQ initialization. 635void restore_local_and_enable(int controller, unsigned long mask)
593 */ 636{
594 if (board_init_irq) 637 int i;
595 board_init_irq(); 638 unsigned long flags, new_mask;
639
640 spin_lock_irqsave(&irq_lock, flags);
641 for (i = 0; i < 32; i++)
642 if (mask & (1 << i)) {
643 if (controller)
644 au1x_ic1_unmask(i + AU1000_INTC1_INT_BASE);
645 else
646 au1x_ic0_unmask(i + AU1000_INTC0_INT_BASE);
647 }
648
649 if (controller)
650 new_mask = au_readl(IC1_MASKSET);
651 else
652 new_mask = au_readl(IC0_MASKSET);
653
654 spin_unlock_irqrestore(&irq_lock, flags);
596} 655}
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index bd854a6d1d89..33a3cdb7444a 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -51,7 +51,6 @@ static void au1000_calibrate_delay(void);
51 51
52extern unsigned long save_local_and_disable(int controller); 52extern unsigned long save_local_and_disable(int controller);
53extern void restore_local_and_enable(int controller, unsigned long mask); 53extern void restore_local_and_enable(int controller, unsigned long mask);
54extern void local_enable_irq(unsigned int irq_nr);
55 54
56static DEFINE_SPINLOCK(pm_lock); 55static DEFINE_SPINLOCK(pm_lock);
57 56
@@ -364,7 +363,10 @@ static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
364 */ 363 */
365 intc0_mask = save_local_and_disable(0); 364 intc0_mask = save_local_and_disable(0);
366 intc1_mask = save_local_and_disable(1); 365 intc1_mask = save_local_and_disable(1);
367 local_enable_irq(AU1000_TOY_MATCH2_INT); 366 val = 1 << (AU1000_TOY_MATCH2_INT - AU1000_INTC0_INT_BASE);
367 au_writel(val, IC0_MASKSET); /* unmask */
368 au_writel(val, IC0_WAKESET); /* enable wake-from-sleep */
369 au_sync();
368 spin_unlock_irqrestore(&pm_lock, flags); 370 spin_unlock_irqrestore(&pm_lock, flags);
369 au1000_calibrate_delay(); 371 au1000_calibrate_delay();
370 restore_local_and_enable(0, intc0_mask); 372 restore_local_and_enable(0, intc0_mask);
diff --git a/arch/mips/alchemy/devboards/db1x00/irqmap.c b/arch/mips/alchemy/devboards/db1x00/irqmap.c
index 94c090e8bf7a..0b09025087c6 100644
--- a/arch/mips/alchemy/devboards/db1x00/irqmap.c
+++ b/arch/mips/alchemy/devboards/db1x00/irqmap.c
@@ -27,6 +27,7 @@
27 */ 27 */
28 28
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/interrupt.h>
30 31
31#include <asm/mach-au1x00/au1000.h> 32#include <asm/mach-au1x00/au1000.h>
32 33
@@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
66 67
67#ifndef CONFIG_MIPS_MIRAGE 68#ifndef CONFIG_MIPS_MIRAGE
68#ifdef CONFIG_MIPS_DB1550 69#ifdef CONFIG_MIPS_DB1550
69 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ 70 { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
70 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ 71 { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
71#else 72#else
72 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */ 73 { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
73 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */ 74 { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
74 { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ 75 { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
75 76
76 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */ 77 { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
77 { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */ 78 { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
78 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ 79 { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
79#endif 80#endif
80#else 81#else
81 { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */ 82 { AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
82#endif 83#endif
83 84
84}; 85};
85 86
86int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); 87void __init board_init_irq(void)
88{
89 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
90}
diff --git a/arch/mips/alchemy/devboards/pb1000/board_setup.c b/arch/mips/alchemy/devboards/pb1000/board_setup.c
index 889c8fda2ab1..aed2fdecc709 100644
--- a/arch/mips/alchemy/devboards/pb1000/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1000/board_setup.c
@@ -32,11 +32,9 @@
32 32
33 33
34struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 34struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
35 { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, 35 { AU1000_GPIO_15, IRQF_TRIGGER_LOW, 0 },
36}; 36};
37 37
38int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
39
40 38
41const char *get_system_type(void) 39const char *get_system_type(void)
42{ 40{
@@ -47,6 +45,11 @@ void board_reset(void)
47{ 45{
48} 46}
49 47
48void __init board_init_irq(void)
49{
50 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
51}
52
50void __init board_setup(void) 53void __init board_setup(void)
51{ 54{
52 u32 pin_func, static_cfg0; 55 u32 pin_func, static_cfg0;
diff --git a/arch/mips/alchemy/devboards/pb1100/board_setup.c b/arch/mips/alchemy/devboards/pb1100/board_setup.c
index fbd211e13489..4df57fae15d4 100644
--- a/arch/mips/alchemy/devboards/pb1100/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1100/board_setup.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/interrupt.h>
28 29
29#include <asm/mach-au1x00/au1000.h> 30#include <asm/mach-au1x00/au1000.h>
30#include <asm/mach-pb1x00/pb1100.h> 31#include <asm/mach-pb1x00/pb1100.h>
@@ -33,14 +34,12 @@
33 34
34 35
35struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 36struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
36 { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */ 37 { AU1000_GPIO_9, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card Fully_Inserted# */
37 { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */ 38 { AU1000_GPIO_10, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card STSCHG# */
38 { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */ 39 { AU1000_GPIO_11, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card IRQ# */
39 { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */ 40 { AU1000_GPIO_13, IRQF_TRIGGER_LOW, 0 }, /* DC_IRQ# */
40}; 41};
41 42
42int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
43
44 43
45const char *get_system_type(void) 44const char *get_system_type(void)
46{ 45{
@@ -53,6 +52,11 @@ void board_reset(void)
53 au_writel(0x00000000, PB1100_RST_VDDI); 52 au_writel(0x00000000, PB1100_RST_VDDI);
54} 53}
55 54
55void __init board_init_irq(void)
56{
57 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
58}
59
56void __init board_setup(void) 60void __init board_setup(void)
57{ 61{
58 volatile void __iomem *base = (volatile void __iomem *)0xac000000UL; 62 volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
diff --git a/arch/mips/alchemy/devboards/pb1200/board_setup.c b/arch/mips/alchemy/devboards/pb1200/board_setup.c
index b5585e462004..94e6b7e7753d 100644
--- a/arch/mips/alchemy/devboards/pb1200/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1200/board_setup.c
@@ -30,8 +30,6 @@
30#include <prom.h> 30#include <prom.h>
31#include <au1xxx.h> 31#include <au1xxx.h>
32 32
33extern void _board_init_irq(void);
34extern void (*board_init_irq)(void);
35 33
36const char *get_system_type(void) 34const char *get_system_type(void)
37{ 35{
@@ -131,9 +129,6 @@ void __init board_setup(void)
131#ifdef CONFIG_MIPS_DB1200 129#ifdef CONFIG_MIPS_DB1200
132 printk(KERN_INFO "AMD Alchemy Db1200 Board\n"); 130 printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
133#endif 131#endif
134
135 /* Setup Pb1200 External Interrupt Controller */
136 board_init_irq = _board_init_irq;
137} 132}
138 133
139int board_au1200fb_panel(void) 134int board_au1200fb_panel(void)
diff --git a/arch/mips/alchemy/devboards/pb1200/irqmap.c b/arch/mips/alchemy/devboards/pb1200/irqmap.c
index 2a505ad8715b..1f92fec24a33 100644
--- a/arch/mips/alchemy/devboards/pb1200/irqmap.c
+++ b/arch/mips/alchemy/devboards/pb1200/irqmap.c
@@ -40,10 +40,9 @@
40 40
41struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 41struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
42 /* This is external interrupt cascade */ 42 /* This is external interrupt cascade */
43 { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, 43 { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
44}; 44};
45 45
46int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
47 46
48/* 47/*
49 * Support for External interrupts on the Pb1200 Development platform. 48 * Support for External interrupts on the Pb1200 Development platform.
@@ -121,10 +120,12 @@ static struct irq_chip external_irq_type = {
121 .unmask = pb1200_enable_irq, 120 .unmask = pb1200_enable_irq,
122}; 121};
123 122
124void _board_init_irq(void) 123void __init board_init_irq(void)
125{ 124{
126 unsigned int irq; 125 unsigned int irq;
127 126
127 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
128
128#ifdef CONFIG_MIPS_PB1200 129#ifdef CONFIG_MIPS_PB1200
129 /* We have a problem with CPLD rev 3. */ 130 /* We have a problem with CPLD rev 3. */
130 if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) { 131 if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
diff --git a/arch/mips/alchemy/devboards/pb1500/board_setup.c b/arch/mips/alchemy/devboards/pb1500/board_setup.c
index dcb36a66442f..fed3b093156a 100644
--- a/arch/mips/alchemy/devboards/pb1500/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1500/board_setup.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/interrupt.h>
28 29
29#include <asm/mach-au1x00/au1000.h> 30#include <asm/mach-au1x00/au1000.h>
30#include <asm/mach-pb1x00/pb1500.h> 31#include <asm/mach-pb1x00/pb1500.h>
@@ -38,15 +39,13 @@ char irq_tab_alchemy[][5] __initdata = {
38}; 39};
39 40
40struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 41struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
41 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, 42 { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
42 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, 43 { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
43 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, 44 { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
44 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, 45 { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
45 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, 46 { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
46}; 47};
47 48
48int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
49
50 49
51const char *get_system_type(void) 50const char *get_system_type(void)
52{ 51{
@@ -59,6 +58,11 @@ void board_reset(void)
59 au_writel(0x00000000, PB1500_RST_VDDI); 58 au_writel(0x00000000, PB1500_RST_VDDI);
60} 59}
61 60
61void __init board_init_irq(void)
62{
63 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
64}
65
62void __init board_setup(void) 66void __init board_setup(void)
63{ 67{
64 u32 pin_func; 68 u32 pin_func;
diff --git a/arch/mips/alchemy/devboards/pb1550/board_setup.c b/arch/mips/alchemy/devboards/pb1550/board_setup.c
index f462652d762a..b6e9e7d247a3 100644
--- a/arch/mips/alchemy/devboards/pb1550/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1550/board_setup.c
@@ -28,6 +28,7 @@
28 */ 28 */
29 29
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/interrupt.h>
31 32
32#include <asm/mach-au1x00/au1000.h> 33#include <asm/mach-au1x00/au1000.h>
33#include <asm/mach-pb1x00/pb1550.h> 34#include <asm/mach-pb1x00/pb1550.h>
@@ -41,13 +42,10 @@ char irq_tab_alchemy[][5] __initdata = {
41}; 42};
42 43
43struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 44struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
44 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, 45 { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
45 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, 46 { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
46}; 47};
47 48
48int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
49
50
51const char *get_system_type(void) 49const char *get_system_type(void)
52{ 50{
53 return "Alchemy Pb1550"; 51 return "Alchemy Pb1550";
@@ -59,6 +57,11 @@ void board_reset(void)
59 au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C); 57 au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C);
60} 58}
61 59
60void __init board_init_irq(void)
61{
62 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
63}
64
62void __init board_setup(void) 65void __init board_setup(void)
63{ 66{
64 u32 pin_func; 67 u32 pin_func;
diff --git a/arch/mips/alchemy/mtx-1/irqmap.c b/arch/mips/alchemy/mtx-1/irqmap.c
index f2bf02951e9c..f1ab12ab3433 100644
--- a/arch/mips/alchemy/mtx-1/irqmap.c
+++ b/arch/mips/alchemy/mtx-1/irqmap.c
@@ -27,7 +27,7 @@
27 */ 27 */
28 28
29#include <linux/init.h> 29#include <linux/init.h>
30 30#include <linux/interrupt.h>
31#include <asm/mach-au1x00/au1000.h> 31#include <asm/mach-au1x00/au1000.h>
32 32
33char irq_tab_alchemy[][5] __initdata = { 33char irq_tab_alchemy[][5] __initdata = {
@@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
42}; 42};
43 43
44struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 44struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
45 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, 45 { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
46 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, 46 { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
47 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, 47 { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
48 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, 48 { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
49 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, 49 { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
50}; 50};
51 51
52int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); 52
53void __init board_init_irq(void)
54{
55 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
56}
diff --git a/arch/mips/alchemy/xxs1500/irqmap.c b/arch/mips/alchemy/xxs1500/irqmap.c
index edf06ed11870..0f0f3012e5fd 100644
--- a/arch/mips/alchemy/xxs1500/irqmap.c
+++ b/arch/mips/alchemy/xxs1500/irqmap.c
@@ -27,23 +27,26 @@
27 */ 27 */
28 28
29#include <linux/init.h> 29#include <linux/init.h>
30 30#include <linux/interrupt.h>
31#include <asm/mach-au1x00/au1000.h> 31#include <asm/mach-au1x00/au1000.h>
32 32
33struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { 33struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
34 { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, 34 { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
35 { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, 35 { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
36 { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, 36 { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
37 { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, 37 { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
38 { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, 38 { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
39 { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, 39 { AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
40 40
41 { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, 41 { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
42 { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, 42 { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
43 { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, 43 { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
44 { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, 44 { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
45 { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */ 45 { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
46 { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, 46 { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 },
47}; 47};
48 48
49int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); 49void __init board_init_irq(void)
50{
51 au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
52}
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index 0d302bad4492..a7ba35247c8a 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -109,10 +109,11 @@ struct au1xxx_irqmap {
109 int im_request; 109 int im_request;
110}; 110};
111 111
112/* 112/* core calls this function to let boards initialize other IRQ sources */
113 * init_IRQ looks for a table with this name. 113void board_init_irq(void);
114 */ 114
115extern struct au1xxx_irqmap au1xxx_irq_map[]; 115/* boards call this to register additional (GPIO) interrupts */
116void au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count);
116 117
117#endif /* !defined (_LANGUAGE_ASSEMBLY) */ 118#endif /* !defined (_LANGUAGE_ASSEMBLY) */
118 119
@@ -505,15 +506,6 @@ extern struct au1xxx_irqmap au1xxx_irq_map[];
505 506
506#define IC1_TESTBIT 0xB1800080 507#define IC1_TESTBIT 0xB1800080
507 508
508/* Interrupt Configuration Modes */
509#define INTC_INT_DISABLED 0x0
510#define INTC_INT_RISE_EDGE 0x1
511#define INTC_INT_FALL_EDGE 0x2
512#define INTC_INT_RISE_AND_FALL_EDGE 0x3
513#define INTC_INT_HIGH_LEVEL 0x5
514#define INTC_INT_LOW_LEVEL 0x6
515#define INTC_INT_HIGH_AND_LOW_LEVEL 0x7
516
517/* Interrupt Numbers */ 509/* Interrupt Numbers */
518/* Au1000 */ 510/* Au1000 */
519#ifdef CONFIG_SOC_AU1000 511#ifdef CONFIG_SOC_AU1000