[PATCH] powerpc: moved ipic code to arch/powerpc
[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 <asm/irq.h>
23 #include <asm/io.h>
24 #include <asm/ipic.h>
25 #include <asm/mpc83xx.h>
26
27 #include "ipic.h"
28
29 static struct ipic p_ipic;
30 static struct ipic * primary_ipic;
31
32 static struct ipic_info ipic_info[] = {
33         [9] = {
34                 .pend   = IPIC_SIPNR_H,
35                 .mask   = IPIC_SIMSR_H,
36                 .prio   = IPIC_SIPRR_D,
37                 .force  = IPIC_SIFCR_H,
38                 .bit    = 24,
39                 .prio_mask = 0,
40         },
41         [10] = {
42                 .pend   = IPIC_SIPNR_H,
43                 .mask   = IPIC_SIMSR_H,
44                 .prio   = IPIC_SIPRR_D,
45                 .force  = IPIC_SIFCR_H,
46                 .bit    = 25,
47                 .prio_mask = 1,
48         },
49         [11] = {
50                 .pend   = IPIC_SIPNR_H,
51                 .mask   = IPIC_SIMSR_H,
52                 .prio   = IPIC_SIPRR_D,
53                 .force  = IPIC_SIFCR_H,
54                 .bit    = 26,
55                 .prio_mask = 2,
56         },
57         [14] = {
58                 .pend   = IPIC_SIPNR_H,
59                 .mask   = IPIC_SIMSR_H,
60                 .prio   = IPIC_SIPRR_D,
61                 .force  = IPIC_SIFCR_H,
62                 .bit    = 29,
63                 .prio_mask = 5,
64         },
65         [15] = {
66                 .pend   = IPIC_SIPNR_H,
67                 .mask   = IPIC_SIMSR_H,
68                 .prio   = IPIC_SIPRR_D,
69                 .force  = IPIC_SIFCR_H,
70                 .bit    = 30,
71                 .prio_mask = 6,
72         },
73         [16] = {
74                 .pend   = IPIC_SIPNR_H,
75                 .mask   = IPIC_SIMSR_H,
76                 .prio   = IPIC_SIPRR_D,
77                 .force  = IPIC_SIFCR_H,
78                 .bit    = 31,
79                 .prio_mask = 7,
80         },
81         [17] = {
82                 .pend   = IPIC_SEPNR,
83                 .mask   = IPIC_SEMSR,
84                 .prio   = IPIC_SMPRR_A,
85                 .force  = IPIC_SEFCR,
86                 .bit    = 1,
87                 .prio_mask = 5,
88         },
89         [18] = {
90                 .pend   = IPIC_SEPNR,
91                 .mask   = IPIC_SEMSR,
92                 .prio   = IPIC_SMPRR_A,
93                 .force  = IPIC_SEFCR,
94                 .bit    = 2,
95                 .prio_mask = 6,
96         },
97         [19] = {
98                 .pend   = IPIC_SEPNR,
99                 .mask   = IPIC_SEMSR,
100                 .prio   = IPIC_SMPRR_A,
101                 .force  = IPIC_SEFCR,
102                 .bit    = 3,
103                 .prio_mask = 7,
104         },
105         [20] = {
106                 .pend   = IPIC_SEPNR,
107                 .mask   = IPIC_SEMSR,
108                 .prio   = IPIC_SMPRR_B,
109                 .force  = IPIC_SEFCR,
110                 .bit    = 4,
111                 .prio_mask = 4,
112         },
113         [21] = {
114                 .pend   = IPIC_SEPNR,
115                 .mask   = IPIC_SEMSR,
116                 .prio   = IPIC_SMPRR_B,
117                 .force  = IPIC_SEFCR,
118                 .bit    = 5,
119                 .prio_mask = 5,
120         },
121         [22] = {
122                 .pend   = IPIC_SEPNR,
123                 .mask   = IPIC_SEMSR,
124                 .prio   = IPIC_SMPRR_B,
125                 .force  = IPIC_SEFCR,
126                 .bit    = 6,
127                 .prio_mask = 6,
128         },
129         [23] = {
130                 .pend   = IPIC_SEPNR,
131                 .mask   = IPIC_SEMSR,
132                 .prio   = IPIC_SMPRR_B,
133                 .force  = IPIC_SEFCR,
134                 .bit    = 7,
135                 .prio_mask = 7,
136         },
137         [32] = {
138                 .pend   = IPIC_SIPNR_H,
139                 .mask   = IPIC_SIMSR_H,
140                 .prio   = IPIC_SIPRR_A,
141                 .force  = IPIC_SIFCR_H,
142                 .bit    = 0,
143                 .prio_mask = 0,
144         },
145         [33] = {
146                 .pend   = IPIC_SIPNR_H,
147                 .mask   = IPIC_SIMSR_H,
148                 .prio   = IPIC_SIPRR_A,
149                 .force  = IPIC_SIFCR_H,
150                 .bit    = 1,
151                 .prio_mask = 1,
152         },
153         [34] = {
154                 .pend   = IPIC_SIPNR_H,
155                 .mask   = IPIC_SIMSR_H,
156                 .prio   = IPIC_SIPRR_A,
157                 .force  = IPIC_SIFCR_H,
158                 .bit    = 2,
159                 .prio_mask = 2,
160         },
161         [35] = {
162                 .pend   = IPIC_SIPNR_H,
163                 .mask   = IPIC_SIMSR_H,
164                 .prio   = IPIC_SIPRR_A,
165                 .force  = IPIC_SIFCR_H,
166                 .bit    = 3,
167                 .prio_mask = 3,
168         },
169         [36] = {
170                 .pend   = IPIC_SIPNR_H,
171                 .mask   = IPIC_SIMSR_H,
172                 .prio   = IPIC_SIPRR_A,
173                 .force  = IPIC_SIFCR_H,
174                 .bit    = 4,
175                 .prio_mask = 4,
176         },
177         [37] = {
178                 .pend   = IPIC_SIPNR_H,
179                 .mask   = IPIC_SIMSR_H,
180                 .prio   = IPIC_SIPRR_A,
181                 .force  = IPIC_SIFCR_H,
182                 .bit    = 5,
183                 .prio_mask = 5,
184         },
185         [38] = {
186                 .pend   = IPIC_SIPNR_H,
187                 .mask   = IPIC_SIMSR_H,
188                 .prio   = IPIC_SIPRR_A,
189                 .force  = IPIC_SIFCR_H,
190                 .bit    = 6,
191                 .prio_mask = 6,
192         },
193         [39] = {
194                 .pend   = IPIC_SIPNR_H,
195                 .mask   = IPIC_SIMSR_H,
196                 .prio   = IPIC_SIPRR_A,
197                 .force  = IPIC_SIFCR_H,
198                 .bit    = 7,
199                 .prio_mask = 7,
200         },
201         [48] = {
202                 .pend   = IPIC_SEPNR,
203                 .mask   = IPIC_SEMSR,
204                 .prio   = IPIC_SMPRR_A,
205                 .force  = IPIC_SEFCR,
206                 .bit    = 0,
207                 .prio_mask = 4,
208         },
209         [64] = {
210                 .pend   = IPIC_SIPNR_H,
211                 .mask   = IPIC_SIMSR_L,
212                 .prio   = IPIC_SMPRR_A,
213                 .force  = IPIC_SIFCR_L,
214                 .bit    = 0,
215                 .prio_mask = 0,
216         },
217         [65] = {
218                 .pend   = IPIC_SIPNR_H,
219                 .mask   = IPIC_SIMSR_L,
220                 .prio   = IPIC_SMPRR_A,
221                 .force  = IPIC_SIFCR_L,
222                 .bit    = 1,
223                 .prio_mask = 1,
224         },
225         [66] = {
226                 .pend   = IPIC_SIPNR_H,
227                 .mask   = IPIC_SIMSR_L,
228                 .prio   = IPIC_SMPRR_A,
229                 .force  = IPIC_SIFCR_L,
230                 .bit    = 2,
231                 .prio_mask = 2,
232         },
233         [67] = {
234                 .pend   = IPIC_SIPNR_H,
235                 .mask   = IPIC_SIMSR_L,
236                 .prio   = IPIC_SMPRR_A,
237                 .force  = IPIC_SIFCR_L,
238                 .bit    = 3,
239                 .prio_mask = 3,
240         },
241         [68] = {
242                 .pend   = IPIC_SIPNR_H,
243                 .mask   = IPIC_SIMSR_L,
244                 .prio   = IPIC_SMPRR_B,
245                 .force  = IPIC_SIFCR_L,
246                 .bit    = 4,
247                 .prio_mask = 0,
248         },
249         [69] = {
250                 .pend   = IPIC_SIPNR_H,
251                 .mask   = IPIC_SIMSR_L,
252                 .prio   = IPIC_SMPRR_B,
253                 .force  = IPIC_SIFCR_L,
254                 .bit    = 5,
255                 .prio_mask = 1,
256         },
257         [70] = {
258                 .pend   = IPIC_SIPNR_H,
259                 .mask   = IPIC_SIMSR_L,
260                 .prio   = IPIC_SMPRR_B,
261                 .force  = IPIC_SIFCR_L,
262                 .bit    = 6,
263                 .prio_mask = 2,
264         },
265         [71] = {
266                 .pend   = IPIC_SIPNR_H,
267                 .mask   = IPIC_SIMSR_L,
268                 .prio   = IPIC_SMPRR_B,
269                 .force  = IPIC_SIFCR_L,
270                 .bit    = 7,
271                 .prio_mask = 3,
272         },
273         [72] = {
274                 .pend   = IPIC_SIPNR_H,
275                 .mask   = IPIC_SIMSR_L,
276                 .prio   = 0,
277                 .force  = IPIC_SIFCR_L,
278                 .bit    = 8,
279         },
280         [73] = {
281                 .pend   = IPIC_SIPNR_H,
282                 .mask   = IPIC_SIMSR_L,
283                 .prio   = 0,
284                 .force  = IPIC_SIFCR_L,
285                 .bit    = 9,
286         },
287         [74] = {
288                 .pend   = IPIC_SIPNR_H,
289                 .mask   = IPIC_SIMSR_L,
290                 .prio   = 0,
291                 .force  = IPIC_SIFCR_L,
292                 .bit    = 10,
293         },
294         [75] = {
295                 .pend   = IPIC_SIPNR_H,
296                 .mask   = IPIC_SIMSR_L,
297                 .prio   = 0,
298                 .force  = IPIC_SIFCR_L,
299                 .bit    = 11,
300         },
301         [76] = {
302                 .pend   = IPIC_SIPNR_H,
303                 .mask   = IPIC_SIMSR_L,
304                 .prio   = 0,
305                 .force  = IPIC_SIFCR_L,
306                 .bit    = 12,
307         },
308         [77] = {
309                 .pend   = IPIC_SIPNR_H,
310                 .mask   = IPIC_SIMSR_L,
311                 .prio   = 0,
312                 .force  = IPIC_SIFCR_L,
313                 .bit    = 13,
314         },
315         [78] = {
316                 .pend   = IPIC_SIPNR_H,
317                 .mask   = IPIC_SIMSR_L,
318                 .prio   = 0,
319                 .force  = IPIC_SIFCR_L,
320                 .bit    = 14,
321         },
322         [79] = {
323                 .pend   = IPIC_SIPNR_H,
324                 .mask   = IPIC_SIMSR_L,
325                 .prio   = 0,
326                 .force  = IPIC_SIFCR_L,
327                 .bit    = 15,
328         },
329         [80] = {
330                 .pend   = IPIC_SIPNR_H,
331                 .mask   = IPIC_SIMSR_L,
332                 .prio   = 0,
333                 .force  = IPIC_SIFCR_L,
334                 .bit    = 16,
335         },
336         [84] = {
337                 .pend   = IPIC_SIPNR_H,
338                 .mask   = IPIC_SIMSR_L,
339                 .prio   = 0,
340                 .force  = IPIC_SIFCR_L,
341                 .bit    = 20,
342         },
343         [85] = {
344                 .pend   = IPIC_SIPNR_H,
345                 .mask   = IPIC_SIMSR_L,
346                 .prio   = 0,
347                 .force  = IPIC_SIFCR_L,
348                 .bit    = 21,
349         },
350         [90] = {
351                 .pend   = IPIC_SIPNR_H,
352                 .mask   = IPIC_SIMSR_L,
353                 .prio   = 0,
354                 .force  = IPIC_SIFCR_L,
355                 .bit    = 26,
356         },
357         [91] = {
358                 .pend   = IPIC_SIPNR_H,
359                 .mask   = IPIC_SIMSR_L,
360                 .prio   = 0,
361                 .force  = IPIC_SIFCR_L,
362                 .bit    = 27,
363         },
364 };
365
366 static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
367 {
368         return in_be32(base + (reg >> 2));
369 }
370
371 static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
372 {
373         out_be32(base + (reg >> 2), value);
374 }
375
376 static inline struct ipic * ipic_from_irq(unsigned int irq)
377 {
378         return primary_ipic;
379 }
380
381 static void ipic_enable_irq(unsigned int irq)
382 {
383         struct ipic *ipic = ipic_from_irq(irq);
384         unsigned int src = irq - ipic->irq_offset;
385         u32 temp;
386
387         temp = ipic_read(ipic->regs, ipic_info[src].mask);
388         temp |= (1 << (31 - ipic_info[src].bit));
389         ipic_write(ipic->regs, ipic_info[src].mask, temp);
390 }
391
392 static void ipic_disable_irq(unsigned int irq)
393 {
394         struct ipic *ipic = ipic_from_irq(irq);
395         unsigned int src = irq - ipic->irq_offset;
396         u32 temp;
397
398         temp = ipic_read(ipic->regs, ipic_info[src].mask);
399         temp &= ~(1 << (31 - ipic_info[src].bit));
400         ipic_write(ipic->regs, ipic_info[src].mask, temp);
401 }
402
403 static void ipic_disable_irq_and_ack(unsigned int irq)
404 {
405         struct ipic *ipic = ipic_from_irq(irq);
406         unsigned int src = irq - ipic->irq_offset;
407         u32 temp;
408
409         ipic_disable_irq(irq);
410
411         temp = ipic_read(ipic->regs, ipic_info[src].pend);
412         temp |= (1 << (31 - ipic_info[src].bit));
413         ipic_write(ipic->regs, ipic_info[src].pend, temp);
414 }
415
416 static void ipic_end_irq(unsigned int irq)
417 {
418         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
419                 ipic_enable_irq(irq);
420 }
421
422 struct hw_interrupt_type ipic = {
423         .typename = " IPIC  ",
424         .enable = ipic_enable_irq,
425         .disable = ipic_disable_irq,
426         .ack = ipic_disable_irq_and_ack,
427         .end = ipic_end_irq,
428 };
429
430 void __init ipic_init(phys_addr_t phys_addr,
431                 unsigned int flags,
432                 unsigned int irq_offset,
433                 unsigned char *senses,
434                 unsigned int senses_count)
435 {
436         u32 i, temp = 0;
437
438         primary_ipic = &p_ipic;
439         primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
440
441         primary_ipic->irq_offset = irq_offset;
442
443         ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
444
445         /* default priority scheme is grouped. If spread mode is required
446          * configure SICFR accordingly */
447         if (flags & IPIC_SPREADMODE_GRP_A)
448                 temp |= SICFR_IPSA;
449         if (flags & IPIC_SPREADMODE_GRP_D)
450                 temp |= SICFR_IPSD;
451         if (flags & IPIC_SPREADMODE_MIX_A)
452                 temp |= SICFR_MPSA;
453         if (flags & IPIC_SPREADMODE_MIX_B)
454                 temp |= SICFR_MPSB;
455
456         ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
457
458         /* handle MCP route */
459         temp = 0;
460         if (flags & IPIC_DISABLE_MCP_OUT)
461                 temp = SERCR_MCPR;
462         ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
463
464         /* handle routing of IRQ0 to MCP */
465         temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
466
467         if (flags & IPIC_IRQ0_MCP)
468                 temp |= SEMSR_SIRQ0;
469         else
470                 temp &= ~SEMSR_SIRQ0;
471
472         ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
473
474         for (i = 0 ; i < NR_IPIC_INTS ; i++) {
475                 irq_desc[i+irq_offset].handler = &ipic;
476                 irq_desc[i+irq_offset].status = IRQ_LEVEL;
477         }
478
479         temp = 0;
480         for (i = 0 ; i < senses_count ; i++) {
481                 if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
482                         temp |= 1 << (15 - i);
483                         if (i != 0)
484                                 irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
485                         else
486                                 irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
487                 }
488         }
489         ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
490
491         printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
492                         senses_count, primary_ipic->regs);
493 }
494
495 int ipic_set_priority(unsigned int irq, unsigned int priority)
496 {
497         struct ipic *ipic = ipic_from_irq(irq);
498         unsigned int src = irq - ipic->irq_offset;
499         u32 temp;
500
501         if (priority > 7)
502                 return -EINVAL;
503         if (src > 127)
504                 return -EINVAL;
505         if (ipic_info[src].prio == 0)
506                 return -EINVAL;
507
508         temp = ipic_read(ipic->regs, ipic_info[src].prio);
509
510         if (priority < 4) {
511                 temp &= ~(0x7 << (20 + (3 - priority) * 3));
512                 temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
513         } else {
514                 temp &= ~(0x7 << (4 + (7 - priority) * 3));
515                 temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
516         }
517
518         ipic_write(ipic->regs, ipic_info[src].prio, temp);
519
520         return 0;
521 }
522
523 void ipic_set_highest_priority(unsigned int irq)
524 {
525         struct ipic *ipic = ipic_from_irq(irq);
526         unsigned int src = irq - ipic->irq_offset;
527         u32 temp;
528
529         temp = ipic_read(ipic->regs, IPIC_SICFR);
530
531         /* clear and set HPI */
532         temp &= 0x7f000000;
533         temp |= (src & 0x7f) << 24;
534
535         ipic_write(ipic->regs, IPIC_SICFR, temp);
536 }
537
538 void ipic_set_default_priority(void)
539 {
540         ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
541         ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
542         ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
543         ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
544         ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
545         ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
546         ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
547         ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
548
549         ipic_set_priority(MPC83xx_IRQ_UART1, 0);
550         ipic_set_priority(MPC83xx_IRQ_UART2, 1);
551         ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
552         ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
553         ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
554         ipic_set_priority(MPC83xx_IRQ_SPI, 7);
555         ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
556         ipic_set_priority(MPC83xx_IRQ_PIT, 1);
557         ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
558         ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
559         ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
560         ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
561         ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
562         ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
563         ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
564         ipic_set_priority(MPC83xx_IRQ_MU, 1);
565         ipic_set_priority(MPC83xx_IRQ_SBA, 2);
566         ipic_set_priority(MPC83xx_IRQ_DMA, 3);
567         ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
568         ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
569         ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
570         ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
571 }
572
573 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
574 {
575         struct ipic *ipic = primary_ipic;
576         u32 temp;
577
578         temp = ipic_read(ipic->regs, IPIC_SERMR);
579         temp |= (1 << (31 - mcp_irq));
580         ipic_write(ipic->regs, IPIC_SERMR, temp);
581 }
582
583 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
584 {
585         struct ipic *ipic = primary_ipic;
586         u32 temp;
587
588         temp = ipic_read(ipic->regs, IPIC_SERMR);
589         temp &= (1 << (31 - mcp_irq));
590         ipic_write(ipic->regs, IPIC_SERMR, temp);
591 }
592
593 u32 ipic_get_mcp_status(void)
594 {
595         return ipic_read(primary_ipic->regs, IPIC_SERMR);
596 }
597
598 void ipic_clear_mcp_status(u32 mask)
599 {
600         ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
601 }
602
603 /* Return an interrupt vector or -1 if no interrupt is pending. */
604 int ipic_get_irq(struct pt_regs *regs)
605 {
606         int irq;
607
608         irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
609
610         if (irq == 0)    /* 0 --> no irq is pending */
611                 irq = -1;
612
613         return irq;
614 }
615
616 static struct sysdev_class ipic_sysclass = {
617         set_kset_name("ipic"),
618 };
619
620 static struct sys_device device_ipic = {
621         .id             = 0,
622         .cls            = &ipic_sysclass,
623 };
624
625 static int __init init_ipic_sysfs(void)
626 {
627         int rc;
628
629         if (!primary_ipic->regs)
630                 return -ENODEV;
631         printk(KERN_DEBUG "Registering ipic with sysfs...\n");
632
633         rc = sysdev_class_register(&ipic_sysclass);
634         if (rc) {
635                 printk(KERN_ERR "Failed registering ipic sys class\n");
636                 return -ENODEV;
637         }
638         rc = sysdev_register(&device_ipic);
639         if (rc) {
640                 printk(KERN_ERR "Failed registering ipic sys device\n");
641                 return -ENODEV;
642         }
643         return 0;
644 }
645
646 subsys_initcall(init_ipic_sysfs);