ppc8xx_pic.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
- /*
- * BK Id: SCCS/s.ppc8xx_pic.c 1.13 12/01/01 17:19:48 trini
- */
- #include <linux/config.h>
- #include <linux/stddef.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/signal.h>
- #include <asm/irq.h>
- #include <asm/8xx_immap.h>
- #include <asm/mpc8xx.h>
- #include "ppc8xx_pic.h"
- /* The 8xx internal interrupt controller. It is usually
- * the only interrupt controller. Some boards, like the MBX and
- * Sandpoint have the 8259 as a secondary controller. Depending
- * upon the processor type, the internal controller can have as
- * few as 16 interrups or as many as 64. We could use the
- * "clear_bit()" and "set_bit()" functions like other platforms,
- * but they are overkill for us.
- */
- static void m8xx_mask_irq(unsigned int irq_nr)
- {
- int bit, word;
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
- ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- ppc_cached_irq_mask[word];
- }
- static void m8xx_unmask_irq(unsigned int irq_nr)
- {
- int bit, word;
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- ppc_cached_irq_mask[word];
- }
- static void m8xx_end_irq(unsigned int irq_nr)
- {
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
- int bit, word;
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- ppc_cached_irq_mask[word];
- }
- }
- static void m8xx_mask_and_ack(unsigned int irq_nr)
- {
- int bit, word;
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
- ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
- ppc_cached_irq_mask[word];
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
- }
- struct hw_interrupt_type ppc8xx_pic = {
- " 8xx SIU ",
- NULL,
- NULL,
- m8xx_unmask_irq,
- m8xx_mask_irq,
- m8xx_mask_and_ack,
- m8xx_end_irq,
- 0
- };
- #if 0
- void
- m8xx_do_IRQ(struct pt_regs *regs,
- int cpu)
- {
- int irq;
- unsigned long bits = 0;
- /* For MPC8xx, read the SIVEC register and shift the bits down
- * to get the irq number. */
- bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
- irq = bits >> 26;
- #if 0
- irq += ppc8xx_pic.irq_offset;
- #endif
- bits = 1UL << irq;
- if (irq < 0) {
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lxn",
- irq, regs->nip);
- ppc_spurious_interrupts++;
- }
- else {
- ppc_irq_dispatch_handler( regs, irq );
- }
- }
- #endif
- /*
- * We either return a valid interrupt or -1 if there is nothing pending
- */
- int
- m8xx_get_irq(struct pt_regs *regs)
- {
- int irq;
- /* For MPC8xx, read the SIVEC register and shift the bits down
- * to get the irq number.
- */
- irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
- /*
- * When we read the sivec without an interrupt to process, we will
- * get back SIU_LEVEL7. In this case, return -1
- */
- if (irq == SIU_LEVEL7)
- return -1;
- return irq;
- }
- /* The MBX is the only 8xx board that uses the 8259.
- */
- #if defined(CONFIG_MBX) && defined(CONFIG_PCI)
- void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
- {
- int bits, irq;
- /* A bug in the QSpan chip causes it to give us 0xff always
- * when doing a character read. So read 32 bits and shift.
- * This doesn't seem to return useful values anyway, but
- * read it to make sure things are acked.
- * -- Cort
- */
- irq = (inl(0x508) >> 24)&0xff;
- if ( irq != 0xff ) printk("iack %dn", irq);
-
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
- outb(0x0C, 0xA0);
- irq = inb(0xA0);
- irq = (irq&7) + 8;
- }
- bits = 1UL << irq;
- irq += i8259_pic.irq_offset;
- ppc_irq_dispatch_handler( regs, irq );
- }
- #endif
- /* Only the MBX uses the external 8259. This allows us to catch standard
- * drivers that may mess up the internal interrupt controllers, and also
- * allow them to run without modification on the MBX.
- */
- int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
- {
- #if defined(CONFIG_MBX) && defined(CONFIG_PCI)
- irq += i8259_pic.irq_offset;
- return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
- #else
- /*
- * Handle other "well-known" interrupts, but panic on unknown ones.
- */
- switch (irq) {
- #ifdef IDE0_INTERRUPT
- case IDE0_INTERRUPT: /* IDE0 */
- return (request_8xxirq(irq, handler, irqflags, devname,
- dev_id));
- #endif
- #ifdef IDE1_INTERRUPT
- case IDE1_INTERRUPT: /* IDE1 */
- return (request_8xxirq(irq, handler, irqflags, devname,
- dev_id));
- #endif
- default: /* unknown IRQ -> panic */
- panic("request_irq");
- }
- #endif
- }