irq.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright 2001 MontaVista Software Inc.
  3.  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  4.  *
  5.  *  arch/mips/ddb5xxx/ddb5477/irq.c
  6.  *     The irq setup and misc routines for DDB5476.
  7.  *
  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.
  12.  */
  13. #include <linux/config.h>
  14. #include <linux/init.h>
  15. #include <linux/irq.h>
  16. #include <linux/types.h>
  17. #include <linux/ptrace.h>
  18. #include <asm/system.h>
  19. #include <asm/mipsregs.h>
  20. #include <asm/ddb5xxx/ddb5xxx.h>
  21. /* [jsun] sooner or later we should move this debug stuff to MIPS common */
  22. #include <asm/ddb5xxx/debug.h>
  23. /*
  24.  * IRQ mapping
  25.  *
  26.  *  0-7: 8 CPU interrupts
  27.  * 0 - software interrupt 0
  28.  * 1 -  software interrupt 1
  29.  * 2 -  most Vrc5477 interrupts are routed to this pin
  30.  * 3 -  (optional) some other interrupts routed to this pin for debugg
  31.  * 4 -  not used
  32.  * 5 -  not used
  33.  * 6 -  not used
  34.  * 7 -  cpu timer (used by default)
  35.  *
  36.  *  8-39: 32 Vrc5477 interrupt sources
  37.  * (refer to the Vrc5477 manual)
  38.  */
  39. #define PCI0 DDB_INTPPES0
  40. #define PCI1 DDB_INTPPES1
  41. #define ACTIVE_LOW 1
  42. #define ACTIVE_HIGH 0
  43. #define LEVEL_SENSE 2
  44. #define EDGE_TRIGGER 0
  45. #define INTA 0
  46. #define INTB 1
  47. #define INTC 2
  48. #define INTD 3
  49. #define INTE 4
  50. static inline void 
  51. set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
  52. {
  53. u32 reg_value;
  54. u32 reg_bitmask;
  55. reg_value = ddb_in32(pci);
  56. reg_bitmask = 0x3 << (intn * 2);
  57. reg_value &= ~reg_bitmask;
  58. reg_value |= (active | trigger) << (intn * 2);
  59. ddb_out32(pci, reg_value);
  60. }
  61. extern void vrc5477_irq_init(u32 base);
  62. extern void mips_cpu_irq_init(u32 base);
  63. extern asmlinkage void ddb5477_handle_int(void);
  64. void
  65. ddb5477_irq_setup(void)
  66. {
  67. MIPS_DEBUG(printk("ddb5477_irq_setup invoked.n"));
  68. /* by default, we disable all interrupts and route all vrc5477 
  69.  * interrupts to pin 0 (irq 2) */
  70. ddb_out32(DDB_INTCTRL0, 0);
  71. ddb_out32(DDB_INTCTRL1, 0);
  72. ddb_out32(DDB_INTCTRL2, 0);
  73. ddb_out32(DDB_INTCTRL3, 0);
  74. clear_cp0_status(0xff00);
  75. set_cp0_status(0x0400);
  76. /* setup PCI interrupt attributes */
  77. set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
  78. set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
  79. set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
  80. set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE);
  81. set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE);
  82. set_pci_int_attr(PCI1, INTA, ACTIVE_LOW, LEVEL_SENSE);
  83. set_pci_int_attr(PCI1, INTB, ACTIVE_LOW, LEVEL_SENSE);
  84. set_pci_int_attr(PCI1, INTC, ACTIVE_LOW, LEVEL_SENSE);
  85. set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE);
  86. set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE);
  87. /* 
  88.  * for debugging purpose, we enable several error interrupts
  89.  * and route them to pin 1. (IP3) 
  90.  */
  91. /* cpu parity check - 0 */
  92. ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0);
  93. /* cpu no-target decode - 1 */
  94. ll_vrc5477_irq_route(1, 1); ll_vrc5477_irq_enable(1);
  95. /* local bus read time-out - 7 */
  96. ll_vrc5477_irq_route(7, 1); ll_vrc5477_irq_enable(7);
  97. /* PCI SERR# - 14 */
  98. ll_vrc5477_irq_route(14, 1); ll_vrc5477_irq_enable(14);
  99. /* PCI internal error - 15 */
  100. ll_vrc5477_irq_route(15, 1); ll_vrc5477_irq_enable(15);
  101. /* IOPCI SERR# - 30 */
  102. ll_vrc5477_irq_route(30, 1); ll_vrc5477_irq_enable(30);
  103. /* IOPCI internal error - 31 */
  104. ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31);
  105. /* init all controllers */
  106. mips_cpu_irq_init(0);
  107. vrc5477_irq_init(8);
  108. /* hook up the first-level interrupt handler */
  109. set_except_vector(0, ddb5477_handle_int);
  110. }
  111. /*
  112.  * the first level int-handler will jump here if it is a vrc5477 irq
  113.  */
  114. #define NUM_5477_IRQS 32
  115. asmlinkage void
  116. vrc5477_irq_dispatch(struct pt_regs *regs)
  117. {
  118. extern unsigned int do_IRQ(int irq, struct pt_regs *regs);
  119. u32 intStatus;
  120. u32 bitmask;
  121. u32 i;
  122. MIPS_ASSERT(ddb_in32(DDB_INT2STAT) == 0);
  123. MIPS_ASSERT(ddb_in32(DDB_INT3STAT) == 0);
  124. MIPS_ASSERT(ddb_in32(DDB_INT4STAT) == 0);
  125. MIPS_ASSERT(ddb_in32(DDB_NMISTAT) == 0);
  126. if (ddb_in32(DDB_INT1STAT) != 0) {
  127. #if defined(CONFIG_LL_DEBUG)
  128. vrc5477_show_int_regs();
  129. #endif
  130. panic("error interrupt has happened.n");
  131. }
  132. intStatus = ddb_in32(DDB_INT0STAT);
  133. for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
  134. /* do we need to "and" with the int mask? */
  135. if (intStatus & bitmask) {
  136. do_IRQ(8 + i, regs);
  137. }
  138. }
  139. }