sh: intc - add a clear register to struct intc_prio_reg
[linux-2.6] / arch / sh / kernel / cpu / irq / intc.c
1 /*
2  * Shared interrupt handling code for IPR and INTC2 types of IRQs.
3  *
4  * Copyright (C) 2007 Magnus Damm
5  *
6  * Based on intc2.c and ipr.c
7  *
8  * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
9  * Copyright (C) 2000  Kazumoto Kojima
10  * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
11  * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
12  * Copyright (C) 2005, 2006  Paul Mundt
13  *
14  * This file is subject to the terms and conditions of the GNU General Public
15  * License.  See the file "COPYING" in the main directory of this archive
16  * for more details.
17  */
18 #include <linux/init.h>
19 #include <linux/irq.h>
20 #include <linux/module.h>
21 #include <linux/io.h>
22 #include <linux/interrupt.h>
23
24 #define _INTC_MK(fn, idx, bit, value) \
25         ((fn) << 24 | ((value) << 16) | ((idx) << 8) | (bit))
26 #define _INTC_FN(h) (h >> 24)
27 #define _INTC_VALUE(h) ((h >> 16) & 0xff)
28 #define _INTC_IDX(h) ((h >> 8) & 0xff)
29 #define _INTC_BIT(h) (h & 0xff)
30
31 #define _INTC_PTR(desc, member, data) \
32         (desc->member + _INTC_IDX(data))
33
34 static inline struct intc_desc *get_intc_desc(unsigned int irq)
35 {
36         struct irq_chip *chip = get_irq_chip(irq);
37         return (void *)((char *)chip - offsetof(struct intc_desc, chip));
38 }
39
40 static inline unsigned int set_field(unsigned int value,
41                                      unsigned int field_value,
42                                      unsigned int width,
43                                      unsigned int shift)
44 {
45         value &= ~(((1 << width) - 1) << shift);
46         value |= field_value << shift;
47         return value;
48 }
49
50 static inline unsigned int set_prio_field(struct intc_desc *desc,
51                                           unsigned int value,
52                                           unsigned int priority,
53                                           unsigned int data)
54 {
55         unsigned int width = _INTC_PTR(desc, prio_regs, data)->field_width;
56
57         return set_field(value, priority, width, _INTC_BIT(data));
58 }
59
60 static void disable_prio_16(struct intc_desc *desc, unsigned int data)
61 {
62         unsigned long addr = _INTC_PTR(desc, prio_regs, data)->set_reg;
63
64         ctrl_outw(set_prio_field(desc, ctrl_inw(addr), 0, data), addr);
65 }
66
67 static void enable_prio_16(struct intc_desc *desc, unsigned int data)
68 {
69         unsigned long addr = _INTC_PTR(desc, prio_regs, data)->set_reg;
70         unsigned int prio = _INTC_VALUE(data);
71
72         ctrl_outw(set_prio_field(desc, ctrl_inw(addr), prio, data), addr);
73 }
74
75 static void disable_prio_32(struct intc_desc *desc, unsigned int data)
76 {
77         unsigned long addr = _INTC_PTR(desc, prio_regs, data)->set_reg;
78
79         ctrl_outl(set_prio_field(desc, ctrl_inl(addr), 0, data), addr);
80 }
81
82 static void enable_prio_32(struct intc_desc *desc, unsigned int data)
83 {
84         unsigned long addr = _INTC_PTR(desc, prio_regs, data)->set_reg;
85         unsigned int prio = _INTC_VALUE(data);
86
87         ctrl_outl(set_prio_field(desc, ctrl_inl(addr), prio, data), addr);
88 }
89
90 static void write_set_reg_8(struct intc_desc *desc, unsigned int data)
91 {
92         ctrl_outb(1 << _INTC_BIT(data),
93                   _INTC_PTR(desc, mask_regs, data)->set_reg);
94 }
95
96 static void write_clr_reg_8(struct intc_desc *desc, unsigned int data)
97 {
98         ctrl_outb(1 << _INTC_BIT(data),
99                   _INTC_PTR(desc, mask_regs, data)->clr_reg);
100 }
101
102 static void write_set_reg_32(struct intc_desc *desc, unsigned int data)
103 {
104         ctrl_outl(1 << _INTC_BIT(data),
105                   _INTC_PTR(desc, mask_regs, data)->set_reg);
106 }
107
108 static void write_clr_reg_32(struct intc_desc *desc, unsigned int data)
109 {
110         ctrl_outl(1 << _INTC_BIT(data),
111                   _INTC_PTR(desc, mask_regs, data)->clr_reg);
112 }
113
114 static void or_set_reg_16(struct intc_desc *desc, unsigned int data)
115 {
116         unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
117
118         ctrl_outw(ctrl_inw(addr) | 1 << _INTC_BIT(data), addr);
119 }
120
121 static void and_set_reg_16(struct intc_desc *desc, unsigned int data)
122 {
123         unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
124
125         ctrl_outw(ctrl_inw(addr) & ~(1 << _INTC_BIT(data)), addr);
126 }
127
128 static void or_set_reg_32(struct intc_desc *desc, unsigned int data)
129 {
130         unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
131
132         ctrl_outl(ctrl_inl(addr) | 1 << _INTC_BIT(data), addr);
133 }
134
135 static void and_set_reg_32(struct intc_desc *desc, unsigned int data)
136 {
137         unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
138
139         ctrl_outl(ctrl_inl(addr) & ~(1 << _INTC_BIT(data)), addr);
140 }
141
142 enum {  REG_FN_ERROR=0,
143         REG_FN_DUAL_8, REG_FN_DUAL_32,
144         REG_FN_ENA_16, REG_FN_ENA_32,
145         REG_FN_PRIO_16, REG_FN_PRIO_32 };
146
147 static struct {
148         void (*enable)(struct intc_desc *, unsigned int);
149         void (*disable)(struct intc_desc *, unsigned int);
150 } intc_reg_fns[] = {
151         [REG_FN_DUAL_8] = { write_clr_reg_8, write_set_reg_8 },
152         [REG_FN_DUAL_32] = { write_clr_reg_32, write_set_reg_32 },
153         [REG_FN_ENA_16] = { or_set_reg_16, and_set_reg_16 },
154         [REG_FN_ENA_32] = { or_set_reg_32, and_set_reg_32 },
155         [REG_FN_PRIO_16] = { enable_prio_16, disable_prio_16 },
156         [REG_FN_PRIO_32] = { enable_prio_32, disable_prio_32 },
157 };
158
159 static void intc_enable(unsigned int irq)
160 {
161         struct intc_desc *desc = get_intc_desc(irq);
162         unsigned int data = (unsigned int) get_irq_chip_data(irq);
163
164         intc_reg_fns[_INTC_FN(data)].enable(desc, data);
165 }
166
167 static void intc_disable(unsigned int irq)
168 {
169         struct intc_desc *desc = get_intc_desc(irq);
170         unsigned int data = (unsigned int) get_irq_chip_data(irq);
171
172         intc_reg_fns[_INTC_FN(data)].disable(desc, data);
173 }
174
175 static void set_sense_16(struct intc_desc *desc, unsigned int data)
176 {
177         unsigned long addr = _INTC_PTR(desc, sense_regs, data)->reg;
178         unsigned int width = _INTC_PTR(desc, sense_regs, data)->field_width;
179         unsigned int bit = _INTC_BIT(data);
180         unsigned int value = _INTC_VALUE(data);
181
182         ctrl_outw(set_field(ctrl_inw(addr), value, width, bit), addr);
183 }
184
185 static void set_sense_32(struct intc_desc *desc, unsigned int data)
186 {
187         unsigned long addr = _INTC_PTR(desc, sense_regs, data)->reg;
188         unsigned int width = _INTC_PTR(desc, sense_regs, data)->field_width;
189         unsigned int bit = _INTC_BIT(data);
190         unsigned int value = _INTC_VALUE(data);
191
192         ctrl_outl(set_field(ctrl_inl(addr), value, width, bit), addr);
193 }
194
195 #define VALID(x) (x | 0x80)
196
197 static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
198         [IRQ_TYPE_EDGE_FALLING] = VALID(0),
199         [IRQ_TYPE_EDGE_RISING] = VALID(1),
200         [IRQ_TYPE_LEVEL_LOW] = VALID(2),
201         [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
202 };
203
204 static int intc_set_sense(unsigned int irq, unsigned int type)
205 {
206         struct intc_desc *desc = get_intc_desc(irq);
207         unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
208         unsigned int i, j, data, bit;
209         intc_enum enum_id = 0;
210
211         for (i = 0; i < desc->nr_vectors; i++) {
212                 struct intc_vect *vect = desc->vectors + i;
213
214                 if (evt2irq(vect->vect) != irq)
215                         continue;
216
217                 enum_id = vect->enum_id;
218                 break;
219         }
220
221         if (!enum_id || !value || !desc->sense_regs)
222                 return -EINVAL;
223
224         value ^= VALID(0);
225
226         for (i = 0; i < desc->nr_sense_regs; i++) {
227                 struct intc_sense_reg *sr = desc->sense_regs + i;
228
229                 for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
230                         if (sr->enum_ids[j] != enum_id)
231                                 continue;
232
233                         bit = sr->reg_width - ((j + 1) * sr->field_width);
234                         data = _INTC_MK(0, i, bit, value);
235
236                         switch(sr->reg_width) {
237                         case 16:
238                                 set_sense_16(desc, data);
239                                 break;
240                         case 32:
241                                 set_sense_32(desc, data);
242                                 break;
243                         }
244
245                         return 0;
246                 }
247         }
248
249         return -EINVAL;
250 }
251
252 static unsigned int __init intc_find_dual_handler(unsigned int width)
253 {
254         switch (width) {
255         case 8:
256                 return REG_FN_DUAL_8;
257         case 32:
258                 return REG_FN_DUAL_32;
259         }
260
261         BUG();
262         return REG_FN_ERROR;
263 }
264
265 static unsigned int __init intc_find_prio_handler(unsigned int width)
266 {
267         switch (width) {
268         case 16:
269                 return REG_FN_PRIO_16;
270         case 32:
271                 return REG_FN_PRIO_32;
272         }
273
274         BUG();
275         return REG_FN_ERROR;
276 }
277
278 static unsigned int __init intc_find_ena_handler(unsigned int width)
279 {
280         switch (width) {
281         case 16:
282                 return REG_FN_ENA_16;
283         case 32:
284                 return REG_FN_ENA_32;
285         }
286
287         BUG();
288         return REG_FN_ERROR;
289 }
290
291 static intc_enum __init intc_grp_id(struct intc_desc *desc, intc_enum enum_id)
292 {
293         struct intc_group *g = desc->groups;
294         unsigned int i, j;
295
296         for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
297                 g = desc->groups + i;
298
299                 for (j = 0; g->enum_ids[j]; j++) {
300                         if (g->enum_ids[j] != enum_id)
301                                 continue;
302
303                         return g->enum_id;
304                 }
305         }
306
307         return 0;
308 }
309
310 static unsigned int __init intc_prio_value(struct intc_desc *desc,
311                                            intc_enum enum_id, int do_grps)
312 {
313         struct intc_prio *p = desc->priorities;
314         unsigned int i;
315
316         for (i = 0; p && enum_id && i < desc->nr_priorities; i++) {
317                 p = desc->priorities + i;
318
319                 if (p->enum_id != enum_id)
320                         continue;
321
322                 return p->priority;
323         }
324
325         if (do_grps)
326                 return intc_prio_value(desc, intc_grp_id(desc, enum_id), 0);
327
328         /* default to the lowest priority possible if no priority is set
329          * - this needs to be at least 2 for 5-bit priorities on 7780
330          */
331
332         return 2;
333 }
334
335 static unsigned int __init intc_mask_data(struct intc_desc *desc,
336                                           intc_enum enum_id, int do_grps)
337 {
338         struct intc_mask_reg *mr = desc->mask_regs;
339         unsigned int i, j, fn;
340
341         for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
342                 mr = desc->mask_regs + i;
343
344                 for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
345                         if (mr->enum_ids[j] != enum_id)
346                                 continue;
347
348                         switch (mr->clr_reg) {
349                         case 1: /* 1 = enabled interrupt - "enable" register */
350                                 fn = intc_find_ena_handler(mr->reg_width);
351                                 break;
352                         default:
353                                 fn = intc_find_dual_handler(mr->reg_width);
354                         }
355
356                         if (fn == REG_FN_ERROR)
357                                 return 0;
358
359                         return _INTC_MK(fn, i, (mr->reg_width - 1) - j, 0);
360                 }
361         }
362
363         if (do_grps)
364                 return intc_mask_data(desc, intc_grp_id(desc, enum_id), 0);
365
366         return 0;
367 }
368
369 static unsigned int __init intc_prio_data(struct intc_desc *desc,
370                                           intc_enum enum_id, int do_grps)
371 {
372         struct intc_prio_reg *pr = desc->prio_regs;
373         unsigned int i, j, fn, bit, prio;
374
375         for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
376                 pr = desc->prio_regs + i;
377
378                 for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
379                         if (pr->enum_ids[j] != enum_id)
380                                 continue;
381
382                         fn = intc_find_prio_handler(pr->reg_width);
383                         if (fn == REG_FN_ERROR)
384                                 return 0;
385
386                         prio = intc_prio_value(desc, enum_id, 1);
387                         bit = pr->reg_width - ((j + 1) * pr->field_width);
388
389                         BUG_ON(bit < 0);
390
391                         return _INTC_MK(fn, i, bit, prio);
392                 }
393         }
394
395         if (do_grps)
396                 return intc_prio_data(desc, intc_grp_id(desc, enum_id), 0);
397
398         return 0;
399 }
400
401 static void __init intc_register_irq(struct intc_desc *desc, intc_enum enum_id,
402                                      unsigned int irq)
403 {
404         unsigned int data[2], primary;
405
406         /* Prefer single interrupt source bitmap over other combinations:
407          * 1. bitmap, single interrupt source
408          * 2. priority, single interrupt source
409          * 3. bitmap, multiple interrupt sources (groups)
410          * 4. priority, multiple interrupt sources (groups)
411          */
412
413         data[0] = intc_mask_data(desc, enum_id, 0);
414         data[1] = intc_prio_data(desc, enum_id, 0);
415
416         primary = 0;
417         if (!data[0] && data[1])
418                 primary = 1;
419
420         data[0] = data[0] ? data[0] : intc_mask_data(desc, enum_id, 1);
421         data[1] = data[1] ? data[1] : intc_prio_data(desc, enum_id, 1);
422
423         if (!data[primary])
424                 primary ^= 1;
425
426         BUG_ON(!data[primary]); /* must have primary masking method */
427
428         disable_irq_nosync(irq);
429         set_irq_chip_and_handler_name(irq, &desc->chip,
430                                       handle_level_irq, "level");
431         set_irq_chip_data(irq, (void *)data[primary]);
432
433         /* enable secondary masking method if present */
434         if (data[!primary])
435                 intc_reg_fns[_INTC_FN(data[!primary])].enable(desc,
436                                                               data[!primary]);
437
438         /* irq should be disabled by default */
439         desc->chip.mask(irq);
440 }
441
442 void __init register_intc_controller(struct intc_desc *desc)
443 {
444         unsigned int i;
445
446         desc->chip.mask = intc_disable;
447         desc->chip.unmask = intc_enable;
448         desc->chip.mask_ack = intc_disable;
449         desc->chip.set_type = intc_set_sense;
450
451         for (i = 0; i < desc->nr_vectors; i++) {
452                 struct intc_vect *vect = desc->vectors + i;
453
454                 intc_register_irq(desc, vect->enum_id, evt2irq(vect->vect));
455         }
456 }