diff options
author | Manuel Lauss <mano@roarinelk.homelinux.net> | 2008-12-21 03:26:17 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-01-11 04:57:26 -0500 |
commit | 785e3268e2951d4c0c21417c8e5d8004b2ab2480 (patch) | |
tree | 3e7e98dbaf2592f22f65090325a823d36caa13f7 | |
parent | 7179380ee9bdeb5fa2ff07581f512fe0f5382e5b (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
-rw-r--r-- | arch/mips/alchemy/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/alchemy/common/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/alchemy/common/au1xxx_irqmap.c | 205 | ||||
-rw-r--r-- | arch/mips/alchemy/common/irq.c | 785 | ||||
-rw-r--r-- | arch/mips/alchemy/common/power.c | 6 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/db1x00/irqmap.c | 24 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1000/board_setup.c | 9 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1100/board_setup.c | 16 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1200/board_setup.c | 5 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1200/irqmap.c | 7 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1500/board_setup.c | 18 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1550/board_setup.c | 13 | ||||
-rw-r--r-- | arch/mips/alchemy/mtx-1/irqmap.c | 18 | ||||
-rw-r--r-- | arch/mips/alchemy/xxs1500/irqmap.c | 31 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-au1x00/au1000.h | 18 |
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 | ||
8 | obj-y += prom.o irq.o puts.o time.o reset.o \ | 8 | obj-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 | ||
12 | obj-$(CONFIG_PCI) += pci.o | 12 | obj-$(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 | */ | ||
40 | struct 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 | |||
205 | int __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 */ | 40 | static 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 | ||
45 | void (*board_init_irq)(void) __initdata = NULL; | 42 | static int au1x_ic_settype(unsigned int irq, unsigned int flow_type); |
43 | |||
44 | /* per-processor fixed function irqs */ | ||
45 | struct 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 | ||
47 | static 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 | ||
133 | inline void local_enable_irq(unsigned int irq_nr) | 293 | static 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 | 301 | static void au1x_ic1_unmask(unsigned int irq_nr) | |
148 | inline 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 | 317 | static void au1x_ic0_mask(unsigned int irq_nr) | |
163 | static 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 | 325 | static void au1x_ic1_mask(unsigned int irq_nr) | |
178 | static 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 | 333 | static void au1x_ic0_ack(unsigned int irq_nr) | |
193 | static 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 | ||
213 | static inline void mask_and_ack_level_irq(unsigned int irq_nr) | 346 | static 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 | |||
225 | static 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 | |||
238 | unsigned 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 | ||
258 | void restore_local_and_enable(int controller, unsigned long mask) | 359 | static 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 | /* | |
281 | static 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 | }; | 389 | static struct irq_chip au1x_ic0_chip = { |
289 | 390 | .name = "Alchemy-IC0", | |
290 | static 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 | |||
299 | static 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 | ||
308 | static struct irq_chip level_irq_type = { | 398 | static 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 | ||
317 | static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req) | 408 | static 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 | ||
439 | static void intc0_req0_irqdispatch(void) | 488 | asmlinkage 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)) { | ||
514 | spurious: | ||
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 */ | |
467 | static void intc0_req1_irqdispatch(void) | 534 | void __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) |
487 | static 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 | |||
503 | static 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 | |||
518 | asmlinkage 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 | ||
536 | void __init arch_init_irq(void) | 561 | void __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 | |||
615 | unsigned 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. | 635 | void 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 | ||
52 | extern unsigned long save_local_and_disable(int controller); | 52 | extern unsigned long save_local_and_disable(int controller); |
53 | extern void restore_local_and_enable(int controller, unsigned long mask); | 53 | extern void restore_local_and_enable(int controller, unsigned long mask); |
54 | extern void local_enable_irq(unsigned int irq_nr); | ||
55 | 54 | ||
56 | static DEFINE_SPINLOCK(pm_lock); | 55 | static 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 | ||
86 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | 87 | void __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 | ||
34 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 34 | struct 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 | ||
38 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | ||
39 | |||
40 | 38 | ||
41 | const char *get_system_type(void) | 39 | const char *get_system_type(void) |
42 | { | 40 | { |
@@ -47,6 +45,11 @@ void board_reset(void) | |||
47 | { | 45 | { |
48 | } | 46 | } |
49 | 47 | ||
48 | void __init board_init_irq(void) | ||
49 | { | ||
50 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); | ||
51 | } | ||
52 | |||
50 | void __init board_setup(void) | 53 | void __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 | ||
35 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 36 | struct 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 | ||
42 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | ||
43 | |||
44 | 43 | ||
45 | const char *get_system_type(void) | 44 | const 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 | ||
55 | void __init board_init_irq(void) | ||
56 | { | ||
57 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); | ||
58 | } | ||
59 | |||
56 | void __init board_setup(void) | 60 | void __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 | ||
33 | extern void _board_init_irq(void); | ||
34 | extern void (*board_init_irq)(void); | ||
35 | 33 | ||
36 | const char *get_system_type(void) | 34 | const 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 | ||
139 | int board_au1200fb_panel(void) | 134 | int 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 | ||
41 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 41 | struct 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 | ||
46 | int __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 | ||
124 | void _board_init_irq(void) | 123 | void __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 | ||
40 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 41 | struct 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 | ||
48 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | ||
49 | |||
50 | 49 | ||
51 | const char *get_system_type(void) | 50 | const 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 | ||
61 | void __init board_init_irq(void) | ||
62 | { | ||
63 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); | ||
64 | } | ||
65 | |||
62 | void __init board_setup(void) | 66 | void __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 | ||
43 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 44 | struct 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 | ||
48 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | ||
49 | |||
50 | |||
51 | const char *get_system_type(void) | 49 | const 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 | ||
60 | void __init board_init_irq(void) | ||
61 | { | ||
62 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); | ||
63 | } | ||
64 | |||
62 | void __init board_setup(void) | 65 | void __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 | ||
33 | char irq_tab_alchemy[][5] __initdata = { | 33 | char irq_tab_alchemy[][5] __initdata = { |
@@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = { | |||
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 44 | struct 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 | ||
52 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | 52 | |
53 | void __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 | ||
33 | struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | 33 | struct 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 | ||
49 | int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map); | 49 | void __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. | 113 | void board_init_irq(void); |
114 | */ | 114 | |
115 | extern struct au1xxx_irqmap au1xxx_irq_map[]; | 115 | /* boards call this to register additional (GPIO) interrupts */ |
116 | void 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 |