diff options
author | Manuel Lauss <manuel.lauss@googlemail.com> | 2011-12-08 05:42:16 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-12-08 05:42:16 -0500 |
commit | 3eab8095ef1658f5cd4927a0224b1214329cb348 (patch) | |
tree | f7500932f3805e2896f381a959bf82721f9c5881 /arch/mips/alchemy/common | |
parent | 894cc87e2e24eccaf9a33f2744d618567f51408c (diff) |
MIPS: Alchemy: merge Au1000 and Au1300-style IRQ controller code.
With a generic plat_irq_dispatch (for Alchemy at least) code for both
interrupt controller types can coexist in a single kernel image and be
autodetected at runtime.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2935/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/alchemy/common')
-rw-r--r-- | arch/mips/alchemy/common/Makefile | 5 | ||||
-rw-r--r-- | arch/mips/alchemy/common/gpioint.c | 413 | ||||
-rw-r--r-- | arch/mips/alchemy/common/irq.c | 719 |
3 files changed, 550 insertions, 587 deletions
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile index d3f5c5137804..407ebc00e661 100644 --- a/arch/mips/alchemy/common/Makefile +++ b/arch/mips/alchemy/common/Makefile | |||
@@ -6,10 +6,7 @@ | |||
6 | # | 6 | # |
7 | 7 | ||
8 | obj-y += prom.o time.o clocks.o platform.o power.o setup.o \ | 8 | obj-y += prom.o time.o clocks.o platform.o power.o setup.o \ |
9 | sleeper.o dma.o dbdma.o vss.o | 9 | sleeper.o dma.o dbdma.o vss.o irq.o |
10 | |||
11 | obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += irq.o | ||
12 | obj-$(CONFIG_ALCHEMY_GPIOINT_AU1300) += gpioint.o | ||
13 | 10 | ||
14 | # optional gpiolib support | 11 | # optional gpiolib support |
15 | ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) | 12 | ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) |
diff --git a/arch/mips/alchemy/common/gpioint.c b/arch/mips/alchemy/common/gpioint.c deleted file mode 100644 index daaaab09044a..000000000000 --- a/arch/mips/alchemy/common/gpioint.c +++ /dev/null | |||
@@ -1,413 +0,0 @@ | |||
1 | /* | ||
2 | * gpioint.c - Au1300 GPIO+Interrupt controller (I call it "GPIC") support. | ||
3 | * | ||
4 | * Copyright (c) 2009-2011 Manuel Lauss <manuel.lauss@googlemail.com> | ||
5 | * | ||
6 | * licensed under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/io.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/syscore_ops.h> | ||
14 | #include <linux/types.h> | ||
15 | |||
16 | #include <asm/irq_cpu.h> | ||
17 | #include <asm/mach-au1x00/au1000.h> | ||
18 | #include <asm/mach-au1x00/gpio-au1300.h> | ||
19 | |||
20 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type); | ||
21 | |||
22 | /* setup for known onchip sources */ | ||
23 | struct gpic_devint_data { | ||
24 | int irq; /* linux IRQ number */ | ||
25 | int type; /* IRQ_TYPE_ */ | ||
26 | int prio; /* irq priority, 0 highest, 3 lowest */ | ||
27 | int internal; /* internal source (no ext. pin)? */ | ||
28 | }; | ||
29 | |||
30 | static const struct gpic_devint_data au1300_devints[] __initdata = { | ||
31 | /* multifunction: gpio pin or device */ | ||
32 | { AU1300_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
33 | { AU1300_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
34 | { AU1300_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
35 | { AU1300_SD1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
36 | { AU1300_SD2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
37 | { AU1300_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
38 | { AU1300_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
39 | { AU1300_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
40 | { AU1300_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
41 | { AU1300_NAND_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, | ||
42 | /* au1300 internal */ | ||
43 | { AU1300_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
44 | { AU1300_MMU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
45 | { AU1300_MPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
46 | { AU1300_GPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
47 | { AU1300_UDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
48 | { AU1300_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
49 | { AU1300_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
50 | { AU1300_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
51 | { AU1300_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
52 | { AU1300_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
53 | { AU1300_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
54 | { AU1300_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
55 | { AU1300_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 1, }, | ||
56 | { AU1300_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
57 | { AU1300_SD0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
58 | { AU1300_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
59 | { AU1300_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
60 | { AU1300_BSA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
61 | { AU1300_MPE_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, | ||
62 | { AU1300_ITE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
63 | { AU1300_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
64 | { AU1300_CIM_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, | ||
65 | { -1, }, /* terminator */ | ||
66 | }; | ||
67 | |||
68 | |||
69 | /* | ||
70 | * au1300_gpic_chgcfg - change PIN configuration. | ||
71 | * @gpio: pin to change (0-based GPIO number from datasheet). | ||
72 | * @clr: clear all bits set in 'clr'. | ||
73 | * @set: set these bits. | ||
74 | * | ||
75 | * modifies a pins' configuration register, bits set in @clr will | ||
76 | * be cleared in the register, bits in @set will be set. | ||
77 | */ | ||
78 | static inline void au1300_gpic_chgcfg(unsigned int gpio, | ||
79 | unsigned long clr, | ||
80 | unsigned long set) | ||
81 | { | ||
82 | void __iomem *r = AU1300_GPIC_ADDR; | ||
83 | unsigned long l; | ||
84 | |||
85 | r += gpio * 4; /* offset into pin config array */ | ||
86 | l = __raw_readl(r + AU1300_GPIC_PINCFG); | ||
87 | l &= ~clr; | ||
88 | l |= set; | ||
89 | __raw_writel(l, r + AU1300_GPIC_PINCFG); | ||
90 | wmb(); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * au1300_pinfunc_to_gpio - assign a pin as GPIO input (GPIO ctrl). | ||
95 | * @pin: pin (0-based GPIO number from datasheet). | ||
96 | * | ||
97 | * Assigns a GPIO pin to the GPIO controller, so its level can either | ||
98 | * be read or set through the generic GPIO functions. | ||
99 | * If you need a GPOUT, use au1300_gpio_set_value(pin, 0/1). | ||
100 | * REVISIT: is this function really necessary? | ||
101 | */ | ||
102 | void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio) | ||
103 | { | ||
104 | au1300_gpio_direction_input(gpio + AU1300_GPIO_BASE); | ||
105 | } | ||
106 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_gpio); | ||
107 | |||
108 | /* | ||
109 | * au1300_pinfunc_to_dev - assign a pin to the device function. | ||
110 | * @pin: pin (0-based GPIO number from datasheet). | ||
111 | * | ||
112 | * Assigns a GPIO pin to its associated device function; the pin will be | ||
113 | * driven by the device and not through GPIO functions. | ||
114 | */ | ||
115 | void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio) | ||
116 | { | ||
117 | void __iomem *r = AU1300_GPIC_ADDR; | ||
118 | unsigned long bit; | ||
119 | |||
120 | r += GPIC_GPIO_BANKOFF(gpio); | ||
121 | bit = GPIC_GPIO_TO_BIT(gpio); | ||
122 | __raw_writel(bit, r + AU1300_GPIC_DEVSEL); | ||
123 | wmb(); | ||
124 | } | ||
125 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_dev); | ||
126 | |||
127 | /* | ||
128 | * au1300_set_irq_priority - set internal priority of IRQ. | ||
129 | * @irq: irq to set priority (linux irq number). | ||
130 | * @p: priority (0 = highest, 3 = lowest). | ||
131 | */ | ||
132 | void au1300_set_irq_priority(unsigned int irq, int p) | ||
133 | { | ||
134 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
135 | au1300_gpic_chgcfg(irq, GPIC_CFG_IL_MASK, GPIC_CFG_IL_SET(p)); | ||
136 | } | ||
137 | EXPORT_SYMBOL_GPL(au1300_set_irq_priority); | ||
138 | |||
139 | /* | ||
140 | * au1300_set_dbdma_gpio - assign a gpio to one of the DBDMA triggers. | ||
141 | * @dchan: dbdma trigger select (0, 1). | ||
142 | * @gpio: pin to assign as trigger. | ||
143 | * | ||
144 | * DBDMA controller has 2 external trigger sources; this function | ||
145 | * assigns a GPIO to the selected trigger. | ||
146 | */ | ||
147 | void au1300_set_dbdma_gpio(int dchan, unsigned int gpio) | ||
148 | { | ||
149 | unsigned long r; | ||
150 | |||
151 | if ((dchan >= 0) && (dchan <= 1)) { | ||
152 | r = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); | ||
153 | r &= ~(0xff << (8 * dchan)); | ||
154 | r |= (gpio & 0x7f) << (8 * dchan); | ||
155 | __raw_writel(r, AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); | ||
156 | wmb(); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /**********************************************************************/ | ||
161 | |||
162 | static inline void gpic_pin_set_idlewake(unsigned int gpio, int allow) | ||
163 | { | ||
164 | au1300_gpic_chgcfg(gpio, GPIC_CFG_IDLEWAKE, | ||
165 | allow ? GPIC_CFG_IDLEWAKE : 0); | ||
166 | } | ||
167 | |||
168 | static void au1300_gpic_mask(struct irq_data *d) | ||
169 | { | ||
170 | void __iomem *r = AU1300_GPIC_ADDR; | ||
171 | unsigned long bit, irq = d->irq; | ||
172 | |||
173 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
174 | r += GPIC_GPIO_BANKOFF(irq); | ||
175 | bit = GPIC_GPIO_TO_BIT(irq); | ||
176 | __raw_writel(bit, r + AU1300_GPIC_IDIS); | ||
177 | wmb(); | ||
178 | |||
179 | gpic_pin_set_idlewake(irq, 0); | ||
180 | } | ||
181 | |||
182 | static void au1300_gpic_unmask(struct irq_data *d) | ||
183 | { | ||
184 | void __iomem *r = AU1300_GPIC_ADDR; | ||
185 | unsigned long bit, irq = d->irq; | ||
186 | |||
187 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
188 | |||
189 | gpic_pin_set_idlewake(irq, 1); | ||
190 | |||
191 | r += GPIC_GPIO_BANKOFF(irq); | ||
192 | bit = GPIC_GPIO_TO_BIT(irq); | ||
193 | __raw_writel(bit, r + AU1300_GPIC_IEN); | ||
194 | wmb(); | ||
195 | } | ||
196 | |||
197 | static void au1300_gpic_maskack(struct irq_data *d) | ||
198 | { | ||
199 | void __iomem *r = AU1300_GPIC_ADDR; | ||
200 | unsigned long bit, irq = d->irq; | ||
201 | |||
202 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
203 | r += GPIC_GPIO_BANKOFF(irq); | ||
204 | bit = GPIC_GPIO_TO_BIT(irq); | ||
205 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
206 | __raw_writel(bit, r + AU1300_GPIC_IDIS); /* mask */ | ||
207 | wmb(); | ||
208 | |||
209 | gpic_pin_set_idlewake(irq, 0); | ||
210 | } | ||
211 | |||
212 | static void au1300_gpic_ack(struct irq_data *d) | ||
213 | { | ||
214 | void __iomem *r = AU1300_GPIC_ADDR; | ||
215 | unsigned long bit, irq = d->irq; | ||
216 | |||
217 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
218 | r += GPIC_GPIO_BANKOFF(irq); | ||
219 | bit = GPIC_GPIO_TO_BIT(irq); | ||
220 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
221 | wmb(); | ||
222 | } | ||
223 | |||
224 | static struct irq_chip au1300_gpic = { | ||
225 | .name = "GPIOINT", | ||
226 | .irq_ack = au1300_gpic_ack, | ||
227 | .irq_mask = au1300_gpic_mask, | ||
228 | .irq_mask_ack = au1300_gpic_maskack, | ||
229 | .irq_unmask = au1300_gpic_unmask, | ||
230 | .irq_set_type = au1300_gpic_settype, | ||
231 | }; | ||
232 | |||
233 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type) | ||
234 | { | ||
235 | unsigned long s; | ||
236 | unsigned char *name = NULL; | ||
237 | irq_flow_handler_t hdl = NULL; | ||
238 | |||
239 | switch (type) { | ||
240 | case IRQ_TYPE_LEVEL_HIGH: | ||
241 | s = GPIC_CFG_IC_LEVEL_HIGH; | ||
242 | name = "high"; | ||
243 | hdl = handle_level_irq; | ||
244 | break; | ||
245 | case IRQ_TYPE_LEVEL_LOW: | ||
246 | s = GPIC_CFG_IC_LEVEL_LOW; | ||
247 | name = "low"; | ||
248 | hdl = handle_level_irq; | ||
249 | break; | ||
250 | case IRQ_TYPE_EDGE_RISING: | ||
251 | s = GPIC_CFG_IC_EDGE_RISE; | ||
252 | name = "posedge"; | ||
253 | hdl = handle_edge_irq; | ||
254 | break; | ||
255 | case IRQ_TYPE_EDGE_FALLING: | ||
256 | s = GPIC_CFG_IC_EDGE_FALL; | ||
257 | name = "negedge"; | ||
258 | hdl = handle_edge_irq; | ||
259 | break; | ||
260 | case IRQ_TYPE_EDGE_BOTH: | ||
261 | s = GPIC_CFG_IC_EDGE_BOTH; | ||
262 | name = "bothedge"; | ||
263 | hdl = handle_edge_irq; | ||
264 | break; | ||
265 | case IRQ_TYPE_NONE: | ||
266 | s = GPIC_CFG_IC_OFF; | ||
267 | name = "disabled"; | ||
268 | hdl = handle_level_irq; | ||
269 | break; | ||
270 | default: | ||
271 | return -EINVAL; | ||
272 | } | ||
273 | |||
274 | __irq_set_chip_handler_name_locked(d->irq, &au1300_gpic, hdl, name); | ||
275 | |||
276 | au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | /******************************************************************************/ | ||
282 | |||
283 | static unsigned long alchemy_gpic_pmdata[ALCHEMY_GPIC_INT_NUM + 6]; | ||
284 | |||
285 | static int alchemy_gpic_suspend(void) | ||
286 | { | ||
287 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
288 | int i; | ||
289 | |||
290 | /* save 4 interrupt mask status registers */ | ||
291 | alchemy_gpic_pmdata[0] = __raw_readl(base + AU1300_GPIC_IEN + 0x0); | ||
292 | alchemy_gpic_pmdata[1] = __raw_readl(base + AU1300_GPIC_IEN + 0x4); | ||
293 | alchemy_gpic_pmdata[2] = __raw_readl(base + AU1300_GPIC_IEN + 0x8); | ||
294 | alchemy_gpic_pmdata[3] = __raw_readl(base + AU1300_GPIC_IEN + 0xc); | ||
295 | |||
296 | /* save misc register(s) */ | ||
297 | alchemy_gpic_pmdata[4] = __raw_readl(base + AU1300_GPIC_DMASEL); | ||
298 | |||
299 | /* molto silenzioso */ | ||
300 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
301 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
302 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
303 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
304 | wmb(); | ||
305 | |||
306 | /* save pin/int-type configuration */ | ||
307 | base += AU1300_GPIC_PINCFG; | ||
308 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
309 | alchemy_gpic_pmdata[i + 5] = __raw_readl(base + (i << 2)); | ||
310 | |||
311 | wmb(); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static void alchemy_gpic_resume(void) | ||
317 | { | ||
318 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
319 | int i; | ||
320 | |||
321 | /* disable all first */ | ||
322 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
323 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
324 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
325 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
326 | wmb(); | ||
327 | |||
328 | /* restore pin/int-type configurations */ | ||
329 | base += AU1300_GPIC_PINCFG; | ||
330 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
331 | __raw_writel(alchemy_gpic_pmdata[i + 5], base + (i << 2)); | ||
332 | wmb(); | ||
333 | |||
334 | /* restore misc register(s) */ | ||
335 | base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
336 | __raw_writel(alchemy_gpic_pmdata[4], base + AU1300_GPIC_DMASEL); | ||
337 | wmb(); | ||
338 | |||
339 | /* finally restore masks */ | ||
340 | __raw_writel(alchemy_gpic_pmdata[0], base + AU1300_GPIC_IEN + 0x0); | ||
341 | __raw_writel(alchemy_gpic_pmdata[1], base + AU1300_GPIC_IEN + 0x4); | ||
342 | __raw_writel(alchemy_gpic_pmdata[2], base + AU1300_GPIC_IEN + 0x8); | ||
343 | __raw_writel(alchemy_gpic_pmdata[3], base + AU1300_GPIC_IEN + 0xc); | ||
344 | wmb(); | ||
345 | } | ||
346 | |||
347 | static struct syscore_ops alchemy_gpic_pmops = { | ||
348 | .suspend = alchemy_gpic_suspend, | ||
349 | .resume = alchemy_gpic_resume, | ||
350 | }; | ||
351 | |||
352 | static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d) | ||
353 | { | ||
354 | int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); | ||
355 | generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i); | ||
356 | } | ||
357 | |||
358 | static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints) | ||
359 | { | ||
360 | int i; | ||
361 | void __iomem *bank_base; | ||
362 | |||
363 | register_syscore_ops(&alchemy_gpic_pmops); | ||
364 | mips_cpu_irq_init(); | ||
365 | |||
366 | /* disable & ack all possible interrupt sources */ | ||
367 | for (i = 0; i < 4; i++) { | ||
368 | bank_base = AU1300_GPIC_ADDR + (i * 4); | ||
369 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IDIS); | ||
370 | wmb(); | ||
371 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IPEND); | ||
372 | wmb(); | ||
373 | } | ||
374 | |||
375 | /* register an irq_chip for them, with 2nd highest priority */ | ||
376 | for (i = ALCHEMY_GPIC_INT_BASE; i <= ALCHEMY_GPIC_INT_LAST; i++) { | ||
377 | au1300_set_irq_priority(i, 1); | ||
378 | au1300_gpic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); | ||
379 | } | ||
380 | |||
381 | /* setup known on-chip sources */ | ||
382 | while ((i = dints->irq) != -1) { | ||
383 | au1300_gpic_settype(irq_get_irq_data(i), dints->type); | ||
384 | au1300_set_irq_priority(i, dints->prio); | ||
385 | |||
386 | if (dints->internal) | ||
387 | au1300_pinfunc_to_dev(i - ALCHEMY_GPIC_INT_BASE); | ||
388 | |||
389 | dints++; | ||
390 | } | ||
391 | |||
392 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch); | ||
393 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch); | ||
394 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch); | ||
395 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch); | ||
396 | } | ||
397 | |||
398 | /**********************************************************************/ | ||
399 | |||
400 | void __init arch_init_irq(void) | ||
401 | { | ||
402 | switch (alchemy_get_cputype()) { | ||
403 | case ALCHEMY_CPU_AU1300: | ||
404 | alchemy_gpic_init_irq(&au1300_devints[0]); | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | asmlinkage void plat_irq_dispatch(void) | ||
410 | { | ||
411 | unsigned long r = (read_c0_status() & read_c0_cause()) >> 8; | ||
412 | do_IRQ(MIPS_CPU_IRQ_BASE + __ffs(r & 0xff)); | ||
413 | } | ||
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c index ee80a32f5ef9..94fbcd19eb9c 100644 --- a/arch/mips/alchemy/common/irq.c +++ b/arch/mips/alchemy/common/irq.c | |||
@@ -25,16 +25,15 @@ | |||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/bitops.h> | 28 | #include <linux/export.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/irq.h> | ||
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
33 | #include <linux/syscore_ops.h> | 32 | #include <linux/syscore_ops.h> |
34 | 33 | ||
35 | #include <asm/irq_cpu.h> | 34 | #include <asm/irq_cpu.h> |
36 | #include <asm/mipsregs.h> | ||
37 | #include <asm/mach-au1x00/au1000.h> | 35 | #include <asm/mach-au1x00/au1000.h> |
36 | #include <asm/mach-au1x00/gpio-au1300.h> | ||
38 | 37 | ||
39 | /* Interrupt Controller register offsets */ | 38 | /* Interrupt Controller register offsets */ |
40 | #define IC_CFG0RD 0x40 | 39 | #define IC_CFG0RD 0x40 |
@@ -66,7 +65,17 @@ | |||
66 | #define IC_FALLINGCLR 0x7C | 65 | #define IC_FALLINGCLR 0x7C |
67 | #define IC_TESTBIT 0x80 | 66 | #define IC_TESTBIT 0x80 |
68 | 67 | ||
69 | static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); | 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 | |||
70 | 79 | ||
71 | /* NOTE on interrupt priorities: The original writers of this code said: | 80 | /* NOTE on interrupt priorities: The original writers of this code said: |
72 | * | 81 | * |
@@ -74,176 +83,207 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type); | |||
74 | * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) | 83 | * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT) |
75 | * needs the highest priority. | 84 | * needs the highest priority. |
76 | */ | 85 | */ |
77 | 86 | struct alchemy_irqmap au1000_irqmap[] __initdata = { | |
78 | /* per-processor fixed function irqs */ | 87 | { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
79 | struct au1xxx_irqmap { | 88 | { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
80 | int im_irq; | 89 | { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
81 | int im_type; | 90 | { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
82 | int im_request; /* set 1 to get higher priority */ | 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, }, | ||
83 | }; | 119 | }; |
84 | 120 | ||
85 | struct au1xxx_irqmap au1000_irqmap[] __initdata = { | 121 | struct alchemy_irqmap au1500_irqmap[] __initdata = { |
86 | { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 122 | { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
87 | { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 123 | { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
88 | { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 124 | { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
89 | { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 125 | { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
90 | { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 126 | { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
91 | { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 127 | { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
92 | { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 128 | { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
93 | { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 129 | { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
94 | { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 130 | { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
95 | { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 131 | { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
96 | { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 132 | { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
97 | { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 133 | { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
98 | { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 134 | { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
99 | { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 135 | { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
100 | { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 136 | { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
101 | { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 137 | { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
102 | { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 138 | { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
103 | { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 139 | { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
104 | { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 140 | { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
105 | { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 141 | { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
106 | { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 142 | { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
107 | { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 143 | { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
108 | { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 144 | { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
109 | { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 145 | { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
110 | { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 146 | { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
111 | { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 147 | { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
112 | { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 148 | { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
113 | { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 149 | { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
114 | { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 150 | { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
115 | { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
116 | { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
117 | { -1, }, | 151 | { -1, }, |
118 | }; | 152 | }; |
119 | 153 | ||
120 | struct au1xxx_irqmap au1500_irqmap[] __initdata = { | 154 | struct alchemy_irqmap au1100_irqmap[] __initdata = { |
121 | { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 155 | { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
122 | { AU1500_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, | 156 | { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
123 | { AU1500_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, | 157 | { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
124 | { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 158 | { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
125 | { AU1500_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, | 159 | { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
126 | { AU1500_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, | 160 | { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
127 | { AU1500_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 161 | { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
128 | { AU1500_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 162 | { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
129 | { AU1500_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 163 | { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
130 | { AU1500_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 164 | { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
131 | { AU1500_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 165 | { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
132 | { AU1500_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 166 | { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
133 | { AU1500_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 167 | { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
134 | { AU1500_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 168 | { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
135 | { AU1500_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 169 | { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
136 | { AU1500_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 170 | { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
137 | { AU1500_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 171 | { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
138 | { AU1500_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 172 | { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
139 | { AU1500_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 173 | { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
140 | { AU1500_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 174 | { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
141 | { AU1500_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 175 | { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
142 | { AU1500_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 176 | { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
143 | { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 177 | { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
144 | { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 178 | { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
145 | { AU1500_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 179 | { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
146 | { AU1500_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 180 | { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
147 | { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 181 | { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
148 | { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 182 | { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
149 | { AU1500_AC97C_INT, IRQ_TYPE_EDGE_RISING, 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 }, | ||
150 | { -1, }, | 186 | { -1, }, |
151 | }; | 187 | }; |
152 | 188 | ||
153 | struct au1xxx_irqmap au1100_irqmap[] __initdata = { | 189 | struct alchemy_irqmap au1550_irqmap[] __initdata = { |
154 | { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 190 | { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
155 | { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 191 | { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
156 | { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 192 | { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
157 | { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 193 | { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
158 | { AU1100_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 194 | { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
159 | { AU1100_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 195 | { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
160 | { AU1100_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 }, | 196 | { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
161 | { AU1100_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 }, | 197 | { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
162 | { AU1100_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 }, | 198 | { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
163 | { AU1100_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 }, | 199 | { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
164 | { AU1100_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 }, | 200 | { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
165 | { AU1100_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 }, | 201 | { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
166 | { AU1100_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 }, | 202 | { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
167 | { AU1100_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 }, | 203 | { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
168 | { AU1100_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 204 | { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
169 | { AU1100_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 205 | { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
170 | { AU1100_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 206 | { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
171 | { AU1100_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 207 | { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
172 | { AU1100_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 208 | { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
173 | { AU1100_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 209 | { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
174 | { AU1100_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 210 | { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
175 | { AU1100_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 211 | { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
176 | { AU1100_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 212 | { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
177 | { AU1100_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 213 | { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0, 0 }, |
178 | { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | 214 | { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
179 | { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 215 | { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 1, 0 }, |
180 | { AU1100_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 216 | { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
181 | { AU1100_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 217 | { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
182 | { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
183 | { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
184 | { AU1100_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
185 | { -1, }, | 218 | { -1, }, |
186 | }; | 219 | }; |
187 | 220 | ||
188 | struct au1xxx_irqmap au1550_irqmap[] __initdata = { | 221 | struct alchemy_irqmap au1200_irqmap[] __initdata = { |
189 | { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 222 | { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
190 | { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 }, | 223 | { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
191 | { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 }, | 224 | { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
192 | { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 225 | { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
193 | { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 226 | { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
194 | { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 }, | 227 | { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
195 | { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 }, | 228 | { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
196 | { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | 229 | { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
197 | { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 230 | { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
198 | { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 231 | { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
199 | { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 232 | { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
200 | { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 233 | { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
201 | { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 234 | { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
202 | { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 235 | { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
203 | { AU1550_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 236 | { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
204 | { AU1550_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 237 | { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
205 | { AU1550_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 238 | { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
206 | { AU1550_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 239 | { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
207 | { AU1550_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 240 | { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0, 0 }, |
208 | { AU1550_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 241 | { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 1, 0 }, |
209 | { AU1550_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 242 | { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
210 | { AU1550_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 243 | { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
211 | { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 244 | { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0 }, |
212 | { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 1 }, | ||
213 | { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 }, | ||
214 | { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 }, | ||
215 | { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
216 | { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | ||
217 | { -1, }, | 245 | { -1, }, |
218 | }; | 246 | }; |
219 | 247 | ||
220 | struct au1xxx_irqmap au1200_irqmap[] __initdata = { | 248 | static struct alchemy_irqmap au1300_irqmap[] __initdata = { |
221 | { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 249 | /* multifunction: gpio pin or device */ |
222 | { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 250 | { AU1300_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
223 | { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 251 | { AU1300_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
224 | { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 252 | { AU1300_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
225 | { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 253 | { AU1300_SD1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
226 | { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 254 | { AU1300_SD2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
227 | { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 255 | { AU1300_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
228 | { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 256 | { AU1300_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
229 | { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 257 | { AU1300_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
230 | { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 258 | { AU1300_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
231 | { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 259 | { AU1300_NAND_INT, IRQ_TYPE_LEVEL_HIGH, 1, 0, }, |
232 | { AU1200_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 260 | /* au1300 internal */ |
233 | { AU1200_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 261 | { AU1300_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
234 | { AU1200_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 262 | { AU1300_MMU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
235 | { AU1200_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 263 | { AU1300_MPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
236 | { AU1200_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 264 | { AU1300_GPU_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
237 | { AU1200_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 265 | { AU1300_UDMA_INT, IRQ_TYPE_LEVEL_HIGH, 1, 1, }, |
238 | { AU1200_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 266 | { AU1300_TOY_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
239 | { AU1200_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 }, | 267 | { AU1300_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
240 | { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 }, | 268 | { AU1300_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
241 | { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 269 | { AU1300_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
242 | { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 270 | { AU1300_RTC_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
243 | { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 }, | 271 | { AU1300_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 1, 1, }, |
244 | { -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 */ | ||
245 | }; | 284 | }; |
246 | 285 | ||
286 | /******************************************************************************/ | ||
247 | 287 | ||
248 | static void au1x_ic0_unmask(struct irq_data *d) | 288 | static void au1x_ic0_unmask(struct irq_data *d) |
249 | { | 289 | { |
@@ -459,6 +499,220 @@ static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type) | |||
459 | return ret; | 499 | return ret; |
460 | } | 500 | } |
461 | 501 | ||
502 | /******************************************************************************/ | ||
503 | |||
504 | /* | ||
505 | * au1300_gpic_chgcfg - change PIN configuration. | ||
506 | * @gpio: pin to change (0-based GPIO number from datasheet). | ||
507 | * @clr: clear all bits set in 'clr'. | ||
508 | * @set: set these bits. | ||
509 | * | ||
510 | * modifies a pins' configuration register, bits set in @clr will | ||
511 | * be cleared in the register, bits in @set will be set. | ||
512 | */ | ||
513 | static inline void au1300_gpic_chgcfg(unsigned int gpio, | ||
514 | unsigned long clr, | ||
515 | unsigned long set) | ||
516 | { | ||
517 | void __iomem *r = AU1300_GPIC_ADDR; | ||
518 | unsigned long l; | ||
519 | |||
520 | r += gpio * 4; /* offset into pin config array */ | ||
521 | l = __raw_readl(r + AU1300_GPIC_PINCFG); | ||
522 | l &= ~clr; | ||
523 | l |= set; | ||
524 | __raw_writel(l, r + AU1300_GPIC_PINCFG); | ||
525 | wmb(); | ||
526 | } | ||
527 | |||
528 | /* | ||
529 | * au1300_pinfunc_to_gpio - assign a pin as GPIO input (GPIO ctrl). | ||
530 | * @pin: pin (0-based GPIO number from datasheet). | ||
531 | * | ||
532 | * Assigns a GPIO pin to the GPIO controller, so its level can either | ||
533 | * be read or set through the generic GPIO functions. | ||
534 | * If you need a GPOUT, use au1300_gpio_set_value(pin, 0/1). | ||
535 | * REVISIT: is this function really necessary? | ||
536 | */ | ||
537 | void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio) | ||
538 | { | ||
539 | au1300_gpio_direction_input(gpio + AU1300_GPIO_BASE); | ||
540 | } | ||
541 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_gpio); | ||
542 | |||
543 | /* | ||
544 | * au1300_pinfunc_to_dev - assign a pin to the device function. | ||
545 | * @pin: pin (0-based GPIO number from datasheet). | ||
546 | * | ||
547 | * Assigns a GPIO pin to its associated device function; the pin will be | ||
548 | * driven by the device and not through GPIO functions. | ||
549 | */ | ||
550 | void au1300_pinfunc_to_dev(enum au1300_multifunc_pins gpio) | ||
551 | { | ||
552 | void __iomem *r = AU1300_GPIC_ADDR; | ||
553 | unsigned long bit; | ||
554 | |||
555 | r += GPIC_GPIO_BANKOFF(gpio); | ||
556 | bit = GPIC_GPIO_TO_BIT(gpio); | ||
557 | __raw_writel(bit, r + AU1300_GPIC_DEVSEL); | ||
558 | wmb(); | ||
559 | } | ||
560 | EXPORT_SYMBOL_GPL(au1300_pinfunc_to_dev); | ||
561 | |||
562 | /* | ||
563 | * au1300_set_irq_priority - set internal priority of IRQ. | ||
564 | * @irq: irq to set priority (linux irq number). | ||
565 | * @p: priority (0 = highest, 3 = lowest). | ||
566 | */ | ||
567 | void au1300_set_irq_priority(unsigned int irq, int p) | ||
568 | { | ||
569 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
570 | au1300_gpic_chgcfg(irq, GPIC_CFG_IL_MASK, GPIC_CFG_IL_SET(p)); | ||
571 | } | ||
572 | EXPORT_SYMBOL_GPL(au1300_set_irq_priority); | ||
573 | |||
574 | /* | ||
575 | * au1300_set_dbdma_gpio - assign a gpio to one of the DBDMA triggers. | ||
576 | * @dchan: dbdma trigger select (0, 1). | ||
577 | * @gpio: pin to assign as trigger. | ||
578 | * | ||
579 | * DBDMA controller has 2 external trigger sources; this function | ||
580 | * assigns a GPIO to the selected trigger. | ||
581 | */ | ||
582 | void au1300_set_dbdma_gpio(int dchan, unsigned int gpio) | ||
583 | { | ||
584 | unsigned long r; | ||
585 | |||
586 | if ((dchan >= 0) && (dchan <= 1)) { | ||
587 | r = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); | ||
588 | r &= ~(0xff << (8 * dchan)); | ||
589 | r |= (gpio & 0x7f) << (8 * dchan); | ||
590 | __raw_writel(r, AU1300_GPIC_ADDR + AU1300_GPIC_DMASEL); | ||
591 | wmb(); | ||
592 | } | ||
593 | } | ||
594 | |||
595 | static inline void gpic_pin_set_idlewake(unsigned int gpio, int allow) | ||
596 | { | ||
597 | au1300_gpic_chgcfg(gpio, GPIC_CFG_IDLEWAKE, | ||
598 | allow ? GPIC_CFG_IDLEWAKE : 0); | ||
599 | } | ||
600 | |||
601 | static void au1300_gpic_mask(struct irq_data *d) | ||
602 | { | ||
603 | void __iomem *r = AU1300_GPIC_ADDR; | ||
604 | unsigned long bit, irq = d->irq; | ||
605 | |||
606 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
607 | r += GPIC_GPIO_BANKOFF(irq); | ||
608 | bit = GPIC_GPIO_TO_BIT(irq); | ||
609 | __raw_writel(bit, r + AU1300_GPIC_IDIS); | ||
610 | wmb(); | ||
611 | |||
612 | gpic_pin_set_idlewake(irq, 0); | ||
613 | } | ||
614 | |||
615 | static void au1300_gpic_unmask(struct irq_data *d) | ||
616 | { | ||
617 | void __iomem *r = AU1300_GPIC_ADDR; | ||
618 | unsigned long bit, irq = d->irq; | ||
619 | |||
620 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
621 | |||
622 | gpic_pin_set_idlewake(irq, 1); | ||
623 | |||
624 | r += GPIC_GPIO_BANKOFF(irq); | ||
625 | bit = GPIC_GPIO_TO_BIT(irq); | ||
626 | __raw_writel(bit, r + AU1300_GPIC_IEN); | ||
627 | wmb(); | ||
628 | } | ||
629 | |||
630 | static void au1300_gpic_maskack(struct irq_data *d) | ||
631 | { | ||
632 | void __iomem *r = AU1300_GPIC_ADDR; | ||
633 | unsigned long bit, irq = d->irq; | ||
634 | |||
635 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
636 | r += GPIC_GPIO_BANKOFF(irq); | ||
637 | bit = GPIC_GPIO_TO_BIT(irq); | ||
638 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
639 | __raw_writel(bit, r + AU1300_GPIC_IDIS); /* mask */ | ||
640 | wmb(); | ||
641 | |||
642 | gpic_pin_set_idlewake(irq, 0); | ||
643 | } | ||
644 | |||
645 | static void au1300_gpic_ack(struct irq_data *d) | ||
646 | { | ||
647 | void __iomem *r = AU1300_GPIC_ADDR; | ||
648 | unsigned long bit, irq = d->irq; | ||
649 | |||
650 | irq -= ALCHEMY_GPIC_INT_BASE; | ||
651 | r += GPIC_GPIO_BANKOFF(irq); | ||
652 | bit = GPIC_GPIO_TO_BIT(irq); | ||
653 | __raw_writel(bit, r + AU1300_GPIC_IPEND); /* ack */ | ||
654 | wmb(); | ||
655 | } | ||
656 | |||
657 | static struct irq_chip au1300_gpic = { | ||
658 | .name = "GPIOINT", | ||
659 | .irq_ack = au1300_gpic_ack, | ||
660 | .irq_mask = au1300_gpic_mask, | ||
661 | .irq_mask_ack = au1300_gpic_maskack, | ||
662 | .irq_unmask = au1300_gpic_unmask, | ||
663 | .irq_set_type = au1300_gpic_settype, | ||
664 | }; | ||
665 | |||
666 | static int au1300_gpic_settype(struct irq_data *d, unsigned int type) | ||
667 | { | ||
668 | unsigned long s; | ||
669 | unsigned char *name = NULL; | ||
670 | irq_flow_handler_t hdl = NULL; | ||
671 | |||
672 | switch (type) { | ||
673 | case IRQ_TYPE_LEVEL_HIGH: | ||
674 | s = GPIC_CFG_IC_LEVEL_HIGH; | ||
675 | name = "high"; | ||
676 | hdl = handle_level_irq; | ||
677 | break; | ||
678 | case IRQ_TYPE_LEVEL_LOW: | ||
679 | s = GPIC_CFG_IC_LEVEL_LOW; | ||
680 | name = "low"; | ||
681 | hdl = handle_level_irq; | ||
682 | break; | ||
683 | case IRQ_TYPE_EDGE_RISING: | ||
684 | s = GPIC_CFG_IC_EDGE_RISE; | ||
685 | name = "posedge"; | ||
686 | hdl = handle_edge_irq; | ||
687 | break; | ||
688 | case IRQ_TYPE_EDGE_FALLING: | ||
689 | s = GPIC_CFG_IC_EDGE_FALL; | ||
690 | name = "negedge"; | ||
691 | hdl = handle_edge_irq; | ||
692 | break; | ||
693 | case IRQ_TYPE_EDGE_BOTH: | ||
694 | s = GPIC_CFG_IC_EDGE_BOTH; | ||
695 | name = "bothedge"; | ||
696 | hdl = handle_edge_irq; | ||
697 | break; | ||
698 | case IRQ_TYPE_NONE: | ||
699 | s = GPIC_CFG_IC_OFF; | ||
700 | name = "disabled"; | ||
701 | hdl = handle_level_irq; | ||
702 | break; | ||
703 | default: | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | |||
707 | __irq_set_chip_handler_name_locked(d->irq, &au1300_gpic, hdl, name); | ||
708 | |||
709 | au1300_gpic_chgcfg(d->irq - ALCHEMY_GPIC_INT_BASE, GPIC_CFG_IC_MASK, s); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | /******************************************************************************/ | ||
715 | |||
462 | static inline void ic_init(void __iomem *base) | 716 | static inline void ic_init(void __iomem *base) |
463 | { | 717 | { |
464 | /* initialize interrupt controller to a safe state */ | 718 | /* initialize interrupt controller to a safe state */ |
@@ -475,7 +729,7 @@ static inline void ic_init(void __iomem *base) | |||
475 | wmb(); | 729 | wmb(); |
476 | } | 730 | } |
477 | 731 | ||
478 | static unsigned long alchemy_ic_pmdata[7 * 2]; | 732 | static unsigned long alchemy_gpic_pmdata[ALCHEMY_GPIC_INT_NUM + 6]; |
479 | 733 | ||
480 | static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d) | 734 | static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d) |
481 | { | 735 | { |
@@ -508,25 +762,94 @@ static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d) | |||
508 | static int alchemy_ic_suspend(void) | 762 | static int alchemy_ic_suspend(void) |
509 | { | 763 | { |
510 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | 764 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), |
511 | alchemy_ic_pmdata); | 765 | alchemy_gpic_pmdata); |
512 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | 766 | alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), |
513 | &alchemy_ic_pmdata[7]); | 767 | &alchemy_gpic_pmdata[7]); |
514 | return 0; | 768 | return 0; |
515 | } | 769 | } |
516 | 770 | ||
517 | static void alchemy_ic_resume(void) | 771 | static void alchemy_ic_resume(void) |
518 | { | 772 | { |
519 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), | 773 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR), |
520 | &alchemy_ic_pmdata[7]); | 774 | &alchemy_gpic_pmdata[7]); |
521 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), | 775 | alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR), |
522 | alchemy_ic_pmdata); | 776 | alchemy_gpic_pmdata); |
523 | } | 777 | } |
524 | 778 | ||
525 | static struct syscore_ops alchemy_ic_syscore_ops = { | 779 | static int alchemy_gpic_suspend(void) |
780 | { | ||
781 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
782 | int i; | ||
783 | |||
784 | /* save 4 interrupt mask status registers */ | ||
785 | alchemy_gpic_pmdata[0] = __raw_readl(base + AU1300_GPIC_IEN + 0x0); | ||
786 | alchemy_gpic_pmdata[1] = __raw_readl(base + AU1300_GPIC_IEN + 0x4); | ||
787 | alchemy_gpic_pmdata[2] = __raw_readl(base + AU1300_GPIC_IEN + 0x8); | ||
788 | alchemy_gpic_pmdata[3] = __raw_readl(base + AU1300_GPIC_IEN + 0xc); | ||
789 | |||
790 | /* save misc register(s) */ | ||
791 | alchemy_gpic_pmdata[4] = __raw_readl(base + AU1300_GPIC_DMASEL); | ||
792 | |||
793 | /* molto silenzioso */ | ||
794 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
795 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
796 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
797 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
798 | wmb(); | ||
799 | |||
800 | /* save pin/int-type configuration */ | ||
801 | base += AU1300_GPIC_PINCFG; | ||
802 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
803 | alchemy_gpic_pmdata[i + 5] = __raw_readl(base + (i << 2)); | ||
804 | |||
805 | wmb(); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static void alchemy_gpic_resume(void) | ||
811 | { | ||
812 | void __iomem *base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
813 | int i; | ||
814 | |||
815 | /* disable all first */ | ||
816 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x0); | ||
817 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x4); | ||
818 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0x8); | ||
819 | __raw_writel(~0UL, base + AU1300_GPIC_IDIS + 0xc); | ||
820 | wmb(); | ||
821 | |||
822 | /* restore pin/int-type configurations */ | ||
823 | base += AU1300_GPIC_PINCFG; | ||
824 | for (i = 0; i < ALCHEMY_GPIC_INT_NUM; i++) | ||
825 | __raw_writel(alchemy_gpic_pmdata[i + 5], base + (i << 2)); | ||
826 | wmb(); | ||
827 | |||
828 | /* restore misc register(s) */ | ||
829 | base = (void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR); | ||
830 | __raw_writel(alchemy_gpic_pmdata[4], base + AU1300_GPIC_DMASEL); | ||
831 | wmb(); | ||
832 | |||
833 | /* finally restore masks */ | ||
834 | __raw_writel(alchemy_gpic_pmdata[0], base + AU1300_GPIC_IEN + 0x0); | ||
835 | __raw_writel(alchemy_gpic_pmdata[1], base + AU1300_GPIC_IEN + 0x4); | ||
836 | __raw_writel(alchemy_gpic_pmdata[2], base + AU1300_GPIC_IEN + 0x8); | ||
837 | __raw_writel(alchemy_gpic_pmdata[3], base + AU1300_GPIC_IEN + 0xc); | ||
838 | wmb(); | ||
839 | } | ||
840 | |||
841 | static struct syscore_ops alchemy_ic_pmops = { | ||
526 | .suspend = alchemy_ic_suspend, | 842 | .suspend = alchemy_ic_suspend, |
527 | .resume = alchemy_ic_resume, | 843 | .resume = alchemy_ic_resume, |
528 | }; | 844 | }; |
529 | 845 | ||
846 | static struct syscore_ops alchemy_gpic_pmops = { | ||
847 | .suspend = alchemy_gpic_suspend, | ||
848 | .resume = alchemy_gpic_resume, | ||
849 | }; | ||
850 | |||
851 | /******************************************************************************/ | ||
852 | |||
530 | /* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */ | 853 | /* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */ |
531 | #define DISP(name, base, addr) \ | 854 | #define DISP(name, base, addr) \ |
532 | static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \ | 855 | static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d) \ |
@@ -543,14 +866,22 @@ DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT) | |||
543 | DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT) | 866 | DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT) |
544 | DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT) | 867 | DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT) |
545 | 868 | ||
546 | static void __init au1000_init_irq(struct au1xxx_irqmap *map) | 869 | static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d) |
870 | { | ||
871 | int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC); | ||
872 | generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i); | ||
873 | } | ||
874 | |||
875 | /******************************************************************************/ | ||
876 | |||
877 | static void __init au1000_init_irq(struct alchemy_irqmap *map) | ||
547 | { | 878 | { |
548 | unsigned int bit, irq_nr; | 879 | unsigned int bit, irq_nr; |
549 | void __iomem *base; | 880 | void __iomem *base; |
550 | 881 | ||
551 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR)); | 882 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR)); |
552 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR)); | 883 | ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR)); |
553 | register_syscore_ops(&alchemy_ic_syscore_ops); | 884 | register_syscore_ops(&alchemy_ic_pmops); |
554 | mips_cpu_irq_init(); | 885 | mips_cpu_irq_init(); |
555 | 886 | ||
556 | /* register all 64 possible IC0+IC1 irq sources as type "none". | 887 | /* register all 64 possible IC0+IC1 irq sources as type "none". |
@@ -567,8 +898,8 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
567 | /* | 898 | /* |
568 | * Initialize IC0, which is fixed per processor. | 899 | * Initialize IC0, which is fixed per processor. |
569 | */ | 900 | */ |
570 | while (map->im_irq != -1) { | 901 | while (map->irq != -1) { |
571 | irq_nr = map->im_irq; | 902 | irq_nr = map->irq; |
572 | 903 | ||
573 | if (irq_nr >= AU1000_INTC1_INT_BASE) { | 904 | if (irq_nr >= AU1000_INTC1_INT_BASE) { |
574 | bit = irq_nr - AU1000_INTC1_INT_BASE; | 905 | bit = irq_nr - AU1000_INTC1_INT_BASE; |
@@ -577,10 +908,10 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
577 | bit = irq_nr - AU1000_INTC0_INT_BASE; | 908 | bit = irq_nr - AU1000_INTC0_INT_BASE; |
578 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); | 909 | base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR); |
579 | } | 910 | } |
580 | if (map->im_request) | 911 | if (map->prio == 0) |
581 | __raw_writel(1 << bit, base + IC_ASSIGNSET); | 912 | __raw_writel(1 << bit, base + IC_ASSIGNSET); |
582 | 913 | ||
583 | au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type); | 914 | au1x_ic_settype(irq_get_irq_data(irq_nr), map->type); |
584 | ++map; | 915 | ++map; |
585 | } | 916 | } |
586 | 917 | ||
@@ -590,6 +921,48 @@ static void __init au1000_init_irq(struct au1xxx_irqmap *map) | |||
590 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch); | 921 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, au1000_ic1r1_dispatch); |
591 | } | 922 | } |
592 | 923 | ||
924 | static void __init alchemy_gpic_init_irq(const struct alchemy_irqmap *dints) | ||
925 | { | ||
926 | int i; | ||
927 | void __iomem *bank_base; | ||
928 | |||
929 | register_syscore_ops(&alchemy_gpic_pmops); | ||
930 | mips_cpu_irq_init(); | ||
931 | |||
932 | /* disable & ack all possible interrupt sources */ | ||
933 | for (i = 0; i < 4; i++) { | ||
934 | bank_base = AU1300_GPIC_ADDR + (i * 4); | ||
935 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IDIS); | ||
936 | wmb(); | ||
937 | __raw_writel(~0UL, bank_base + AU1300_GPIC_IPEND); | ||
938 | wmb(); | ||
939 | } | ||
940 | |||
941 | /* register an irq_chip for them, with 2nd highest priority */ | ||
942 | for (i = ALCHEMY_GPIC_INT_BASE; i <= ALCHEMY_GPIC_INT_LAST; i++) { | ||
943 | au1300_set_irq_priority(i, 1); | ||
944 | au1300_gpic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE); | ||
945 | } | ||
946 | |||
947 | /* setup known on-chip sources */ | ||
948 | while ((i = dints->irq) != -1) { | ||
949 | au1300_gpic_settype(irq_get_irq_data(i), dints->type); | ||
950 | au1300_set_irq_priority(i, dints->prio); | ||
951 | |||
952 | if (dints->internal) | ||
953 | au1300_pinfunc_to_dev(i - ALCHEMY_GPIC_INT_BASE); | ||
954 | |||
955 | dints++; | ||
956 | } | ||
957 | |||
958 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 2, alchemy_gpic_dispatch); | ||
959 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 3, alchemy_gpic_dispatch); | ||
960 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 4, alchemy_gpic_dispatch); | ||
961 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + 5, alchemy_gpic_dispatch); | ||
962 | } | ||
963 | |||
964 | /******************************************************************************/ | ||
965 | |||
593 | void __init arch_init_irq(void) | 966 | void __init arch_init_irq(void) |
594 | { | 967 | { |
595 | switch (alchemy_get_cputype()) { | 968 | switch (alchemy_get_cputype()) { |
@@ -608,6 +981,12 @@ void __init arch_init_irq(void) | |||
608 | case ALCHEMY_CPU_AU1200: | 981 | case ALCHEMY_CPU_AU1200: |
609 | au1000_init_irq(au1200_irqmap); | 982 | au1000_init_irq(au1200_irqmap); |
610 | break; | 983 | break; |
984 | case ALCHEMY_CPU_AU1300: | ||
985 | alchemy_gpic_init_irq(au1300_irqmap); | ||
986 | break; | ||
987 | default: | ||
988 | pr_err("unknown Alchemy IRQ core\n"); | ||
989 | break; | ||
611 | } | 990 | } |
612 | } | 991 | } |
613 | 992 | ||