]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/AmigaOneG3SE/interrupts.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / MAI / AmigaOneG3SE / interrupts.c
1 /*
2  * (C) Copyright 2002
3  * John W. Linville <linville@tuxdriver.com>
4  *
5  *    Copied and modified from original code by Josh Huber.  Original
6  *    copyright notice preserved below.
7  *
8  * (C) Copyright 2001
9  * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
10  *
11  * See file CREDITS for list of people who contributed to this
12  * project.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27  * MA 02111-1307 USA
28  */
29
30 /*
31  * interrupts.c - just enough support for the decrementer/timer
32  */
33
34 #include <common.h>
35 #include <asm/processor.h>
36 #include <command.h>
37 #include "i8259.h"
38
39 #undef DEBUG
40 #ifdef  DEBUG
41 #define PRINTF(fmt,args...)     printf (fmt ,##args)
42 #else
43 #define PRINTF(fmt,args...)
44 #endif
45 #define NR_IRQS 16
46
47 void irq_alloc_init(void);
48 long irq_alloc(long wanted);
49
50 /****************************************************************************/
51
52 unsigned decrementer_count;          /* count value for 1e6/HZ microseconds */
53
54 struct irq_action {
55     interrupt_handler_t *handler;
56     void *arg;
57     ulong count;
58 };
59
60 static struct irq_action irq_handlers[NR_IRQS];
61
62 /****************************************************************************/
63
64 static __inline__ unsigned long
65 get_msr(void)
66 {
67         unsigned long msr;
68
69         asm volatile("mfmsr %0" : "=r" (msr) :);
70         return msr;
71 }
72
73 static __inline__ void
74 set_msr(unsigned long msr)
75 {
76         asm volatile("mtmsr %0" : : "r" (msr));
77 }
78
79 static __inline__ unsigned long
80 get_dec(void)
81 {
82         unsigned long val;
83
84         asm volatile("mfdec %0" : "=r" (val) :);
85         return val;
86 }
87
88
89 static __inline__ void
90 set_dec(unsigned long val)
91 {
92         asm volatile("mtdec %0" : : "r" (val));
93 }
94
95
96 void
97 enable_interrupts(void)
98 {
99     set_msr (get_msr() | MSR_EE);
100 }
101
102 /* returns flag if MSR_EE was set before */
103 int
104 disable_interrupts(void)
105 {
106     ulong msr;
107
108     msr = get_msr();
109     set_msr (msr & ~MSR_EE);
110     return ((msr & MSR_EE) != 0);
111 }
112
113 /****************************************************************************/
114
115 int interrupt_init (void)
116 {
117     extern void new_reset(void);
118     extern void new_reset_end(void);
119 #ifdef DEBUG
120         puts("interrupt_init: setting decrementer_count\n");
121 #endif
122         decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
123
124 #ifdef DEBUG
125         puts("interrupt_init: setting actual decremter\n");
126 #endif
127         set_dec (get_tbclk() / CONFIG_SYS_HZ);
128
129 #ifdef DEBUG
130         puts("interrupt_init: clearing external interrupt table\n");
131 #endif
132         /* clear external interrupt table here */
133         memset(irq_handlers, 0, sizeof(irq_handlers));
134
135 #ifdef DEBUG
136         puts("interrupt_init: initializing interrupt controller\n");
137 #endif
138         i8259_init();
139
140 #ifdef DEBUG
141         puts("Copying reset trampoline\n");
142 #endif
143         /* WARNING: Assmues that the first megabyte is CACHEINHIBIT! */
144         memcpy((void *)0x100, new_reset, new_reset_end - new_reset);
145
146 #ifdef DEBUG
147         PRINTF("interrupt_init: enabling interrupts (msr = %08x)\n",
148                 get_msr());
149 #endif
150         set_msr (get_msr() | MSR_EE);
151
152 #ifdef DEBUG
153         PRINTF("interrupt_init: done. (msr = %08x)\n", get_msr());
154 #endif
155
156 }
157
158 /****************************************************************************/
159
160 /*
161  * Handle external interrupts
162  */
163 void
164 external_interrupt(struct pt_regs *regs)
165 {
166     extern int i8259_irq(void);
167
168         int irq, unmask = 1;
169
170         irq = i8259_irq(); /*i8259_get_irq(regs); */
171 /*      printf("irq = %d, handler at %p ack=%d\n", irq, irq_handlers[irq].handler, *(volatile unsigned char *)0xFEF00000); */
172         i8259_mask_and_ack(irq);
173
174         if (irq_handlers[irq].handler != NULL)
175                 (*irq_handlers[irq].handler)(irq_handlers[irq].arg);
176         else {
177                 PRINTF ("\nBogus External Interrupt IRQ %d\n", irq);
178                 /*
179                 * turn off the bogus interrupt, otherwise it
180                 * might repeat forever
181                 */
182                 unmask = 0;
183         }
184
185         if (unmask) i8259_unmask_irq(irq);
186 }
187
188 volatile ulong timestamp = 0;
189
190 /*
191  * timer_interrupt - gets called when the decrementer overflows,
192  * with interrupts disabled.
193  * Trivial implementation - no need to be really accurate.
194  */
195 void
196 timer_interrupt(struct pt_regs *regs)
197 {
198         set_dec(decrementer_count);
199         timestamp++;
200 }
201
202 /****************************************************************************/
203
204 void
205 reset_timer(void)
206 {
207         timestamp = 0;
208 }
209
210 ulong
211 get_timer(ulong base)
212 {
213         return (timestamp - base);
214 }
215
216 void
217 set_timer(ulong t)
218 {
219         timestamp = t;
220 }
221
222 /****************************************************************************/
223
224 /*
225  * Install and free a interrupt handler.
226  */
227
228 void
229 irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
230 {
231         if (irq < 0 || irq >= NR_IRQS) {
232                 PRINTF("irq_install_handler: bad irq number %d\n", irq);
233                 return;
234         }
235
236         if (irq_handlers[irq].handler != NULL)
237                 PRINTF("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
238                        (ulong)handler, (ulong)irq_handlers[irq].handler);
239
240         irq_handlers[irq].handler = handler;
241         irq_handlers[irq].arg     = arg;
242
243         i8259_unmask_irq(irq);
244 }
245
246 void
247 irq_free_handler(int irq)
248 {
249         if (irq < 0 || irq >= NR_IRQS) {
250                 PRINTF("irq_free_handler: bad irq number %d\n", irq);
251                 return;
252         }
253
254         i8259_mask_irq(irq);
255
256         irq_handlers[irq].handler = NULL;
257         irq_handlers[irq].arg     = NULL;
258 }
259
260 /****************************************************************************/
261
262 void
263 do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
264 {
265         puts("IRQ related functions are unimplemented currently.\n");
266 }