1 | /* exception.S |
---|
2 | * |
---|
3 | * This file contains a customized MIPS exception handler. |
---|
4 | * It hooks into the exception handler present in the resident |
---|
5 | * PMON debug monitor. |
---|
6 | * |
---|
7 | * Author: Bruce Robinson |
---|
8 | * |
---|
9 | * This code was derived from cpu_asm.S with the following copyright: |
---|
10 | * |
---|
11 | * COPYRIGHT (c) 1996 by Transition Networks Inc. |
---|
12 | * |
---|
13 | * To anyone who acknowledges that this file is provided "AS IS" |
---|
14 | * without any express or implied warranty: |
---|
15 | * permission to use, copy, modify, and distribute this file |
---|
16 | * for any purpose is hereby granted without fee, provided that |
---|
17 | * the above copyright notice and this notice appears in all |
---|
18 | * copies, and that the name of Transition Networks not be used in |
---|
19 | * advertising or publicity pertaining to distribution of the |
---|
20 | * software without specific, written prior permission. |
---|
21 | * Transition Networks makes no representations about the suitability |
---|
22 | * of this software for any purpose. |
---|
23 | * |
---|
24 | * Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s: |
---|
25 | * |
---|
26 | * COPYRIGHT (c) 1989-1999. |
---|
27 | * On-Line Applications Research Corporation (OAR). |
---|
28 | * |
---|
29 | * The license and distribution terms for this file may be |
---|
30 | * found in the file LICENSE in this distribution or at |
---|
31 | * http://www.rtems.com/license/LICENSE. |
---|
32 | * |
---|
33 | * $Id$ |
---|
34 | */ |
---|
35 | /* @(#)exception.S 10/11/04 1.00 */ |
---|
36 | |
---|
37 | #include <rtems/mips/iregdef.h> |
---|
38 | #include <rtems/mips/idtcpu.h> |
---|
39 | #include <usc.h> |
---|
40 | |
---|
41 | |
---|
42 | #define FRAME(name,frm_reg,offset,ret_reg) \ |
---|
43 | .globl name; \ |
---|
44 | .ent name; \ |
---|
45 | name:; \ |
---|
46 | .frame frm_reg,offset,ret_reg |
---|
47 | #define ENDFRAME(name) \ |
---|
48 | .end name |
---|
49 | |
---|
50 | |
---|
51 | #if __mips == 3 |
---|
52 | /* 64 bit register operations */ |
---|
53 | #define NOP nop |
---|
54 | #define ADD dadd |
---|
55 | #define STREG sd |
---|
56 | #define LDREG ld |
---|
57 | #define ADDU addu |
---|
58 | #define ADDIU addiu |
---|
59 | #define STREGC1 sdc1 |
---|
60 | #define LDREGC1 ldc1 |
---|
61 | #define R_SZ 8 |
---|
62 | #define F_SZ 8 |
---|
63 | #define SZ_INT 8 |
---|
64 | #define SZ_INT_POW2 3 |
---|
65 | |
---|
66 | /* XXX if we don't always want 64 bit register ops, then another ifdef */ |
---|
67 | |
---|
68 | #elif __mips == 1 |
---|
69 | /* 32 bit register operations*/ |
---|
70 | #define NOP nop |
---|
71 | #define ADD add |
---|
72 | #define STREG sw |
---|
73 | #define LDREG lw |
---|
74 | #define ADDU add |
---|
75 | #define ADDIU addi |
---|
76 | #define STREGC1 swc1 |
---|
77 | #define LDREGC1 lwc1 |
---|
78 | #define R_SZ 4 |
---|
79 | #define F_SZ 4 |
---|
80 | #define SZ_INT 4 |
---|
81 | #define SZ_INT_POW2 2 |
---|
82 | #else |
---|
83 | #error "mips assembly: what size registers do I deal with?" |
---|
84 | #endif |
---|
85 | |
---|
86 | |
---|
87 | #define ISR_VEC_SIZE 4 |
---|
88 | #define EXCP_STACK_SIZE (NREGS*R_SZ) |
---|
89 | |
---|
90 | |
---|
91 | #ifdef __GNUC__ |
---|
92 | #define EXTERN(x,size) .extern x,size |
---|
93 | #else |
---|
94 | #define EXTERN(x,size) |
---|
95 | #endif |
---|
96 | |
---|
97 | |
---|
98 | EXTERN(_ISR_Nest_level, 4) |
---|
99 | EXTERN(_Thread_Dispatch_disable_level,4) |
---|
100 | EXTERN(_Context_Switch_necessary,1) |
---|
101 | EXTERN(_ISR_Signals_to_thread_executing,1) |
---|
102 | .extern _Thread_Dispatch |
---|
103 | .extern _ISR_Vector_table |
---|
104 | |
---|
105 | /* void __ISR_Handler() |
---|
106 | * |
---|
107 | * This routine provides the RTEMS interrupt management. |
---|
108 | * |
---|
109 | */ |
---|
110 | |
---|
111 | #if 0 |
---|
112 | void _ISR_Handler() |
---|
113 | { |
---|
114 | /* |
---|
115 | * This discussion ignores a lot of the ugly details in a real |
---|
116 | * implementation such as saving enough registers/state to be |
---|
117 | * able to do something real. Keep in mind that the goal is |
---|
118 | * to invoke a user's ISR handler which is written in C and |
---|
119 | * uses a certain set of registers. |
---|
120 | * |
---|
121 | * Also note that the exact order is to a large extent flexible. |
---|
122 | * Hardware will dictate a sequence for a certain subset of |
---|
123 | * _ISR_Handler while requirements for setting |
---|
124 | */ |
---|
125 | |
---|
126 | /* |
---|
127 | * At entry to "common" _ISR_Handler, the vector number must be |
---|
128 | * available. On some CPUs the hardware puts either the vector |
---|
129 | * number or the offset into the vector table for this ISR in a |
---|
130 | * known place. If the hardware does not give us this information, |
---|
131 | * then the assembly portion of RTEMS for this port will contain |
---|
132 | * a set of distinct interrupt entry points which somehow place |
---|
133 | * the vector number in a known place (which is safe if another |
---|
134 | * interrupt nests this one) and branches to _ISR_Handler. |
---|
135 | * |
---|
136 | */ |
---|
137 | #endif |
---|
138 | FRAME(hurricane_ISR_Handler,sp,0,ra) |
---|
139 | .set noreorder |
---|
140 | |
---|
141 | mfc0 k0,C0_CAUSE /* Determine if an interrupt generated this exception */ |
---|
142 | nop |
---|
143 | and k1,k0,CAUSE_EXCMASK |
---|
144 | beq k1,zero,_chk_int /* If so, branch to service here */ |
---|
145 | nop |
---|
146 | 1: la k0,_int_esr_link /* Otherwise, jump to next exception handler in PMON exception chain */ |
---|
147 | lw k0,(k0) |
---|
148 | lw k0,4(k0) |
---|
149 | j k0 |
---|
150 | nop |
---|
151 | _chk_int: |
---|
152 | mfc0 k1,C0_SR |
---|
153 | nop |
---|
154 | and k0,k1 |
---|
155 | and k0,CAUSE_IPMASK |
---|
156 | beq k0,zero,_ISR_Handler_quick_exit /* external interrupt not enabled, ignore */ |
---|
157 | |
---|
158 | nop |
---|
159 | |
---|
160 | /* For debugging interrupts, clear EXL to allow breakpoints */ |
---|
161 | #if 0 |
---|
162 | MFC0 k0, C0_SR |
---|
163 | #if __mips == 3 |
---|
164 | li k1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ |
---|
165 | not k1 |
---|
166 | and k0,k1 |
---|
167 | li k1,SR_IE |
---|
168 | #elif __mips == 1 |
---|
169 | li k1,SR_IEC |
---|
170 | #endif |
---|
171 | or k0, k1 |
---|
172 | mtc0 k0, C0_SR |
---|
173 | NOP |
---|
174 | #endif |
---|
175 | |
---|
176 | |
---|
177 | /* |
---|
178 | * save some or all context on stack |
---|
179 | * may need to save some special interrupt information for exit |
---|
180 | */ |
---|
181 | |
---|
182 | /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */ |
---|
183 | |
---|
184 | /* wastes a lot of stack space for context?? */ |
---|
185 | ADDIU sp,sp,-EXCP_STACK_SIZE |
---|
186 | |
---|
187 | STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */ |
---|
188 | STREG v0, R_V0*R_SZ(sp) |
---|
189 | STREG v1, R_V1*R_SZ(sp) |
---|
190 | STREG a0, R_A0*R_SZ(sp) |
---|
191 | STREG a1, R_A1*R_SZ(sp) |
---|
192 | STREG a2, R_A2*R_SZ(sp) |
---|
193 | STREG a3, R_A3*R_SZ(sp) |
---|
194 | STREG t0, R_T0*R_SZ(sp) |
---|
195 | STREG t1, R_T1*R_SZ(sp) |
---|
196 | STREG t2, R_T2*R_SZ(sp) |
---|
197 | STREG t3, R_T3*R_SZ(sp) |
---|
198 | STREG t4, R_T4*R_SZ(sp) |
---|
199 | STREG t5, R_T5*R_SZ(sp) |
---|
200 | STREG t6, R_T6*R_SZ(sp) |
---|
201 | STREG t7, R_T7*R_SZ(sp) |
---|
202 | mflo t0 |
---|
203 | STREG t8, R_T8*R_SZ(sp) |
---|
204 | STREG t0, R_MDLO*R_SZ(sp) |
---|
205 | STREG t9, R_T9*R_SZ(sp) |
---|
206 | mfhi t0 |
---|
207 | STREG gp, R_GP*R_SZ(sp) |
---|
208 | STREG t0, R_MDHI*R_SZ(sp) |
---|
209 | STREG fp, R_FP*R_SZ(sp) |
---|
210 | |
---|
211 | .set noat |
---|
212 | STREG AT, R_AT*R_SZ(sp) |
---|
213 | .set at |
---|
214 | |
---|
215 | mfc0 t0,C0_SR |
---|
216 | dmfc0 t1,C0_EPC |
---|
217 | STREG t0,R_SR*R_SZ(sp) |
---|
218 | STREG t1,R_EPC*R_SZ(sp) |
---|
219 | |
---|
220 | /* |
---|
221 | * |
---|
222 | * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) |
---|
223 | * if ( _ISR_Nest_level == 0 ) |
---|
224 | * switch to software interrupt stack |
---|
225 | * #endif |
---|
226 | */ |
---|
227 | |
---|
228 | /* |
---|
229 | * _ISR_Nest_level++; |
---|
230 | */ |
---|
231 | lw t0,_ISR_Nest_level |
---|
232 | NOP |
---|
233 | add t0,t0,1 |
---|
234 | sw t0,_ISR_Nest_level |
---|
235 | /* |
---|
236 | * _Thread_Dispatch_disable_level++; |
---|
237 | */ |
---|
238 | lw t1,_Thread_Dispatch_disable_level |
---|
239 | NOP |
---|
240 | add t1,t1,1 |
---|
241 | sw t1,_Thread_Dispatch_disable_level |
---|
242 | |
---|
243 | /* |
---|
244 | * Call the CPU model or BSP specific routine to decode the |
---|
245 | * interrupt source and actually vector to device ISR handlers. |
---|
246 | */ |
---|
247 | move a0,sp |
---|
248 | jal mips_vector_isr_handlers |
---|
249 | NOP |
---|
250 | |
---|
251 | _ISR_Handler_cleanup: |
---|
252 | |
---|
253 | /* |
---|
254 | * --_ISR_Nest_level; |
---|
255 | */ |
---|
256 | lw t2,_ISR_Nest_level |
---|
257 | NOP |
---|
258 | add t2,t2,-1 |
---|
259 | sw t2,_ISR_Nest_level |
---|
260 | /* |
---|
261 | * --_Thread_Dispatch_disable_level; |
---|
262 | */ |
---|
263 | lw t1,_Thread_Dispatch_disable_level |
---|
264 | NOP |
---|
265 | add t1,t1,-1 |
---|
266 | sw t1,_Thread_Dispatch_disable_level |
---|
267 | /* |
---|
268 | * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level ) |
---|
269 | * goto the label "exit interrupt (simple case)" |
---|
270 | */ |
---|
271 | or t0,t2,t1 |
---|
272 | bne t0,zero,_ISR_Handler_exit |
---|
273 | NOP |
---|
274 | |
---|
275 | |
---|
276 | /* |
---|
277 | * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) |
---|
278 | * restore stack |
---|
279 | * #endif |
---|
280 | * |
---|
281 | * if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing ) |
---|
282 | * goto the label "exit interrupt (simple case)" |
---|
283 | */ |
---|
284 | lb t0,_Context_Switch_necessary |
---|
285 | lb t1,_ISR_Signals_to_thread_executing |
---|
286 | NOP |
---|
287 | or t0,t0,t1 |
---|
288 | beq t0,zero,_ISR_Handler_exit |
---|
289 | NOP |
---|
290 | |
---|
291 | /* |
---|
292 | ** Turn on interrupts before entering Thread_Dispatch which |
---|
293 | ** will run for a while, thus allowing new interrupts to |
---|
294 | ** be serviced. Observe the Thread_Dispatch_disable_level interlock |
---|
295 | ** that prevents recursive entry into Thread_Dispatch. |
---|
296 | */ |
---|
297 | |
---|
298 | mfc0 t0, C0_SR |
---|
299 | #if __mips == 3 |
---|
300 | li t1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ |
---|
301 | not t1 |
---|
302 | and t0,t1 |
---|
303 | li t1,SR_IE |
---|
304 | #elif __mips == 1 |
---|
305 | li t1,SR_IEC |
---|
306 | #endif |
---|
307 | or t0, t1 |
---|
308 | mtc0 t0, C0_SR |
---|
309 | NOP |
---|
310 | |
---|
311 | /* save off our stack frame so the context switcher can get to it */ |
---|
312 | la t0,__exceptionStackFrame |
---|
313 | STREG sp,(t0) |
---|
314 | |
---|
315 | jal _Thread_Dispatch |
---|
316 | NOP |
---|
317 | |
---|
318 | /* and make sure its clear in case we didn't dispatch. if we did, its |
---|
319 | ** already cleared */ |
---|
320 | la t0,__exceptionStackFrame |
---|
321 | STREG zero,(t0) |
---|
322 | NOP |
---|
323 | |
---|
324 | /* |
---|
325 | ** turn interrupts back off while we restore context so |
---|
326 | ** a badly timed interrupt won't accidentally mess things up |
---|
327 | */ |
---|
328 | mfc0 t0, C0_SR |
---|
329 | #if __mips == 3 |
---|
330 | li t1,SR_IE /* Clear IE first (recommended) */ |
---|
331 | not t1 |
---|
332 | and t0,t1 |
---|
333 | mtc0 t0, C0_SR |
---|
334 | li t1,SR_EXL | SR_IE /* Set EXL and IE, this puts status register bits back to interrupted state */ |
---|
335 | or t0,t1 |
---|
336 | #elif __mips == 1 |
---|
337 | /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */ |
---|
338 | li t1,SR_IEC | SR_KUP | SR_KUC |
---|
339 | not t1 |
---|
340 | and t0, t1 |
---|
341 | #endif |
---|
342 | |
---|
343 | #if __mips == 1 |
---|
344 | /* disabled 7/29, gregm, this tasks context was saved previously in an interrupt, |
---|
345 | ** so we'll just restore the task's previous interrupt enables. |
---|
346 | |
---|
347 | ** |
---|
348 | ** make sure previous int enable is on because we're returning from an interrupt |
---|
349 | ** which means interrupts have to be enabled |
---|
350 | |
---|
351 | li t1,SR_IEP |
---|
352 | or t0,t1 |
---|
353 | */ |
---|
354 | #endif |
---|
355 | mtc0 t0, C0_SR |
---|
356 | NOP |
---|
357 | |
---|
358 | /* |
---|
359 | * prepare to get out of interrupt |
---|
360 | * return from interrupt (maybe to _ISR_Dispatch) |
---|
361 | * |
---|
362 | * LABEL "exit interrupt (simple case):" |
---|
363 | * prepare to get out of interrupt |
---|
364 | * return from interrupt |
---|
365 | */ |
---|
366 | |
---|
367 | _ISR_Handler_exit: |
---|
368 | |
---|
369 | /* restore interrupt context from stack */ |
---|
370 | LDREG t8, R_MDLO*R_SZ(sp) |
---|
371 | LDREG t0, R_T0*R_SZ(sp) |
---|
372 | mtlo t8 |
---|
373 | LDREG t8, R_MDHI*R_SZ(sp) |
---|
374 | LDREG t1, R_T1*R_SZ(sp) |
---|
375 | mthi t8 |
---|
376 | LDREG t2, R_T2*R_SZ(sp) |
---|
377 | LDREG t3, R_T3*R_SZ(sp) |
---|
378 | LDREG t4, R_T4*R_SZ(sp) |
---|
379 | LDREG t5, R_T5*R_SZ(sp) |
---|
380 | LDREG t6, R_T6*R_SZ(sp) |
---|
381 | LDREG t7, R_T7*R_SZ(sp) |
---|
382 | LDREG t8, R_T8*R_SZ(sp) |
---|
383 | LDREG t9, R_T9*R_SZ(sp) |
---|
384 | LDREG gp, R_GP*R_SZ(sp) |
---|
385 | LDREG fp, R_FP*R_SZ(sp) |
---|
386 | LDREG ra, R_RA*R_SZ(sp) |
---|
387 | LDREG a0, R_A0*R_SZ(sp) |
---|
388 | LDREG a1, R_A1*R_SZ(sp) |
---|
389 | LDREG a2, R_A2*R_SZ(sp) |
---|
390 | LDREG a3, R_A3*R_SZ(sp) |
---|
391 | LDREG v1, R_V1*R_SZ(sp) |
---|
392 | LDREG v0, R_V0*R_SZ(sp) |
---|
393 | |
---|
394 | LDREG k1, R_EPC*R_SZ(sp) |
---|
395 | mtc0 k1,C0_EPC |
---|
396 | |
---|
397 | .set noat |
---|
398 | LDREG AT, R_AT*R_SZ(sp) |
---|
399 | .set at |
---|
400 | |
---|
401 | ADDIU sp,sp,EXCP_STACK_SIZE |
---|
402 | |
---|
403 | _ISR_Handler_quick_exit: |
---|
404 | eret |
---|
405 | nop |
---|
406 | |
---|
407 | |
---|
408 | /* Interrupts from USC320 are serviced here */ |
---|
409 | .global USC_isr |
---|
410 | .extern Clock_isr |
---|
411 | USC_isr: |
---|
412 | /* check if it's a USC320 heartbeat interrupt */ |
---|
413 | la k0,INT_STAT /* read INT_STAT register */ |
---|
414 | lw k0,(k0) |
---|
415 | nop /* reading from external device */ |
---|
416 | sll k0,(31-21) /* test bit 21 (HBI) */ |
---|
417 | |
---|
418 | bgez k0,USC_isr2 /* branch if not a heartbeat interrupt */ |
---|
419 | NOP |
---|
420 | |
---|
421 | /* clear the heartbeat interrupt */ |
---|
422 | la k0,INT_STAT |
---|
423 | li t0,HBI_MASK |
---|
424 | sw t0,(k0) |
---|
425 | /* wait for interrupt to clear */ |
---|
426 | USC_isr1: |
---|
427 | la k0,INT_STAT /* read INT_STAT register */ |
---|
428 | lw k0,(k0) |
---|
429 | nop /* reading from external device */ |
---|
430 | sll k0,(31-21) /* test bit 21 (HBI) */ |
---|
431 | bltz k0,USC_isr1 /* branch if bit set */ |
---|
432 | nop |
---|
433 | j Clock_isr /* Jump to clock isr */ |
---|
434 | nop |
---|
435 | USC_isr2: |
---|
436 | j ra /* no serviceable interrupt, return without doing anything */ |
---|
437 | nop |
---|
438 | |
---|
439 | .set reorder |
---|
440 | |
---|
441 | ENDFRAME(hurricane_ISR_Handler) |
---|
442 | |
---|
443 | |
---|
444 | FRAME(_BRK_Handler,sp,0,ra) |
---|
445 | .set noreorder |
---|
446 | |
---|
447 | la k0,INT_CFG3 /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */ |
---|
448 | lw k1,(k0) |
---|
449 | li k0,~HBI_MASK |
---|
450 | and k1,k1,k0 |
---|
451 | la k0,INT_CFG3 |
---|
452 | sw k1,(k0) |
---|
453 | |
---|
454 | la k0,_brk_esr_link /* Jump to next exception handler in PMON exception chain */ |
---|
455 | lw k0,(k0) |
---|
456 | lw k0,4(k0) |
---|
457 | j k0 |
---|
458 | nop |
---|
459 | |
---|
460 | .set reorder |
---|
461 | ENDFRAME(_BRK_Handler) |
---|
462 | |
---|
463 | |
---|
464 | /************************************************************************** |
---|
465 | ** |
---|
466 | ** init_exc_vecs() - moves the exception code into the addresses |
---|
467 | ** reserved for exception vectors |
---|
468 | ** |
---|
469 | ** UTLB Miss exception vector at address 0x80000000 |
---|
470 | ** |
---|
471 | ** General exception vector at address 0x80000080 |
---|
472 | ** |
---|
473 | ** RESET exception vector is at address 0xbfc00000 |
---|
474 | ** |
---|
475 | ***************************************************************************/ |
---|
476 | |
---|
477 | FRAME(init_exc_vecs,sp,0,ra) |
---|
478 | .set noreorder |
---|
479 | |
---|
480 | .extern mon_onintr |
---|
481 | |
---|
482 | /* Install interrupt handler in PMON exception handling chain */ |
---|
483 | |
---|
484 | addiu sp,sp,-8 |
---|
485 | sw ra,(sp) /* Save ra contents on stack */ |
---|
486 | move a0,zero |
---|
487 | la a1,_int_esr_link |
---|
488 | jal mon_onintr /* Make PMON system call to install interrupt exception handler */ |
---|
489 | nop |
---|
490 | li a0,9 |
---|
491 | la a1,_brk_esr_link |
---|
492 | jal mon_onintr /* Make PMON system call to install break exception handler */ |
---|
493 | nop |
---|
494 | lw ra,(sp) |
---|
495 | addiu sp,sp,8 /* Restore ra contents from stack */ |
---|
496 | j ra |
---|
497 | nop |
---|
498 | |
---|
499 | .set reorder |
---|
500 | ENDFRAME(init_exc_vecs) |
---|
501 | |
---|
502 | |
---|
503 | |
---|
504 | /*************************************************************************** |
---|
505 | ** |
---|
506 | ** The following code was added to support boards using V3 USC320 |
---|
507 | ** system controller chip. |
---|
508 | ** |
---|
509 | ****************************************************************************/ |
---|
510 | |
---|
511 | /************************************************************* |
---|
512 | * init_hbt() |
---|
513 | * Initialize the heartbeat timer |
---|
514 | */ |
---|
515 | FRAME(init_hbt,sp,0,ra) |
---|
516 | .set noreorder |
---|
517 | la t0,SYSTEM # Unlock USC registers |
---|
518 | li t1,0xA5 |
---|
519 | sb t1,(t0) |
---|
520 | |
---|
521 | la t0,WD_HBI # Initialize heatbeat and watchdog timers |
---|
522 | |
---|
523 | # (1 / 64 MHz) * 4000 * (63 + 1) = 4000.0 microseconds |
---|
524 | # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) |
---|
525 | # Watchdog period = 4000 * 5 = 20000 microseconds |
---|
526 | li t1,(WD_EN | HBI_4000_PS | 0x00003F00 | 0x5) |
---|
527 | |
---|
528 | # (1 / 64 MHz) * 4000 * (15 + 1) = 1000.0 microseconds |
---|
529 | # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) |
---|
530 | # Watchdog period = 1000 * 20 = 20000 microseconds |
---|
531 | li t1,(WD_EN | HBI_4000_PS | 0x00000F00 | 0x14) |
---|
532 | |
---|
533 | # (1 / 64 MHz) * 40000 * (15 + 1) = 10000.0 microseconds |
---|
534 | # Watchdog period is heartbeat period times watchdog timer constant (bits 7 - 0) |
---|
535 | # Watchdog period = 10000 * 20 = 200000 microseconds |
---|
536 | li t1,(WD_EN | HBI_4000_PS | 0x00009600 | 0x14) |
---|
537 | |
---|
538 | sw t1,(t0) |
---|
539 | |
---|
540 | la t0,SYSTEM # Lock USC registers |
---|
541 | li t1,0x60 |
---|
542 | sb t1,(t0) |
---|
543 | |
---|
544 | .set reorder |
---|
545 | j ra |
---|
546 | nop |
---|
547 | .set reorder |
---|
548 | ENDFRAME(init_hbt) |
---|
549 | |
---|
550 | /************************************************************* |
---|
551 | * reset_wdt() |
---|
552 | * Reset the watchdog timer |
---|
553 | */ |
---|
554 | FRAME(reset_wdt,sp,0,ra) |
---|
555 | .set noreorder |
---|
556 | |
---|
557 | la t0,WD_HBI+2 # Load address watchdog timer reset byte |
---|
558 | li t1,WD_INIT |
---|
559 | sb t1,(t0) |
---|
560 | |
---|
561 | .set reorder |
---|
562 | j ra |
---|
563 | nop |
---|
564 | .set reorder |
---|
565 | ENDFRAME(reset_wdt) |
---|
566 | |
---|
567 | /************************************************************* |
---|
568 | * disable_wdt() |
---|
569 | * Disable watchdog timer |
---|
570 | */ |
---|
571 | FRAME(disable_wdt,sp,0,ra) |
---|
572 | .set noreorder |
---|
573 | la t0,WD_HBI # Clear watchdog enable bit in control register |
---|
574 | lw t1,(t0) |
---|
575 | li t2,~WD_EN |
---|
576 | and t1,t1,t2 |
---|
577 | sw t1,(t0) |
---|
578 | |
---|
579 | .set reorder |
---|
580 | j ra |
---|
581 | nop |
---|
582 | .set reorder |
---|
583 | ENDFRAME(disable_wdt) |
---|
584 | |
---|
585 | /************************************************************* |
---|
586 | * enable_hbi(ints) |
---|
587 | * Enable the heartbeat interrupt |
---|
588 | */ |
---|
589 | FRAME(enable_hbi,sp,0,ra) |
---|
590 | .set noreorder |
---|
591 | |
---|
592 | la t0,INT_CFG3 # Enable heartbeat interrupt in USC320 |
---|
593 | lw t1,(t0) |
---|
594 | li t2,(HBI_MASK | MODE_TOTEM_POLE) |
---|
595 | or t1,t1,t2 |
---|
596 | sw t1,(t0) |
---|
597 | |
---|
598 | .set reorder |
---|
599 | j ra |
---|
600 | nop |
---|
601 | .set reorder |
---|
602 | ENDFRAME(enable_hbi) |
---|
603 | |
---|
604 | /************************************************************* |
---|
605 | * disable_hbi(ints) |
---|
606 | * Disable the heartbeat interrupt |
---|
607 | */ |
---|
608 | FRAME(disable_hbi,sp,0,ra) |
---|
609 | .set noreorder |
---|
610 | la t0,INT_CFG3 # Disable heartbeat interrupt in USC320 |
---|
611 | lw t1,(t0) |
---|
612 | li t2,~HBI_MASK |
---|
613 | and t1,t1,t2 |
---|
614 | sw t1,(t0) |
---|
615 | |
---|
616 | .set reorder |
---|
617 | j ra |
---|
618 | nop |
---|
619 | .set reorder |
---|
620 | ENDFRAME(disable_hbi) |
---|
621 | |
---|
622 | |
---|
623 | /************************************************************* |
---|
624 | * enable_wdi() |
---|
625 | * Enable the watchdog interrupt |
---|
626 | */ |
---|
627 | FRAME(enable_wdi,sp,0,ra) |
---|
628 | .set noreorder |
---|
629 | |
---|
630 | la t0,INT_CFG1 # Enable watchdog interrupt in USC320 |
---|
631 | lw t1,(t0) |
---|
632 | li t2,(WDI_MASK | MODE_TOTEM_POLE) |
---|
633 | or t1,t1,t2 |
---|
634 | sw t1,(t0) |
---|
635 | |
---|
636 | .set reorder |
---|
637 | j ra |
---|
638 | nop |
---|
639 | .set reorder |
---|
640 | ENDFRAME(enable_wdi) |
---|
641 | |
---|
642 | /************************************************************* |
---|
643 | * disable_wdi(ints) |
---|
644 | * Disable the watchdog interrupt |
---|
645 | */ |
---|
646 | FRAME(disable_wdi,sp,0,ra) |
---|
647 | .set noreorder |
---|
648 | |
---|
649 | la t0,INT_CFG1 # Disable watchdog interrupt in USC320 |
---|
650 | lw t1,(t0) |
---|
651 | li t2,~(WDI_MASK | MODE_TOTEM_POLE) |
---|
652 | and t1,t1,t2 |
---|
653 | sw t1,(t0) |
---|
654 | |
---|
655 | la t0,INT_STAT # Clear watchdog interrupt status bit |
---|
656 | li t1,WDI_MASK |
---|
657 | sw t1,(t0) |
---|
658 | |
---|
659 | .set reorder |
---|
660 | j ra |
---|
661 | nop |
---|
662 | .set reorder |
---|
663 | ENDFRAME(disable_wdi) |
---|
664 | |
---|
665 | |
---|
666 | .data |
---|
667 | |
---|
668 | k1tmp: .word 0 /* Temporary strage for K1 during interrupt service */ |
---|
669 | |
---|
670 | /************************************************************* |
---|
671 | * |
---|
672 | * Exception handler links, used in PMON exception handler chains |
---|
673 | */ |
---|
674 | /* Interrupt exception service routine link */ |
---|
675 | .global _int_esr_link |
---|
676 | _int_esr_link: |
---|
677 | .word 0 |
---|
678 | .word hurricane_ISR_Handler |
---|
679 | |
---|
680 | /* Break exception service routine link */ |
---|
681 | .global _brk_esr_link |
---|
682 | _brk_esr_link: |
---|
683 | .word 0 |
---|
684 | .word _BRK_Handler |
---|
685 | |
---|
686 | |
---|
687 | |
---|
688 | |
---|