]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/arm720t/interrupts.c
Initial revision
[karo-tx-uboot.git] / cpu / arm720t / interrupts.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * (C) Copyright 2002
7  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8  * Alex Zuepke <azu@sysgo.de>
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28
29 #include <common.h>
30 #include <clps7111.h>
31
32 #include <asm/proc-armv/ptrace.h>
33
34 extern void reset_cpu(ulong addr);
35
36 /* we always count down the max. */
37 #define TIMER_LOAD_VAL 0xffff
38
39 /* macro to read the 16 bit timer */
40 #define READ_TIMER (IO_TC1D & 0xffff)
41
42 #ifdef CONFIG_USE_IRQ
43 /* enable IRQ/FIQ interrupts */
44 void enable_interrupts (void)
45 {
46         unsigned long temp;
47         __asm__ __volatile__("mrs %0, cpsr\n"
48                              "bic %0, %0, #0x80\n"
49                              "msr cpsr_c, %0"
50                              : "=r" (temp)
51                              :
52                              : "memory");
53 }
54
55
56 /*
57  * disable IRQ/FIQ interrupts
58  * returns true if interrupts had been enabled before we disabled them
59  */
60 int disable_interrupts (void)
61 {
62         unsigned long old,temp;
63         __asm__ __volatile__("mrs %0, cpsr\n"
64                              "orr %1, %0, #0x80\n"
65                              "msr cpsr_c, %1"
66                              : "=r" (old), "=r" (temp)
67                              :
68                              : "memory");
69         return (old & 0x80) == 0;
70 }
71 #else
72 void enable_interrupts (void)
73 {
74         return;
75 }
76 int disable_interrupts (void)
77 {
78         return 0;
79 }
80 #endif
81
82
83
84 void bad_mode (void)
85 {
86         panic ("Resetting CPU ...\n");
87         reset_cpu (0);
88 }
89
90 void show_regs (struct pt_regs *regs)
91 {
92         unsigned long flags;
93         const char *processor_modes[] =
94                         { "USER_26", "FIQ_26", "IRQ_26", "SVC_26", "UK4_26", "UK5_26",
95 "UK6_26", "UK7_26",
96                 "UK8_26", "UK9_26", "UK10_26", "UK11_26", "UK12_26", "UK13_26",
97                                 "UK14_26", "UK15_26",
98                 "USER_32", "FIQ_32", "IRQ_32", "SVC_32", "UK4_32", "UK5_32",
99                                 "UK6_32", "ABT_32",
100                 "UK8_32", "UK9_32", "UK10_32", "UND_32", "UK12_32", "UK13_32",
101                                 "UK14_32", "SYS_32"
102         };
103
104         flags = condition_codes (regs);
105
106         printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
107                         "sp : %08lx  ip : %08lx  fp : %08lx\n",
108                         instruction_pointer (regs),
109                         regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
110         printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
111                         regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
112         printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
113                         regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
114         printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
115                         regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
116         printf ("Flags: %c%c%c%c",
117                         flags & CC_N_BIT ? 'N' : 'n',
118                         flags & CC_Z_BIT ? 'Z' : 'z',
119                         flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
120         printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
121                         interrupts_enabled (regs) ? "on" : "off",
122                         fast_interrupts_enabled (regs) ? "on" : "off",
123                         processor_modes[processor_mode (regs)],
124                         thumb_mode (regs) ? " (T)" : "");
125 }
126
127 void do_undefined_instruction (struct pt_regs *pt_regs)
128 {
129         printf ("undefined instruction\n");
130         show_regs (pt_regs);
131         bad_mode ();
132 }
133
134 void do_software_interrupt (struct pt_regs *pt_regs)
135 {
136         printf ("software interrupt\n");
137         show_regs (pt_regs);
138         bad_mode ();
139 }
140
141 void do_prefetch_abort (struct pt_regs *pt_regs)
142 {
143         printf ("prefetch abort\n");
144         show_regs (pt_regs);
145         bad_mode ();
146 }
147
148 void do_data_abort (struct pt_regs *pt_regs)
149 {
150         printf ("data abort\n");
151         show_regs (pt_regs);
152         bad_mode ();
153 }
154
155 void do_not_used (struct pt_regs *pt_regs)
156 {
157         printf ("not used\n");
158         show_regs (pt_regs);
159         bad_mode ();
160 }
161
162 void do_fiq (struct pt_regs *pt_regs)
163 {
164         printf ("fast interrupt request\n");
165         show_regs (pt_regs);
166         bad_mode ();
167 }
168
169 void do_irq (struct pt_regs *pt_regs)
170 {
171         printf ("interrupt request\n");
172         show_regs (pt_regs);
173         bad_mode ();
174 }
175
176 static ulong timestamp;
177 static ulong lastdec;
178
179 int interrupt_init (void)
180 {
181         /* disable all interrupts */
182         IO_INTMR1 = 0;
183
184         /* operate timer 1 in prescale mode */
185         IO_SYSCON1 |= SYSCON1_TC1M;
186
187         /* select 2kHz clock source for timer 1 */
188         IO_SYSCON1 &= ~SYSCON1_TC1S;
189
190         /* set timer 1 counter */
191         lastdec = IO_TC1D = TIMER_LOAD_VAL;
192         timestamp = 0;
193
194         return (0);
195 }
196
197 /*
198  * timer without interrupts
199  */
200
201 void reset_timer (void)
202 {
203         reset_timer_masked ();
204 }
205
206 ulong get_timer (ulong base)
207 {
208         return get_timer_masked () - base;
209 }
210
211 void set_timer (ulong t)
212 {
213         timestamp = t;
214 }
215
216 void udelay (unsigned long usec)
217 {
218         ulong tmo;
219
220         tmo = usec / 1000;
221         tmo *= CFG_HZ;
222         tmo /= 1000;
223
224         tmo += get_timer (0);
225
226         while (get_timer_masked () < tmo)
227                 /*NOP*/;
228 }
229
230 void reset_timer_masked (void)
231 {
232         /* reset time */
233         lastdec = READ_TIMER;
234         timestamp = 0;
235 }
236
237 ulong get_timer_masked (void)
238 {
239         ulong now = READ_TIMER;
240
241         if (lastdec >= now) {
242                 /* normal mode */
243                 timestamp += lastdec - now;
244         } else {
245                 /* we have an overflow ... */
246                 timestamp += lastdec + TIMER_LOAD_VAL - now;
247         }
248         lastdec = now;
249
250         return timestamp;
251 }
252
253 void udelay_masked (unsigned long usec)
254 {
255         ulong tmo;
256
257         tmo = usec / 1000;
258         tmo *= CFG_HZ;
259         tmo /= 1000;
260
261         reset_timer_masked ();
262
263         while (get_timer_masked () < tmo)
264                 /*NOP*/;
265 }