m68k/irq: Extract irq_set_chip()
[firefly-linux-kernel-4.4.55.git] / arch / m68k / kernel / ints.c
1 /*
2  * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file COPYING in the main directory of this archive
6  * for more details.
7  *
8  * 07/03/96: Timer initialization, and thus mach_sched_init(),
9  *           removed from request_irq() and moved to init_time().
10  *           We should therefore consider renaming our add_isr() and
11  *           remove_isr() to request_irq() and free_irq()
12  *           respectively, so they are compliant with the other
13  *           architectures.                                     /Jes
14  * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
15  *           Removed irq list support, if any machine needs an irq server
16  *           it must implement this itself (as it's already done), instead
17  *           only default handler are used with mach_default_handler.
18  *           request_irq got some flags different from other architectures:
19  *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
20  *                               can be replaced without this flag)
21  *           - IRQ_FLG_LOCK : handler can't be replaced
22  *           There are other machine depending flags, see there
23  *           If you want to replace a default handler you should know what
24  *           you're doing, since it might handle different other irq sources
25  *           which must be served                               /Roman Zippel
26  */
27
28 #include <linux/module.h>
29 #include <linux/types.h>
30 #include <linux/sched.h>
31 #include <linux/interrupt.h>
32 #include <linux/kernel_stat.h>
33 #include <linux/errno.h>
34 #include <linux/init.h>
35
36 #include <asm/setup.h>
37 #include <asm/system.h>
38 #include <asm/irq.h>
39 #include <asm/traps.h>
40 #include <asm/page.h>
41 #include <asm/machdep.h>
42 #include <asm/cacheflush.h>
43 #include <asm/irq_regs.h>
44
45 #ifdef CONFIG_Q40
46 #include <asm/q40ints.h>
47 #endif
48
49 extern u32 auto_irqhandler_fixup[];
50 extern u32 user_irqhandler_fixup[];
51 extern u16 user_irqvec_fixup[];
52
53 /* table for system interrupt handlers */
54 static struct irq_data *irq_list[NR_IRQS];
55 static struct irq_chip *irq_chip[NR_IRQS];
56 static int irq_depth[NR_IRQS];
57
58 static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip)
59 {
60         irq_chip[irq] = chip;
61         return 0;
62 }
63
64 static int m68k_first_user_vec;
65
66 static struct irq_chip auto_irq_chip = {
67         .name           = "auto",
68         .irq_startup    = m68k_irq_startup,
69         .irq_shutdown   = m68k_irq_shutdown,
70 };
71
72 static struct irq_chip user_irq_chip = {
73         .name           = "user",
74         .irq_startup    = m68k_irq_startup,
75         .irq_shutdown   = m68k_irq_shutdown,
76 };
77
78 #define NUM_IRQ_NODES 100
79 static struct irq_data nodes[NUM_IRQ_NODES];
80
81 /*
82  * void init_IRQ(void)
83  *
84  * Parameters:  None
85  *
86  * Returns:     Nothing
87  *
88  * This function should be called during kernel startup to initialize
89  * the IRQ handling routines.
90  */
91
92 void __init init_IRQ(void)
93 {
94         int i;
95
96         /* assembly irq entry code relies on this... */
97         if (HARDIRQ_MASK != 0x00ff0000) {
98                 extern void hardirq_mask_is_broken(void);
99                 hardirq_mask_is_broken();
100         }
101
102         for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
103                 irq_set_chip(i, &auto_irq_chip);
104
105         mach_init_IRQ();
106 }
107
108 /**
109  * m68k_setup_auto_interrupt
110  * @handler: called from auto vector interrupts
111  *
112  * setup the handler to be called from auto vector interrupts instead of the
113  * standard __m68k_handle_int(), it will be called with irq numbers in the range
114  * from IRQ_AUTO_1 - IRQ_AUTO_7.
115  */
116 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
117 {
118         if (handler)
119                 *auto_irqhandler_fixup = (u32)handler;
120         flush_icache();
121 }
122
123 /**
124  * m68k_setup_user_interrupt
125  * @vec: first user vector interrupt to handle
126  * @cnt: number of active user vector interrupts
127  * @handler: called from user vector interrupts
128  *
129  * setup user vector interrupts, this includes activating the specified range
130  * of interrupts, only then these interrupts can be requested (note: this is
131  * different from auto vector interrupts). An optional handler can be installed
132  * to be called instead of the default __m68k_handle_int(), it will be called
133  * with irq numbers starting from IRQ_USER.
134  */
135 void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
136                                       void (*handler)(unsigned int, struct pt_regs *))
137 {
138         int i;
139
140         BUG_ON(IRQ_USER + cnt > NR_IRQS);
141         m68k_first_user_vec = vec;
142         for (i = 0; i < cnt; i++)
143                 irq_set_chip(IRQ_USER + i, &user_irq_chip);
144         *user_irqvec_fixup = vec - IRQ_USER;
145         if (handler)
146                 *user_irqhandler_fixup = (u32)handler;
147         flush_icache();
148 }
149
150 /**
151  * m68k_setup_irq_chip
152  * @contr: irq controller which controls specified irq
153  * @irq: first irq to be managed by the controller
154  *
155  * Change the controller for the specified range of irq, which will be used to
156  * manage these irq. auto/user irq already have a default controller, which can
157  * be changed as well, but the controller probably should use m68k_irq_startup/
158  * m68k_irq_shutdown.
159  */
160 void m68k_setup_irq_chip(struct irq_chip *contr, unsigned int irq,
161                                unsigned int cnt)
162 {
163         int i;
164
165         for (i = 0; i < cnt; i++)
166                 irq_set_chip(irq + i, contr);
167 }
168
169 struct irq_data *new_irq_node(void)
170 {
171         struct irq_data *node;
172         short i;
173
174         for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
175                 if (!node->handler) {
176                         memset(node, 0, sizeof(*node));
177                         return node;
178                 }
179         }
180
181         printk ("new_irq_node: out of nodes\n");
182         return NULL;
183 }
184
185 static int m68k_setup_irq(unsigned int irq, struct irq_data *node)
186 {
187         struct irq_chip *contr;
188         struct irq_data **prev;
189         unsigned long flags;
190
191         if (irq >= NR_IRQS || !(contr = irq_chip[irq])) {
192                 printk("%s: Incorrect IRQ %d from %s\n",
193                        __func__, irq, node->devname);
194                 return -ENXIO;
195         }
196
197         local_irq_save(flags);
198
199         prev = irq_list + irq;
200         if (*prev) {
201                 /* Can't share interrupts unless both agree to */
202                 if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
203                         local_irq_restore(flags);
204                         return -EBUSY;
205                 }
206                 while (*prev)
207                         prev = &(*prev)->next;
208         }
209
210         if (!irq_list[irq]) {
211                 if (contr->irq_startup)
212                         contr->irq_startup(node);
213                 else
214                         contr->irq_enable(node);
215         }
216         node->next = NULL;
217         *prev = node;
218
219         local_irq_restore(flags);
220
221         return 0;
222 }
223
224 int request_irq(unsigned int irq,
225                 irq_handler_t handler,
226                 unsigned long flags, const char *devname, void *dev_id)
227 {
228         struct irq_data *node;
229         int res;
230
231         node = new_irq_node();
232         if (!node)
233                 return -ENOMEM;
234
235         node->irq     = irq;
236         node->handler = handler;
237         node->flags   = flags;
238         node->dev_id  = dev_id;
239         node->devname = devname;
240
241         res = m68k_setup_irq(irq, node);
242         if (res)
243                 node->handler = NULL;
244
245         return res;
246 }
247
248 EXPORT_SYMBOL(request_irq);
249
250 void free_irq(unsigned int irq, void *dev_id)
251 {
252         struct irq_chip *contr;
253         struct irq_data **p, *node;
254         unsigned long flags;
255
256         if (irq >= NR_IRQS || !(contr = irq_chip[irq])) {
257                 printk("%s: Incorrect IRQ %d\n", __func__, irq);
258                 return;
259         }
260
261         local_irq_save(flags);
262
263         p = irq_list + irq;
264         while ((node = *p)) {
265                 if (node->dev_id == dev_id)
266                         break;
267                 p = &node->next;
268         }
269
270         if (node) {
271                 *p = node->next;
272                 node->handler = NULL;
273         } else
274                 printk("%s: Removing probably wrong IRQ %d\n",
275                        __func__, irq);
276
277         if (!irq_list[irq]) {
278                 if (contr->irq_shutdown)
279                         contr->irq_shutdown(node);
280                 else
281                         contr->irq_disable(node);
282         }
283
284         local_irq_restore(flags);
285 }
286
287 EXPORT_SYMBOL(free_irq);
288
289 void enable_irq(unsigned int irq)
290 {
291         struct irq_chip *contr;
292         unsigned long flags;
293
294         if (irq >= NR_IRQS || !(contr = irq_chip[irq])) {
295                 printk("%s: Incorrect IRQ %d\n",
296                        __func__, irq);
297                 return;
298         }
299
300         local_irq_save(flags);
301         if (irq_depth[irq]) {
302                 if (!--irq_depth[irq]) {
303                         if (contr->irq_enable)
304                                 contr->irq_enable(irq_list[irq]);
305                 }
306         } else
307                 WARN_ON(1);
308         local_irq_restore(flags);
309 }
310
311 EXPORT_SYMBOL(enable_irq);
312
313 void disable_irq(unsigned int irq)
314 {
315         struct irq_chip *contr;
316         unsigned long flags;
317
318         if (irq >= NR_IRQS || !(contr = irq_chip[irq])) {
319                 printk("%s: Incorrect IRQ %d\n",
320                        __func__, irq);
321                 return;
322         }
323
324         local_irq_save(flags);
325         if (!irq_depth[irq]++) {
326                 if (contr->irq_disable)
327                         contr->irq_disable(irq_list[irq]);
328         }
329         local_irq_restore(flags);
330 }
331
332 EXPORT_SYMBOL(disable_irq);
333
334 void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
335
336 EXPORT_SYMBOL(disable_irq_nosync);
337
338 unsigned int m68k_irq_startup_irq(unsigned int irq)
339 {
340         if (irq <= IRQ_AUTO_7)
341                 vectors[VEC_SPUR + irq] = auto_inthandler;
342         else
343                 vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
344         return 0;
345 }
346
347 unsigned int m68k_irq_startup(struct irq_data *data)
348 {
349         return m68k_irq_startup_irq(data->irq);
350 }
351
352 void m68k_irq_shutdown(struct irq_data *data)
353 {
354         unsigned int irq = data->irq;
355
356         if (irq <= IRQ_AUTO_7)
357                 vectors[VEC_SPUR + irq] = bad_inthandler;
358         else
359                 vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
360 }
361
362
363 /*
364  * Do we need these probe functions on the m68k?
365  *
366  *  ... may be useful with ISA devices
367  */
368 unsigned long probe_irq_on (void)
369 {
370 #ifdef CONFIG_Q40
371         if (MACH_IS_Q40)
372                 return q40_probe_irq_on();
373 #endif
374         return 0;
375 }
376
377 EXPORT_SYMBOL(probe_irq_on);
378
379 int probe_irq_off (unsigned long irqs)
380 {
381 #ifdef CONFIG_Q40
382         if (MACH_IS_Q40)
383                 return q40_probe_irq_off(irqs);
384 #endif
385         return 0;
386 }
387
388 EXPORT_SYMBOL(probe_irq_off);
389
390 unsigned int irq_canonicalize(unsigned int irq)
391 {
392 #ifdef CONFIG_Q40
393         if (MACH_IS_Q40 && irq == 11)
394                 irq = 10;
395 #endif
396         return irq;
397 }
398
399 EXPORT_SYMBOL(irq_canonicalize);
400
401 asmlinkage void m68k_handle_int(unsigned int irq)
402 {
403         struct irq_data *node;
404         kstat_cpu(0).irqs[irq]++;
405         node = irq_list[irq];
406         do {
407                 node->handler(irq, node->dev_id);
408                 node = node->next;
409         } while (node);
410 }
411
412 asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
413 {
414         struct pt_regs *old_regs;
415         old_regs = set_irq_regs(regs);
416         m68k_handle_int(irq);
417         set_irq_regs(old_regs);
418 }
419
420 asmlinkage void handle_badint(struct pt_regs *regs)
421 {
422         kstat_cpu(0).irqs[0]++;
423         printk("unexpected interrupt from %u\n", regs->vector);
424 }
425
426 int show_interrupts(struct seq_file *p, void *v)
427 {
428         struct irq_chip *contr;
429         struct irq_data *node;
430         int i = *(loff_t *) v;
431
432         /* autovector interrupts */
433         if (irq_list[i]) {
434                 contr = irq_chip[i];
435                 node = irq_list[i];
436                 seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
437                 while ((node = node->next))
438                         seq_printf(p, ", %s", node->devname);
439                 seq_puts(p, "\n");
440         }
441         return 0;
442 }
443
444 #ifdef CONFIG_PROC_FS
445 void init_irq_proc(void)
446 {
447         /* Insert /proc/irq driver here */
448 }
449 #endif