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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BRIEF MODULE DESCRIPTION
  3.  * Au1000 interrupt routines.
  4.  *
  5.  * Copyright 2001 MontaVista Software Inc.
  6.  * Author: MontaVista Software, Inc.
  7.  * ppopov@mvista.com or source@mvista.com
  8.  *
  9.  *  This program is free software; you can redistribute  it and/or modify it
  10.  *  under  the terms of  the GNU General  Public License as published by the
  11.  *  Free Software Foundation;  either version 2 of the License, or (at your
  12.  *  option) any later version.
  13.  *
  14.  *  THIS  SOFTWARE  IS PROVIDED   ``AS IS'' AND   ANY EXPRESS OR IMPLIED
  15.  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  16.  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  17.  *  NO EVENT  SHALL   THE AUTHOR  BE  LIABLE FOR ANY   DIRECT, INDIRECT,
  18.  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19.  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS OR SERVICES; LOSS OF
  20.  *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  21.  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  22.  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23.  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24.  *
  25.  *  You should have received a copy of the  GNU General Public License along
  26.  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  27.  *  675 Mass Ave, Cambridge, MA 02139, USA.
  28.  */
  29. #include <linux/errno.h>
  30. #include <linux/init.h>
  31. #include <linux/kernel_stat.h>
  32. #include <linux/module.h>
  33. #include <linux/signal.h>
  34. #include <linux/sched.h>
  35. #include <linux/types.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/ioport.h>
  38. #include <linux/timex.h>
  39. #include <linux/slab.h>
  40. #include <linux/random.h>
  41. #include <linux/delay.h>
  42. #include <asm/bitops.h>
  43. #include <asm/bootinfo.h>
  44. #include <asm/io.h>
  45. #include <asm/mipsregs.h>
  46. #include <asm/system.h>
  47. #include <asm/au1000.h>
  48. #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
  49. #undef DEBUG_IRQ
  50. #ifdef DEBUG_IRQ
  51. /* note: prints function name for you */
  52. #define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
  53. #else
  54. #define DPRINTK(fmt, args...)
  55. #endif
  56. #define EXT_INTC0_REQ0 2 /* IP 2 */
  57. #define EXT_INTC0_REQ1 3 /* IP 3 */
  58. #define EXT_INTC1_REQ0 4 /* IP 4 */
  59. #define EXT_INTC1_REQ1 5 /* IP 5 */
  60. #define MIPS_TIMER_IP  7 /* IP 7 */
  61. #ifdef CONFIG_REMOTE_DEBUG
  62. extern void breakpoint(void);
  63. #endif
  64. extern asmlinkage void au1000_IRQ(void);
  65. extern void set_debug_traps(void);
  66. extern irq_cpustat_t irq_stat [];
  67. extern irq_desc_t irq_desc[NR_IRQS];
  68. unsigned int local_bh_count[NR_CPUS];
  69. unsigned int local_irq_count[NR_CPUS];
  70. static void setup_local_irq(unsigned int irq, int type, int int_req);
  71. static unsigned int startup_irq(unsigned int irq);
  72. static void end_irq(unsigned int irq_nr);
  73. static inline void mask_and_ack_level_irq(unsigned int irq_nr);
  74. static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr);
  75. static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr);
  76. static inline void local_enable_irq(unsigned int irq_nr);
  77. static inline void local_disable_irq(unsigned int irq_nr);
  78. unsigned long spurious_interrupts;
  79. extern unsigned int do_IRQ(int irq, struct pt_regs *regs);
  80. extern void __init init_generic_irq(void);
  81. static inline void sync(void)
  82. {
  83. __asm volatile ("sync");
  84. }
  85. /* Function for careful CP0 interrupt mask access */
  86. static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
  87. {
  88. unsigned long status = read_32bit_cp0_register(CP0_STATUS);
  89. status &= ~((clr_mask & 0xFF) << 8);
  90. status |=   (set_mask & 0xFF) << 8;
  91. write_32bit_cp0_register(CP0_STATUS, status);
  92. }
  93. static inline void mask_cpu_irq_input(unsigned int irq_nr)
  94. {
  95. modify_cp0_intmask(irq_nr, 0);
  96. }
  97. static inline void unmask_cpu_irq_input(unsigned int irq_nr)
  98. {
  99. modify_cp0_intmask(0, irq_nr);
  100. }
  101. static void disable_cpu_irq_input(unsigned int irq_nr)
  102. {
  103. unsigned long flags;
  104. save_and_cli(flags);
  105. mask_cpu_irq_input(irq_nr);
  106. restore_flags(flags);
  107. }
  108. static void enable_cpu_irq_input(unsigned int irq_nr)
  109. {
  110. unsigned long flags;
  111. save_and_cli(flags);
  112. unmask_cpu_irq_input(irq_nr);
  113. restore_flags(flags);
  114. }
  115. static void setup_local_irq(unsigned int irq_nr, int type, int int_req)
  116. {
  117. /* Config2[n], Config1[n], Config0[n] */
  118. if (irq_nr > AU1000_LAST_INTC0_INT) {
  119. switch (type) {
  120. case INTC_INT_RISE_EDGE: /* 0:0:1 */
  121. outl(1<<irq_nr,INTC1_CONFIG2_CLEAR);
  122. outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
  123. outl(1<<irq_nr, INTC1_CONFIG0_SET);
  124. break;
  125. case INTC_INT_FALL_EDGE: /* 0:1:0 */
  126. outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
  127. outl(1<<irq_nr, INTC1_CONFIG1_SET);
  128. outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
  129. break;
  130. case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
  131. outl(1<<irq_nr, INTC1_CONFIG2_SET);
  132. outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
  133. outl(1<<irq_nr, INTC1_CONFIG0_SET);
  134. break;
  135. case INTC_INT_LOW_LEVEL: /* 1:1:0 */
  136. outl(1<<irq_nr, INTC1_CONFIG2_SET);
  137. outl(1<<irq_nr, INTC1_CONFIG1_SET);
  138. outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
  139. break;
  140. case INTC_INT_DISABLED: /* 0:0:0 */
  141. outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
  142. outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
  143. outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
  144. break;
  145. default: /* disable the interrupt */
  146. printk("unexpected int type %d (irq %d)n", type, irq_nr);
  147. outl(1<<irq_nr, INTC1_CONFIG0_CLEAR);
  148. outl(1<<irq_nr, INTC1_CONFIG1_CLEAR);
  149. outl(1<<irq_nr, INTC1_CONFIG2_CLEAR);
  150. return;
  151. }
  152. if (int_req) /* assign to interrupt request 1 */
  153. outl(1<<irq_nr, INTC1_ASSIGN_REQ_CLEAR);
  154. else      /* assign to interrupt request 0 */
  155. outl(1<<irq_nr, INTC1_ASSIGN_REQ_SET);
  156. outl(1<<irq_nr, INTC1_SOURCE_SET);
  157. outl(1<<irq_nr, INTC1_MASK_CLEAR);
  158. }
  159. else {
  160. switch (type) {
  161. case INTC_INT_RISE_EDGE: /* 0:0:1 */
  162. outl(1<<irq_nr,INTC0_CONFIG2_CLEAR);
  163. outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
  164. outl(1<<irq_nr, INTC0_CONFIG0_SET);
  165. break;
  166. case INTC_INT_FALL_EDGE: /* 0:1:0 */
  167. outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
  168. outl(1<<irq_nr, INTC0_CONFIG1_SET);
  169. outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
  170. break;
  171. case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
  172. outl(1<<irq_nr, INTC0_CONFIG2_SET);
  173. outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
  174. outl(1<<irq_nr, INTC0_CONFIG0_SET);
  175. break;
  176. case INTC_INT_LOW_LEVEL: /* 1:1:0 */
  177. outl(1<<irq_nr, INTC0_CONFIG2_SET);
  178. outl(1<<irq_nr, INTC0_CONFIG1_SET);
  179. outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
  180. break;
  181. case INTC_INT_DISABLED: /* 0:0:0 */
  182. outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
  183. outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
  184. outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
  185. break;
  186. default: /* disable the interrupt */
  187. printk("unexpected int type %d (irq %d)n", type, irq_nr);
  188. outl(1<<irq_nr, INTC0_CONFIG0_CLEAR);
  189. outl(1<<irq_nr, INTC0_CONFIG1_CLEAR);
  190. outl(1<<irq_nr, INTC0_CONFIG2_CLEAR);
  191. return;
  192. }
  193. if (int_req) /* assign to interrupt request 1 */
  194. outl(1<<irq_nr, INTC0_ASSIGN_REQ_CLEAR);
  195. else      /* assign to interrupt request 0 */
  196. outl(1<<irq_nr, INTC0_ASSIGN_REQ_SET);
  197. outl(1<<irq_nr, INTC0_SOURCE_SET);
  198. outl(1<<irq_nr, INTC0_MASK_CLEAR);
  199. }
  200. sync();
  201. }
  202. static unsigned int startup_irq(unsigned int irq_nr)
  203. {
  204. local_enable_irq(irq_nr);
  205. return 0; 
  206. }
  207. static void shutdown_irq(unsigned int irq_nr)
  208. {
  209. local_disable_irq(irq_nr);
  210. return;
  211. }
  212. static inline void local_enable_irq(unsigned int irq_nr)
  213. {
  214. if (irq_nr > AU1000_LAST_INTC0_INT) {
  215. outl(1<<irq_nr, INTC1_MASK_SET);
  216. }
  217. else {
  218. outl(1<<irq_nr, INTC0_MASK_SET);
  219. }
  220. sync();
  221. }
  222. static inline void local_disable_irq(unsigned int irq_nr)
  223. {
  224. if (irq_nr > AU1000_LAST_INTC0_INT) {
  225. outl(1<<irq_nr, INTC1_MASK_CLEAR);
  226. }
  227. else {
  228. outl(1<<irq_nr, INTC0_MASK_CLEAR);
  229. }
  230. sync();
  231. }
  232. static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
  233. {
  234. if (irq_nr > AU1000_LAST_INTC0_INT) {
  235. outl(1<<irq_nr, INTC1_R_EDGE_DETECT_CLEAR);
  236. outl(1<<irq_nr, INTC1_MASK_CLEAR);
  237. }
  238. else {
  239. outl(1<<irq_nr, INTC0_R_EDGE_DETECT_CLEAR);
  240. outl(1<<irq_nr, INTC0_MASK_CLEAR);
  241. }
  242. sync();
  243. }
  244. static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
  245. {
  246. if (irq_nr > AU1000_LAST_INTC0_INT) {
  247. outl(1<<irq_nr, INTC1_F_EDGE_DETECT_CLEAR);
  248. outl(1<<irq_nr, INTC1_MASK_CLEAR);
  249. }
  250. else {
  251. outl(1<<irq_nr, INTC0_F_EDGE_DETECT_CLEAR);
  252. outl(1<<irq_nr, INTC0_MASK_CLEAR);
  253. }
  254. }
  255. static inline void mask_and_ack_level_irq(unsigned int irq_nr)
  256. {
  257. local_disable_irq(irq_nr);
  258. sync();
  259. return;
  260. }
  261. static void end_irq(unsigned int irq_nr)
  262. {
  263. if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
  264. local_enable_irq(irq_nr);
  265. else
  266. printk("warning: end_irq %d did not enablen", irq_nr);
  267. }
  268. static struct hw_interrupt_type rise_edge_irq_type = {
  269. "Au1000 Rise Edge",
  270. startup_irq,
  271. shutdown_irq,
  272. local_enable_irq,
  273. local_disable_irq,
  274. mask_and_ack_rise_edge_irq,
  275. end_irq,
  276. NULL
  277. };
  278. static struct hw_interrupt_type fall_edge_irq_type = {
  279. "Au1000 Fall Edge",
  280. startup_irq,
  281. shutdown_irq,
  282. local_enable_irq,
  283. local_disable_irq,
  284. mask_and_ack_fall_edge_irq,
  285. end_irq,
  286. NULL
  287. };
  288. static struct hw_interrupt_type level_irq_type = {
  289. "Au1000 Level",
  290. startup_irq,
  291. shutdown_irq,
  292. local_enable_irq,
  293. local_disable_irq,
  294. mask_and_ack_level_irq,
  295. end_irq,
  296. NULL
  297. };
  298. void enable_cpu_timer(void)
  299. {
  300. enable_cpu_irq_input(1<<MIPS_TIMER_IP); /* timer interrupt */
  301. }
  302. void __init init_IRQ(void)
  303. {
  304. int i;
  305. unsigned long cp0_status;
  306. cp0_status = read_32bit_cp0_register(CP0_STATUS);
  307. memset(irq_desc, 0, sizeof(irq_desc));
  308. set_except_vector(0, au1000_IRQ);
  309. init_generic_irq();
  310. /* 
  311.  * Setup high priority interrupts on int_request0; low priority on
  312.  * int_request1
  313.  */
  314. for (i = 0; i <= NR_IRQS; i++) {
  315. switch (i) {
  316. case AU1000_MAC0_DMA_INT:
  317. case AU1000_MAC1_DMA_INT:
  318. setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0);
  319. irq_desc[i].handler = &level_irq_type;
  320. break;
  321. default: /* active high, level interrupt */
  322. setup_local_irq(i, INTC_INT_HIGH_LEVEL, 1);
  323. irq_desc[i].handler = &level_irq_type;
  324. break;
  325. }
  326. }
  327. set_cp0_status(ALLINTS);
  328. #ifdef CONFIG_REMOTE_DEBUG
  329. /* If local serial I/O used for debug port, enter kgdb at once */
  330. puts("Waiting for kgdb to connect...");
  331. set_debug_traps();
  332. breakpoint(); 
  333. #endif
  334. }
  335. void mips_spurious_interrupt(struct pt_regs *regs)
  336. {
  337. spurious_interrupts++;
  338. }
  339. void intc0_req0_irqdispatch(struct pt_regs *regs)
  340. {
  341. int irq = 0, i;
  342. unsigned long int_request;
  343. int_request = inl(INTC0_REQ0_INT);
  344. if (!int_request) return;
  345. for (i=0; i<32; i++) {
  346. if ((int_request & 0x1)) {
  347. do_IRQ(irq, regs);
  348. }
  349. irq++;
  350. int_request >>= 1;
  351. }
  352. }
  353. void intc0_req1_irqdispatch(struct pt_regs *regs)
  354. {
  355. int irq = 0, i;
  356. unsigned long int_request;
  357. int_request = inl(INTC0_REQ1_INT);
  358. if (!int_request) return;
  359. for (i=0; i<32; i++) {
  360. if ((int_request & 0x1)) {
  361. do_IRQ(irq, regs);
  362. }
  363. irq++;
  364. int_request >>= 1;
  365. }
  366. }
  367. void intc1_req0_irqdispatch(struct pt_regs *regs)
  368. {
  369. int irq = 0, i;
  370. unsigned long int_request;
  371. int_request = inl(INTC1_REQ0_INT);
  372. if (!int_request) return;
  373. for (i=0; i<32; i++) {
  374. if ((int_request & 0x1)) {
  375. do_IRQ(irq, regs);
  376. }
  377. irq++;
  378. int_request >>= 1;
  379. }
  380. }
  381. void intc1_req1_irqdispatch(struct pt_regs *regs)
  382. {
  383. int irq = 0, i;
  384. unsigned long int_request;
  385. int_request = inl(INTC1_REQ1_INT);
  386. if (!int_request) return;
  387. for (i=0; i<32; i++) {
  388. if ((int_request & 0x1)) {
  389. do_IRQ(irq, regs);
  390. }
  391. irq++;
  392. int_request >>= 1;
  393. }
  394. }