Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-2.6-block.git] / arch / unicore32 / kernel / irq.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
752bcb4d
G
2/*
3 * linux/arch/unicore32/kernel/irq.c
4 *
5 * Code specific to PKUnity SoC and UniCore ISA
6 *
7 * Copyright (C) 2001-2010 GUAN Xue-tao
752bcb4d
G
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>
f98bf4aa 23#include <linux/syscore_ops.h>
752bcb4d
G
24#include <linux/gpio.h>
25
752bcb4d
G
26#include <mach/hardware.h>
27
28#include "setup.h"
29
30/*
31 * PKUnity GPIO edge detection for IRQs:
32 * IRQs are generated on Falling-Edge, Rising-Edge, or both.
33 * Use this instead of directly setting GRER/GFER.
34 */
35static int GPIO_IRQ_rising_edge;
36static int GPIO_IRQ_falling_edge;
37static int GPIO_IRQ_mask = 0;
38
39#define GPIO_MASK(irq) (1 << (irq - IRQ_GPIO0))
40
36a8b8c3 41static int puv3_gpio_type(struct irq_data *d, unsigned int type)
752bcb4d
G
42{
43 unsigned int mask;
44
36a8b8c3
G
45 if (d->irq < IRQ_GPIOHIGH)
46 mask = 1 << d->irq;
752bcb4d 47 else
36a8b8c3 48 mask = GPIO_MASK(d->irq);
752bcb4d
G
49
50 if (type == IRQ_TYPE_PROBE) {
51 if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
52 return 0;
53 type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
54 }
55
56 if (type & IRQ_TYPE_EDGE_RISING)
57 GPIO_IRQ_rising_edge |= mask;
58 else
59 GPIO_IRQ_rising_edge &= ~mask;
60 if (type & IRQ_TYPE_EDGE_FALLING)
61 GPIO_IRQ_falling_edge |= mask;
62 else
63 GPIO_IRQ_falling_edge &= ~mask;
64
e5abf78b
G
65 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
66 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
752bcb4d
G
67
68 return 0;
69}
70
71/*
72 * GPIO IRQs must be acknowledged. This is for IRQs from 0 to 7.
73 */
36a8b8c3 74static void puv3_low_gpio_ack(struct irq_data *d)
752bcb4d 75{
e5abf78b 76 writel((1 << d->irq), GPIO_GEDR);
752bcb4d
G
77}
78
36a8b8c3 79static void puv3_low_gpio_mask(struct irq_data *d)
752bcb4d 80{
e5abf78b 81 writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
752bcb4d
G
82}
83
36a8b8c3 84static void puv3_low_gpio_unmask(struct irq_data *d)
752bcb4d 85{
e5abf78b 86 writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
752bcb4d
G
87}
88
36a8b8c3 89static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
752bcb4d
G
90{
91 if (on)
e5abf78b 92 writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
752bcb4d 93 else
e5abf78b 94 writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
752bcb4d
G
95 return 0;
96}
97
98static struct irq_chip puv3_low_gpio_chip = {
99 .name = "GPIO-low",
36a8b8c3
G
100 .irq_ack = puv3_low_gpio_ack,
101 .irq_mask = puv3_low_gpio_mask,
102 .irq_unmask = puv3_low_gpio_unmask,
103 .irq_set_type = puv3_gpio_type,
104 .irq_set_wake = puv3_low_gpio_wake,
752bcb4d
G
105};
106
107/*
108 * IRQ8 (GPIO0 through 27) handler. We enter here with the
109 * irq_controller_lock held, and IRQs disabled. Decode the IRQ
110 * and call the handler.
111 */
bd0b9ac4 112static void puv3_gpio_handler(struct irq_desc *desc)
752bcb4d 113{
f70229e2 114 unsigned int mask, irq;
752bcb4d 115
e5abf78b 116 mask = readl(GPIO_GEDR);
752bcb4d
G
117 do {
118 /*
119 * clear down all currently active IRQ sources.
120 * We will be processing them all.
121 */
e5abf78b 122 writel(mask, GPIO_GEDR);
752bcb4d
G
123
124 irq = IRQ_GPIO0;
125 do {
126 if (mask & 1)
127 generic_handle_irq(irq);
128 mask >>= 1;
129 irq++;
130 } while (mask);
e5abf78b 131 mask = readl(GPIO_GEDR);
752bcb4d
G
132 } while (mask);
133}
134
135/*
136 * GPIO0-27 edge IRQs need to be handled specially.
137 * In addition, the IRQs are all collected up into one bit in the
138 * interrupt controller registers.
139 */
36a8b8c3 140static void puv3_high_gpio_ack(struct irq_data *d)
752bcb4d 141{
36a8b8c3 142 unsigned int mask = GPIO_MASK(d->irq);
752bcb4d 143
e5abf78b 144 writel(mask, GPIO_GEDR);
752bcb4d
G
145}
146
36a8b8c3 147static void puv3_high_gpio_mask(struct irq_data *d)
752bcb4d 148{
36a8b8c3 149 unsigned int mask = GPIO_MASK(d->irq);
752bcb4d
G
150
151 GPIO_IRQ_mask &= ~mask;
152
e5abf78b
G
153 writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
154 writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
752bcb4d
G
155}
156
36a8b8c3 157static void puv3_high_gpio_unmask(struct irq_data *d)
752bcb4d 158{
36a8b8c3 159 unsigned int mask = GPIO_MASK(d->irq);
752bcb4d
G
160
161 GPIO_IRQ_mask |= mask;
162
e5abf78b
G
163 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
164 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
752bcb4d
G
165}
166
36a8b8c3 167static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
752bcb4d
G
168{
169 if (on)
e5abf78b 170 writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
752bcb4d 171 else
e5abf78b 172 writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
752bcb4d
G
173 return 0;
174}
175
176static struct irq_chip puv3_high_gpio_chip = {
177 .name = "GPIO-high",
36a8b8c3
G
178 .irq_ack = puv3_high_gpio_ack,
179 .irq_mask = puv3_high_gpio_mask,
180 .irq_unmask = puv3_high_gpio_unmask,
181 .irq_set_type = puv3_gpio_type,
182 .irq_set_wake = puv3_high_gpio_wake,
752bcb4d
G
183};
184
185/*
186 * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
187 * this is for internal IRQs i.e. from 8 to 31.
188 */
36a8b8c3 189static void puv3_mask_irq(struct irq_data *d)
752bcb4d 190{
e5abf78b 191 writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
752bcb4d
G
192}
193
36a8b8c3 194static void puv3_unmask_irq(struct irq_data *d)
752bcb4d 195{
e5abf78b 196 writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
752bcb4d
G
197}
198
199/*
200 * Apart form GPIOs, only the RTC alarm can be a wakeup event.
201 */
36a8b8c3 202static int puv3_set_wake(struct irq_data *d, unsigned int on)
752bcb4d 203{
36a8b8c3 204 if (d->irq == IRQ_RTCAlarm) {
752bcb4d 205 if (on)
e5abf78b 206 writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
752bcb4d 207 else
e5abf78b 208 writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
752bcb4d
G
209 return 0;
210 }
211 return -EINVAL;
212}
213
214static struct irq_chip puv3_normal_chip = {
215 .name = "PKUnity-v3",
36a8b8c3
G
216 .irq_ack = puv3_mask_irq,
217 .irq_mask = puv3_mask_irq,
218 .irq_unmask = puv3_unmask_irq,
219 .irq_set_wake = puv3_set_wake,
752bcb4d
G
220};
221
222static struct resource irq_resource = {
223 .name = "irqs",
1cf46c42
G
224 .start = io_v2p(PKUNITY_INTC_BASE),
225 .end = io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
752bcb4d
G
226};
227
228static struct puv3_irq_state {
229 unsigned int saved;
230 unsigned int icmr;
231 unsigned int iclr;
232 unsigned int iccr;
233} puv3_irq_state;
234
f98bf4aa 235static int puv3_irq_suspend(void)
752bcb4d
G
236{
237 struct puv3_irq_state *st = &puv3_irq_state;
238
239 st->saved = 1;
e5abf78b
G
240 st->icmr = readl(INTC_ICMR);
241 st->iclr = readl(INTC_ICLR);
242 st->iccr = readl(INTC_ICCR);
752bcb4d
G
243
244 /*
245 * Disable all GPIO-based interrupts.
246 */
e5abf78b 247 writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
752bcb4d
G
248
249 /*
250 * Set the appropriate edges for wakeup.
251 */
e5abf78b
G
252 writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
253 writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
752bcb4d
G
254
255 /*
256 * Clear any pending GPIO interrupts.
257 */
e5abf78b 258 writel(readl(GPIO_GEDR), GPIO_GEDR);
752bcb4d
G
259
260 return 0;
261}
262
f98bf4aa 263static void puv3_irq_resume(void)
752bcb4d
G
264{
265 struct puv3_irq_state *st = &puv3_irq_state;
266
267 if (st->saved) {
e5abf78b
G
268 writel(st->iccr, INTC_ICCR);
269 writel(st->iclr, INTC_ICLR);
752bcb4d 270
e5abf78b
G
271 writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
272 writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
752bcb4d 273
e5abf78b 274 writel(st->icmr, INTC_ICMR);
752bcb4d 275 }
752bcb4d
G
276}
277
f98bf4aa 278static struct syscore_ops puv3_irq_syscore_ops = {
752bcb4d
G
279 .suspend = puv3_irq_suspend,
280 .resume = puv3_irq_resume,
281};
282
f98bf4aa 283static int __init puv3_irq_init_syscore(void)
752bcb4d 284{
f98bf4aa
RW
285 register_syscore_ops(&puv3_irq_syscore_ops);
286 return 0;
752bcb4d
G
287}
288
f98bf4aa 289device_initcall(puv3_irq_init_syscore);
752bcb4d
G
290
291void __init init_IRQ(void)
292{
293 unsigned int irq;
294
295 request_resource(&iomem_resource, &irq_resource);
296
297 /* disable all IRQs */
e5abf78b 298 writel(0, INTC_ICMR);
752bcb4d
G
299
300 /* all IRQs are IRQ, not REAL */
e5abf78b 301 writel(0, INTC_ICLR);
752bcb4d
G
302
303 /* clear all GPIO edge detects */
e5abf78b
G
304 writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
305 writel(0, GPIO_GFER);
306 writel(0, GPIO_GRER);
307 writel(0x0FFFFFFF, GPIO_GEDR);
752bcb4d 308
e5abf78b 309 writel(1, INTC_ICCR);
752bcb4d
G
310
311 for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
e1f5ce81
TG
312 irq_set_chip(irq, &puv3_low_gpio_chip);
313 irq_set_handler(irq, handle_edge_irq);
752bcb4d
G
314 irq_modify_status(irq,
315 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
316 0);
317 }
318
319 for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
e1f5ce81
TG
320 irq_set_chip(irq, &puv3_normal_chip);
321 irq_set_handler(irq, handle_level_irq);
752bcb4d
G
322 irq_modify_status(irq,
323 IRQ_NOREQUEST | IRQ_NOAUTOEN,
324 IRQ_NOPROBE);
325 }
326
327 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
e1f5ce81
TG
328 irq_set_chip(irq, &puv3_high_gpio_chip);
329 irq_set_handler(irq, handle_edge_irq);
752bcb4d
G
330 irq_modify_status(irq,
331 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
332 0);
333 }
334
335 /*
336 * Install handler for GPIO 0-27 edge detect interrupts
337 */
e1f5ce81
TG
338 irq_set_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
339 irq_set_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
752bcb4d
G
340
341#ifdef CONFIG_PUV3_GPIO
342 puv3_init_gpio();
343#endif
344}
345
752bcb4d
G
346/*
347 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
348 * come via this function. Instead, they should provide their
349 * own 'handler'
350 */
351asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
352{
353 struct pt_regs *old_regs = set_irq_regs(regs);
354
355 irq_enter();
356
357 /*
358 * Some hardware gives randomly wrong interrupts. Rather
359 * than crashing, do something sensible.
360 */
361 if (unlikely(irq >= nr_irqs)) {
362 if (printk_ratelimit())
363 printk(KERN_WARNING "Bad IRQ%u\n", irq);
364 ack_bad_irq(irq);
365 } else {
366 generic_handle_irq(irq);
367 }
368
369 irq_exit();
370 set_irq_regs(old_regs);
371}
372