]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/AmigaOneG3SE/interrupts.c
rename CFG_ macros to CONFIG_SYS
[people/ms/u-boot.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 }