xref: /OK3568_Linux_fs/u-boot/arch/nios2/cpu/interrupts.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2000-2002
3*4882a593Smuzhiyun  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
6*4882a593Smuzhiyun  * Scott McNutt <smcnutt@psyent.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <command.h>
13*4882a593Smuzhiyun #include <asm/nios2.h>
14*4882a593Smuzhiyun #include <asm/types.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <asm/ptrace.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /*************************************************************************/
19*4882a593Smuzhiyun struct	irq_action {
20*4882a593Smuzhiyun 	interrupt_handler_t *handler;
21*4882a593Smuzhiyun 	void *arg;
22*4882a593Smuzhiyun 	int count;
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static struct irq_action vecs[32];
26*4882a593Smuzhiyun 
disable_interrupts(void)27*4882a593Smuzhiyun int disable_interrupts (void)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	int val = rdctl (CTL_STATUS);
30*4882a593Smuzhiyun 	wrctl (CTL_STATUS, val & ~STATUS_IE);
31*4882a593Smuzhiyun 	return (val & STATUS_IE);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
enable_interrupts(void)34*4882a593Smuzhiyun void enable_interrupts( void )
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	int val = rdctl (CTL_STATUS);
37*4882a593Smuzhiyun 	wrctl (CTL_STATUS, val | STATUS_IE);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun 
external_interrupt(struct pt_regs * regs)40*4882a593Smuzhiyun void external_interrupt (struct pt_regs *regs)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	unsigned irqs;
43*4882a593Smuzhiyun 	struct irq_action *act;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/* Evaluate only irqs that are both enabled AND pending */
46*4882a593Smuzhiyun 	irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
47*4882a593Smuzhiyun 	act = vecs;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	/* Assume (as does the Nios2 HAL) that bit 0 is highest
50*4882a593Smuzhiyun 	 * priority. NOTE: There is ALWAYS a handler assigned
51*4882a593Smuzhiyun 	 * (the default if no other).
52*4882a593Smuzhiyun 	 */
53*4882a593Smuzhiyun 	while (irqs) {
54*4882a593Smuzhiyun 		if (irqs & 1) {
55*4882a593Smuzhiyun 			act->handler (act->arg);
56*4882a593Smuzhiyun 			act->count++;
57*4882a593Smuzhiyun 		}
58*4882a593Smuzhiyun 		irqs >>=1;
59*4882a593Smuzhiyun 		act++;
60*4882a593Smuzhiyun 	}
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
def_hdlr(void * arg)63*4882a593Smuzhiyun static void def_hdlr (void *arg)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	unsigned irqs = rdctl (CTL_IENABLE);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* Disable the individual interrupt -- with gratuitous
68*4882a593Smuzhiyun 	 * warning.
69*4882a593Smuzhiyun 	 */
70*4882a593Smuzhiyun 	irqs &= ~(1 << (int)arg);
71*4882a593Smuzhiyun 	wrctl (CTL_IENABLE, irqs);
72*4882a593Smuzhiyun 	printf ("WARNING: Disabling unhandled interrupt: %d\n",
73*4882a593Smuzhiyun 			(int)arg);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /*************************************************************************/
irq_install_handler(int irq,interrupt_handler_t * hdlr,void * arg)77*4882a593Smuzhiyun void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	int flag;
81*4882a593Smuzhiyun 	struct irq_action *act;
82*4882a593Smuzhiyun 	unsigned ena = rdctl (CTL_IENABLE);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if ((irq < 0) || (irq > 31))
85*4882a593Smuzhiyun 		return;
86*4882a593Smuzhiyun 	act = &vecs[irq];
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	flag = disable_interrupts ();
89*4882a593Smuzhiyun 	if (hdlr) {
90*4882a593Smuzhiyun 		act->handler = hdlr;
91*4882a593Smuzhiyun 		act->arg = arg;
92*4882a593Smuzhiyun 		ena |= (1 << irq);		/* enable */
93*4882a593Smuzhiyun 	} else {
94*4882a593Smuzhiyun 		act->handler = def_hdlr;
95*4882a593Smuzhiyun 		act->arg = (void *)irq;
96*4882a593Smuzhiyun 		ena &= ~(1 << irq);		/* disable */
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 	wrctl (CTL_IENABLE, ena);
99*4882a593Smuzhiyun 	if (flag) enable_interrupts ();
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 
interrupt_init(void)103*4882a593Smuzhiyun int interrupt_init (void)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	int i;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	/* Assign the default handler to all */
108*4882a593Smuzhiyun 	for (i = 0; i < 32; i++) {
109*4882a593Smuzhiyun 		vecs[i].handler = def_hdlr;
110*4882a593Smuzhiyun 		vecs[i].arg = (void *)i;
111*4882a593Smuzhiyun 		vecs[i].count = 0;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	enable_interrupts ();
115*4882a593Smuzhiyun 	return (0);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun /*************************************************************************/
120*4882a593Smuzhiyun #if defined(CONFIG_CMD_IRQ)
do_irqinfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])121*4882a593Smuzhiyun int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	int i;
124*4882a593Smuzhiyun 	struct irq_action *act = vecs;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	printf ("\nInterrupt-Information:\n\n");
127*4882a593Smuzhiyun 	printf ("Nr  Routine   Arg       Count\n");
128*4882a593Smuzhiyun 	printf ("-----------------------------\n");
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	for (i=0; i<32; i++) {
131*4882a593Smuzhiyun 		if (act->handler != def_hdlr) {
132*4882a593Smuzhiyun 			printf ("%02d  %08lx  %08lx  %d\n",
133*4882a593Smuzhiyun 				i,
134*4882a593Smuzhiyun 				(ulong)act->handler,
135*4882a593Smuzhiyun 				(ulong)act->arg,
136*4882a593Smuzhiyun 				act->count);
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 		act++;
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 	printf ("\n");
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	return (0);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun #endif
145