1 #include <linux/config.h>
2 #include <linux/stddef.h>
3 #include <linux/init.h>
4 #include <linux/sched.h>
5 #include <linux/signal.h>
7 #include <asm/8xx_immap.h>
8 #include <asm/mpc8xx.h>
9 #include "ppc8xx_pic.h"
11 extern int cpm_get_irq(struct pt_regs *regs);
13 /* The 8xx internal interrupt controller. It is usually
14 * the only interrupt controller. Some boards, like the MBX and
15 * Sandpoint have the 8259 as a secondary controller. Depending
16 * upon the processor type, the internal controller can have as
17 * few as 16 interrups or as many as 64. We could use the
18 * "clear_bit()" and "set_bit()" functions like other platforms,
19 * but they are overkill for us.
22 static void m8xx_mask_irq(unsigned int irq_nr)
29 ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
30 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
31 ppc_cached_irq_mask[word];
34 static void m8xx_unmask_irq(unsigned int irq_nr)
41 ppc_cached_irq_mask[word] |= (1 << (31-bit));
42 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
43 ppc_cached_irq_mask[word];
46 static void m8xx_end_irq(unsigned int irq_nr)
48 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
54 ppc_cached_irq_mask[word] |= (1 << (31-bit));
55 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
56 ppc_cached_irq_mask[word];
61 static void m8xx_mask_and_ack(unsigned int irq_nr)
68 ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
69 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
70 ppc_cached_irq_mask[word];
71 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
74 struct hw_interrupt_type ppc8xx_pic = {
86 * We either return a valid interrupt or -1 if there is nothing pending
89 m8xx_get_irq(struct pt_regs *regs)
93 /* For MPC8xx, read the SIVEC register and shift the bits down
94 * to get the irq number.
96 irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
99 * When we read the sivec without an interrupt to process, we will
100 * get back SIU_LEVEL7. In this case, return -1
102 if (irq == CPM_INTERRUPT)
103 irq = CPM_IRQ_OFFSET + cpm_get_irq(regs);
104 #if defined(CONFIG_PCI)
105 else if (irq == ISA_BRIDGE_INT) {
108 if ((isa_irq = i8259_poll(regs)) >= 0)
109 irq = I8259_IRQ_OFFSET + isa_irq;
111 #endif /* CONFIG_PCI */
112 else if (irq == SIU_LEVEL7)
118 #if defined(CONFIG_PCI)
119 /* Handler for the MPC8xx SIU cascade interrupt for the 8259 interrupt
122 void mbx_i8259_action(int irq, void *dev_id, struct pt_regs *regs)
124 /* This interrupt handler never actually gets called. It is
125 * installed only to unmask the 8259 cascade interrupt in the SIU
126 * and to make the 8259 cascade interrupt visible in /proc/interrupts.
129 #endif /* CONFIG_PCI */