This source file includes following definitions.
- puv3_gpio_type
- puv3_low_gpio_ack
- puv3_low_gpio_mask
- puv3_low_gpio_unmask
- puv3_low_gpio_wake
- puv3_gpio_handler
- puv3_high_gpio_ack
- puv3_high_gpio_mask
- puv3_high_gpio_unmask
- puv3_high_gpio_wake
- puv3_mask_irq
- puv3_unmask_irq
- puv3_set_wake
- puv3_irq_suspend
- puv3_irq_resume
- puv3_irq_init_syscore
- init_IRQ
- asm_do_IRQ
1
2
3
4
5
6
7
8
9 #include <linux/kernel_stat.h>
10 #include <linux/module.h>
11 #include <linux/signal.h>
12 #include <linux/ioport.h>
13 #include <linux/interrupt.h>
14 #include <linux/irq.h>
15 #include <linux/random.h>
16 #include <linux/smp.h>
17 #include <linux/init.h>
18 #include <linux/seq_file.h>
19 #include <linux/errno.h>
20 #include <linux/list.h>
21 #include <linux/kallsyms.h>
22 #include <linux/proc_fs.h>
23 #include <linux/syscore_ops.h>
24
25 #include <mach/hardware.h>
26
27 #include "setup.h"
28
29
30
31
32
33
34 static int GPIO_IRQ_rising_edge;
35 static int GPIO_IRQ_falling_edge;
36 static int GPIO_IRQ_mask = 0;
37
38 #define GPIO_MASK(irq) (1 << (irq - IRQ_GPIO0))
39
40 static int puv3_gpio_type(struct irq_data *d, unsigned int type)
41 {
42 unsigned int mask;
43
44 if (d->irq < IRQ_GPIOHIGH)
45 mask = 1 << d->irq;
46 else
47 mask = GPIO_MASK(d->irq);
48
49 if (type == IRQ_TYPE_PROBE) {
50 if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
51 return 0;
52 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
53 }
54
55 if (type & IRQ_TYPE_EDGE_RISING)
56 GPIO_IRQ_rising_edge |= mask;
57 else
58 GPIO_IRQ_rising_edge &= ~mask;
59 if (type & IRQ_TYPE_EDGE_FALLING)
60 GPIO_IRQ_falling_edge |= mask;
61 else
62 GPIO_IRQ_falling_edge &= ~mask;
63
64 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
65 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
66
67 return 0;
68 }
69
70
71
72
73 static void puv3_low_gpio_ack(struct irq_data *d)
74 {
75 writel((1 << d->irq), GPIO_GEDR);
76 }
77
78 static void puv3_low_gpio_mask(struct irq_data *d)
79 {
80 writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
81 }
82
83 static void puv3_low_gpio_unmask(struct irq_data *d)
84 {
85 writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
86 }
87
88 static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
89 {
90 if (on)
91 writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
92 else
93 writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
94 return 0;
95 }
96
97 static struct irq_chip puv3_low_gpio_chip = {
98 .name = "GPIO-low",
99 .irq_ack = puv3_low_gpio_ack,
100 .irq_mask = puv3_low_gpio_mask,
101 .irq_unmask = puv3_low_gpio_unmask,
102 .irq_set_type = puv3_gpio_type,
103 .irq_set_wake = puv3_low_gpio_wake,
104 };
105
106
107
108
109
110
111 static void puv3_gpio_handler(struct irq_desc *desc)
112 {
113 unsigned int mask, irq;
114
115 mask = readl(GPIO_GEDR);
116 do {
117
118
119
120
121 writel(mask, GPIO_GEDR);
122
123 irq = IRQ_GPIO0;
124 do {
125 if (mask & 1)
126 generic_handle_irq(irq);
127 mask >>= 1;
128 irq++;
129 } while (mask);
130 mask = readl(GPIO_GEDR);
131 } while (mask);
132 }
133
134
135
136
137
138
139 static void puv3_high_gpio_ack(struct irq_data *d)
140 {
141 unsigned int mask = GPIO_MASK(d->irq);
142
143 writel(mask, GPIO_GEDR);
144 }
145
146 static void puv3_high_gpio_mask(struct irq_data *d)
147 {
148 unsigned int mask = GPIO_MASK(d->irq);
149
150 GPIO_IRQ_mask &= ~mask;
151
152 writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
153 writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
154 }
155
156 static void puv3_high_gpio_unmask(struct irq_data *d)
157 {
158 unsigned int mask = GPIO_MASK(d->irq);
159
160 GPIO_IRQ_mask |= mask;
161
162 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
163 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
164 }
165
166 static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
167 {
168 if (on)
169 writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
170 else
171 writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
172 return 0;
173 }
174
175 static struct irq_chip puv3_high_gpio_chip = {
176 .name = "GPIO-high",
177 .irq_ack = puv3_high_gpio_ack,
178 .irq_mask = puv3_high_gpio_mask,
179 .irq_unmask = puv3_high_gpio_unmask,
180 .irq_set_type = puv3_gpio_type,
181 .irq_set_wake = puv3_high_gpio_wake,
182 };
183
184
185
186
187
188 static void puv3_mask_irq(struct irq_data *d)
189 {
190 writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
191 }
192
193 static void puv3_unmask_irq(struct irq_data *d)
194 {
195 writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
196 }
197
198
199
200
201 static int puv3_set_wake(struct irq_data *d, unsigned int on)
202 {
203 if (d->irq == IRQ_RTCAlarm) {
204 if (on)
205 writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
206 else
207 writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
208 return 0;
209 }
210 return -EINVAL;
211 }
212
213 static struct irq_chip puv3_normal_chip = {
214 .name = "PKUnity-v3",
215 .irq_ack = puv3_mask_irq,
216 .irq_mask = puv3_mask_irq,
217 .irq_unmask = puv3_unmask_irq,
218 .irq_set_wake = puv3_set_wake,
219 };
220
221 static struct resource irq_resource = {
222 .name = "irqs",
223 .start = io_v2p(PKUNITY_INTC_BASE),
224 .end = io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
225 };
226
227 static struct puv3_irq_state {
228 unsigned int saved;
229 unsigned int icmr;
230 unsigned int iclr;
231 unsigned int iccr;
232 } puv3_irq_state;
233
234 static int puv3_irq_suspend(void)
235 {
236 struct puv3_irq_state *st = &puv3_irq_state;
237
238 st->saved = 1;
239 st->icmr = readl(INTC_ICMR);
240 st->iclr = readl(INTC_ICLR);
241 st->iccr = readl(INTC_ICCR);
242
243
244
245
246 writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
247
248
249
250
251 writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
252 writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
253
254
255
256
257 writel(readl(GPIO_GEDR), GPIO_GEDR);
258
259 return 0;
260 }
261
262 static void puv3_irq_resume(void)
263 {
264 struct puv3_irq_state *st = &puv3_irq_state;
265
266 if (st->saved) {
267 writel(st->iccr, INTC_ICCR);
268 writel(st->iclr, INTC_ICLR);
269
270 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
271 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
272
273 writel(st->icmr, INTC_ICMR);
274 }
275 }
276
277 static struct syscore_ops puv3_irq_syscore_ops = {
278 .suspend = puv3_irq_suspend,
279 .resume = puv3_irq_resume,
280 };
281
282 static int __init puv3_irq_init_syscore(void)
283 {
284 register_syscore_ops(&puv3_irq_syscore_ops);
285 return 0;
286 }
287
288 device_initcall(puv3_irq_init_syscore);
289
290 void __init init_IRQ(void)
291 {
292 unsigned int irq;
293
294 request_resource(&iomem_resource, &irq_resource);
295
296
297 writel(0, INTC_ICMR);
298
299
300 writel(0, INTC_ICLR);
301
302
303 writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
304 writel(0, GPIO_GFER);
305 writel(0, GPIO_GRER);
306 writel(0x0FFFFFFF, GPIO_GEDR);
307
308 writel(1, INTC_ICCR);
309
310 for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
311 irq_set_chip(irq, &puv3_low_gpio_chip);
312 irq_set_handler(irq, handle_edge_irq);
313 irq_modify_status(irq,
314 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
315 0);
316 }
317
318 for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
319 irq_set_chip(irq, &puv3_normal_chip);
320 irq_set_handler(irq, handle_level_irq);
321 irq_modify_status(irq,
322 IRQ_NOREQUEST | IRQ_NOAUTOEN,
323 IRQ_NOPROBE);
324 }
325
326 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
327 irq_set_chip(irq, &puv3_high_gpio_chip);
328 irq_set_handler(irq, handle_edge_irq);
329 irq_modify_status(irq,
330 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
331 0);
332 }
333
334
335
336
337 irq_set_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
338 irq_set_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
339
340 #ifdef CONFIG_PUV3_GPIO
341 puv3_init_gpio();
342 #endif
343 }
344
345
346
347
348
349
350 asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
351 {
352 struct pt_regs *old_regs = set_irq_regs(regs);
353
354 irq_enter();
355
356
357
358
359
360 if (unlikely(irq >= nr_irqs)) {
361 if (printk_ratelimit())
362 printk(KERN_WARNING "Bad IRQ%u\n", irq);
363 ack_bad_irq(irq);
364 } else {
365 generic_handle_irq(irq);
366 }
367
368 irq_exit();
369 set_irq_regs(old_regs);
370 }
371