1 | /* |
2 | * Copyright 2001, 2007-2008 MontaVista Software Inc. |
3 | * Author: MontaVista Software, Inc. <source@mvista.com> |
4 | * |
5 | * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the |
9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. |
11 | * |
12 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
13 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
14 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
15 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
17 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
18 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
19 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
21 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
22 | * |
23 | * You should have received a copy of the GNU General Public License along |
24 | * with this program; if not, write to the Free Software Foundation, Inc., |
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ |
27 | |
28 | #include <linux/export.h> |
29 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> |
31 | #include <linux/slab.h> |
32 | #include <linux/syscore_ops.h> |
33 | |
34 | #include <asm/irq_cpu.h> |
35 | #include <asm/mach-au1x00/au1000.h> |
36 | #include <asm/mach-au1x00/gpio-au1300.h> |
37 | |
38 | /* Interrupt Controller register offsets */ |
39 | #define IC_CFG0RD 0x40 |
40 | #define IC_CFG0SET 0x40 |
41 | #define IC_CFG0CLR 0x44 |
42 | #define IC_CFG1RD 0x48 |
43 | #define IC_CFG1SET 0x48 |
44 | #define IC_CFG1CLR 0x4C |
45 | #define IC_CFG2RD 0x50 |
46 | #define IC_CFG2SET 0x50 |
47 | #define IC_CFG2CLR 0x54 |
48 | #define IC_REQ0INT 0x54 |
49 | #define IC_SRCRD 0x58 |
50 | #define IC_SRCSET 0x58 |
51 | #define IC_SRCCLR 0x5C |
52 | #define IC_REQ1INT 0x5C |
53 | #define IC_ASSIGNRD 0x60 |
54 | #define IC_ASSIGNSET 0x60 |
55 | #define IC_ASSIGNCLR 0x64 |
56 | #define IC_WAKERD 0x68 |
57 | #define IC_WAKESET 0x68 |
58 | #define IC_WAKECLR 0x6C |
59 | #define IC_MASKRD 0x70 |
60 | #define IC_MASKSET 0x70 |
61 | #define IC_MASKCLR 0x74 |
62 | #define IC_RISINGRD 0x78 |
63 | #define IC_RISINGCLR 0x78 |
64 | #define IC_FALLINGRD 0x7C |
65 | #define IC_FALLINGCLR 0x7C |
66 | #define IC_TESTBIT 0x80 |
67 | |
68 | /* per-processor fixed function irqs */ |
69 | struct alchemy_irqmap { |
70 | int irq; /* linux IRQ number */ |
71 | int type; /* IRQ_TYPE_ */ |
72 | int prio; /* irq priority, 0 highest, 3 lowest */ |
73 | int internal; /* GPIC: internal source (no ext. pin)? */ |
74 | }; |
75 | |
76 | static int au1x_ic_settype(struct irq_data *d, unsigned int type); |
77 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type); |
78 | |
79 | |
80 | /* NOTE on interrupt priorities: The original writers of this code said: |
81 | * |
82 | * Because of the tight timing of SETUP token to reply transactions, |
83 | * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) |
84 | * needs the highest priority. |
85 | */ |
86 | struct alchemy_irqmap au1000_irqmap[] __initdata = { |
87 | { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
88 | { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
89 | { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
90 | { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
91 | { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
92 | { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
93 | { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
94 | { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
95 | { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
96 | { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
97 | { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
98 | { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
99 | { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
100 | { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
101 | { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
102 | { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
103 | { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
104 | { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
105 | { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
106 | { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
107 | { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
108 | { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
109 | { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
110 | { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
111 | { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
112 | { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
113 | { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
114 | { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
115 | { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
116 | { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
117 | { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
118 | { -1, }, |
119 | }; |
120 | |
121 | struct alchemy_irqmap au1500_irqmap[] __initdata = { |
122 | { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
123 | { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
124 | { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
125 | { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
126 | { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
127 | { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
128 | { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
129 | { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
130 | { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
131 | { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
132 | { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
133 | { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
134 | { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
135 | { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
136 | { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
137 | { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
138 | { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
139 | { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
140 | { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
141 | { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
142 | { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
143 | { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
144 | { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
145 | { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
146 | { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
147 | { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
148 | { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
149 | { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
150 | { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
151 | { -1, }, |
152 | }; |
153 | |
154 | struct alchemy_irqmap au1100_irqmap[] __initdata = { |
155 | { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
156 | { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
157 | { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
158 | { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
159 | { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
160 | { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
161 | { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
162 | { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
163 | { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
164 | { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
165 | { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
166 | { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
167 | { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
168 | { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
169 | { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
170 | { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
171 | { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
172 | { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
173 | { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
174 | { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
175 | { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
176 | { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
177 | { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
178 | { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
179 | { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
180 | { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
181 | { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
182 | { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
183 | { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
184 | { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
185 | { AU1100_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
186 | { -1, }, |
187 | }; |
188 | |
189 | struct alchemy_irqmap au1550_irqmap[] __initdata = { |
190 | { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
191 | { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
192 | { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
193 | { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
194 | { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
195 | { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
196 | { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
197 | { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
198 | { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
199 | { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
200 | { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
201 | { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
202 | { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
203 | { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
204 | { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
205 | { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
206 | { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
207 | { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
208 | { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
209 | { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
210 | { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
211 | { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
212 | { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
213 | { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
214 | { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
215 | { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
216 | { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
217 | { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
218 | { -1, }, |
219 | }; |
220 | |
221 | struct alchemy_irqmap au1200_irqmap[] __initdata = { |
222 | { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
223 | { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
224 | { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
225 | { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
226 | { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
227 | { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
228 | { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
229 | { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
230 | { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
231 | { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
232 | { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
233 | { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
234 | { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
235 | { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
236 | { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
237 | { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
238 | { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
239 | { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
240 | { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
241 | { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
242 | { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
243 | { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
244 | { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
245 | { -1, }, |
246 | }; |
247 | |
248 | static struct alchemy_irqmap au1300_irqmap[] __initdata = { |
249 | /* multifunction: gpio pin or device */ |
250 | { AU1300_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
251 | { AU1300_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
252 | { AU1300_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
253 | { AU1300_SD1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
254 | { AU1300_SD2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
255 | { AU1300_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
256 | { AU1300_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
257 | { AU1300_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
258 | { AU1300_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
259 | { AU1300_NAND_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
260 | /* au1300 internal */ |
261 | { AU1300_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
262 | { AU1300_MMU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
263 | { AU1300_MPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
264 | { AU1300_GPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
265 | { AU1300_UDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
266 | { AU1300_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
267 | { AU1300_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
268 | { AU1300_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
269 | { AU1300_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
270 | { AU1300_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
271 | { AU1300_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
272 | { AU1300_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
273 | { AU1300_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 1, }, |
274 | { AU1300_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
275 | { AU1300_SD0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
276 | { AU1300_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
277 | { AU1300_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
278 | { AU1300_BSA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
279 | { AU1300_MPE_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
280 | { AU1300_ITE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
281 | { AU1300_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
282 | { AU1300_CIM_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
283 | { -1, }, /* terminator */ |
284 | }; |
285 | |
286 | /******************************************************************************/ |
287 | |
288 | static void au1x_ic0_unmask(struct irq_data *d) |
289 | { |
290 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
291 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
292 | |
293 | __raw_writel(1 << bit, base + IC_MASKSET); |
294 | __raw_writel(1 << bit, base + IC_WAKESET); |
295 | wmb(); |
296 | } |
297 | |
298 | static void au1x_ic1_unmask(struct irq_data *d) |
299 | { |
300 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
301 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
302 | |
303 | __raw_writel(1 << bit, base + IC_MASKSET); |
304 | __raw_writel(1 << bit, base + IC_WAKESET); |
305 | wmb(); |
306 | } |
307 | |
308 | static void au1x_ic0_mask(struct irq_data *d) |
309 | { |
310 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
311 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
312 | |
313 | __raw_writel(1 << bit, base + IC_MASKCLR); |
314 | __raw_writel(1 << bit, base + IC_WAKECLR); |
315 | wmb(); |
316 | } |
317 | |
318 | static void au1x_ic1_mask(struct irq_data *d) |
319 | { |
320 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
321 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
322 | |
323 | __raw_writel(1 << bit, base + IC_MASKCLR); |
324 | __raw_writel(1 << bit, base + IC_WAKECLR); |
325 | wmb(); |
326 | } |
327 | |
328 | static void au1x_ic0_ack(struct irq_data *d) |
329 | { |
330 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
331 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
332 | |
333 | /* |
334 | * This may assume that we don't get interrupts from |
335 | * both edges at once, or if we do, that we don't care. |
336 | */ |
337 | __raw_writel(1 << bit, base + IC_FALLINGCLR); |
338 | __raw_writel(1 << bit, base + IC_RISINGCLR); |
339 | wmb(); |
340 | } |
341 | |
342 | static void au1x_ic1_ack(struct irq_data *d) |
343 | { |
344 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
345 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
346 | |
347 | /* |
348 | * This may assume that we don't get interrupts from |
349 | * both edges at once, or if we do, that we don't care. |
350 | */ |
351 | __raw_writel(1 << bit, base + IC_FALLINGCLR); |
352 | __raw_writel(1 << bit, base + IC_RISINGCLR); |
353 | wmb(); |
354 | } |
355 | |
356 | static void au1x_ic0_maskack(struct irq_data *d) |
357 | { |
358 | unsigned int bit = d->irq - AU1000_INTC0_INT_BASE; |
359 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
360 | |
361 | __raw_writel(1 << bit, base + IC_WAKECLR); |
362 | __raw_writel(1 << bit, base + IC_MASKCLR); |
363 | __raw_writel(1 << bit, base + IC_RISINGCLR); |
364 | __raw_writel(1 << bit, base + IC_FALLINGCLR); |
365 | wmb(); |
366 | } |
367 | |
368 | static void au1x_ic1_maskack(struct irq_data *d) |
369 | { |
370 | unsigned int bit = d->irq - AU1000_INTC1_INT_BASE; |
371 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
372 | |
373 | __raw_writel(1 << bit, base + IC_WAKECLR); |
374 | __raw_writel(1 << bit, base + IC_MASKCLR); |
375 | __raw_writel(1 << bit, base + IC_RISINGCLR); |
376 | __raw_writel(1 << bit, base + IC_FALLINGCLR); |
377 | wmb(); |
378 | } |
379 | |
380 | static int au1x_ic1_setwake(struct irq_data *d, unsigned int on) |
381 | { |
382 | int bit = d->irq - AU1000_INTC1_INT_BASE; |
383 | unsigned long wakemsk, flags; |
384 | |
385 | /* only GPIO 0-7 can act as wakeup source. Fortunately these |
386 | * are wired up identically on all supported variants. |
387 | */ |
388 | if ((bit < 0) || (bit > 7)) |
389 | return -EINVAL; |
390 | |
391 | local_irq_save(flags); |
392 | wakemsk = alchemy_rdsys(AU1000_SYS_WAKEMSK); |
393 | if (on) |
394 | wakemsk |= 1 << bit; |
395 | else |
396 | wakemsk &= ~(1 << bit); |
397 | alchemy_wrsys(wakemsk, AU1000_SYS_WAKEMSK); |
398 | local_irq_restore(flags); |
399 | |
400 | return 0; |
401 | } |
402 | |
403 | /* |
404 | * irq_chips for both ICs; this way the mask handlers can be |
405 | * as short as possible. |
406 | */ |
407 | static struct irq_chip au1x_ic0_chip = { |
408 | .name = "Alchemy-IC0" , |
409 | .irq_ack = au1x_ic0_ack, |
410 | .irq_mask = au1x_ic0_mask, |
411 | .irq_mask_ack = au1x_ic0_maskack, |
412 | .irq_unmask = au1x_ic0_unmask, |
413 | .irq_set_type = au1x_ic_settype, |
414 | }; |
415 | |
416 | static struct irq_chip au1x_ic1_chip = { |
417 | .name = "Alchemy-IC1" , |
418 | .irq_ack = au1x_ic1_ack, |
419 | .irq_mask = au1x_ic1_mask, |
420 | .irq_mask_ack = au1x_ic1_maskack, |
421 | .irq_unmask = au1x_ic1_unmask, |
422 | .irq_set_type = au1x_ic_settype, |
423 | .irq_set_wake = au1x_ic1_setwake, |
424 | }; |
425 | |
426 | static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) |
427 | { |
428 | struct irq_chip *chip; |
429 | unsigned int bit, irq = d->irq; |
430 | irq_flow_handler_t handler = NULL; |
431 | unsigned char *name = NULL; |
432 | void __iomem *base; |
433 | int ret; |
434 | |
435 | if (irq >= AU1000_INTC1_INT_BASE) { |
436 | bit = irq - AU1000_INTC1_INT_BASE; |
437 | chip = &au1x_ic1_chip; |
438 | base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
439 | } else { |
440 | bit = irq - AU1000_INTC0_INT_BASE; |
441 | chip = &au1x_ic0_chip; |
442 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
443 | } |
444 | |
445 | if (bit > 31) |
446 | return -EINVAL; |
447 | |
448 | ret = 0; |
449 | |
450 | switch (flow_type) { /* cfgregs 2:1:0 */ |
451 | case IRQ_TYPE_EDGE_RISING: /* 0:0:1 */ |
452 | __raw_writel(1 << bit, base + IC_CFG2CLR); |
453 | __raw_writel(1 << bit, base + IC_CFG1CLR); |
454 | __raw_writel(1 << bit, base + IC_CFG0SET); |
455 | handler = handle_edge_irq; |
456 | name = "riseedge" ; |
457 | break; |
458 | case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */ |
459 | __raw_writel(1 << bit, base + IC_CFG2CLR); |
460 | __raw_writel(1 << bit, base + IC_CFG1SET); |
461 | __raw_writel(1 << bit, base + IC_CFG0CLR); |
462 | handler = handle_edge_irq; |
463 | name = "falledge" ; |
464 | break; |
465 | case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */ |
466 | __raw_writel(1 << bit, base + IC_CFG2CLR); |
467 | __raw_writel(1 << bit, base + IC_CFG1SET); |
468 | __raw_writel(1 << bit, base + IC_CFG0SET); |
469 | handler = handle_edge_irq; |
470 | name = "bothedge" ; |
471 | break; |
472 | case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */ |
473 | __raw_writel(1 << bit, base + IC_CFG2SET); |
474 | __raw_writel(1 << bit, base + IC_CFG1CLR); |
475 | __raw_writel(1 << bit, base + IC_CFG0SET); |
476 | handler = handle_level_irq; |
477 | name = "hilevel" ; |
478 | break; |
479 | case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */ |
480 | __raw_writel(1 << bit, base + IC_CFG2SET); |
481 | __raw_writel(1 << bit, base + IC_CFG1SET); |
482 | __raw_writel(1 << bit, base + IC_CFG0CLR); |
483 | handler = handle_level_irq; |
484 | name = "lowlevel" ; |
485 | break; |
486 | case IRQ_TYPE_NONE: /* 0:0:0 */ |
487 | __raw_writel(1 << bit, base + IC_CFG2CLR); |
488 | __raw_writel(1 << bit, base + IC_CFG1CLR); |
489 | __raw_writel(1 << bit, base + IC_CFG0CLR); |
490 | break; |
491 | default: |
492 | ret = -EINVAL; |
493 | } |
494 | irq_set_chip_handler_name_locked(d, chip, handler, name); |
495 | |
496 | wmb(); |
497 | |
498 | return ret; |
499 | } |
500 | |
501 | /******************************************************************************/ |
502 | |
503 | /* |
504 | * au1300_gpic_chgcfg - change PIN configuration. |
505 | * @gpio: pin to change (0-based GPIO number from datasheet). |
506 | * @clr: clear all bits set in 'clr'. |
507 | * @set: set these bits. |
508 | * |
509 | * modifies a pins' configuration register, bits set in @clr will |
510 | * be cleared in the register, bits in @set will be set. |
511 | */ |
512 | static inline void au1300_gpic_chgcfg(unsigned int gpio, |
513 | unsigned long clr, |
514 | unsigned long set) |
515 | { |
516 | void __iomem *r = AU1300_GPIC_ADDR; |
517 | unsigned long l; |
518 | |
519 | r += gpio * 4; /* offset into pin config array */ |
520 | l = __raw_readl(r + AU1300_GPIC_PINCFG); |
521 | l &= ~clr; |
522 | l |= set; |
523 | __raw_writel(l, r + AU1300_GPIC_PINCFG); |
524 | wmb(); |
525 | } |
526 | |
527 | /* |
528 | * au1300_pinfunc_to_gpio - assign a pin as GPIO input (GPIO ctrl). |
529 | * @pin: pin (0-based GPIO number from datasheet). |
530 | * |
531 | * Assigns a GPIO pin to the GPIO controller, so its level can either |
532 | * be read or set through the generic GPIO functions. |
533 | * If you need a GPOUT, use au1300_gpio_set_value(pin, 0/1). |
534 | * REVISIT: is this function really necessary? |
535 | */ |
536 | void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio) |
537 | { |
538 | au1300_gpio_direction_input(gpio + AU1300_GPIO_BASE); |
539 | } |
540 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_gpio); |
541 | |
542 | /* |
543 | * au1300_pinfunc_to_dev - assign a pin to the device function. |
544 | * @pin: pin (0-based GPIO number from datasheet). |
545 | * |
546 | * Assigns a GPIO pin to its associated device function; the pin will be |
547 | * driven by the device and not through GPIO functions. |
548 | */ |
549 | void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio) |
550 | { |
551 | void __iomem *r = AU1300_GPIC_ADDR; |
552 | unsigned long bit; |
553 | |
554 | r += GPIC_GPIO_BANKOFF(gpio); |
555 | bit = GPIC_GPIO_TO_BIT(gpio); |
556 | __raw_writel(bit, r + AU1300_GPIC_DEVSEL); |
557 | wmb(); |
558 | } |
559 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_dev); |
560 | |
561 | /* |
562 | * au1300_set_irq_priority - set internal priority of IRQ. |
563 | * @irq: irq to set priority (linux irq number). |
564 | * @p: priority (0 = highest, 3 = lowest). |
565 | */ |
566 | void au1300_set_irq_priority(unsigned int irq, int p) |
567 | { |
568 | irq -= ALCHEMY_GPIC_INT_BASE; |
569 | au1300_gpic_chgcfg(irq, GPIC_CFG_IL_MASK, GPIC_CFG_IL_SET(p)); |
570 | } |
571 | EXPORT_SYMBOL_GPL(au1300_set_irq_priority); |
572 | |
573 | /* |
574 | * au1300_set_dbdma_gpio - assign a gpio to one of the DBDMA triggers. |
575 | * @dchan: dbdma trigger select (0, 1). |
576 | * @gpio: pin to assign as trigger. |
577 | * |
578 | * DBDMA controller has 2 external trigger sources; this function |
579 | * assigns a GPIO to the selected trigger. |
580 | */ |
581 | void au1300_set_dbdma_gpio(int dchan, unsigned int gpio) |
582 | { |
583 | unsigned long r; |
584 | |
585 | if ((dchan >= 0) && (dchan <= 1)) { |
586 | r = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); |
587 | r &= ~(0xff << (8 * dchan)); |
588 | r |= (gpio & 0x7f) << (8 * dchan); |
589 | __raw_writel(r, AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); |
590 | wmb(); |
591 | } |
592 | } |
593 | |
594 | static inline void gpic_pin_set_idlewake(unsigned int gpio, int allow) |
595 | { |
596 | au1300_gpic_chgcfg(gpio, GPIC_CFG_IDLEWAKE, |
597 | allow ? GPIC_CFG_IDLEWAKE : 0); |
598 | } |
599 | |
600 | static void au1300_gpic_mask(struct irq_data *d) |
601 | { |
602 | void __iomem *r = AU1300_GPIC_ADDR; |
603 | unsigned long bit, irq = d->irq; |
604 | |
605 | irq -= ALCHEMY_GPIC_INT_BASE; |
606 | r += GPIC_GPIO_BANKOFF(irq); |
607 | bit = GPIC_GPIO_TO_BIT(irq); |
608 | __raw_writel(bit, r + AU1300_GPIC_IDIS); |
609 | wmb(); |
610 | |
611 | gpic_pin_set_idlewake(gpio: irq, allow: 0); |
612 | } |
613 | |
614 | static void au1300_gpic_unmask(struct irq_data *d) |
615 | { |
616 | void __iomem *r = AU1300_GPIC_ADDR; |
617 | unsigned long bit, irq = d->irq; |
618 | |
619 | irq -= ALCHEMY_GPIC_INT_BASE; |
620 | |
621 | gpic_pin_set_idlewake(gpio: irq, allow: 1); |
622 | |
623 | r += GPIC_GPIO_BANKOFF(irq); |
624 | bit = GPIC_GPIO_TO_BIT(irq); |
625 | __raw_writel(bit, r + AU1300_GPIC_IEN); |
626 | wmb(); |
627 | } |
628 | |
629 | static void au1300_gpic_maskack(struct irq_data *d) |
630 | { |
631 | void __iomem *r = AU1300_GPIC_ADDR; |
632 | unsigned long bit, irq = d->irq; |
633 | |
634 | irq -= ALCHEMY_GPIC_INT_BASE; |
635 | r += GPIC_GPIO_BANKOFF(irq); |
636 | bit = GPIC_GPIO_TO_BIT(irq); |
637 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ |
638 | __raw_writel(bit, r + AU1300_GPIC_IDIS); /* mask */ |
639 | wmb(); |
640 | |
641 | gpic_pin_set_idlewake(gpio: irq, allow: 0); |
642 | } |
643 | |
644 | static void au1300_gpic_ack(struct irq_data *d) |
645 | { |
646 | void __iomem *r = AU1300_GPIC_ADDR; |
647 | unsigned long bit, irq = d->irq; |
648 | |
649 | irq -= ALCHEMY_GPIC_INT_BASE; |
650 | r += GPIC_GPIO_BANKOFF(irq); |
651 | bit = GPIC_GPIO_TO_BIT(irq); |
652 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ |
653 | wmb(); |
654 | } |
655 | |
656 | static struct irq_chip au1300_gpic = { |
657 | .name = "GPIOINT" , |
658 | .irq_ack = au1300_gpic_ack, |
659 | .irq_mask = au1300_gpic_mask, |
660 | .irq_mask_ack = au1300_gpic_maskack, |
661 | .irq_unmask = au1300_gpic_unmask, |
662 | .irq_set_type = au1300_gpic_settype, |
663 | }; |
664 | |
665 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type) |
666 | { |
667 | unsigned long s; |
668 | unsigned char *name = NULL; |
669 | irq_flow_handler_t hdl = NULL; |
670 | |
671 | switch (type) { |
672 | case IRQ_TYPE_LEVEL_HIGH: |
673 | s = GPIC_CFG_IC_LEVEL_HIGH; |
674 | name = "high" ; |
675 | hdl = handle_level_irq; |
676 | break; |
677 | case IRQ_TYPE_LEVEL_LOW: |
678 | s = GPIC_CFG_IC_LEVEL_LOW; |
679 | name = "low" ; |
680 | hdl = handle_level_irq; |
681 | break; |
682 | case IRQ_TYPE_EDGE_RISING: |
683 | s = GPIC_CFG_IC_EDGE_RISE; |
684 | name = "posedge" ; |
685 | hdl = handle_edge_irq; |
686 | break; |
687 | case IRQ_TYPE_EDGE_FALLING: |
688 | s = GPIC_CFG_IC_EDGE_FALL; |
689 | name = "negedge" ; |
690 | hdl = handle_edge_irq; |
691 | break; |
692 | case IRQ_TYPE_EDGE_BOTH: |
693 | s = GPIC_CFG_IC_EDGE_BOTH; |
694 | name = "bothedge" ; |
695 | hdl = handle_edge_irq; |
696 | break; |
697 | case IRQ_TYPE_NONE: |
698 | s = GPIC_CFG_IC_OFF; |
699 | name = "disabled" ; |
700 | hdl = handle_level_irq; |
701 | break; |
702 | default: |
703 | return -EINVAL; |
704 | } |
705 | |
706 | irq_set_chip_handler_name_locked(d, &au1300_gpic, hdl, name); |
707 | |
708 | au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s); |
709 | |
710 | return 0; |
711 | } |
712 | |
713 | /******************************************************************************/ |
714 | |
715 | static inline void ic_init(void __iomem *base) |
716 | { |
717 | /* initialize interrupt controller to a safe state */ |
718 | __raw_writel(0xffffffff, base + IC_CFG0CLR); |
719 | __raw_writel(0xffffffff, base + IC_CFG1CLR); |
720 | __raw_writel(0xffffffff, base + IC_CFG2CLR); |
721 | __raw_writel(0xffffffff, base + IC_MASKCLR); |
722 | __raw_writel(0xffffffff, base + IC_ASSIGNCLR); |
723 | __raw_writel(0xffffffff, base + IC_WAKECLR); |
724 | __raw_writel(0xffffffff, base + IC_SRCSET); |
725 | __raw_writel(0xffffffff, base + IC_FALLINGCLR); |
726 | __raw_writel(0xffffffff, base + IC_RISINGCLR); |
727 | __raw_writel(0x00000000, base + IC_TESTBIT); |
728 | wmb(); |
729 | } |
730 | |
731 | static unsigned long alchemy_gpic_pmdata[ALCHEMY_GPIC_INT_NUM + 6]; |
732 | |
733 | static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d) |
734 | { |
735 | d[0] = __raw_readl(base + IC_CFG0RD); |
736 | d[1] = __raw_readl(base + IC_CFG1RD); |
737 | d[2] = __raw_readl(base + IC_CFG2RD); |
738 | d[3] = __raw_readl(base + IC_SRCRD); |
739 | d[4] = __raw_readl(base + IC_ASSIGNRD); |
740 | d[5] = __raw_readl(base + IC_WAKERD); |
741 | d[6] = __raw_readl(base + IC_MASKRD); |
742 | ic_init(base); /* shut it up too while at it */ |
743 | } |
744 | |
745 | static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d) |
746 | { |
747 | ic_init(base); |
748 | |
749 | __raw_writel(d[0], base + IC_CFG0SET); |
750 | __raw_writel(d[1], base + IC_CFG1SET); |
751 | __raw_writel(d[2], base + IC_CFG2SET); |
752 | __raw_writel(d[3], base + IC_SRCSET); |
753 | __raw_writel(d[4], base + IC_ASSIGNSET); |
754 | __raw_writel(d[5], base + IC_WAKESET); |
755 | wmb(); |
756 | |
757 | __raw_writel(d[6], base + IC_MASKSET); |
758 | wmb(); |
759 | } |
760 | |
761 | static int alchemy_ic_suspend(void) |
762 | { |
763 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), |
764 | alchemy_gpic_pmdata); |
765 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), |
766 | &alchemy_gpic_pmdata[7]); |
767 | return 0; |
768 | } |
769 | |
770 | static void alchemy_ic_resume(void) |
771 | { |
772 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), |
773 | &alchemy_gpic_pmdata[7]); |
774 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), |
775 | alchemy_gpic_pmdata); |
776 | } |
777 | |
778 | static int alchemy_gpic_suspend(void) |
779 | { |
780 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); |
781 | int i; |
782 | |
783 | /* save 4 interrupt mask status registers */ |
784 | alchemy_gpic_pmdata[0] = __raw_readl(base + AU1300_GPIC_IEN + 0x0); |
785 | alchemy_gpic_pmdata[1] = __raw_readl(base + AU1300_GPIC_IEN + 0x4); |
786 | alchemy_gpic_pmdata[2] = __raw_readl(base + AU1300_GPIC_IEN + 0x8); |
787 | alchemy_gpic_pmdata[3] = __raw_readl(base + AU1300_GPIC_IEN + 0xc); |
788 | |
789 | /* save misc register(s) */ |
790 | alchemy_gpic_pmdata[4] = __raw_readl(base + AU1300_GPIC_DMASEL); |
791 | |
792 | /* molto silenzioso */ |
793 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); |
794 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); |
795 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); |
796 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); |
797 | wmb(); |
798 | |
799 | /* save pin/int-type configuration */ |
800 | base += AU1300_GPIC_PINCFG; |
801 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) |
802 | alchemy_gpic_pmdata[i + 5] = __raw_readl(base + (i << 2)); |
803 | |
804 | wmb(); |
805 | |
806 | return 0; |
807 | } |
808 | |
809 | static void alchemy_gpic_resume(void) |
810 | { |
811 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); |
812 | int i; |
813 | |
814 | /* disable all first */ |
815 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); |
816 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); |
817 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); |
818 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); |
819 | wmb(); |
820 | |
821 | /* restore pin/int-type configurations */ |
822 | base += AU1300_GPIC_PINCFG; |
823 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) |
824 | __raw_writel(alchemy_gpic_pmdata[i + 5], base + (i << 2)); |
825 | wmb(); |
826 | |
827 | /* restore misc register(s) */ |
828 | base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); |
829 | __raw_writel(alchemy_gpic_pmdata[4], base + AU1300_GPIC_DMASEL); |
830 | wmb(); |
831 | |
832 | /* finally restore masks */ |
833 | __raw_writel(alchemy_gpic_pmdata[0], base + AU1300_GPIC_IEN + 0x0); |
834 | __raw_writel(alchemy_gpic_pmdata[1], base + AU1300_GPIC_IEN + 0x4); |
835 | __raw_writel(alchemy_gpic_pmdata[2], base + AU1300_GPIC_IEN + 0x8); |
836 | __raw_writel(alchemy_gpic_pmdata[3], base + AU1300_GPIC_IEN + 0xc); |
837 | wmb(); |
838 | } |
839 | |
840 | static struct syscore_ops alchemy_ic_pmops = { |
841 | .suspend = alchemy_ic_suspend, |
842 | .resume = alchemy_ic_resume, |
843 | }; |
844 | |
845 | static struct syscore_ops alchemy_gpic_pmops = { |
846 | .suspend = alchemy_gpic_suspend, |
847 | .resume = alchemy_gpic_resume, |
848 | }; |
849 | |
850 | /******************************************************************************/ |
851 | |
852 | /* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */ |
853 | #define DISP(name, base, addr) \ |
854 | static void au1000_##name##_dispatch(struct irq_desc *d) \ |
855 | { \ |
856 | unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr)); \ |
857 | if (likely(r)) \ |
858 | generic_handle_irq(base + __ffs(r)); \ |
859 | else \ |
860 | spurious_interrupt(); \ |
861 | } |
862 | |
863 | DISP(ic0r0, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ0INT) |
864 | DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT) |
865 | DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT) |
866 | DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT) |
867 | |
868 | static void alchemy_gpic_dispatch(struct irq_desc *d) |
869 | { |
870 | int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); |
871 | generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i); |
872 | } |
873 | |
874 | /******************************************************************************/ |
875 | |
876 | static void __init au1000_init_irq(struct alchemy_irqmap *map) |
877 | { |
878 | unsigned int bit, irq_nr; |
879 | void __iomem *base; |
880 | |
881 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR)); |
882 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR)); |
883 | register_syscore_ops(ops: &alchemy_ic_pmops); |
884 | mips_cpu_irq_init(); |
885 | |
886 | /* register all 64 possible IC0+IC1 irq sources as type "none". |
887 | * Use set_irq_type() to set edge/level behaviour at runtime. |
888 | */ |
889 | for (irq_nr = AU1000_INTC0_INT_BASE; |
890 | (irq_nr < AU1000_INTC0_INT_BASE + 32); irq_nr++) |
891 | au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE); |
892 | |
893 | for (irq_nr = AU1000_INTC1_INT_BASE; |
894 | (irq_nr < AU1000_INTC1_INT_BASE + 32); irq_nr++) |
895 | au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE); |
896 | |
897 | /* |
898 | * Initialize IC0, which is fixed per processor. |
899 | */ |
900 | while (map->irq != -1) { |
901 | irq_nr = map->irq; |
902 | |
903 | if (irq_nr >= AU1000_INTC1_INT_BASE) { |
904 | bit = irq_nr - AU1000_INTC1_INT_BASE; |
905 | base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR); |
906 | } else { |
907 | bit = irq_nr - AU1000_INTC0_INT_BASE; |
908 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
909 | } |
910 | if (map->prio == 0) |
911 | __raw_writel(1 << bit, base + IC_ASSIGNSET); |
912 | |
913 | au1x_ic_settype(d: irq_get_irq_data(irq_nr), type: map->type); |
914 | ++map; |
915 | } |
916 | |
917 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, au1000_ic0r0_dispatch); |
918 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, au1000_ic0r1_dispatch); |
919 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, au1000_ic1r0_dispatch); |
920 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch); |
921 | } |
922 | |
923 | static void __init alchemy_gpic_init_irq(const struct alchemy_irqmap *dints) |
924 | { |
925 | int i; |
926 | void __iomem *bank_base; |
927 | |
928 | register_syscore_ops(ops: &alchemy_gpic_pmops); |
929 | mips_cpu_irq_init(); |
930 | |
931 | /* disable & ack all possible interrupt sources */ |
932 | for (i = 0; i < 4; i++) { |
933 | bank_base = AU1300_GPIC_ADDR + (i * 4); |
934 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IDIS); |
935 | wmb(); |
936 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IPEND); |
937 | wmb(); |
938 | } |
939 | |
940 | /* register an irq_chip for them, with 2nd highest priority */ |
941 | for (i = ALCHEMY_GPIC_INT_BASE; i <= ALCHEMY_GPIC_INT_LAST; i++) { |
942 | au1300_set_irq_priority(i, 1); |
943 | au1300_gpic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); |
944 | } |
945 | |
946 | /* setup known on-chip sources */ |
947 | while ((i = dints->irq) != -1) { |
948 | au1300_gpic_settype(d: irq_get_irq_data(i), type: dints->type); |
949 | au1300_set_irq_priority(i, dints->prio); |
950 | |
951 | if (dints->internal) |
952 | au1300_pinfunc_to_dev(i - ALCHEMY_GPIC_INT_BASE); |
953 | |
954 | dints++; |
955 | } |
956 | |
957 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch); |
958 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch); |
959 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch); |
960 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch); |
961 | } |
962 | |
963 | /******************************************************************************/ |
964 | |
965 | void __init arch_init_irq(void) |
966 | { |
967 | switch (alchemy_get_cputype()) { |
968 | case ALCHEMY_CPU_AU1000: |
969 | au1000_init_irq(map: au1000_irqmap); |
970 | break; |
971 | case ALCHEMY_CPU_AU1500: |
972 | au1000_init_irq(map: au1500_irqmap); |
973 | break; |
974 | case ALCHEMY_CPU_AU1100: |
975 | au1000_init_irq(map: au1100_irqmap); |
976 | break; |
977 | case ALCHEMY_CPU_AU1550: |
978 | au1000_init_irq(map: au1550_irqmap); |
979 | break; |
980 | case ALCHEMY_CPU_AU1200: |
981 | au1000_init_irq(map: au1200_irqmap); |
982 | break; |
983 | case ALCHEMY_CPU_AU1300: |
984 | alchemy_gpic_init_irq(dints: au1300_irqmap); |
985 | break; |
986 | default: |
987 | pr_err("unknown Alchemy IRQ core\n" ); |
988 | break; |
989 | } |
990 | } |
991 | |
992 | asmlinkage void plat_irq_dispatch(void) |
993 | { |
994 | unsigned long r = (read_c0_status() & read_c0_cause()) >> 8; |
995 | do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff)); |
996 | } |
997 | |