blob: 5d7729a59908b63212c9a318d84bc3cdbe0c031f [file] [log] [blame]
Manuel Lauss809f36c2011-11-01 20:03:30 +01001/*
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
20static int au1300_gpic_settype(struct irq_data *d, unsigned int type);
21
22/* setup for known onchip sources */
23struct 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
30static 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 */
78static 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 */
102void au1300_pinfunc_to_gpio(enum au1300_multifunc_pins gpio)
103{
104 au1300_gpio_direction_input(gpio + AU1300_GPIO_BASE);
105}
106EXPORT_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 */
115void 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}
125EXPORT_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 */
132void 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}
137EXPORT_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 */
147void 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
162static 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
168static 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
182static 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
197static 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
212static 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
224static 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
233static 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
Manuel Laussf267c882011-12-08 10:42:15 +0000281/******************************************************************************/
Manuel Lauss809f36c2011-11-01 20:03:30 +0100282
283static unsigned long alchemy_gpic_pmdata[ALCHEMY_GPIC_INT_NUM + 6];
284
285static 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
316static 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
347static struct syscore_ops alchemy_gpic_pmops = {
348 .suspend = alchemy_gpic_suspend,
349 .resume = alchemy_gpic_resume,
350};
351
Manuel Laussf267c882011-12-08 10:42:15 +0000352static void __init alchemy_gpic_init_irq(const struct gpic_devint_data *dints)
353{
354 int i;
355 void __iomem *bank_base;
356
357 register_syscore_ops(&alchemy_gpic_pmops);
358 mips_cpu_irq_init();
359
360 /* disable & ack all possible interrupt sources */
361 for (i = 0; i < 4; i++) {
362 bank_base = AU1300_GPIC_ADDR + (i * 4);
363 __raw_writel(~0UL, bank_base + AU1300_GPIC_IDIS);
364 wmb();
365 __raw_writel(~0UL, bank_base + AU1300_GPIC_IPEND);
366 wmb();
367 }
368
369 /* register an irq_chip for them, with 2nd highest priority */
370 for (i = ALCHEMY_GPIC_INT_BASE; i <= ALCHEMY_GPIC_INT_LAST; i++) {
371 au1300_set_irq_priority(i, 1);
372 au1300_gpic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE);
373 }
374
375 /* setup known on-chip sources */
376 while ((i = dints->irq) != -1) {
377 au1300_gpic_settype(irq_get_irq_data(i), dints->type);
378 au1300_set_irq_priority(i, dints->prio);
379
380 if (dints->internal)
381 au1300_pinfunc_to_dev(i - ALCHEMY_GPIC_INT_BASE);
382
383 dints++;
384 }
385
386 set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
387}
388
Manuel Lauss809f36c2011-11-01 20:03:30 +0100389/**********************************************************************/
390
391void __init arch_init_irq(void)
392{
393 switch (alchemy_get_cputype()) {
394 case ALCHEMY_CPU_AU1300:
395 alchemy_gpic_init_irq(&au1300_devints[0]);
Manuel Lauss809f36c2011-11-01 20:03:30 +0100396 break;
397 }
398}
399
400#define CAUSEF_GPIC (CAUSEF_IP2 | CAUSEF_IP3 | CAUSEF_IP4 | CAUSEF_IP5)
401
402void plat_irq_dispatch(void)
403{
404 unsigned long i, c = read_c0_cause() & read_c0_status();
405
406 if (c & CAUSEF_IP7) /* c0 timer */
407 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
408 else if (likely(c & CAUSEF_GPIC)) {
409 i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC);
410 do_IRQ(i + ALCHEMY_GPIC_INT_BASE);
411 } else
412 spurious_interrupt();
413}