]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/mips/upd985xx/v2_0/include/var_intr.h
Initial revision
[karo-tx-redboot.git] / packages / hal / mips / upd985xx / v2_0 / include / var_intr.h
1 #ifndef CYGONCE_HAL_VAR_INTR_H
2 #define CYGONCE_HAL_VAR_INTR_H
3 //==========================================================================
4 //
5 //      var_intr.h
6 //
7 //      VR4300 Interrupt and clock support
8 //
9 //==========================================================================
10 //####ECOSGPLCOPYRIGHTBEGIN####
11 // -------------------------------------------
12 // This file is part of eCos, the Embedded Configurable Operating System.
13 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14 //
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
18 //
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22 // for more details.
23 //
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 //
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
34 //
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
37 //
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
44 //
45 // Author(s):    hmt, nickg
46 // Contributors: nickg, jskov,
47 //               gthomas, jlarmour
48 // Date:         2001-05-24
49 // Purpose:      uPD985xx Interrupt support
50 // Description:  The macros defined here provide the HAL APIs for handling
51 //               interrupts and the clock for variants of the NEC uPD985xx
52 //               architecture.
53 //              
54 // Usage:
55 //              #include <cyg/hal/var_intr.h>
56 //              ...
57 //              
58 //
59 //####DESCRIPTIONEND####
60 //
61 //==========================================================================
62
63 #include <cyg/hal/var_arch.h>
64 #include <cyg/hal/plf_intr.h>
65
66 //--------------------------------------------------------------------------
67 // Interrupt controller stuff.
68
69 #ifndef CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED
70 // Interrupts dealt with via the status and cause registers
71 // must be numbered in bit order:
72 #define CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW  (0)
73 // The first two are the "software interrupts" - you just set a bit.
74 #define CYGNUM_HAL_INTERRUPT_SOFT_ZERO         (0)
75 #define CYGNUM_HAL_INTERRUPT_SOFT_ONE          (1)
76 #define CYGNUM_HAL_INTERRUPT_FREE_TWO          (2)
77 #define CYGNUM_HAL_INTERRUPT_USB               (3)
78 #define CYGNUM_HAL_INTERRUPT_ETHER             (4)
79 #define CYGNUM_HAL_INTERRUPT_FREE_FIVE         (5)
80 #define CYGNUM_HAL_INTERRUPT_SYSCTL            (6)
81 #define CYGNUM_HAL_INTERRUPT_COMPARE           (7)
82
83 // Number 6 "SYSCTL" is all external sources in the system controller and
84 // will normally be decoded into one of 8-12 instead.  If you use number 6
85 // directly, then this will disable *all* system controller sources.
86 // Startup code will ensure number 6 is unmasked by default, and it will
87 // have an arbitration routine installed to call all of the subsequent
88 // interrupts from the S_ISR register.  This has to be an external routine
89 // because the S_ISR register is read-clear, and the interrupt sources are
90 // edge-triggered so they do not re-assert themselves - so we must address
91 // multiple sources per actual interrupt, in a loop.
92
93 #define CYGNUM_HAL_INTERRUPT_SYSCTL_LOW        (8)
94 #define CYGNUM_HAL_INTERRUPT_SYSCTL_HI        (12)
95
96 #define CYGNUM_HAL_INTERRUPT_TM0               (8) // TIMER CH0 interrupt.
97 #define CYGNUM_HAL_INTERRUPT_TM1               (9) // TIMER CH1 interrupt.
98 #define CYGNUM_HAL_INTERRUPT_UART             (10) // UART interrupt.
99 #define CYGNUM_HAL_INTERRUPT_EXT              (11) // External Interrupt.
100 #define CYGNUM_HAL_INTERRUPT_WU               (12) // Wakeup Interrupt.
101
102 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART
103
104 // Min/Max ISR numbers and how many there are
105 #define CYGNUM_HAL_ISR_MIN                     0
106 #define CYGNUM_HAL_ISR_MAX                     12
107 #define CYGNUM_HAL_ISR_COUNT                   13
108
109 // The vector used by the Real time clock. The default here is to use
110 // interrupt 5, which is connected to the counter/comparator registers
111 // in many MIPS variants.
112
113 #ifndef CYGNUM_HAL_INTERRUPT_RTC
114 #define CYGNUM_HAL_INTERRUPT_RTC            CYGNUM_HAL_INTERRUPT_COMPARE
115 #endif
116
117 #define CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED
118
119 #endif // CYGHWR_HAL_INTERRUPT_VECTORS_DEFINED
120
121 #ifndef __ASSEMBLER__
122
123 // ------------------------------------------------------------------------
124
125 // This is placed in memory at a fixed location because we must share it
126 // with RedBoot, along with the VSR table and Virtual Vector table.
127 // It has to be an array to get the correct code generation to access it
128 // over all that distance.
129 externC volatile cyg_uint32 hal_interrupt_sr_mask_shadow_base[];
130 #define hal_interrupt_sr_mask_shadow (hal_interrupt_sr_mask_shadow_base[0])
131
132 // We have to have local versions of these to preserve the mask bits in the
133 // SR correctly when an interrupt occurs within one of these code sequences
134 // which are doing a read-modify-write to the main interrupt bit of the SR.
135
136 // Disable, it doesn't matter what the SR IM bits are - but it is possible
137 // for control to return with interrupts enabled if a context switch occurs
138 // away from the thread that disabled interrupts.  Therefore we also make
139 // sure the contents of the SR match the shadow variable at the end.
140
141 #define HAL_DISABLE_INTERRUPTS(_old_)                                   \
142 CYG_MACRO_START                                                         \
143     register int _tmp;                                                  \
144     asm volatile (                                                      \
145         "mfc0   $8,$12; nop;"                                           \
146         "move   %0,$8;"                                                 \
147         "and    $8,$8,0xfffffffe;"                                      \
148         "mtc0   $8,$12;"                                                \
149         "nop; nop; nop;"                                                \
150         : "=r"(_tmp)                                                    \
151         :                                                               \
152         : "$8"                                                          \
153         );                                                              \
154     /* interrupts disabled so can now inject the correct IM bits */     \
155     (_old_) = _tmp & 1;                                                 \
156     _tmp &= 0xffff00fe;                                                 \
157     _tmp |= (hal_interrupt_sr_mask_shadow & 0xff00);                    \
158     asm volatile (                                                      \
159         "mtc0   %0,$12;"                                                \
160         "nop; nop; nop;"                                                \
161         :                                                               \
162         : "r"(_tmp)                                                     \
163         );                                                              \
164 CYG_MACRO_END
165
166 // Enable and restore, we must pick up hal_interrupt_sr_mask_shadow because
167 // it contains the truth.  This is also for the convenience of the
168 // mask/unmask macros below.
169 #define HAL_ENABLE_INTERRUPTS() HAL_RESTORE_INTERRUPTS(1)
170
171 #define HAL_RESTORE_INTERRUPTS(_old_)                                   \
172 CYG_MACRO_START                                                         \
173     asm volatile (                                                      \
174         "mfc0   $8,$12; nop;"                                           \
175         "or     $8,$8,%0;"         /* inject IE bit  */                 \
176         "and    $8,$8,0xffff00ff;" /* clear IM bits  */                 \
177         "or     $8,$8,%1;"         /* insert true IM */                 \
178         "mtc0   $8,$12;"                                                \
179         "nop; nop; nop;"                                                \
180         :                                                               \
181         : "r"((_old_) & 1),"r"(hal_interrupt_sr_mask_shadow & 0xff00)   \
182         : "$8"                                                          \
183         );                                                              \
184 CYG_MACRO_END
185
186 #define HAL_QUERY_INTERRUPTS( _state_ )         \
187 CYG_MACRO_START                                 \
188     asm volatile (                              \
189         "mfc0   %0,$12; nop;"                   \
190         "and    %0,%0,0x1;"                     \
191         : "=r"(_state_)                         \
192         );                                      \
193 CYG_MACRO_END
194
195 #define CYGHWR_HAL_INTERRUPT_ENABLE_DISABLE_RESTORE_DEFINED
196
197 // ------------------------------------------------------------------------
198
199 // For the bits which are in the SR, we only need to diddle the shadow
200 // variable; restore interrupts will pick that up at the end of the macro.
201 // Neat, huh.
202
203 #ifndef CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2
204 // Vanilla versions here: trick versions with the workaround follow:
205
206 #define HAL_INTERRUPT_MASK( _vector_ )                                  \
207 CYG_MACRO_START                                                         \
208 register int _intstate;                                                 \
209 register int _shift;                                                    \
210 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
211 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) {                   \
212     /* mask starts at bit 8 */                                          \
213     _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW;    \
214     hal_interrupt_sr_mask_shadow &=~(1 << _shift);                      \
215 }                                                                       \
216 else {                                                                  \
217     _shift = (_vector_) - CYGNUM_HAL_INTERRUPT_SYSCTL_LOW;              \
218     *S_IMR &=~(1 << _shift);                                            \
219 }                                                                       \
220 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
221 CYG_MACRO_END
222
223
224 #define HAL_INTERRUPT_UNMASK( _vector_ )                                \
225 CYG_MACRO_START                                                         \
226 register int _intstate;                                                 \
227 register int _shift;                                                    \
228 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
229 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) {                   \
230     /* mask starts at bit 8 */                                          \
231     _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW;    \
232     hal_interrupt_sr_mask_shadow |= (1 << _shift);                      \
233 }                                                                       \
234 else {                                                                  \
235     _shift = (_vector_) - CYGNUM_HAL_INTERRUPT_SYSCTL_LOW;              \
236     *S_IMR |= (1 << _shift);                                            \
237 }                                                                       \
238 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
239 CYG_MACRO_END
240
241
242 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )                           \
243 CYG_MACRO_START                                                         \
244 register int _intstate;                                                          \
245 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
246 /* Default clears the bit in the cause register.  But VR4120 doc   */   \
247 /* says this is a NOP so we ignore low numbered sources except the */   \
248 /* software interrupt bits.                                        */   \
249 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW <= (_vector_) ||                   \
250      CYGNUM_HAL_INTERRUPT_SYSCTL     == (_vector_) ) {                  \
251     register int i;                                                     \
252     i = *S_ISR; /* This is read-clear! */                               \
253 }                                                                       \
254 else if ( CYGNUM_HAL_INTERRUPT_SOFT_ZERO ==  (_vector_) ||              \
255           CYGNUM_HAL_INTERRUPT_SOFT_ONE  ==  (_vector_) ) {             \
256     /* These two are acknowledged by writing the bit to zero in */      \
257     /* the cause register.  NB not the status register!         */      \
258     asm volatile (                                                      \
259         "mfc0   $3,$13\n"                                               \
260         "la     $2,0x00000100\n"                                        \
261         "sllv   $2,$2,%0\n"                                             \
262         "andi   $2,$2,0x0300\n"                                         \
263         "nor    $2,$2,$0\n"                                             \
264         "and    $3,$3,$2\n"                                             \
265         "mtc0   $3,$13\n"                                               \
266         "nop; nop; nop\n"                                               \
267         :                                                               \
268         : "r"((_vector_)-CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW)         \
269         : "$2", "$3"                                                    \
270         );                                                              \
271 }                                                                       \
272 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
273 CYG_MACRO_END
274
275 #else // DEFINED:  CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2
276
277 #ifdef __cplusplus
278 extern "C" {
279 #endif
280 extern void cyg_hal_interrupt_unmask( int vec );
281 extern void cyg_hal_interrupt_mask( int vec );
282 extern void cyg_hal_interrupt_acknowledge( int vec );
283 #ifdef __cplusplus
284 }      /* extern "C" */
285 #endif
286
287 #define HAL_INTERRUPT_MASK( _vector_ )                                  \
288 CYG_MACRO_START                                                         \
289 register int _intstate;                                                 \
290 register int _shift;                                                    \
291 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
292 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) {                   \
293     /* mask starts at bit 8 */                                          \
294     _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW;    \
295     hal_interrupt_sr_mask_shadow &=~(1 << _shift);                      \
296 }                                                                       \
297 else {                                                                  \
298     cyg_hal_interrupt_mask( (_vector_) );                               \
299 }                                                                       \
300 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
301 CYG_MACRO_END
302
303
304 #define HAL_INTERRUPT_UNMASK( _vector_ )                                \
305 CYG_MACRO_START                                                         \
306 register int _intstate;                                                 \
307 register int _shift;                                                    \
308 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
309 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW > (_vector_) ) {                   \
310     /* mask starts at bit 8 */                                          \
311     _shift = 8 + (_vector_) - CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW;    \
312     hal_interrupt_sr_mask_shadow |= (1 << _shift);                      \
313 }                                                                       \
314 else {                                                                  \
315     cyg_hal_interrupt_unmask( (_vector_) );                             \
316 }                                                                       \
317 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
318 CYG_MACRO_END
319
320
321 #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ )                           \
322 CYG_MACRO_START                                                         \
323 register int _intstate;                                                          \
324 HAL_DISABLE_INTERRUPTS( _intstate );                                    \
325 /* Default clears the bit in the cause register.  But VR4120 doc   */   \
326 /* says this is a NOP so we ignore low numbered sources except the */   \
327 /* software interrupt bits.                                        */   \
328 if ( CYGNUM_HAL_INTERRUPT_SYSCTL_LOW <= (_vector_) ||                   \
329      CYGNUM_HAL_INTERRUPT_SYSCTL     == (_vector_) ) {                  \
330     cyg_hal_interrupt_acknowledge( (_vector_) );                        \
331 }                                                                       \
332 else if ( CYGNUM_HAL_INTERRUPT_SOFT_ZERO ==  (_vector_) ||              \
333           CYGNUM_HAL_INTERRUPT_SOFT_ONE  ==  (_vector_) ) {             \
334     /* These two are acknowledged by writing the bit to zero in */      \
335     /* the cause register.  NB not the status register!         */      \
336     asm volatile (                                                      \
337         "mfc0   $3,$13\n"                                               \
338         "la     $2,0x00000100\n"                                        \
339         "sllv   $2,$2,%0\n"                                             \
340         "andi   $2,$2,0x0300\n"                                         \
341         "nor    $2,$2,$0\n"                                             \
342         "and    $3,$3,$2\n"                                             \
343         "mtc0   $3,$13\n"                                               \
344         "nop; nop; nop\n"                                               \
345         :                                                               \
346         : "r"((_vector_)-CYGNUM_HAL_INTERRUPT_STATUS_CAUSE_LOW)         \
347         : "$2", "$3"                                                    \
348         );                                                              \
349 }                                                                       \
350 HAL_RESTORE_INTERRUPTS( _intstate );                                    \
351 CYG_MACRO_END
352
353 #endif // CYGOPT_HAL_MIPS_UPD985XX_HARDWARE_BUGS_S2
354
355 #define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ )
356
357 #define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ )
358
359 #define CYGHWR_HAL_INTERRUPT_CONTROLLER_ACCESS_DEFINED
360
361 //--------------------------------------------------------------------------
362 // Useful for debugging...
363
364 #define HAL_READ_INTR_REGS( _status, _cause )   \
365 {                                               \
366     asm volatile (                              \
367         "mfc0   %0,$12; nop;"                   \
368         : "=r"(_status)                         \
369         );                                      \
370     asm volatile (                              \
371         "mfc0   %0,$13; nop;"                   \
372         : "=r"(_cause)                          \
373         );                                      \
374 }    
375
376 //--------------------------------------------------------------------------
377 #endif // ! __ASSEMBLER__
378
379 #endif // ifndef CYGONCE_HAL_VAR_INTR_H
380 // End of var_intr.h