xref: /openbmc/u-boot/arch/m68k/lib/interrupts.c (revision b46694df)
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2007 Freescale Semiconductor Inc
6  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26 
27 #include <common.h>
28 #include <watchdog.h>
29 #include <asm/processor.h>
30 #include <asm/immap.h>
31 
32 #define	NR_IRQS		(CONFIG_SYS_NUM_IRQS)
33 
34 /*
35  * Interrupt vector functions.
36  */
37 struct interrupt_action {
38 	interrupt_handler_t *handler;
39 	void *arg;
40 };
41 
42 static struct interrupt_action irq_vecs[NR_IRQS];
43 
44 static __inline__ unsigned short get_sr (void)
45 {
46 	unsigned short sr;
47 
48 	asm volatile ("move.w %%sr,%0":"=r" (sr):);
49 
50 	return sr;
51 }
52 
53 static __inline__ void set_sr (unsigned short sr)
54 {
55 	asm volatile ("move.w %0,%%sr"::"r" (sr));
56 }
57 
58 /************************************************************************/
59 /*
60  * Install and free an interrupt handler
61  */
62 void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
63 {
64 	if ((vec < 0) || (vec >= NR_IRQS)) {
65 		printf ("irq_install_handler: wrong interrupt vector %d\n",
66 			vec);
67 		return;
68 	}
69 
70 	irq_vecs[vec].handler = handler;
71 	irq_vecs[vec].arg = arg;
72 }
73 
74 void irq_free_handler (int vec)
75 {
76 	if ((vec < 0) || (vec >= NR_IRQS)) {
77 		return;
78 	}
79 
80 	irq_vecs[vec].handler = NULL;
81 	irq_vecs[vec].arg = NULL;
82 }
83 
84 void enable_interrupts (void)
85 {
86 	unsigned short sr;
87 
88 	sr = get_sr ();
89 	set_sr (sr & ~0x0700);
90 }
91 
92 int disable_interrupts (void)
93 {
94 	unsigned short sr;
95 
96 	sr = get_sr ();
97 	set_sr (sr | 0x0700);
98 
99 	return ((sr & 0x0700) == 0);	/* return true, if interrupts were enabled before */
100 }
101 
102 void int_handler (struct pt_regs *fp)
103 {
104 	int vec;
105 
106 	vec = (fp->vector >> 2) & 0xff;
107 	if (vec > 0x40)
108 		vec -= 0x40;
109 
110 	if (irq_vecs[vec].handler != NULL) {
111 		irq_vecs[vec].handler (irq_vecs[vec].arg);
112 	} else {
113 		printf ("\nBogus External Interrupt Vector %d\n", vec);
114 	}
115 }
116