OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [powerpc/] [ppc40x/] [current/] [src/] [var_intr.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      var_intr.c
4
//
5
//      PowerPC variant interrupt handlers
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    jskov
43
// Contributors: jskov, gthomas
44
// Date:         2000-02-11
45
// Purpose:      PowerPC variant interrupt handlers
46
// Description:  This file contains code to handle interrupt related issues
47
//               on the PowerPC variant.
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/hal.h>
54
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
55
#include <cyg/hal/ppc_regs.h>
56
#include <cyg/hal/hal_intr.h>
57
#include <cyg/infra/cyg_type.h>
58
 
59
extern void hal_platform_IRQ_init(void);
60
 
61
//
62
// Sadly, the IBM PPC40x family of devices are only related by number
63
// and not always by functionality.  In particular, the 403 has a
64
// completely different interrupt controller than the 405.  For now
65
// at least, these differences are controlled by CDL within this file.
66
//
67
 
68
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_403)
69
 
70
static cyg_uint32 exier_mask[] = {
71
    0x00000000, // Unused
72
    0x00000000, // Unused
73
    0x80000000, // CYGNUM_HAL_INTERRUPT_CRITICAL         2
74
    0x08000000, // CYGNUM_HAL_INTERRUPT_SERIAL_RCV       3
75
    0x04000000, // CYGNUM_HAL_INTERRUPT_SERIAL_XMT       4
76
    0x02000000, // CYGNUM_HAL_INTERRUPT_JTAG_RCV         5
77
    0x01000000, // CYGNUM_HAL_INTERRUPT_JTAG_XMT         6
78
    0x00800000, // CYGNUM_HAL_INTERRUPT_DMA0             7
79
    0x00400000, // CYGNUM_HAL_INTERRUPT_DMA1             8
80
    0x00200000, // CYGNUM_HAL_INTERRUPT_DMA2             9
81
    0x00100000, // CYGNUM_HAL_INTERRUPT_DMA3            10
82
    0x00000010, // CYGNUM_HAL_INTERRUPT_EXT0            11
83
    0x00000008, // CYGNUM_HAL_INTERRUPT_EXT1            12
84
    0x00000004, // CYGNUM_HAL_INTERRUPT_EXT2            13
85
    0x00000002, // CYGNUM_HAL_INTERRUPT_EXT3            14
86
    0x00000001, // CYGNUM_HAL_INTERRUPT_EXT4            15
87
};
88
 
89
// This table inverts bit number to signal number
90
cyg_uint32 EXISR_TAB[] = {
91
    CYGNUM_HAL_INTERRUPT_CRITICAL,     // 0x80000000
92
    0x00000000,                        // 0x40000000
93
    0x00000000,                        // 0x20000000
94
    0x00000000,                        // 0x10000000
95
    CYGNUM_HAL_INTERRUPT_SERIAL_RCV,   // 0x08000000
96
    CYGNUM_HAL_INTERRUPT_SERIAL_XMT,   // 0x04000000
97
    CYGNUM_HAL_INTERRUPT_JTAG_RCV,     // 0x02000000
98
    CYGNUM_HAL_INTERRUPT_JTAG_XMT,     // 0x01000000
99
    CYGNUM_HAL_INTERRUPT_DMA0,         // 0x00800000
100
    CYGNUM_HAL_INTERRUPT_DMA1,         // 0x00400000
101
    CYGNUM_HAL_INTERRUPT_DMA2,         // 0x00200000
102
    CYGNUM_HAL_INTERRUPT_DMA3,         // 0x00100000
103
    0x00000000,                        // 0x00080000
104
    0x00000000,                        // 0x00040000
105
    0x00000000,                        // 0x00020000
106
    0x00000000,                        // 0x00010000
107
    0x00000000,                        // 0x00008000
108
    0x00000000,                        // 0x00004000
109
    0x00000000,                        // 0x00002000
110
    0x00000000,                        // 0x00001000
111
    0x00000000,                        // 0x00000800
112
    0x00000000,                        // 0x00000400
113
    0x00000000,                        // 0x00000200
114
    0x00000000,                        // 0x00000100
115
    0x00000000,                        // 0x00000080
116
    0x00000000,                        // 0x00000040
117
    0x00000000,                        // 0x00000020
118
    CYGNUM_HAL_INTERRUPT_EXT0,         // 0x00000010
119
    CYGNUM_HAL_INTERRUPT_EXT1,         // 0x00000008
120
    CYGNUM_HAL_INTERRUPT_EXT2,         // 0x00000004
121
    CYGNUM_HAL_INTERRUPT_EXT3,         // 0x00000002
122
    CYGNUM_HAL_INTERRUPT_EXT4          // 0x00000001
123
};
124
 
125
cyg_uint32 _hold_tcr = 0;  // Shadow of hardware register
126
 
127
externC void
128
hal_variant_IRQ_init(void)
129
{
130
    cyg_uint32 iocr;
131
 
132
    // Ensure all interrupts masked (disabled) & cleared
133
    CYGARC_MTDCR(DCR_EXIER, 0);
134
    CYGARC_MTDCR(DCR_EXISR, 0xFFFFFFFF);
135
 
136
    // Configure all external interrupts to be level/low
137
    CYGARC_MFDCR(DCR_IOCR, iocr);
138
    iocr &= ~0xFFC00000;
139
    CYGARC_MTDCR(DCR_IOCR, iocr);
140
 
141
    // Disable timers
142
    CYGARC_MTSPR(SPR_TCR, 0);
143
 
144
    // Let the platform do any overrides
145
    hal_platform_IRQ_init();
146
}
147
 
148
externC void
149
hal_ppc40x_interrupt_mask(int vector)
150
{
151
    cyg_uint32 exier, tcr;
152
 
153
    switch (vector) {
154
    case CYGNUM_HAL_INTERRUPT_CRITICAL:
155
    case CYGNUM_HAL_INTERRUPT_SERIAL_RCV:
156
    case CYGNUM_HAL_INTERRUPT_SERIAL_XMT:
157
    case CYGNUM_HAL_INTERRUPT_JTAG_RCV:
158
    case CYGNUM_HAL_INTERRUPT_JTAG_XMT:
159
    case CYGNUM_HAL_INTERRUPT_DMA0:
160
    case CYGNUM_HAL_INTERRUPT_DMA1:
161
    case CYGNUM_HAL_INTERRUPT_DMA2:
162
    case CYGNUM_HAL_INTERRUPT_DMA3:
163
    case CYGNUM_HAL_INTERRUPT_EXT0:
164
    case CYGNUM_HAL_INTERRUPT_EXT1:
165
    case CYGNUM_HAL_INTERRUPT_EXT2:
166
    case CYGNUM_HAL_INTERRUPT_EXT3:
167
    case CYGNUM_HAL_INTERRUPT_EXT4:
168
        CYGARC_MFDCR(DCR_EXIER, exier);
169
        exier &= ~exier_mask[vector];
170
        CYGARC_MTDCR(DCR_EXIER, exier);
171
        break;
172
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
173
        CYGARC_MFSPR(SPR_TCR, tcr);
174
        tcr = _hold_tcr;
175
        tcr &= ~TCR_PIE;
176
        CYGARC_MTSPR(SPR_TCR, tcr);
177
        _hold_tcr = tcr;
178
        break;
179
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
180
        CYGARC_MFSPR(SPR_TCR, tcr);
181
        tcr = _hold_tcr;
182
        tcr &= ~TCR_FIE;
183
        CYGARC_MTSPR(SPR_TCR, tcr);
184
        _hold_tcr = tcr;
185
        break;
186
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
187
        CYGARC_MFSPR(SPR_TCR, tcr);
188
        tcr = _hold_tcr;
189
        tcr &= ~TCR_WIE;
190
        CYGARC_MTSPR(SPR_TCR, tcr);
191
        _hold_tcr = tcr;
192
        break;
193
    default:
194
        break;
195
    }
196
}
197
 
198
externC void
199
hal_ppc40x_interrupt_unmask(int vector)
200
{
201
    cyg_uint32 exier, tcr;
202
 
203
    switch (vector) {
204
    case CYGNUM_HAL_INTERRUPT_CRITICAL:
205
    case CYGNUM_HAL_INTERRUPT_SERIAL_RCV:
206
    case CYGNUM_HAL_INTERRUPT_SERIAL_XMT:
207
    case CYGNUM_HAL_INTERRUPT_JTAG_RCV:
208
    case CYGNUM_HAL_INTERRUPT_JTAG_XMT:
209
    case CYGNUM_HAL_INTERRUPT_DMA0:
210
    case CYGNUM_HAL_INTERRUPT_DMA1:
211
    case CYGNUM_HAL_INTERRUPT_DMA2:
212
    case CYGNUM_HAL_INTERRUPT_DMA3:
213
    case CYGNUM_HAL_INTERRUPT_EXT0:
214
    case CYGNUM_HAL_INTERRUPT_EXT1:
215
    case CYGNUM_HAL_INTERRUPT_EXT2:
216
    case CYGNUM_HAL_INTERRUPT_EXT3:
217
    case CYGNUM_HAL_INTERRUPT_EXT4:
218
        CYGARC_MFDCR(DCR_EXIER, exier);
219
        exier |= exier_mask[vector];
220
        CYGARC_MTDCR(DCR_EXIER, exier);
221
        break;
222
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
223
        CYGARC_MFSPR(SPR_TCR, tcr);
224
        tcr = _hold_tcr;
225
        tcr |= TCR_PIE;
226
        CYGARC_MTSPR(SPR_TCR, tcr);
227
        _hold_tcr = tcr;
228
        break;
229
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
230
        CYGARC_MFSPR(SPR_TCR, tcr);
231
        tcr = _hold_tcr;
232
        tcr |= TCR_FIE;
233
        CYGARC_MTSPR(SPR_TCR, tcr);
234
        _hold_tcr = tcr;
235
        break;
236
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
237
        CYGARC_MFSPR(SPR_TCR, tcr);
238
        tcr = _hold_tcr;
239
        tcr |= TCR_WIE;
240
        CYGARC_MTSPR(SPR_TCR, tcr);
241
        _hold_tcr = tcr;
242
        break;
243
    default:
244
        break;
245
    }
246
}
247
 
248
externC void
249
hal_ppc40x_interrupt_acknowledge(int vector)
250
{
251
    switch (vector) {
252
    case CYGNUM_HAL_INTERRUPT_EXT0:
253
    case CYGNUM_HAL_INTERRUPT_EXT1:
254
    case CYGNUM_HAL_INTERRUPT_EXT2:
255
    case CYGNUM_HAL_INTERRUPT_EXT3:
256
    case CYGNUM_HAL_INTERRUPT_EXT4:
257
        CYGARC_MTDCR(DCR_EXISR, exier_mask[vector]);
258
        break;
259
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
260
        CYGARC_MTSPR(SPR_TSR, TSR_PIS);  // clear & acknowledge interrupt
261
        break;
262
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
263
        CYGARC_MTSPR(SPR_TSR, TSR_FIS);  // clear & acknowledge interrupt
264
        break;
265
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
266
        CYGARC_MTSPR(SPR_TSR, TSR_WIS);  // clear & acknowledge interrupt
267
        break;
268
    case CYGNUM_HAL_INTERRUPT_CRITICAL:
269
    case CYGNUM_HAL_INTERRUPT_SERIAL_RCV:
270
    case CYGNUM_HAL_INTERRUPT_SERIAL_XMT:
271
    case CYGNUM_HAL_INTERRUPT_JTAG_RCV:
272
    case CYGNUM_HAL_INTERRUPT_JTAG_XMT:
273
    case CYGNUM_HAL_INTERRUPT_DMA0:
274
    case CYGNUM_HAL_INTERRUPT_DMA1:
275
    case CYGNUM_HAL_INTERRUPT_DMA2:
276
    case CYGNUM_HAL_INTERRUPT_DMA3:
277
    default:
278
        break;
279
    }
280
}
281
 
282
// Note: These functions are only [well] defined for "external" interrupts
283
// which can be controlled via the EXIER register.
284
externC void
285
hal_ppc40x_interrupt_configure(int vector, int level, int dir)
286
{
287
    cyg_uint32 mask, new_state, iocr;
288
 
289
    if ((vector >= CYGNUM_HAL_INTERRUPT_EXT0) &&
290
        (vector <= CYGNUM_HAL_INTERRUPT_EXT4)) {
291
        mask = 0x03 << (30 - ((vector - CYGNUM_HAL_INTERRUPT_EXT0)*2));
292
        new_state = (dir & 0x01);  // Up/Down    
293
        if (level == 0) {
294
            // Edge triggered
295
            new_state = 0x02;
296
        }
297
        new_state <<= (30 - ((vector - CYGNUM_HAL_INTERRUPT_EXT0)*2));
298
        CYGARC_MFDCR(DCR_IOCR, iocr);
299
        iocr = (iocr & ~mask) | new_state;
300
        CYGARC_MTDCR(DCR_IOCR, iocr);
301
    }
302
}
303
 
304
externC void
305
hal_ppc40x_interrupt_set_level(int vector, int level)
306
{
307
}
308
#endif // CYGHWR_HAL_POWERPC_PPC4XX_403
309
 
310
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
311
 
312
cyg_uint32 _hold_tcr = 0;  // Shadow of hardware register
313
 
314
externC void
315
hal_variant_IRQ_init(void)
316
{
317
#ifndef HAL_PLF_INTERRUPT_INIT
318
    // Ensure all interrupts masked (disabled) & cleared
319
    CYGARC_MTDCR(DCR_UIC0_ER, 0);
320
    CYGARC_MTDCR(DCR_UIC0_CR, 0);
321
    CYGARC_MTDCR(DCR_UIC0_PR, 0xFFFFE000);
322
    CYGARC_MTDCR(DCR_UIC0_TR, 0);
323
    CYGARC_MTDCR(DCR_UIC0_VCR, 0);  // Makes vector identification easy
324
    CYGARC_MTDCR(DCR_UIC0_SR, 0xFFFFFFFF);
325
#else
326
    HAL_PLF_INTERRUPT_INIT();
327
#endif
328
 
329
    // Disable timers
330
    CYGARC_MTSPR(SPR_TCR, 0);
331
 
332
    // Let the platform do any overrides
333
    hal_platform_IRQ_init();
334
}
335
 
336
externC void
337
hal_ppc40x_interrupt_mask(int vector)
338
{
339
    cyg_uint32 exier, tcr;
340
 
341
    switch (vector) {
342
    case CYGNUM_HAL_INTERRUPT_first...CYGNUM_HAL_INTERRUPT_last:
343
#ifndef HAL_PLF_INTERRUPT_MASK
344
        CYGARC_MFDCR(DCR_UIC0_ER, exier);
345
        exier &= ~(1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE)));
346
        CYGARC_MTDCR(DCR_UIC0_ER, exier);
347
#else
348
        HAL_PLF_INTERRUPT_MASK(vector);
349
#endif
350
        break;
351
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
352
        CYGARC_MFSPR(SPR_TCR, tcr);
353
        tcr = _hold_tcr;
354
        tcr &= ~TCR_PIE;
355
        CYGARC_MTSPR(SPR_TCR, tcr);
356
        _hold_tcr = tcr;
357
        break;
358
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
359
        CYGARC_MFSPR(SPR_TCR, tcr);
360
        tcr = _hold_tcr;
361
        tcr &= ~TCR_FIE;
362
        CYGARC_MTSPR(SPR_TCR, tcr);
363
        _hold_tcr = tcr;
364
        break;
365
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
366
        CYGARC_MFSPR(SPR_TCR, tcr);
367
        tcr = _hold_tcr;
368
        tcr &= ~TCR_WIE;
369
        CYGARC_MTSPR(SPR_TCR, tcr);
370
        _hold_tcr = tcr;
371
        break;
372
    default:
373
        break;
374
    }
375
}
376
 
377
externC void
378
hal_ppc40x_interrupt_unmask(int vector)
379
{
380
    cyg_uint32 exier, tcr;
381
 
382
    switch (vector) {
383
    case CYGNUM_HAL_INTERRUPT_first...CYGNUM_HAL_INTERRUPT_last:
384
#ifndef HAL_PLF_INTERRUPT_UNMASK
385
        CYGARC_MFDCR(DCR_UIC0_ER, exier);
386
        exier |= (1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE)));
387
        CYGARC_MTDCR(DCR_UIC0_ER, exier);
388
#else
389
        HAL_PLF_INTERRUPT_UNMASK(vector);
390
#endif
391
        break;
392
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
393
        CYGARC_MFSPR(SPR_TCR, tcr);
394
        tcr = _hold_tcr;
395
        tcr |= TCR_PIE;
396
        CYGARC_MTSPR(SPR_TCR, tcr);
397
        _hold_tcr = tcr;
398
        break;
399
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
400
        CYGARC_MFSPR(SPR_TCR, tcr);
401
        tcr = _hold_tcr;
402
        tcr |= TCR_FIE;
403
        CYGARC_MTSPR(SPR_TCR, tcr);
404
        _hold_tcr = tcr;
405
        break;
406
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
407
        CYGARC_MFSPR(SPR_TCR, tcr);
408
        tcr = _hold_tcr;
409
        tcr |= TCR_WIE;
410
        CYGARC_MTSPR(SPR_TCR, tcr);
411
        _hold_tcr = tcr;
412
        break;
413
    default:
414
        break;
415
    }
416
}
417
 
418
externC void
419
hal_ppc40x_interrupt_acknowledge(int vector)
420
{
421
    switch (vector) {
422
    case CYGNUM_HAL_INTERRUPT_first...CYGNUM_HAL_INTERRUPT_last:
423
#ifndef HAL_PLF_INTERRUPT_ACKNOWLEDGE
424
        CYGARC_MTDCR(DCR_UIC0_SR, (1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE))));
425
#else
426
        HAL_PLF_INTERRUPT_ACKNOWLEDGE(vector);
427
#endif
428
        break;
429
    case CYGNUM_HAL_INTERRUPT_VAR_TIMER:
430
        CYGARC_MTSPR(SPR_TSR, TSR_PIS);  // clear & acknowledge interrupt
431
        break;
432
    case CYGNUM_HAL_INTERRUPT_FIXED_TIMER:
433
        CYGARC_MTSPR(SPR_TSR, TSR_FIS);  // clear & acknowledge interrupt
434
        break;
435
    case CYGNUM_HAL_INTERRUPT_WATCHDOG_TIMER:
436
        CYGARC_MTSPR(SPR_TSR, TSR_WIS);  // clear & acknowledge interrupt
437
        break;
438
    default:
439
        break;
440
    }
441
}
442
 
443
// Note: These functions are only [well] defined for "external" interrupts
444
externC void
445
hal_ppc40x_interrupt_configure(int vector, int level, int dir)
446
{
447
#ifndef HAL_PLF_INTERRUPT_CONFIGURE
448
    cyg_uint32 mask, new_state, iocr;
449
 
450
    if ((vector >= CYGNUM_HAL_INTERRUPT_IRQ0) &&
451
        (vector <= CYGNUM_HAL_INTERRUPT_IRQ6)) {
452
        mask = (1<<(31-(vector-CYGNUM_HAL_INTERRUPT_405_BASE)));
453
        // Set polarity
454
        if (dir) {
455
            // High true
456
            new_state = mask;
457
        } else {
458
            // Low true
459
            new_state = 0;
460
        }
461
        CYGARC_MFDCR(DCR_UIC0_PR, iocr);
462
        iocr = (iocr & ~mask) | new_state;
463
        CYGARC_MTDCR(DCR_UIC0_PR, iocr);
464
        // Set edge/level
465
        if (level == 0) {
466
            // Edge triggered
467
            new_state = mask;
468
        } else {
469
            // Level triggered
470
            new_state = 0;
471
        }
472
        CYGARC_MFDCR(DCR_UIC0_TR, iocr);
473
        iocr = (iocr & ~mask) | new_state;
474
        CYGARC_MTDCR(DCR_UIC0_TR, iocr);
475
    }
476
#else
477
    HAL_PLF_INTERRUPT_CONFIGURE(vector, level, dir);
478
#endif
479
}
480
 
481
externC void
482
hal_ppc40x_interrupt_set_level(int vector, int level)
483
{
484
#ifndef HAL_PLF_INTERRUPT_SET_LEVEL
485
    // Nothing to do for UIC
486
#else
487
    HAL_PLF_INTERRUPT_SET_LEVEL(vector, level);
488
#endif
489
}
490
#endif // CYGHWR_HAL_POWERPC_PPC4XX_405
491
 
492
// -------------------------------------------------------------------------
493
// EOF var_intr.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.