xref: /netbsd/sys/arch/arc/arc/interrupt.c (revision 4e07cefc)
1 /*	$NetBSD: interrupt.c,v 1.9 2011/03/02 10:51:04 tsutsui Exp $	*/
2 /*	$OpenBSD: trap.c,v 1.22 1999/05/24 23:08:59 jason Exp $	*/
3 
4 /*
5  * Copyright (c) 1988 University of Utah.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * the Systems Programming Group of the University of Utah Computer
11  * Science Department and Ralph Campbell.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * from: Utah Hdr: trap.c 1.32 91/04/06
38  *
39  *	@(#)trap.c	8.5 (Berkeley) 1/11/94
40  */
41 
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.9 2011/03/02 10:51:04 tsutsui Exp $");
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/intr.h>
49 #include <sys/cpu.h>
50 
51 #include <mips/locore.h>
52 
53 #include <machine/autoconf.h>
54 #include <machine/pio.h>
55 
56 #include <arc/arc/timervar.h>
57 #include <arc/jazz/pica.h>
58 #include <arc/jazz/rd94.h>
59 
60 struct cpu_inttab {
61 	uint32_t int_mask;
62 	uint32_t (*int_hand)(uint32_t, struct clockframe *);
63 };
64 static struct cpu_inttab cpu_int_tab[ARC_NINTPRI];
65 
66 uint32_t cpu_int_mask;	/* External cpu interrupt mask */
67 
68 #ifdef ENABLE_INT5_STATCLOCK
69 struct evcnt statclock_ev =
70     EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "cpu", "statclock");
71 #endif
72 
73 /*
74  *	Set up handler for external interrupt events.
75  *	Events are checked in priority order.
76  */
77 void
arc_set_intr(uint32_t mask,uint32_t (* int_hand)(uint32_t,struct clockframe *),int prio)78 arc_set_intr(uint32_t mask, uint32_t (*int_hand)(uint32_t, struct clockframe *),
79     int prio)
80 {
81 
82 	if (prio >= ARC_NINTPRI)
83 		panic("arc_set_intr: too high priority");
84 
85 	if (cpu_int_tab[prio].int_mask != 0 &&
86 	    (cpu_int_tab[prio].int_mask != mask ||
87 	     cpu_int_tab[prio].int_hand != int_hand)) {
88 		panic("set_intr: int already set");
89 	}
90 
91 	cpu_int_tab[prio].int_hand = int_hand;
92 	cpu_int_tab[prio].int_mask = mask;
93 	cpu_int_mask |= mask >> 10;
94 }
95 
96 /*
97  * Handle an interrupt.
98  */
99 void
cpu_intr(int ppl,vaddr_t pc,uint32_t status)100 cpu_intr(int ppl, vaddr_t pc, uint32_t status)
101 {
102 	struct cpu_inttab *inttab;
103 	struct clockframe cf;
104 	uint32_t ipending;
105 	u_int i;
106 	int ipl;
107 
108 	curcpu()->ci_data.cpu_nintr++;
109 
110 	cf.pc = pc;
111 	cf.sr = status;
112 	cf.intr = (curcpu()->ci_idepth > 1);
113 
114 	while (ppl < (ipl = splintr(&ipending))) {
115 		/* check MIPS3 internal clock interrupt */
116 		if (ipending & MIPS_INT_MASK_5) {
117 #ifdef ENABLE_INT5_STATCLOCK
118 			/* call statclock(9) handler */
119 			statclockintr(&cf);
120 			statclock_ev.ev_count++;
121 #else
122 			/*
123 			 * Writing a value to the Compare register, as a side
124 			 * effect, clears the timer interrupt request.
125 			 */
126 			mips3_cp0_compare_write(0);
127 #endif
128 		}
129 
130 		/*
131 		 * If there is an independent timer interrupt handler,
132 		 * call it first.
133 		 */
134 		inttab = &cpu_int_tab[ARC_INTPRI_TIMER_INT];
135 		if (inttab->int_mask & ipending) {
136 			(*inttab->int_hand)(ipending, &cf);
137 		}
138 
139 		/*
140 		 *  Check off all other enabled interrupts.
141 		 *  Called handlers return mask of interrupts to be reenabled.
142 		 */
143 		for (inttab++, i = ARC_INTPRI_TIMER_INT + 1;
144 		     i < ARC_NINTPRI;
145 		     inttab++, i++) {
146 			if (inttab->int_mask & ipending) {
147 				(*inttab->int_hand)(ipending, &cf);
148 			}
149 		}
150 		(void)splhigh();
151 	}
152 }
153