Commit | Line | Data |
---|---|---|
c41b16f8 RK |
1 | /* |
2 | * Support for Versatile FPGA-based IRQ controllers | |
3 | */ | |
4 | #include <linux/irq.h> | |
5 | #include <linux/io.h> | |
6 | ||
7 | #include <asm/mach/irq.h> | |
8 | #include <plat/fpga-irq.h> | |
9 | ||
10 | #define IRQ_STATUS 0x00 | |
11 | #define IRQ_RAW_STATUS 0x04 | |
12 | #define IRQ_ENABLE_SET 0x08 | |
13 | #define IRQ_ENABLE_CLEAR 0x0c | |
14 | ||
15 | static void fpga_irq_mask(struct irq_data *d) | |
16 | { | |
17 | struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); | |
18 | u32 mask = 1 << (d->irq - f->irq_start); | |
19 | ||
20 | writel(mask, f->base + IRQ_ENABLE_CLEAR); | |
21 | } | |
22 | ||
23 | static void fpga_irq_unmask(struct irq_data *d) | |
24 | { | |
25 | struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); | |
26 | u32 mask = 1 << (d->irq - f->irq_start); | |
27 | ||
28 | writel(mask, f->base + IRQ_ENABLE_SET); | |
29 | } | |
30 | ||
31 | static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) | |
32 | { | |
33 | struct fpga_irq_data *f = get_irq_desc_data(desc); | |
34 | u32 status = readl(f->base + IRQ_STATUS); | |
35 | ||
36 | if (status == 0) { | |
37 | do_bad_IRQ(irq, desc); | |
38 | return; | |
39 | } | |
40 | ||
41 | do { | |
42 | irq = ffs(status) - 1; | |
43 | status &= ~(1 << irq); | |
44 | ||
45 | generic_handle_irq(irq + f->irq_start); | |
46 | } while (status); | |
47 | } | |
48 | ||
49 | void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f) | |
50 | { | |
51 | unsigned int i; | |
52 | ||
53 | f->chip.irq_ack = fpga_irq_mask; | |
54 | f->chip.irq_mask = fpga_irq_mask; | |
55 | f->chip.irq_unmask = fpga_irq_unmask; | |
56 | ||
57 | if (parent_irq != -1) { | |
58 | set_irq_data(parent_irq, f); | |
59 | set_irq_chained_handler(parent_irq, fpga_irq_handle); | |
60 | } | |
61 | ||
62 | for (i = 0; i < 32; i++) { | |
63 | if (valid & (1 << i)) { | |
64 | unsigned int irq = f->irq_start + i; | |
65 | ||
66 | set_irq_chip_data(irq, f); | |
67 | set_irq_chip(irq, &f->chip); | |
68 | set_irq_handler(irq, handle_level_irq); | |
69 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
70 | } | |
71 | } | |
72 | } |