ppc8xx_pic.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.ppc8xx_pic.c 1.13 12/01/01 17:19:48 trini
  3.  */
  4. #include <linux/config.h>
  5. #include <linux/stddef.h>
  6. #include <linux/init.h>
  7. #include <linux/sched.h>
  8. #include <linux/signal.h>
  9. #include <asm/irq.h>
  10. #include <asm/8xx_immap.h>
  11. #include <asm/mpc8xx.h>
  12. #include "ppc8xx_pic.h"
  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.
  20.  */
  21. static void m8xx_mask_irq(unsigned int irq_nr)
  22. {
  23. int bit, word;
  24. bit = irq_nr & 0x1f;
  25. word = irq_nr >> 5;
  26. ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
  27. ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
  28. ppc_cached_irq_mask[word];
  29. }
  30. static void m8xx_unmask_irq(unsigned int irq_nr)
  31. {
  32. int bit, word;
  33. bit = irq_nr & 0x1f;
  34. word = irq_nr >> 5;
  35. ppc_cached_irq_mask[word] |= (1 << (31-bit));
  36. ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
  37. ppc_cached_irq_mask[word];
  38. }
  39. static void m8xx_end_irq(unsigned int irq_nr)
  40. {
  41. if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
  42. int bit, word;
  43. bit = irq_nr & 0x1f;
  44. word = irq_nr >> 5;
  45. ppc_cached_irq_mask[word] |= (1 << (31-bit));
  46. ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 
  47. ppc_cached_irq_mask[word];
  48. }
  49. }
  50. static void m8xx_mask_and_ack(unsigned int irq_nr)
  51. {
  52. int bit, word;
  53. bit = irq_nr & 0x1f;
  54. word = irq_nr >> 5;
  55. ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
  56. ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
  57. ppc_cached_irq_mask[word];
  58. ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
  59. }
  60. struct hw_interrupt_type ppc8xx_pic = {
  61. " 8xx SIU  ",
  62. NULL,
  63. NULL,
  64. m8xx_unmask_irq,
  65. m8xx_mask_irq,
  66. m8xx_mask_and_ack,
  67. m8xx_end_irq,
  68. 0
  69. };
  70. #if 0
  71. void
  72. m8xx_do_IRQ(struct pt_regs *regs,
  73.    int            cpu)
  74. {
  75. int irq;
  76.         unsigned long bits = 0;
  77.         /* For MPC8xx, read the SIVEC register and shift the bits down
  78.          * to get the irq number.         */
  79.         bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
  80.         irq = bits >> 26;
  81. #if 0
  82.         irq += ppc8xx_pic.irq_offset;
  83. #endif
  84.         bits = 1UL << irq;
  85. if (irq < 0) {
  86. printk(KERN_DEBUG "Bogus interrupt %d from PC = %lxn",
  87.        irq, regs->nip);
  88. ppc_spurious_interrupts++;
  89. }
  90. else {
  91.                 ppc_irq_dispatch_handler( regs, irq );
  92. }
  93. }
  94. #endif
  95. /*
  96.  * We either return a valid interrupt or -1 if there is nothing pending
  97.  */
  98. int
  99. m8xx_get_irq(struct pt_regs *regs)
  100. {
  101. int irq;
  102. /* For MPC8xx, read the SIVEC register and shift the bits down
  103.  * to get the irq number.
  104.  */
  105. irq = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26;
  106. /*
  107.  * When we read the sivec without an interrupt to process, we will 
  108.  * get back SIU_LEVEL7.  In this case, return -1
  109.  */
  110. if (irq == SIU_LEVEL7)
  111. return -1;
  112. return irq;
  113. }
  114. /* The MBX is the only 8xx board that uses the 8259.
  115. */
  116. #if defined(CONFIG_MBX) && defined(CONFIG_PCI)
  117. void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
  118. {
  119. int bits, irq;
  120. /* A bug in the QSpan chip causes it to give us 0xff always
  121.  * when doing a character read.  So read 32 bits and shift.
  122.  * This doesn't seem to return useful values anyway, but
  123.  * read it to make sure things are acked.
  124.  * -- Cort
  125.  */
  126. irq = (inl(0x508) >> 24)&0xff;
  127. if ( irq != 0xff ) printk("iack %dn", irq);
  128. outb(0x0C, 0x20);
  129. irq = inb(0x20) & 7;
  130. if (irq == 2)
  131. {
  132. outb(0x0C, 0xA0);
  133. irq = inb(0xA0);
  134. irq = (irq&7) + 8;
  135. }
  136. bits = 1UL << irq;
  137. irq += i8259_pic.irq_offset;
  138. ppc_irq_dispatch_handler( regs, irq );
  139. }
  140. #endif
  141. /* Only the MBX uses the external 8259.  This allows us to catch standard
  142.  * drivers that may mess up the internal interrupt controllers, and also
  143.  * allow them to run without modification on the MBX.
  144.  */
  145. int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
  146. unsigned long irqflags, const char * devname, void *dev_id)
  147. {
  148. #if defined(CONFIG_MBX) && defined(CONFIG_PCI)
  149. irq += i8259_pic.irq_offset;
  150. return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
  151. #else
  152. /*
  153.  * Handle other "well-known" interrupts, but panic on unknown ones.
  154.  */
  155. switch (irq) {
  156. #ifdef IDE0_INTERRUPT
  157. case IDE0_INTERRUPT: /* IDE0 */
  158. return (request_8xxirq(irq, handler, irqflags, devname,
  159. dev_id));
  160. #endif
  161. #ifdef IDE1_INTERRUPT
  162. case IDE1_INTERRUPT: /* IDE1 */
  163. return (request_8xxirq(irq, handler, irqflags, devname,
  164. dev_id));
  165. #endif
  166. default: /* unknown IRQ -> panic */
  167. panic("request_irq");
  168. }
  169. #endif
  170. }