powerpc: Convert to new irq_* function names
[linux-2.6.git] / arch / powerpc / platforms / 85xx / socrates_fpga_pic.c
1 /*
2  *  Copyright (C) 2008 Ilya Yanok, Emcraft Systems
3  *
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  */
10
11 #include <linux/irq.h>
12 #include <linux/of_platform.h>
13 #include <linux/io.h>
14
15 /*
16  * The FPGA supports 9 interrupt sources, which can be routed to 3
17  * interrupt request lines of the MPIC. The line to be used can be
18  * specified through the third cell of FDT property  "interrupts".
19  */
20
21 #define SOCRATES_FPGA_NUM_IRQS  9
22
23 #define FPGA_PIC_IRQCFG         (0x0)
24 #define FPGA_PIC_IRQMASK(n)     (0x4 + 0x4 * (n))
25
26 #define SOCRATES_FPGA_IRQ_MASK  ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
27
28 struct socrates_fpga_irq_info {
29         unsigned int irq_line;
30         int type;
31 };
32
33 /*
34  * Interrupt routing and type table
35  *
36  * IRQ_TYPE_NONE means the interrupt type is configurable,
37  * otherwise it's fixed to the specified value.
38  */
39 static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
40         [0] = {0, IRQ_TYPE_NONE},
41         [1] = {0, IRQ_TYPE_LEVEL_HIGH},
42         [2] = {0, IRQ_TYPE_LEVEL_LOW},
43         [3] = {0, IRQ_TYPE_NONE},
44         [4] = {0, IRQ_TYPE_NONE},
45         [5] = {0, IRQ_TYPE_NONE},
46         [6] = {0, IRQ_TYPE_NONE},
47         [7] = {0, IRQ_TYPE_NONE},
48         [8] = {0, IRQ_TYPE_LEVEL_HIGH},
49 };
50
51 #define socrates_fpga_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
52
53 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
54
55 static void __iomem *socrates_fpga_pic_iobase;
56 static struct irq_host *socrates_fpga_pic_irq_host;
57 static unsigned int socrates_fpga_irqs[3];
58
59 static inline uint32_t socrates_fpga_pic_read(int reg)
60 {
61         return in_be32(socrates_fpga_pic_iobase + reg);
62 }
63
64 static inline void socrates_fpga_pic_write(int reg, uint32_t val)
65 {
66         out_be32(socrates_fpga_pic_iobase + reg, val);
67 }
68
69 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
70 {
71         uint32_t cause;
72         unsigned long flags;
73         int i;
74
75         /* Check irq line routed to the MPIC */
76         for (i = 0; i < 3; i++) {
77                 if (irq == socrates_fpga_irqs[i])
78                         break;
79         }
80         if (i == 3)
81                 return NO_IRQ;
82
83         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
84         cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
85         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
86         for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
87                 if (cause >> (i + 16))
88                         break;
89         }
90         return irq_linear_revmap(socrates_fpga_pic_irq_host,
91                         (irq_hw_number_t)i);
92 }
93
94 void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
95 {
96         struct irq_chip *chip = irq_desc_get_chip(desc);
97         unsigned int cascade_irq;
98
99         /*
100          * See if we actually have an interrupt, call generic handling code if
101          * we do.
102          */
103         cascade_irq = socrates_fpga_pic_get_irq(irq);
104
105         if (cascade_irq != NO_IRQ)
106                 generic_handle_irq(cascade_irq);
107         chip->irq_eoi(&desc->irq_data);
108 }
109
110 static void socrates_fpga_pic_ack(struct irq_data *d)
111 {
112         unsigned long flags;
113         unsigned int hwirq, irq_line;
114         uint32_t mask;
115
116         hwirq = socrates_fpga_irq_to_hw(d->irq);
117
118         irq_line = fpga_irqs[hwirq].irq_line;
119         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
120         mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
121                 & SOCRATES_FPGA_IRQ_MASK;
122         mask |= (1 << (hwirq + 16));
123         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
124         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
125 }
126
127 static void socrates_fpga_pic_mask(struct irq_data *d)
128 {
129         unsigned long flags;
130         unsigned int hwirq;
131         int irq_line;
132         u32 mask;
133
134         hwirq = socrates_fpga_irq_to_hw(d->irq);
135
136         irq_line = fpga_irqs[hwirq].irq_line;
137         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
138         mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
139                 & SOCRATES_FPGA_IRQ_MASK;
140         mask &= ~(1 << hwirq);
141         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
142         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
143 }
144
145 static void socrates_fpga_pic_mask_ack(struct irq_data *d)
146 {
147         unsigned long flags;
148         unsigned int hwirq;
149         int irq_line;
150         u32 mask;
151
152         hwirq = socrates_fpga_irq_to_hw(d->irq);
153
154         irq_line = fpga_irqs[hwirq].irq_line;
155         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
156         mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
157                 & SOCRATES_FPGA_IRQ_MASK;
158         mask &= ~(1 << hwirq);
159         mask |= (1 << (hwirq + 16));
160         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
161         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
162 }
163
164 static void socrates_fpga_pic_unmask(struct irq_data *d)
165 {
166         unsigned long flags;
167         unsigned int hwirq;
168         int irq_line;
169         u32 mask;
170
171         hwirq = socrates_fpga_irq_to_hw(d->irq);
172
173         irq_line = fpga_irqs[hwirq].irq_line;
174         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
175         mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
176                 & SOCRATES_FPGA_IRQ_MASK;
177         mask |= (1 << hwirq);
178         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
179         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
180 }
181
182 static void socrates_fpga_pic_eoi(struct irq_data *d)
183 {
184         unsigned long flags;
185         unsigned int hwirq;
186         int irq_line;
187         u32 mask;
188
189         hwirq = socrates_fpga_irq_to_hw(d->irq);
190
191         irq_line = fpga_irqs[hwirq].irq_line;
192         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
193         mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
194                 & SOCRATES_FPGA_IRQ_MASK;
195         mask |= (1 << (hwirq + 16));
196         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
197         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
198 }
199
200 static int socrates_fpga_pic_set_type(struct irq_data *d,
201                 unsigned int flow_type)
202 {
203         unsigned long flags;
204         unsigned int hwirq;
205         int polarity;
206         u32 mask;
207
208         hwirq = socrates_fpga_irq_to_hw(d->irq);
209
210         if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
211                 return -EINVAL;
212
213         switch (flow_type & IRQ_TYPE_SENSE_MASK) {
214         case IRQ_TYPE_LEVEL_HIGH:
215                 polarity = 1;
216                 break;
217         case IRQ_TYPE_LEVEL_LOW:
218                 polarity = 0;
219                 break;
220         default:
221                 return -EINVAL;
222         }
223         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
224         mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
225         if (polarity)
226                 mask |= (1 << hwirq);
227         else
228                 mask &= ~(1 << hwirq);
229         socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
230         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
231         return 0;
232 }
233
234 static struct irq_chip socrates_fpga_pic_chip = {
235         .name           = "FPGA-PIC",
236         .irq_ack        = socrates_fpga_pic_ack,
237         .irq_mask       = socrates_fpga_pic_mask,
238         .irq_mask_ack   = socrates_fpga_pic_mask_ack,
239         .irq_unmask     = socrates_fpga_pic_unmask,
240         .irq_eoi        = socrates_fpga_pic_eoi,
241         .irq_set_type   = socrates_fpga_pic_set_type,
242 };
243
244 static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
245                 irq_hw_number_t hwirq)
246 {
247         /* All interrupts are LEVEL sensitive */
248         irq_set_status_flags(virq, IRQ_LEVEL);
249         irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip,
250                                  handle_fasteoi_irq);
251
252         return 0;
253 }
254
255 static int socrates_fpga_pic_host_xlate(struct irq_host *h,
256                 struct device_node *ct, const u32 *intspec, unsigned int intsize,
257                 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
258 {
259         struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
260
261         *out_hwirq = intspec[0];
262         if  (fpga_irq->type == IRQ_TYPE_NONE) {
263                 /* type is configurable */
264                 if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
265                     intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
266                         pr_warning("FPGA PIC: invalid irq type, "
267                                    "setting default active low\n");
268                         *out_flags = IRQ_TYPE_LEVEL_LOW;
269                 } else {
270                         *out_flags = intspec[1];
271                 }
272         } else {
273                 /* type is fixed */
274                 *out_flags = fpga_irq->type;
275         }
276
277         /* Use specified interrupt routing */
278         if (intspec[2] <= 2)
279                 fpga_irq->irq_line = intspec[2];
280         else
281                 pr_warning("FPGA PIC: invalid irq routing\n");
282
283         return 0;
284 }
285
286 static struct irq_host_ops socrates_fpga_pic_host_ops = {
287         .map    = socrates_fpga_pic_host_map,
288         .xlate  = socrates_fpga_pic_host_xlate,
289 };
290
291 void socrates_fpga_pic_init(struct device_node *pic)
292 {
293         unsigned long flags;
294         int i;
295
296         /* Setup an irq_host structure */
297         socrates_fpga_pic_irq_host = irq_alloc_host(pic, IRQ_HOST_MAP_LINEAR,
298                         SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops,
299                         SOCRATES_FPGA_NUM_IRQS);
300         if (socrates_fpga_pic_irq_host == NULL) {
301                 pr_err("FPGA PIC: Unable to allocate host\n");
302                 return;
303         }
304
305         for (i = 0; i < 3; i++) {
306                 socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
307                 if (socrates_fpga_irqs[i] == NO_IRQ) {
308                         pr_warning("FPGA PIC: can't get irq%d.\n", i);
309                         continue;
310                 }
311                 irq_set_chained_handler(socrates_fpga_irqs[i],
312                                         socrates_fpga_pic_cascade);
313         }
314
315         socrates_fpga_pic_iobase = of_iomap(pic, 0);
316
317         raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
318         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
319                         SOCRATES_FPGA_IRQ_MASK << 16);
320         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
321                         SOCRATES_FPGA_IRQ_MASK << 16);
322         socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
323                         SOCRATES_FPGA_IRQ_MASK << 16);
324         raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
325
326         pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
327 }