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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 2000 RidgeRun, Inc.
  3.  * Author: RidgeRun, Inc.
  4.  *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
  5.  *
  6.  * Copyright 2001 MontaVista Software Inc.
  7.  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  8.  * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
  9.  *
  10.  *  This program is free software; you can redistribute  it and/or modify it
  11.  *  under  the terms of  the GNU General  Public License as published by the
  12.  *  Free Software Foundation;  either version 2 of the  License, or (at your
  13.  *  option) any later version.
  14.  *
  15.  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  16.  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  17.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  18.  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  19.  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20.  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  21.  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  22.  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  23.  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24.  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  *
  26.  *  You should have received a copy of the  GNU General Public License along
  27.  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  28.  *  675 Mass Ave, Cambridge, MA 02139, USA.
  29.  *
  30.  */
  31. #include <linux/errno.h>
  32. #include <linux/init.h>
  33. #include <linux/kernel_stat.h>
  34. #include <linux/module.h>
  35. #include <linux/signal.h>
  36. #include <linux/sched.h>
  37. #include <linux/types.h>
  38. #include <linux/interrupt.h>
  39. #include <linux/ioport.h>
  40. #include <linux/timex.h>
  41. #include <linux/slab.h>
  42. #include <linux/random.h>
  43. #include <linux/irq.h>
  44. #include <asm/bitops.h>
  45. #include <asm/bootinfo.h>
  46. #include <asm/io.h>
  47. #include <asm/irq.h>
  48. #include <asm/mipsregs.h>
  49. #include <asm/system.h>
  50. static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED;
  51. /* Function for careful CP0 interrupt mask access */
  52. static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in)
  53. {
  54. unsigned long status;
  55. unsigned clr_mask;
  56. unsigned set_mask;
  57. /* do the low 8 bits first */
  58. clr_mask = 0xff & clr_mask_in;
  59. set_mask = 0xff & set_mask_in;
  60. status = read_32bit_cp0_register(CP0_STATUS);
  61. status &= ~((clr_mask & 0xFF) << 8);
  62. status |= (set_mask & 0xFF) << 8;
  63. write_32bit_cp0_register(CP0_STATUS, status);
  64. /* do the high 8 bits */
  65. clr_mask = 0xff & (clr_mask_in >> 8);
  66. set_mask = 0xff & (set_mask_in >> 8);
  67. status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL);
  68. status &= ~((clr_mask & 0xFF) << 8);
  69. status |= (set_mask & 0xFF) << 8;
  70. write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status);
  71. }
  72. static inline void mask_irq(unsigned int irq)
  73. {
  74. modify_cp0_intmask(irq, 0);
  75. }
  76. static inline void unmask_irq(unsigned int irq)
  77. {
  78. modify_cp0_intmask(0, irq);
  79. }
  80. static void enable_cp7000_irq(unsigned int irq)
  81. {
  82. unsigned long flags;
  83. spin_lock_irqsave(&rm7000_irq_lock, flags);
  84. unmask_irq(1 << irq);
  85. spin_unlock_irqrestore(&rm7000_irq_lock, flags);
  86. }
  87. static unsigned int startup_cp7000_irq(unsigned int irq)
  88. {
  89. enable_cp7000_irq(irq);
  90. return 0; /* never anything pending */
  91. }
  92. static void disable_cp7000_irq(unsigned int irq)
  93. {
  94. unsigned long flags;
  95. spin_lock_irqsave(&rm7000_irq_lock, flags);
  96. mask_irq(1 << irq);
  97. spin_unlock_irqrestore(&rm7000_irq_lock, flags);
  98. }
  99. #define shutdown_cp7000_irq disable_cp7000_irq
  100. static void mask_and_ack_cp7000_irq(unsigned int irq)
  101. {
  102. mask_irq(1 << irq);
  103. }
  104. static void end_cp7000_irq(unsigned int irq)
  105. {
  106. if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  107. unmask_irq(1 << irq);
  108. }
  109. static struct hw_interrupt_type cp7000_hpcdma_irq_type = {
  110. "CP7000",
  111. startup_cp7000_irq,
  112. shutdown_cp7000_irq,
  113. enable_cp7000_irq,
  114. disable_cp7000_irq,
  115. mask_and_ack_cp7000_irq,
  116. end_cp7000_irq,
  117. NULL
  118. };
  119. extern asmlinkage void ocelot_handle_int(void);
  120. extern void gt64120_irq_init(void);
  121. void __init init_IRQ(void)
  122. {
  123. int i;
  124. /*
  125.  * Clear all of the interrupts while we change the able around a bit.
  126.  * int-handler is not on bootstrap
  127.  */
  128. clear_cp0_status(ST0_IM | ST0_BEV);
  129. __cli();
  130. /* Sets the first-level interrupt dispatcher. */
  131. set_except_vector(0, ocelot_handle_int);
  132. init_generic_irq();
  133. for (i = 0; i <= 15; i++) {
  134. irq_desc[i].status = IRQ_DISABLED;
  135. irq_desc[i].action = 0;
  136. irq_desc[i].depth = 1;
  137. irq_desc[i].handler = &cp7000_hpcdma_irq_type;
  138. }
  139. gt64120_irq_init();
  140. #ifdef CONFIG_REMOTE_DEBUG
  141. printk("start kgdb ...n");
  142. set_debug_traps();
  143. breakpoint(); /* you may move this line to whereever you want :-) */
  144. #endif
  145. #ifdef CONFIG_GDB_CONSOLE
  146. register_gdb_console();
  147. #endif
  148. }