2 * include/asm-ppc/ipic.c
4 * IPIC routines implementations.
6 * Copyright 2005 Freescale Semiconductor, Inc.
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.
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>
25 #include <asm/mpc83xx.h>
29 static struct ipic p_ipic
;
30 static struct ipic
* primary_ipic
;
32 static struct ipic_info ipic_info
[] = {
37 .force
= IPIC_SIFCR_H
,
45 .force
= IPIC_SIFCR_H
,
53 .force
= IPIC_SIFCR_H
,
61 .force
= IPIC_SIFCR_H
,
69 .force
= IPIC_SIFCR_H
,
77 .force
= IPIC_SIFCR_H
,
100 .prio
= IPIC_SMPRR_A
,
108 .prio
= IPIC_SMPRR_B
,
116 .prio
= IPIC_SMPRR_B
,
124 .prio
= IPIC_SMPRR_B
,
132 .prio
= IPIC_SMPRR_B
,
138 .pend
= IPIC_SIPNR_H
,
139 .mask
= IPIC_SIMSR_H
,
140 .prio
= IPIC_SIPRR_A
,
141 .force
= IPIC_SIFCR_H
,
146 .pend
= IPIC_SIPNR_H
,
147 .mask
= IPIC_SIMSR_H
,
148 .prio
= IPIC_SIPRR_A
,
149 .force
= IPIC_SIFCR_H
,
154 .pend
= IPIC_SIPNR_H
,
155 .mask
= IPIC_SIMSR_H
,
156 .prio
= IPIC_SIPRR_A
,
157 .force
= IPIC_SIFCR_H
,
162 .pend
= IPIC_SIPNR_H
,
163 .mask
= IPIC_SIMSR_H
,
164 .prio
= IPIC_SIPRR_A
,
165 .force
= IPIC_SIFCR_H
,
170 .pend
= IPIC_SIPNR_H
,
171 .mask
= IPIC_SIMSR_H
,
172 .prio
= IPIC_SIPRR_A
,
173 .force
= IPIC_SIFCR_H
,
178 .pend
= IPIC_SIPNR_H
,
179 .mask
= IPIC_SIMSR_H
,
180 .prio
= IPIC_SIPRR_A
,
181 .force
= IPIC_SIFCR_H
,
186 .pend
= IPIC_SIPNR_H
,
187 .mask
= IPIC_SIMSR_H
,
188 .prio
= IPIC_SIPRR_A
,
189 .force
= IPIC_SIFCR_H
,
194 .pend
= IPIC_SIPNR_H
,
195 .mask
= IPIC_SIMSR_H
,
196 .prio
= IPIC_SIPRR_A
,
197 .force
= IPIC_SIFCR_H
,
204 .prio
= IPIC_SMPRR_A
,
210 .pend
= IPIC_SIPNR_H
,
211 .mask
= IPIC_SIMSR_L
,
212 .prio
= IPIC_SMPRR_A
,
213 .force
= IPIC_SIFCR_L
,
218 .pend
= IPIC_SIPNR_H
,
219 .mask
= IPIC_SIMSR_L
,
220 .prio
= IPIC_SMPRR_A
,
221 .force
= IPIC_SIFCR_L
,
226 .pend
= IPIC_SIPNR_H
,
227 .mask
= IPIC_SIMSR_L
,
228 .prio
= IPIC_SMPRR_A
,
229 .force
= IPIC_SIFCR_L
,
234 .pend
= IPIC_SIPNR_H
,
235 .mask
= IPIC_SIMSR_L
,
236 .prio
= IPIC_SMPRR_A
,
237 .force
= IPIC_SIFCR_L
,
242 .pend
= IPIC_SIPNR_H
,
243 .mask
= IPIC_SIMSR_L
,
244 .prio
= IPIC_SMPRR_B
,
245 .force
= IPIC_SIFCR_L
,
250 .pend
= IPIC_SIPNR_H
,
251 .mask
= IPIC_SIMSR_L
,
252 .prio
= IPIC_SMPRR_B
,
253 .force
= IPIC_SIFCR_L
,
258 .pend
= IPIC_SIPNR_H
,
259 .mask
= IPIC_SIMSR_L
,
260 .prio
= IPIC_SMPRR_B
,
261 .force
= IPIC_SIFCR_L
,
266 .pend
= IPIC_SIPNR_H
,
267 .mask
= IPIC_SIMSR_L
,
268 .prio
= IPIC_SMPRR_B
,
269 .force
= IPIC_SIFCR_L
,
274 .pend
= IPIC_SIPNR_H
,
275 .mask
= IPIC_SIMSR_L
,
277 .force
= IPIC_SIFCR_L
,
281 .pend
= IPIC_SIPNR_H
,
282 .mask
= IPIC_SIMSR_L
,
284 .force
= IPIC_SIFCR_L
,
288 .pend
= IPIC_SIPNR_H
,
289 .mask
= IPIC_SIMSR_L
,
291 .force
= IPIC_SIFCR_L
,
295 .pend
= IPIC_SIPNR_H
,
296 .mask
= IPIC_SIMSR_L
,
298 .force
= IPIC_SIFCR_L
,
302 .pend
= IPIC_SIPNR_H
,
303 .mask
= IPIC_SIMSR_L
,
305 .force
= IPIC_SIFCR_L
,
309 .pend
= IPIC_SIPNR_H
,
310 .mask
= IPIC_SIMSR_L
,
312 .force
= IPIC_SIFCR_L
,
316 .pend
= IPIC_SIPNR_H
,
317 .mask
= IPIC_SIMSR_L
,
319 .force
= IPIC_SIFCR_L
,
323 .pend
= IPIC_SIPNR_H
,
324 .mask
= IPIC_SIMSR_L
,
326 .force
= IPIC_SIFCR_L
,
330 .pend
= IPIC_SIPNR_H
,
331 .mask
= IPIC_SIMSR_L
,
333 .force
= IPIC_SIFCR_L
,
337 .pend
= IPIC_SIPNR_H
,
338 .mask
= IPIC_SIMSR_L
,
340 .force
= IPIC_SIFCR_L
,
344 .pend
= IPIC_SIPNR_H
,
345 .mask
= IPIC_SIMSR_L
,
347 .force
= IPIC_SIFCR_L
,
351 .pend
= IPIC_SIPNR_H
,
352 .mask
= IPIC_SIMSR_L
,
354 .force
= IPIC_SIFCR_L
,
358 .pend
= IPIC_SIPNR_H
,
359 .mask
= IPIC_SIMSR_L
,
361 .force
= IPIC_SIFCR_L
,
366 static inline u32
ipic_read(volatile u32 __iomem
*base
, unsigned int reg
)
368 return in_be32(base
+ (reg
>> 2));
371 static inline void ipic_write(volatile u32 __iomem
*base
, unsigned int reg
, u32 value
)
373 out_be32(base
+ (reg
>> 2), value
);
376 static inline struct ipic
* ipic_from_irq(unsigned int irq
)
381 static void ipic_enable_irq(unsigned int irq
)
383 struct ipic
*ipic
= ipic_from_irq(irq
);
384 unsigned int src
= irq
- ipic
->irq_offset
;
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
);
392 static void ipic_disable_irq(unsigned int irq
)
394 struct ipic
*ipic
= ipic_from_irq(irq
);
395 unsigned int src
= irq
- ipic
->irq_offset
;
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
);
403 static void ipic_disable_irq_and_ack(unsigned int irq
)
405 struct ipic
*ipic
= ipic_from_irq(irq
);
406 unsigned int src
= irq
- ipic
->irq_offset
;
409 ipic_disable_irq(irq
);
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
);
416 static void ipic_end_irq(unsigned int irq
)
418 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
)))
419 ipic_enable_irq(irq
);
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
,
430 void __init
ipic_init(phys_addr_t phys_addr
,
432 unsigned int irq_offset
,
433 unsigned char *senses
,
434 unsigned int senses_count
)
438 primary_ipic
= &p_ipic
;
439 primary_ipic
->regs
= ioremap(phys_addr
, MPC83xx_IPIC_SIZE
);
441 primary_ipic
->irq_offset
= irq_offset
;
443 ipic_write(primary_ipic
->regs
, IPIC_SICNR
, 0x0);
445 /* default priority scheme is grouped. If spread mode is required
446 * configure SICFR accordingly */
447 if (flags
& IPIC_SPREADMODE_GRP_A
)
449 if (flags
& IPIC_SPREADMODE_GRP_D
)
451 if (flags
& IPIC_SPREADMODE_MIX_A
)
453 if (flags
& IPIC_SPREADMODE_MIX_B
)
456 ipic_write(primary_ipic
->regs
, IPIC_SICNR
, temp
);
458 /* handle MCP route */
460 if (flags
& IPIC_DISABLE_MCP_OUT
)
462 ipic_write(primary_ipic
->regs
, IPIC_SERCR
, temp
);
464 /* handle routing of IRQ0 to MCP */
465 temp
= ipic_read(primary_ipic
->regs
, IPIC_SEMSR
);
467 if (flags
& IPIC_IRQ0_MCP
)
470 temp
&= ~SEMSR_SIRQ0
;
472 ipic_write(primary_ipic
->regs
, IPIC_SEMSR
, temp
);
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
;
480 for (i
= 0 ; i
< senses_count
; i
++) {
481 if ((senses
[i
] & IRQ_SENSE_MASK
) == IRQ_SENSE_EDGE
) {
482 temp
|= 1 << (15 - i
);
484 irq_desc
[i
+ irq_offset
+ MPC83xx_IRQ_EXT1
- 1].status
= 0;
486 irq_desc
[irq_offset
+ MPC83xx_IRQ_EXT0
].status
= 0;
489 ipic_write(primary_ipic
->regs
, IPIC_SECNR
, temp
);
491 printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS
,
492 senses_count
, primary_ipic
->regs
);
495 int ipic_set_priority(unsigned int irq
, unsigned int priority
)
497 struct ipic
*ipic
= ipic_from_irq(irq
);
498 unsigned int src
= irq
- ipic
->irq_offset
;
505 if (ipic_info
[src
].prio
== 0)
508 temp
= ipic_read(ipic
->regs
, ipic_info
[src
].prio
);
511 temp
&= ~(0x7 << (20 + (3 - priority
) * 3));
512 temp
|= ipic_info
[src
].prio_mask
<< (20 + (3 - priority
) * 3);
514 temp
&= ~(0x7 << (4 + (7 - priority
) * 3));
515 temp
|= ipic_info
[src
].prio_mask
<< (4 + (7 - priority
) * 3);
518 ipic_write(ipic
->regs
, ipic_info
[src
].prio
, temp
);
523 void ipic_set_highest_priority(unsigned int irq
)
525 struct ipic
*ipic
= ipic_from_irq(irq
);
526 unsigned int src
= irq
- ipic
->irq_offset
;
529 temp
= ipic_read(ipic
->regs
, IPIC_SICFR
);
531 /* clear and set HPI */
533 temp
|= (src
& 0x7f) << 24;
535 ipic_write(ipic
->regs
, IPIC_SICFR
, temp
);
538 void ipic_set_default_priority(void)
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);
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);
573 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq
)
575 struct ipic
*ipic
= primary_ipic
;
578 temp
= ipic_read(ipic
->regs
, IPIC_SERMR
);
579 temp
|= (1 << (31 - mcp_irq
));
580 ipic_write(ipic
->regs
, IPIC_SERMR
, temp
);
583 void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq
)
585 struct ipic
*ipic
= primary_ipic
;
588 temp
= ipic_read(ipic
->regs
, IPIC_SERMR
);
589 temp
&= (1 << (31 - mcp_irq
));
590 ipic_write(ipic
->regs
, IPIC_SERMR
, temp
);
593 u32
ipic_get_mcp_status(void)
595 return ipic_read(primary_ipic
->regs
, IPIC_SERMR
);
598 void ipic_clear_mcp_status(u32 mask
)
600 ipic_write(primary_ipic
->regs
, IPIC_SERMR
, mask
);
603 /* Return an interrupt vector or -1 if no interrupt is pending. */
604 int ipic_get_irq(struct pt_regs
*regs
)
608 irq
= ipic_read(primary_ipic
->regs
, IPIC_SIVCR
) & 0x7f;
610 if (irq
== 0) /* 0 --> no irq is pending */
616 static struct sysdev_class ipic_sysclass
= {
617 set_kset_name("ipic"),
620 static struct sys_device device_ipic
= {
622 .cls
= &ipic_sysclass
,
625 static int __init
init_ipic_sysfs(void)
629 if (!primary_ipic
->regs
)
631 printk(KERN_DEBUG
"Registering ipic with sysfs...\n");
633 rc
= sysdev_class_register(&ipic_sysclass
);
635 printk(KERN_ERR
"Failed registering ipic sys class\n");
638 rc
= sysdev_register(&device_ipic
);
640 printk(KERN_ERR
"Failed registering ipic sys device\n");
646 subsys_initcall(init_ipic_sysfs
);