1 #include <linux/config.h>
2 #include <linux/module.h>
3 #include <linux/stddef.h>
4 #include <linux/init.h>
5 #include <linux/sched.h>
6 #include <linux/signal.h>
7 #include <linux/interrupt.h>
10 #include <asm/8xx_immap.h>
11 #include <asm/mpc8xx.h>
12 #include "ppc8xx_pic.h"
14 extern int cpm_get_irq(struct pt_regs
*regs
);
16 /* The 8xx internal interrupt controller. It is usually
17 * the only interrupt controller. Some boards, like the MBX and
18 * Sandpoint have the 8259 as a secondary controller. Depending
19 * upon the processor type, the internal controller can have as
20 * few as 16 interrups or as many as 64. We could use the
21 * "clear_bit()" and "set_bit()" functions like other platforms,
22 * but they are overkill for us.
25 static void m8xx_mask_irq(unsigned int irq_nr
)
32 ppc_cached_irq_mask
[word
] &= ~(1 << (31-bit
));
33 out_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_simask
, ppc_cached_irq_mask
[word
]);
36 static void m8xx_unmask_irq(unsigned int irq_nr
)
43 ppc_cached_irq_mask
[word
] |= (1 << (31-bit
));
44 out_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_simask
, ppc_cached_irq_mask
[word
]);
47 static void m8xx_end_irq(unsigned int irq_nr
)
49 if (!(irq_desc
[irq_nr
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
))
50 && irq_desc
[irq_nr
].action
) {
56 ppc_cached_irq_mask
[word
] |= (1 << (31-bit
));
57 out_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_simask
, ppc_cached_irq_mask
[word
]);
62 static void m8xx_mask_and_ack(unsigned int irq_nr
)
69 ppc_cached_irq_mask
[word
] &= ~(1 << (31-bit
));
70 out_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_simask
, ppc_cached_irq_mask
[word
]);
71 out_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sipend
, 1 << (31-bit
));
74 struct hw_interrupt_type ppc8xx_pic
= {
75 .typename
= " 8xx SIU ",
76 .enable
= m8xx_unmask_irq
,
77 .disable
= m8xx_mask_irq
,
78 .ack
= m8xx_mask_and_ack
,
83 * We either return a valid interrupt or -1 if there is nothing pending
86 m8xx_get_irq(struct pt_regs
*regs
)
90 /* For MPC8xx, read the SIVEC register and shift the bits down
91 * to get the irq number.
93 irq
= in_be32(&((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sivec
) >> 26;
96 * When we read the sivec without an interrupt to process, we will
97 * get back SIU_LEVEL7. In this case, return -1
99 if (irq
== CPM_INTERRUPT
)
100 irq
= CPM_IRQ_OFFSET
+ cpm_get_irq(regs
);
101 #if defined(CONFIG_PCI)
102 else if (irq
== ISA_BRIDGE_INT
) {
105 if ((isa_irq
= i8259_poll(regs
)) >= 0)
106 irq
= I8259_IRQ_OFFSET
+ isa_irq
;
108 #endif /* CONFIG_PCI */
109 else if (irq
== SIU_LEVEL7
)
115 #if defined(CONFIG_MBX) && defined(CONFIG_PCI)
116 /* Only the MBX uses the external 8259. This allows us to catch standard
117 * drivers that may mess up the internal interrupt controllers, and also
118 * allow them to run without modification on the MBX.
120 void mbx_i8259_action(int irq
, void *dev_id
, struct pt_regs
*regs
)
122 /* This interrupt handler never actually gets called. It is
123 * installed only to unmask the 8259 cascade interrupt in the SIU
124 * and to make the 8259 cascade interrupt visible in /proc/interrupts.
127 #endif /* CONFIG_PCI */