Merge tag '8139cp-20060912-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux...
[linux-2.6] / arch / powerpc / sysdev / ipic.c
1 /*
2  * include/asm-ppc/ipic.c
3  *
4  * IPIC routines implementations.
5  *
6  * Copyright 2005 Freescale Semiconductor, Inc.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/reboot.h>
17 #include <linux/slab.h>
18 #include <linux/stddef.h>
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/sysdev.h>
22 #include <linux/device.h>
23 #include <linux/bootmem.h>
24 #include <linux/spinlock.h>
25 #include <asm/irq.h>
26 #include <asm/io.h>
27 #include <asm/prom.h>
28 #include <asm/ipic.h>
29
30 #include "ipic.h"
31
32 static struct ipic * primary_ipic;
33 static DEFINE_SPINLOCK(ipic_lock);
34
35 static struct ipic_info ipic_info[] = {
36         [9] = {
37                 .pend   = IPIC_SIPNR_H,
38                 .mask   = IPIC_SIMSR_H,
39                 .prio   = IPIC_SIPRR_D,
40                 .force  = IPIC_SIFCR_H,
41                 .bit    = 24,
42                 .prio_mask = 0,
43         },
44         [10] = {
45                 .pend   = IPIC_SIPNR_H,
46                 .mask   = IPIC_SIMSR_H,
47                 .prio   = IPIC_SIPRR_D,
48                 .force  = IPIC_SIFCR_H,
49                 .bit    = 25,
50                 .prio_mask = 1,
51         },
52         [11] = {
53                 .pend   = IPIC_SIPNR_H,
54                 .mask   = IPIC_SIMSR_H,
55                 .prio   = IPIC_SIPRR_D,
56                 .force  = IPIC_SIFCR_H,
57                 .bit    = 26,
58                 .prio_mask = 2,
59         },
60         [14] = {
61                 .pend   = IPIC_SIPNR_H,
62                 .mask   = IPIC_SIMSR_H,
63                 .prio   = IPIC_SIPRR_D,
64                 .force  = IPIC_SIFCR_H,
65                 .bit    = 29,
66                 .prio_mask = 5,
67         },
68         [15] = {
69                 .pend   = IPIC_SIPNR_H,
70                 .mask   = IPIC_SIMSR_H,
71                 .prio   = IPIC_SIPRR_D,
72                 .force  = IPIC_SIFCR_H,
73                 .bit    = 30,
74                 .prio_mask = 6,
75         },
76         [16] = {
77                 .pend   = IPIC_SIPNR_H,
78                 .mask   = IPIC_SIMSR_H,
79                 .prio   = IPIC_SIPRR_D,
80                 .force  = IPIC_SIFCR_H,
81                 .bit    = 31,
82                 .prio_mask = 7,
83         },
84         [17] = {
85                 .pend   = IPIC_SEPNR,
86                 .mask   = IPIC_SEMSR,
87                 .prio   = IPIC_SMPRR_A,
88                 .force  = IPIC_SEFCR,
89                 .bit    = 1,
90                 .prio_mask = 5,
91         },
92         [18] = {
93                 .pend   = IPIC_SEPNR,
94                 .mask   = IPIC_SEMSR,
95                 .prio   = IPIC_SMPRR_A,
96                 .force  = IPIC_SEFCR,
97                 .bit    = 2,
98                 .prio_mask = 6,
99         },
100         [19] = {
101                 .pend   = IPIC_SEPNR,
102                 .mask   = IPIC_SEMSR,
103                 .prio   = IPIC_SMPRR_A,
104                 .force  = IPIC_SEFCR,
105                 .bit    = 3,
106                 .prio_mask = 7,
107         },
108         [20] = {
109                 .pend   = IPIC_SEPNR,
110                 .mask   = IPIC_SEMSR,
111                 .prio   = IPIC_SMPRR_B,
112                 .force  = IPIC_SEFCR,
113                 .bit    = 4,
114                 .prio_mask = 4,
115         },
116         [21] = {
117                 .pend   = IPIC_SEPNR,
118                 .mask   = IPIC_SEMSR,
119                 .prio   = IPIC_SMPRR_B,
120                 .force  = IPIC_SEFCR,
121                 .bit    = 5,
122                 .prio_mask = 5,
123         },
124         [22] = {
125                 .pend   = IPIC_SEPNR,
126                 .mask   = IPIC_SEMSR,
127                 .prio   = IPIC_SMPRR_B,
128                 .force  = IPIC_SEFCR,
129                 .bit    = 6,
130                 .prio_mask = 6,
131         },
132         [23] = {
133                 .pend   = IPIC_SEPNR,
134                 .mask   = IPIC_SEMSR,
135                 .prio   = IPIC_SMPRR_B,
136                 .force  = IPIC_SEFCR,
137                 .bit    = 7,
138                 .prio_mask = 7,
139         },
140         [32] = {
141                 .pend   = IPIC_SIPNR_H,
142                 .mask   = IPIC_SIMSR_H,
143                 .prio   = IPIC_SIPRR_A,
144                 .force  = IPIC_SIFCR_H,
145                 .bit    = 0,
146                 .prio_mask = 0,
147         },
148         [33] = {
149                 .pend   = IPIC_SIPNR_H,
150                 .mask   = IPIC_SIMSR_H,
151                 .prio   = IPIC_SIPRR_A,
152                 .force  = IPIC_SIFCR_H,
153                 .bit    = 1,
154                 .prio_mask = 1,
155         },
156         [34] = {
157                 .pend   = IPIC_SIPNR_H,
158                 .mask   = IPIC_SIMSR_H,
159                 .prio   = IPIC_SIPRR_A,
160                 .force  = IPIC_SIFCR_H,
161                 .bit    = 2,
162                 .prio_mask = 2,
163         },
164         [35] = {
165                 .pend   = IPIC_SIPNR_H,
166                 .mask   = IPIC_SIMSR_H,
167                 .prio   = IPIC_SIPRR_A,
168                 .force  = IPIC_SIFCR_H,
169                 .bit    = 3,
170                 .prio_mask = 3,
171         },
172         [36] = {
173                 .pend   = IPIC_SIPNR_H,
174                 .mask   = IPIC_SIMSR_H,
175                 .prio   = IPIC_SIPRR_A,
176                 .force  = IPIC_SIFCR_H,
177                 .bit    = 4,
178                 .prio_mask = 4,
179         },
180         [37] = {
181                 .pend   = IPIC_SIPNR_H,
182                 .mask   = IPIC_SIMSR_H,
183                 .prio   = IPIC_SIPRR_A,
184                 .force  = IPIC_SIFCR_H,
185                 .bit    = 5,
186                 .prio_mask = 5,
187         },
188         [38] = {
189                 .pend   = IPIC_SIPNR_H,
190                 .mask   = IPIC_SIMSR_H,
191                 .prio   = IPIC_SIPRR_A,
192                 .force  = IPIC_SIFCR_H,
193                 .bit    = 6,
194                 .prio_mask = 6,
195         },
196         [39] = {
197                 .pend   = IPIC_SIPNR_H,
198                 .mask   = IPIC_SIMSR_H,
199                 .prio   = IPIC_SIPRR_A,
200                 .force  = IPIC_SIFCR_H,
201                 .bit    = 7,
202                 .prio_mask = 7,
203         },
204         [48] = {
205                 .pend   = IPIC_SEPNR,
206                 .mask   = IPIC_SEMSR,
207                 .prio   = IPIC_SMPRR_A,
208                 .force  = IPIC_SEFCR,
209                 .bit    = 0,
210                 .prio_mask = 4,
211         },
212         [64] = {
213                 .pend   = IPIC_SIPNR_H,
214                 .mask   = IPIC_SIMSR_L,
215                 .prio   = IPIC_SMPRR_A,
216                 .force  = IPIC_SIFCR_L,
217                 .bit    = 0,
218                 .prio_mask = 0,
219         },
220         [65] = {
221                 .pend   = IPIC_SIPNR_H,
222                 .mask   = IPIC_SIMSR_L,
223                 .prio   = IPIC_SMPRR_A,
224                 .force  = IPIC_SIFCR_L,
225                 .bit    = 1,
226                 .prio_mask = 1,
227         },
228         [66] = {
229                 .pend   = IPIC_SIPNR_H,
230                 .mask   = IPIC_SIMSR_L,
231                 .prio   = IPIC_SMPRR_A,
232                 .force  = IPIC_SIFCR_L,
233                 .bit    = 2,
234                 .prio_mask = 2,
235         },
236         [67] = {
237                 .pend   = IPIC_SIPNR_H,
238                 .mask   = IPIC_SIMSR_L,
239                 .prio   = IPIC_SMPRR_A,
240                 .force  = IPIC_SIFCR_L,
241                 .bit    = 3,
242                 .prio_mask = 3,
243         },
244         [68] = {
245                 .pend   = IPIC_SIPNR_H,
246                 .mask   = IPIC_SIMSR_L,
247                 .prio   = IPIC_SMPRR_B,
248                 .force  = IPIC_SIFCR_L,
249                 .bit    = 4,
250                 .prio_mask = 0,
251         },
252         [69] = {
253                 .pend   = IPIC_SIPNR_H,
254                 .mask   = IPIC_SIMSR_L,
255                 .prio   = IPIC_SMPRR_B,
256                 .force  = IPIC_SIFCR_L,
257                 .bit    = 5,
258                 .prio_mask = 1,
259         },
260         [70] = {
261                 .pend   = IPIC_SIPNR_H,
262                 .mask   = IPIC_SIMSR_L,
263                 .prio   = IPIC_SMPRR_B,
264                 .force  = IPIC_SIFCR_L,
265                 .bit    = 6,
266                 .prio_mask = 2,
267         },
268         [71] = {
269                 .pend   = IPIC_SIPNR_H,
270                 .mask   = IPIC_SIMSR_L,
271                 .prio   = IPIC_SMPRR_B,
272                 .force  = IPIC_SIFCR_L,
273                 .bit    = 7,
274                 .prio_mask = 3,
275         },
276         [72] = {
277                 .pend   = IPIC_SIPNR_H,
278                 .mask   = IPIC_SIMSR_L,
279                 .prio   = 0,
280                 .force  = IPIC_SIFCR_L,
281                 .bit    = 8,
282         },
283         [73] = {
284                 .pend   = IPIC_SIPNR_H,
285                 .mask   = IPIC_SIMSR_L,
286                 .prio   = 0,
287                 .force  = IPIC_SIFCR_L,
288                 .bit    = 9,
289         },
290         [74] = {
291                 .pend   = IPIC_SIPNR_H,
292                 .mask   = IPIC_SIMSR_L,
293                 .prio   = 0,
294                 .force  = IPIC_SIFCR_L,
295                 .bit    = 10,
296         },
297         [75] = {
298                 .pend   = IPIC_SIPNR_H,
299                 .mask   = IPIC_SIMSR_L,
300                 .prio   = 0,
301                 .force  = IPIC_SIFCR_L,
302                 .bit    = 11,
303         },
304         [76] = {
305                 .pend   = IPIC_SIPNR_H,
306                 .mask   = IPIC_SIMSR_L,
307                 .prio   = 0,
308                 .force  = IPIC_SIFCR_L,
309                 .bit    = 12,
310         },
311         [77] = {
312                 .pend   = IPIC_SIPNR_H,
313                 .mask   = IPIC_SIMSR_L,
314                 .prio   = 0,
315                 .force  = IPIC_SIFCR_L,
316                 .bit    = 13,
317         },
318         [78] = {
319                 .pend   = IPIC_SIPNR_H,
320                 .mask   = IPIC_SIMSR_L,
321                 .prio   = 0,
322                 .force  = IPIC_SIFCR_L,
323                 .bit    = 14,
324         },
325         [79] = {
326                 .pend   = IPIC_SIPNR_H,
327                 .mask   = IPIC_SIMSR_L,
328                 .prio   = 0,
329                 .force  = IPIC_SIFCR_L,
330                 .bit    = 15,
331         },
332         [80] = {
333                 .pend   = IPIC_SIPNR_H,
334                 .mask   = IPIC_SIMSR_L,
335                 .prio   = 0,
336                 .force  = IPIC_SIFCR_L,
337                 .bit    = 16,
338         },
339         [84] = {
340                 .pend   = IPIC_SIPNR_H,
341                 .mask   = IPIC_SIMSR_L,
342                 .prio   = 0,
343                 .force  = IPIC_SIFCR_L,
344                 .bit    = 20,
345         },
346         [85] = {
347                 .pend   = IPIC_SIPNR_H,
348                 .mask   = IPIC_SIMSR_L,
349                 .prio   = 0,
350                 .force  = IPIC_SIFCR_L,
351                 .bit    = 21,
352         },
353         [90] = {
354                 .pend   = IPIC_SIPNR_H,
355                 .mask   = IPIC_SIMSR_L,
356                 .prio   = 0,
357                 .force  = IPIC_SIFCR_L,
358                 .bit    = 26,
359         },
360         [91] = {
361                 .pend   = IPIC_SIPNR_H,
362                 .mask   = IPIC_SIMSR_L,
363                 .prio   = 0,
364                 .force  = IPIC_SIFCR_L,
365                 .bit    = 27,
366         },
367 };
368
369 static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
370 {
371         return in_be32(base + (reg >> 2));
372 }
373
374 static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
375 {
376         out_be32(base + (reg >> 2), value);
377 }
378
379 static inline struct ipic * ipic_from_irq(unsigned int virq)
380 {
381         return primary_ipic;
382 }
383
384 #define ipic_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
385
386 static void ipic_unmask_irq(unsigned int virq)
387 {
388         struct ipic *ipic = ipic_from_irq(virq);
389         unsigned int src = ipic_irq_to_hw(virq);
390         unsigned long flags;
391         u32 temp;
392
393         spin_lock_irqsave(&ipic_lock, flags);
394
395         temp = ipic_read(ipic->regs, ipic_info[src].mask);
396         temp |= (1 << (31 - ipic_info[src].bit));
397         ipic_write(ipic->regs, ipic_info[src].mask, temp);
398
399         spin_unlock_irqrestore(&ipic_lock, flags);
400 }
401
402 static void ipic_mask_irq(unsigned int virq)
403 {
404         struct ipic *ipic = ipic_from_irq(virq);
405         unsigned int src = ipic_irq_to_hw(virq);
406         unsigned long flags;
407         u32 temp;
408
409         spin_lock_irqsave(&ipic_lock, flags);
410
411         temp = ipic_read(ipic->regs, ipic_info[src].mask);
412         temp &= ~(1 << (31 - ipic_info[src].bit));
413         ipic_write(ipic->regs, ipic_info[src].mask, temp);
414
415         spin_unlock_irqrestore(&ipic_lock, flags);
416 }
417
418 static void ipic_ack_irq(unsigned int virq)
419 {
420         struct ipic *ipic = ipic_from_irq(virq);
421         unsigned int src = ipic_irq_to_hw(virq);
422         unsigned long flags;
423         u32 temp;
424
425         spin_lock_irqsave(&ipic_lock, flags);
426
427         temp = ipic_read(ipic->regs, ipic_info[src].pend);
428         temp |= (1 << (31 - ipic_info[src].bit));
429         ipic_write(ipic->regs, ipic_info[src].pend, temp);
430
431         spin_unlock_irqrestore(&ipic_lock, flags);
432 }
433
434 static void ipic_mask_irq_and_ack(unsigned int virq)
435 {
436         struct ipic *ipic = ipic_from_irq(virq);
437         unsigned int src = ipic_irq_to_hw(virq);
438         unsigned long flags;
439         u32 temp;
440
441         spin_lock_irqsave(&ipic_lock, flags);
442
443         temp = ipic_read(ipic->regs, ipic_info[src].mask);
444         temp &= ~(1 << (31 - ipic_info[src].bit));
445         ipic_write(ipic->regs, ipic_info[src].mask, temp);
446
447         temp = ipic_read(ipic->regs, ipic_info[src].pend);
448         temp |= (1 << (31 - ipic_info[src].bit));
449         ipic_write(ipic->regs, ipic_info[src].pend, temp);
450
451         spin_unlock_irqrestore(&ipic_lock, flags);
452 }
453
454 static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
455 {
456         struct ipic *ipic = ipic_from_irq(virq);
457         unsigned int src = ipic_irq_to_hw(virq);
458         struct irq_desc *desc = get_irq_desc(virq);
459         unsigned int vold, vnew, edibit;
460
461         if (flow_type == IRQ_TYPE_NONE)
462                 flow_type = IRQ_TYPE_LEVEL_LOW;
463
464         /* ipic supports only low assertion and high-to-low change senses
465          */
466         if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
467                 printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
468                         flow_type);
469                 return -EINVAL;
470         }
471
472         desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
473         desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
474         if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
475                 desc->status |= IRQ_LEVEL;
476                 set_irq_handler(virq, handle_level_irq);
477         } else {
478                 set_irq_handler(virq, handle_edge_irq);
479         }
480
481         /* only EXT IRQ senses are programmable on ipic
482          * internal IRQ senses are LEVEL_LOW
483          */
484         if (src == IPIC_IRQ_EXT0)
485                 edibit = 15;
486         else
487                 if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
488                         edibit = (14 - (src - IPIC_IRQ_EXT1));
489                 else
490                         return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
491
492         vold = ipic_read(ipic->regs, IPIC_SECNR);
493         if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
494                 vnew = vold | (1 << edibit);
495         } else {
496                 vnew = vold & ~(1 << edibit);
497         }
498         if (vold != vnew)
499                 ipic_write(ipic->regs, IPIC_SECNR, vnew);
500         return 0;
501 }
502
503 static struct irq_chip ipic_irq_chip = {
504         .typename       = " IPIC  ",
505         .unmask         = ipic_unmask_irq,
506         .mask           = ipic_mask_irq,
507         .mask_ack       = ipic_mask_irq_and_ack,
508         .ack            = ipic_ack_irq,
509         .set_type       = ipic_set_irq_type,
510 };
511
512 static int ipic_host_match(struct irq_host *h, struct device_node *node)
513 {
514         struct ipic *ipic = h->host_data;
515
516         /* Exact match, unless ipic node is NULL */
517         return ipic->of_node == NULL || ipic->of_node == node;
518 }
519
520 static int ipic_host_map(struct irq_host *h, unsigned int virq,
521                          irq_hw_number_t hw)
522 {
523         struct ipic *ipic = h->host_data;
524         struct irq_chip *chip;
525
526         /* Default chip */
527         chip = &ipic->hc_irq;
528
529         set_irq_chip_data(virq, ipic);
530         set_irq_chip_and_handler(virq, chip, handle_level_irq);
531
532         /* Set default irq type */
533         set_irq_type(virq, IRQ_TYPE_NONE);
534
535         return 0;
536 }
537
538 static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
539                            u32 *intspec, unsigned int intsize,
540                            irq_hw_number_t *out_hwirq, unsigned int *out_flags)
541
542 {
543         /* interrupt sense values coming from the device tree equal either
544          * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
545          */
546         *out_hwirq = intspec[0];
547         if (intsize > 1)
548                 *out_flags = intspec[1];
549         else
550                 *out_flags = IRQ_TYPE_NONE;
551         return 0;
552 }
553
554 static struct irq_host_ops ipic_host_ops = {
555         .match  = ipic_host_match,
556         .map    = ipic_host_map,
557         .xlate  = ipic_host_xlate,
558 };
559
560 void __init ipic_init(struct device_node *node,
561                 unsigned int flags)
562 {
563         struct ipic     *ipic;
564         struct resource res;
565         u32 temp = 0, ret;
566
567         ipic = alloc_bootmem(sizeof(struct ipic));
568         if (ipic == NULL)
569                 return;
570
571         memset(ipic, 0, sizeof(struct ipic));
572         ipic->of_node = node ? of_node_get(node) : NULL;
573
574         ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
575                                        NR_IPIC_INTS,
576                                        &ipic_host_ops, 0);
577         if (ipic->irqhost == NULL) {
578                 of_node_put(node);
579                 return;
580         }
581
582         ret = of_address_to_resource(node, 0, &res);
583         if (ret)
584                 return;
585
586         ipic->regs = ioremap(res.start, res.end - res.start + 1);
587
588         ipic->irqhost->host_data = ipic;
589         ipic->hc_irq = ipic_irq_chip;
590
591         /* init hw */
592         ipic_write(ipic->regs, IPIC_SICNR, 0x0);
593
594         /* default priority scheme is grouped. If spread mode is required
595          * configure SICFR accordingly */
596         if (flags & IPIC_SPREADMODE_GRP_A)
597                 temp |= SICFR_IPSA;
598         if (flags & IPIC_SPREADMODE_GRP_D)
599                 temp |= SICFR_IPSD;
600         if (flags & IPIC_SPREADMODE_MIX_A)
601                 temp |= SICFR_MPSA;
602         if (flags & IPIC_SPREADMODE_MIX_B)
603                 temp |= SICFR_MPSB;
604
605         ipic_write(ipic->regs, IPIC_SICNR, temp);
606
607         /* handle MCP route */
608         temp = 0;
609         if (flags & IPIC_DISABLE_MCP_OUT)
610                 temp = SERCR_MCPR;
611         ipic_write(ipic->regs, IPIC_SERCR, temp);
612
613         /* handle routing of IRQ0 to MCP */
614         temp = ipic_read(ipic->regs, IPIC_SEMSR);
615
616         if (flags & IPIC_IRQ0_MCP)
617                 temp |= SEMSR_SIRQ0;
618         else
619                 temp &= ~SEMSR_SIRQ0;
620
621         ipic_write(ipic->regs, IPIC_SEMSR, temp);
622
623         primary_ipic = ipic;
624         irq_set_default_host(primary_ipic->irqhost);
625
626         printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
627                         primary_ipic->regs);
628 }
629
630 int ipic_set_priority(unsigned int virq, unsigned int priority)
631 {
632         struct ipic *ipic = ipic_from_irq(virq);
633         unsigned int src = ipic_irq_to_hw(virq);
634         u32 temp;
635
636         if (priority > 7)
637                 return -EINVAL;
638         if (src > 127)
639                 return -EINVAL;
640         if (ipic_info[src].prio == 0)
641                 return -EINVAL;
642
643         temp = ipic_read(ipic->regs, ipic_info[src].prio);
644
645         if (priority < 4) {
646                 temp &= ~(0x7 << (20 + (3 - priority) * 3));
647                 temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
648         } else {
649                 temp &= ~(0x7 << (4 + (7 - priority) * 3));
650                 temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
651         }
652
653         ipic_write(ipic->regs, ipic_info[src].prio, temp);
654
655         return 0;
656 }
657
658 void ipic_set_highest_priority(unsigned int virq)
659 {
660         struct ipic *ipic = ipic_from_irq(virq);
661         unsigned int src = ipic_irq_to_hw(virq);
662         u32 temp;
663
664         temp = ipic_read(ipic->regs, IPIC_SICFR);
665
666         /* clear and set HPI */
667         temp &= 0x7f000000;
668         temp |= (src & 0x7f) << 24;
669
670         ipic_write(ipic->regs, IPIC_SICFR, temp);
671 }
672
673 void ipic_set_default_priority(void)
674 {
675         ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
676         ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
677         ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
678         ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
679 }
680
681 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
682 {
683         struct ipic *ipic = primary_ipic;
684         u32 temp;
685
686         temp = ipic_read(ipic->regs, IPIC_SERMR);
687         temp |= (1 << (31 - mcp_irq));
688         ipic_write(ipic->regs, IPIC_SERMR, temp);
689 }
690
691 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
692 {
693         struct ipic *ipic = primary_ipic;
694         u32 temp;
695
696         temp = ipic_read(ipic->regs, IPIC_SERMR);
697         temp &= (1 << (31 - mcp_irq));
698         ipic_write(ipic->regs, IPIC_SERMR, temp);
699 }
700
701 u32 ipic_get_mcp_status(void)
702 {
703         return ipic_read(primary_ipic->regs, IPIC_SERMR);
704 }
705
706 void ipic_clear_mcp_status(u32 mask)
707 {
708         ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
709 }
710
711 /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
712 unsigned int ipic_get_irq(struct pt_regs *regs)
713 {
714         int irq;
715
716         BUG_ON(primary_ipic == NULL);
717
718 #define IPIC_SIVCR_VECTOR_MASK  0x7f
719         irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
720
721         if (irq == 0)    /* 0 --> no irq is pending */
722                 return NO_IRQ;
723
724         return irq_linear_revmap(primary_ipic->irqhost, irq);
725 }
726
727 static struct sysdev_class ipic_sysclass = {
728         set_kset_name("ipic"),
729 };
730
731 static struct sys_device device_ipic = {
732         .id             = 0,
733         .cls            = &ipic_sysclass,
734 };
735
736 static int __init init_ipic_sysfs(void)
737 {
738         int rc;
739
740         if (!primary_ipic->regs)
741                 return -ENODEV;
742         printk(KERN_DEBUG "Registering ipic with sysfs...\n");
743
744         rc = sysdev_class_register(&ipic_sysclass);
745         if (rc) {
746                 printk(KERN_ERR "Failed registering ipic sys class\n");
747                 return -ENODEV;
748         }
749         rc = sysdev_register(&device_ipic);
750         if (rc) {
751                 printk(KERN_ERR "Failed registering ipic sys device\n");
752                 return -ENODEV;
753         }
754         return 0;
755 }
756
757 subsys_initcall(init_ipic_sysfs);