Merge git://git.infradead.org/mtd-2.6
[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 #include <linux/bootmem.h>
24
25 #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
26         ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
27          ((addr_e) << 16) | ((addr_d << 24)))
28
29 #define _INTC_SHIFT(h) (h & 0x1f)
30 #define _INTC_WIDTH(h) ((h >> 5) & 0xf)
31 #define _INTC_FN(h) ((h >> 9) & 0xf)
32 #define _INTC_MODE(h) ((h >> 13) & 0x7)
33 #define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
34 #define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
35
36 struct intc_handle_int {
37         unsigned int irq;
38         unsigned long handle;
39 };
40
41 struct intc_desc_int {
42         unsigned long *reg;
43 #ifdef CONFIG_SMP
44         unsigned long *smp;
45 #endif
46         unsigned int nr_reg;
47         struct intc_handle_int *prio;
48         unsigned int nr_prio;
49         struct intc_handle_int *sense;
50         unsigned int nr_sense;
51         struct irq_chip chip;
52 };
53
54 #ifdef CONFIG_SMP
55 #define IS_SMP(x) x.smp
56 #define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
57 #define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
58 #else
59 #define IS_SMP(x) 0
60 #define INTC_REG(d, x, c) (d->reg[(x)])
61 #define SMP_NR(d, x) 1
62 #endif
63
64 static unsigned int intc_prio_level[NR_IRQS]; /* for now */
65
66 static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
67 {
68         struct irq_chip *chip = get_irq_chip(irq);
69         return (void *)((char *)chip - offsetof(struct intc_desc_int, chip));
70 }
71
72 static inline unsigned int set_field(unsigned int value,
73                                      unsigned int field_value,
74                                      unsigned int handle)
75 {
76         unsigned int width = _INTC_WIDTH(handle);
77         unsigned int shift = _INTC_SHIFT(handle);
78
79         value &= ~(((1 << width) - 1) << shift);
80         value |= field_value << shift;
81         return value;
82 }
83
84 static void write_8(unsigned long addr, unsigned long h, unsigned long data)
85 {
86         ctrl_outb(set_field(0, data, h), addr);
87 }
88
89 static void write_16(unsigned long addr, unsigned long h, unsigned long data)
90 {
91         ctrl_outw(set_field(0, data, h), addr);
92 }
93
94 static void write_32(unsigned long addr, unsigned long h, unsigned long data)
95 {
96         ctrl_outl(set_field(0, data, h), addr);
97 }
98
99 static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
100 {
101         ctrl_outb(set_field(ctrl_inb(addr), data, h), addr);
102 }
103
104 static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
105 {
106         ctrl_outw(set_field(ctrl_inw(addr), data, h), addr);
107 }
108
109 static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
110 {
111         ctrl_outl(set_field(ctrl_inl(addr), data, h), addr);
112 }
113
114 enum {  REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };
115
116 static void (*intc_reg_fns[])(unsigned long addr,
117                               unsigned long h,
118                               unsigned long data) = {
119         [REG_FN_WRITE_BASE + 0] = write_8,
120         [REG_FN_WRITE_BASE + 1] = write_16,
121         [REG_FN_WRITE_BASE + 3] = write_32,
122         [REG_FN_MODIFY_BASE + 0] = modify_8,
123         [REG_FN_MODIFY_BASE + 1] = modify_16,
124         [REG_FN_MODIFY_BASE + 3] = modify_32,
125 };
126
127 enum {  MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
128         MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
129         MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
130         MODE_PRIO_REG,       /* Priority value written to enable interrupt */
131         MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
132 };
133
134 static void intc_mode_field(unsigned long addr,
135                             unsigned long handle,
136                             void (*fn)(unsigned long,
137                                        unsigned long,
138                                        unsigned long),
139                             unsigned int irq)
140 {
141         fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
142 }
143
144 static void intc_mode_zero(unsigned long addr,
145                            unsigned long handle,
146                            void (*fn)(unsigned long,
147                                        unsigned long,
148                                        unsigned long),
149                            unsigned int irq)
150 {
151         fn(addr, handle, 0);
152 }
153
154 static void intc_mode_prio(unsigned long addr,
155                            unsigned long handle,
156                            void (*fn)(unsigned long,
157                                        unsigned long,
158                                        unsigned long),
159                            unsigned int irq)
160 {
161         fn(addr, handle, intc_prio_level[irq]);
162 }
163
164 static void (*intc_enable_fns[])(unsigned long addr,
165                                  unsigned long handle,
166                                  void (*fn)(unsigned long,
167                                             unsigned long,
168                                             unsigned long),
169                                  unsigned int irq) = {
170         [MODE_ENABLE_REG] = intc_mode_field,
171         [MODE_MASK_REG] = intc_mode_zero,
172         [MODE_DUAL_REG] = intc_mode_field,
173         [MODE_PRIO_REG] = intc_mode_prio,
174         [MODE_PCLR_REG] = intc_mode_prio,
175 };
176
177 static void (*intc_disable_fns[])(unsigned long addr,
178                                   unsigned long handle,
179                                   void (*fn)(unsigned long,
180                                              unsigned long,
181                                              unsigned long),
182                                   unsigned int irq) = {
183         [MODE_ENABLE_REG] = intc_mode_zero,
184         [MODE_MASK_REG] = intc_mode_field,
185         [MODE_DUAL_REG] = intc_mode_field,
186         [MODE_PRIO_REG] = intc_mode_zero,
187         [MODE_PCLR_REG] = intc_mode_field,
188 };
189
190 static inline void _intc_enable(unsigned int irq, unsigned long handle)
191 {
192         struct intc_desc_int *d = get_intc_desc(irq);
193         unsigned long addr;
194         unsigned int cpu;
195
196         for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
197                 addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
198                 intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
199                                                     [_INTC_FN(handle)], irq);
200         }
201 }
202
203 static void intc_enable(unsigned int irq)
204 {
205         _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
206 }
207
208 static void intc_disable(unsigned int irq)
209 {
210         struct intc_desc_int *d = get_intc_desc(irq);
211         unsigned long handle = (unsigned long) get_irq_chip_data(irq);
212         unsigned long addr;
213         unsigned int cpu;
214
215         for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
216                 addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
217                 intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
218                                                      [_INTC_FN(handle)], irq);
219         }
220 }
221
222 static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
223                                              unsigned int nr_hp,
224                                              unsigned int irq)
225 {
226         int i;
227
228         /* this doesn't scale well, but...
229          *
230          * this function should only be used for cerain uncommon
231          * operations such as intc_set_priority() and intc_set_sense()
232          * and in those rare cases performance doesn't matter that much.
233          * keeping the memory footprint low is more important.
234          *
235          * one rather simple way to speed this up and still keep the
236          * memory footprint down is to make sure the array is sorted
237          * and then perform a bisect to lookup the irq.
238          */
239
240         for (i = 0; i < nr_hp; i++) {
241                 if ((hp + i)->irq != irq)
242                         continue;
243
244                 return hp + i;
245         }
246
247         return NULL;
248 }
249
250 int intc_set_priority(unsigned int irq, unsigned int prio)
251 {
252         struct intc_desc_int *d = get_intc_desc(irq);
253         struct intc_handle_int *ihp;
254
255         if (!intc_prio_level[irq] || prio <= 1)
256                 return -EINVAL;
257
258         ihp = intc_find_irq(d->prio, d->nr_prio, irq);
259         if (ihp) {
260                 if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
261                         return -EINVAL;
262
263                 intc_prio_level[irq] = prio;
264
265                 /*
266                  * only set secondary masking method directly
267                  * primary masking method is using intc_prio_level[irq]
268                  * priority level will be set during next enable()
269                  */
270
271                 if (_INTC_FN(ihp->handle) != REG_FN_ERR)
272                         _intc_enable(irq, ihp->handle);
273         }
274         return 0;
275 }
276
277 #define VALID(x) (x | 0x80)
278
279 static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
280         [IRQ_TYPE_EDGE_FALLING] = VALID(0),
281         [IRQ_TYPE_EDGE_RISING] = VALID(1),
282         [IRQ_TYPE_LEVEL_LOW] = VALID(2),
283         [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
284 };
285
286 static int intc_set_sense(unsigned int irq, unsigned int type)
287 {
288         struct intc_desc_int *d = get_intc_desc(irq);
289         unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
290         struct intc_handle_int *ihp;
291         unsigned long addr;
292
293         if (!value)
294                 return -EINVAL;
295
296         ihp = intc_find_irq(d->sense, d->nr_sense, irq);
297         if (ihp) {
298                 addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
299                 intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
300         }
301         return 0;
302 }
303
304 static unsigned int __init intc_get_reg(struct intc_desc_int *d,
305                                  unsigned long address)
306 {
307         unsigned int k;
308
309         for (k = 0; k < d->nr_reg; k++) {
310                 if (d->reg[k] == address)
311                         return k;
312         }
313
314         BUG();
315         return 0;
316 }
317
318 static intc_enum __init intc_grp_id(struct intc_desc *desc,
319                                     intc_enum enum_id)
320 {
321         struct intc_group *g = desc->groups;
322         unsigned int i, j;
323
324         for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
325                 g = desc->groups + i;
326
327                 for (j = 0; g->enum_ids[j]; j++) {
328                         if (g->enum_ids[j] != enum_id)
329                                 continue;
330
331                         return g->enum_id;
332                 }
333         }
334
335         return 0;
336 }
337
338 static unsigned int __init intc_prio_value(struct intc_desc *desc,
339                                            intc_enum enum_id, int do_grps)
340 {
341         struct intc_prio *p = desc->priorities;
342         unsigned int i;
343
344         for (i = 0; p && enum_id && i < desc->nr_priorities; i++) {
345                 p = desc->priorities + i;
346
347                 if (p->enum_id != enum_id)
348                         continue;
349
350                 return p->priority;
351         }
352
353         if (do_grps)
354                 return intc_prio_value(desc, intc_grp_id(desc, enum_id), 0);
355
356         /* default to the lowest priority possible if no priority is set
357          * - this needs to be at least 2 for 5-bit priorities on 7780
358          */
359
360         return 2;
361 }
362
363 static unsigned int __init intc_mask_data(struct intc_desc *desc,
364                                           struct intc_desc_int *d,
365                                           intc_enum enum_id, int do_grps)
366 {
367         struct intc_mask_reg *mr = desc->mask_regs;
368         unsigned int i, j, fn, mode;
369         unsigned long reg_e, reg_d;
370
371         for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
372                 mr = desc->mask_regs + i;
373
374                 for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
375                         if (mr->enum_ids[j] != enum_id)
376                                 continue;
377
378                         if (mr->set_reg && mr->clr_reg) {
379                                 fn = REG_FN_WRITE_BASE;
380                                 mode = MODE_DUAL_REG;
381                                 reg_e = mr->clr_reg;
382                                 reg_d = mr->set_reg;
383                         } else {
384                                 fn = REG_FN_MODIFY_BASE;
385                                 if (mr->set_reg) {
386                                         mode = MODE_ENABLE_REG;
387                                         reg_e = mr->set_reg;
388                                         reg_d = mr->set_reg;
389                                 } else {
390                                         mode = MODE_MASK_REG;
391                                         reg_e = mr->clr_reg;
392                                         reg_d = mr->clr_reg;
393                                 }
394                         }
395
396                         fn += (mr->reg_width >> 3) - 1;
397                         return _INTC_MK(fn, mode,
398                                         intc_get_reg(d, reg_e),
399                                         intc_get_reg(d, reg_d),
400                                         1,
401                                         (mr->reg_width - 1) - j);
402                 }
403         }
404
405         if (do_grps)
406                 return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
407
408         return 0;
409 }
410
411 static unsigned int __init intc_prio_data(struct intc_desc *desc,
412                                           struct intc_desc_int *d,
413                                           intc_enum enum_id, int do_grps)
414 {
415         struct intc_prio_reg *pr = desc->prio_regs;
416         unsigned int i, j, fn, mode, bit;
417         unsigned long reg_e, reg_d;
418
419         for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
420                 pr = desc->prio_regs + i;
421
422                 for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
423                         if (pr->enum_ids[j] != enum_id)
424                                 continue;
425
426                         if (pr->set_reg && pr->clr_reg) {
427                                 fn = REG_FN_WRITE_BASE;
428                                 mode = MODE_PCLR_REG;
429                                 reg_e = pr->set_reg;
430                                 reg_d = pr->clr_reg;
431                         } else {
432                                 fn = REG_FN_MODIFY_BASE;
433                                 mode = MODE_PRIO_REG;
434                                 if (!pr->set_reg)
435                                         BUG();
436                                 reg_e = pr->set_reg;
437                                 reg_d = pr->set_reg;
438                         }
439
440                         fn += (pr->reg_width >> 3) - 1;
441                         bit = pr->reg_width - ((j + 1) * pr->field_width);
442
443                         BUG_ON(bit < 0);
444
445                         return _INTC_MK(fn, mode,
446                                         intc_get_reg(d, reg_e),
447                                         intc_get_reg(d, reg_d),
448                                         pr->field_width, bit);
449                 }
450         }
451
452         if (do_grps)
453                 return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
454
455         return 0;
456 }
457
458 static unsigned int __init intc_sense_data(struct intc_desc *desc,
459                                            struct intc_desc_int *d,
460                                            intc_enum enum_id)
461 {
462         struct intc_sense_reg *sr = desc->sense_regs;
463         unsigned int i, j, fn, bit;
464
465         for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {
466                 sr = desc->sense_regs + i;
467
468                 for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
469                         if (sr->enum_ids[j] != enum_id)
470                                 continue;
471
472                         fn = REG_FN_MODIFY_BASE;
473                         fn += (sr->reg_width >> 3) - 1;
474                         bit = sr->reg_width - ((j + 1) * sr->field_width);
475
476                         BUG_ON(bit < 0);
477
478                         return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
479                                         0, sr->field_width, bit);
480                 }
481         }
482
483         return 0;
484 }
485
486 static void __init intc_register_irq(struct intc_desc *desc,
487                                      struct intc_desc_int *d,
488                                      intc_enum enum_id,
489                                      unsigned int irq)
490 {
491         struct intc_handle_int *hp;
492         unsigned int data[2], primary;
493
494         /* Prefer single interrupt source bitmap over other combinations:
495          * 1. bitmap, single interrupt source
496          * 2. priority, single interrupt source
497          * 3. bitmap, multiple interrupt sources (groups)
498          * 4. priority, multiple interrupt sources (groups)
499          */
500
501         data[0] = intc_mask_data(desc, d, enum_id, 0);
502         data[1] = intc_prio_data(desc, d, enum_id, 0);
503
504         primary = 0;
505         if (!data[0] && data[1])
506                 primary = 1;
507
508         data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
509         data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
510
511         if (!data[primary])
512                 primary ^= 1;
513
514         BUG_ON(!data[primary]); /* must have primary masking method */
515
516         disable_irq_nosync(irq);
517         set_irq_chip_and_handler_name(irq, &d->chip,
518                                       handle_level_irq, "level");
519         set_irq_chip_data(irq, (void *)data[primary]);
520
521         /* record the desired priority level */
522         intc_prio_level[irq] = intc_prio_value(desc, enum_id, 1);
523
524         /* enable secondary masking method if present */
525         if (data[!primary])
526                 _intc_enable(irq, data[!primary]);
527
528         /* add irq to d->prio list if priority is available */
529         if (data[1]) {
530                 hp = d->prio + d->nr_prio;
531                 hp->irq = irq;
532                 hp->handle = data[1];
533
534                 if (primary) {
535                         /*
536                          * only secondary priority should access registers, so
537                          * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
538                          */
539
540                         hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
541                         hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
542                 }
543                 d->nr_prio++;
544         }
545
546         /* add irq to d->sense list if sense is available */
547         data[0] = intc_sense_data(desc, d, enum_id);
548         if (data[0]) {
549                 (d->sense + d->nr_sense)->irq = irq;
550                 (d->sense + d->nr_sense)->handle = data[0];
551                 d->nr_sense++;
552         }
553
554         /* irq should be disabled by default */
555         d->chip.mask(irq);
556 }
557
558 static unsigned int __init save_reg(struct intc_desc_int *d,
559                                     unsigned int cnt,
560                                     unsigned long value,
561                                     unsigned int smp)
562 {
563         if (value) {
564                 d->reg[cnt] = value;
565 #ifdef CONFIG_SMP
566                 d->smp[cnt] = smp;
567 #endif
568                 return 1;
569         }
570
571         return 0;
572 }
573
574
575 void __init register_intc_controller(struct intc_desc *desc)
576 {
577         unsigned int i, k, smp;
578         struct intc_desc_int *d;
579
580         d = alloc_bootmem(sizeof(*d));
581
582         d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
583         d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
584         d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
585
586         d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
587 #ifdef CONFIG_SMP
588         d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
589 #endif
590         k = 0;
591
592         if (desc->mask_regs) {
593                 for (i = 0; i < desc->nr_mask_regs; i++) {
594                         smp = IS_SMP(desc->mask_regs[i]);
595                         k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);
596                         k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);
597                 }
598         }
599
600         if (desc->prio_regs) {
601                 d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));
602
603                 for (i = 0; i < desc->nr_prio_regs; i++) {
604                         smp = IS_SMP(desc->prio_regs[i]);
605                         k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);
606                         k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);
607                 }
608         }
609
610         if (desc->sense_regs) {
611                 d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));
612
613                 for (i = 0; i < desc->nr_sense_regs; i++) {
614                         k += save_reg(d, k, desc->sense_regs[i].reg, 0);
615                 }
616         }
617
618         BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
619
620         d->chip.name = desc->name;
621         d->chip.mask = intc_disable;
622         d->chip.unmask = intc_enable;
623         d->chip.mask_ack = intc_disable;
624         d->chip.set_type = intc_set_sense;
625
626         for (i = 0; i < desc->nr_vectors; i++) {
627                 struct intc_vect *vect = desc->vectors + i;
628
629                 intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
630         }
631 }