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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [xscale/] [iop310/] [current/] [src/] [iop310_misc.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      iop310_misc.c
4
//
5
//      HAL misc board support code for XScale IOP310
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 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):    msalter
43
// Contributors: msalter, gthomas
44
// Date:         2000-10-10
45
// Purpose:      HAL board support
46
// Description:  Implementations of HAL board interfaces
47
//
48
//####DESCRIPTIONEND####
49
//
50
//========================================================================*/
51
 
52
#include <pkgconf/hal.h>
53
#include <pkgconf/system.h>
54
#include CYGBLD_HAL_PLATFORM_H
55
#include CYGHWR_MEMORY_LAYOUT_H
56
 
57
#include <cyg/infra/cyg_type.h>         // base types
58
#include <cyg/infra/cyg_trac.h>         // tracing macros
59
#include <cyg/infra/cyg_ass.h>          // assertion macros
60
 
61
#include <cyg/hal/hal_io.h>             // IO macros
62
#include <cyg/hal/hal_stub.h>           // Stub macros
63
#include <cyg/hal/hal_if.h>             // calling interface API
64
#include <cyg/hal/hal_arch.h>           // Register state info
65
#include <cyg/hal/hal_diag.h>
66
#include <cyg/hal/hal_intr.h>           // Interrupt names
67
#include <cyg/hal/hal_cache.h>
68
#include <cyg/hal/hal_iop310.h>         // Hardware definitions
69
#include <cyg/infra/diag.h>             // diag_printf
70
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
71
 
72
static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data);
73
static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data);
74
static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data);
75
static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data);
76
static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data);
77
static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data);
78
static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data);
79
 
80
// Some initialization has already been done before we get here.
81
//
82
// Set up the interrupt environment.
83
// Set up the MMU so that we can use caches.
84
// Enable caches.
85
// - All done!
86
 
87
void hal_hardware_init(void)
88
{
89
    hal_xscale_core_init();
90
 
91
    // Route INTA-INTD to IRQ pin
92
    //   The Yavapai manual is incorrect in that a '1' value
93
    //   routes to the IRQ line, not a '0' value.
94
    *PIRSR_REG = 0x0f;
95
 
96
    // Disable all interrupt sources:
97
    *IIMR_REG = 0x7f;
98
    *OIMR_REG = 0x7f; // don't mask INTD which is really xint3
99
 
100
    // Let the platform do any specific initializations
101
    hal_plf_hardware_init();
102
 
103
    // Mask off all interrupts via xint3
104
    *X3MASK_REG = 0x1F;
105
 
106
    // Let the timer run at a default rate (for delays)
107
    hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
108
 
109
    // Set up eCos/ROM interfaces
110
    hal_if_init();
111
 
112
    // attach some builtin interrupt handlers
113
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NIRQ, &nirq_ISR, CYGNUM_HAL_INTERRUPT_NIRQ, 0);
114
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NIRQ);
115
 
116
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_NFIQ, &nfiq_ISR, CYGNUM_HAL_INTERRUPT_NFIQ, 0);
117
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_NFIQ);
118
 
119
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_MCU_ERR, &nmi_mcu_ISR, CYGNUM_HAL_INTERRUPT_MCU_ERR, 0);
120
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_MCU_ERR);
121
 
122
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PATU_ERR, &nmi_patu_ISR, CYGNUM_HAL_INTERRUPT_PATU_ERR, 0);
123
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PATU_ERR);
124
 
125
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SATU_ERR, &nmi_satu_ISR, CYGNUM_HAL_INTERRUPT_SATU_ERR, 0);
126
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SATU_ERR);
127
 
128
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_PBDG_ERR, &nmi_pb_ISR, CYGNUM_HAL_INTERRUPT_PBDG_ERR, 0);
129
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_PBDG_ERR);
130
 
131
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_SBDG_ERR, &nmi_sb_ISR, CYGNUM_HAL_INTERRUPT_SBDG_ERR, 0);
132
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_SBDG_ERR);
133
 
134
#if 0
135
    // Enable FIQ
136
    {
137
        unsigned rtmp = 0;
138
 
139
        asm volatile ("mrs %0,cpsr\n"
140
                      "bic %0,%0,#0x40\n"
141
                      "msr cpsr,%0\n"
142
                      : "=r"(rtmp) : );
143
    }
144
#endif
145
 
146
    // Enable caches
147
    HAL_DCACHE_ENABLE();
148
    HAL_ICACHE_ENABLE();
149
}
150
 
151
/*------------------------------------------------------------------------*/
152
 
153
//
154
// Memory layout
155
//
156
 
157
externC cyg_uint8 *
158
hal_arm_mem_real_region_top( cyg_uint8 *regionend )
159
{
160
    CYG_ASSERT( hal_dram_size > 0, "Didn't detect DRAM size!" );
161
    CYG_ASSERT( hal_dram_size <=  512<<20,
162
                "More than 512MB reported - that can't be right" );
163
 
164
    // is it the "normal" end of the DRAM region? If so, it should be
165
    // replaced by the real size
166
    if ( regionend ==
167
         ((cyg_uint8 *)CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE) ) {
168
        regionend = (cyg_uint8 *)CYGMEM_REGION_ram + hal_dram_size;
169
    }
170
    return regionend;
171
} // hal_arm_mem_real_region_top()
172
 
173
 
174
// -------------------------------------------------------------------------
175
 
176
// Clock can come from the PMU or from an external timer.
177
// The external timer is the preferred choice.
178
 
179
#if CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL
180
 
181
// Proper version that uses the clock counter in the PMU to do proper
182
// interrupts that require acknowledgement and all that good stuff.
183
 
184
static cyg_uint32 hal_clock_init_period; // The START value, it counts up
185
 
186
void hal_clock_initialize(cyg_uint32 period)
187
{
188
    // event types both zero; clear all 3 interrupts;
189
    // disable all 3 counter interrupts;
190
    // CCNT counts every processor cycle; reset all counters;
191
    // enable PMU.
192
    register cyg_uint32 init = 0x00000707;
193
    asm volatile (
194
        "mcr      p14,0,%0,c0,c0,0;" // write into PMNC
195
        :
196
        : "r"(init)
197
        /*:*/
198
        );
199
    // the CCNT in the PMU counts *up* then interrupts at overflow
200
    // ie. at 0x1_0000_0000 as it were.
201
    // So init to 0xffffffff - period + 1 to get the right answer.
202
    period = (~period) + 1;
203
    hal_clock_init_period = period;
204
    hal_clock_reset( 0, 0 );
205
}
206
 
207
// This routine is called during a clock interrupt.
208
// (before acknowledging the interrupt)
209
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
210
{
211
    asm volatile (
212
        "mrc      p14,0,r0,c1,c0,0;" // read from CCNT - how long since OVFL
213
        "add      %0, %0, r0;"       // synchronize with previous overflow
214
        "mcr      p14,0,%0,c1,c0,0;" // write into CCNT
215
        :
216
        : "r"(hal_clock_init_period)
217
        : "r0"
218
        );
219
}
220
 
221
// Read the current value of the clock, returning the number of hardware
222
// "ticks" that have occurred (i.e. how far away the current value is from
223
// the start)
224
 
225
void hal_clock_read(cyg_uint32 *pvalue)
226
{
227
    register cyg_uint32 now;
228
    asm volatile (
229
        "mrc      p14,0,%0,c1,c0,0;" // read from CCNT
230
        : "=r"(now)
231
        :
232
        /*:*/
233
        );
234
    *pvalue = now - hal_clock_init_period;
235
}
236
 
237
// Delay for some usecs.
238
void hal_delay_us(cyg_uint32 delay)
239
{
240
  int i;
241
  // the loop is going to take 3 ticks.  At 600 MHz, to give uS, multiply
242
  // by 600/3 = 200. No volatile is needed on i; gcc recognizes delay
243
  // loops and does NOT elide them.
244
  for ( i = 200 * delay; i ; i--)
245
    ;
246
}
247
 
248
#else // external timer
249
 
250
static cyg_uint32 _period;
251
 
252
void hal_clock_initialize(cyg_uint32 period)
253
{
254
    _period = period;
255
 
256
    // disable timer
257
    EXT_TIMER_INT_DISAB();
258
    EXT_TIMER_CNT_DISAB();
259
 
260
    *TIMER_LA0_REG_ADDR = period;
261
    *TIMER_LA1_REG_ADDR = period >> 8;
262
    *TIMER_LA2_REG_ADDR = period >> 16;
263
 
264
    EXT_TIMER_INT_ENAB();
265
    EXT_TIMER_CNT_ENAB();
266
}
267
 
268
// Dynamically set the timer interrupt rate.
269
// Not for eCos application use at all, just special GPROF code in RedBoot.
270
 
271
void
272
hal_clock_reinitialize(          int *pfreq,    /* inout */
273
                        unsigned int *pperiod,  /* inout */
274
                        unsigned int old_hz )   /* in */
275
{
276
    unsigned int newp = 0, period, i = 0;
277
    int hz;
278
    int do_set_hw;
279
 
280
// Arbitrary choice somewhat - so the CPU can make
281
// progress with the clock set like this, we hope.
282
#define MIN_TICKS (500)
283
#define MAX_TICKS (0xffffff) // 24-bit timer
284
 
285
    if ( ! pfreq || ! pperiod )
286
        return; // we cannot even report a problem!
287
 
288
    hz = *pfreq;
289
    period = *pperiod;
290
 
291
// Requested HZ:
292
// 0         => tell me the current value (no change, implemented in caller)
293
// - 1       => tell me the slowest (no change)
294
// - 2       => tell me the default (no change, implemented in caller)
295
// -nnn      => tell me what you would choose for nnn (no change)
296
// MIN_INT   => tell me the fastest (no change)
297
//        
298
// 1         => tell me the slowest (sets the clock)
299
// MAX_INT   => tell me the fastest (sets the clock)
300
 
301
    do_set_hw = (hz > 0);
302
    if ( hz < 0 )
303
        hz = -hz;
304
 
305
    // Be paranoid about bad args, and very defensive about underflows
306
    if ( 0 < hz && 0 < period && 0 < old_hz ) {
307
 
308
        newp = period * old_hz / (unsigned)hz;
309
 
310
        if ( newp < MIN_TICKS ) {
311
            newp = MIN_TICKS;
312
            // recalculate to get the exact delay for this integral hz
313
            // and hunt hz down to an acceptable value if necessary
314
            i = period * old_hz / newp;
315
            if ( i ) do {
316
                newp = period * old_hz / i;
317
                i--;
318
            } while (newp < MIN_TICKS && i);
319
        }
320
        else if ( newp > MAX_TICKS ) {
321
            newp = MAX_TICKS;
322
            // recalculate to get the exact delay for this integral hz
323
            // and hunt hz up to an acceptable value if necessary
324
            i = period * old_hz / newp;
325
            if ( i ) do {
326
                newp = period * old_hz / i;
327
                i++;
328
            } while (newp > MAX_TICKS && i);
329
        }
330
 
331
        // Recalculate the actual value installed.
332
        i = period * old_hz / newp;
333
    }
334
 
335
    *pfreq = i;
336
    *pperiod = newp;
337
 
338
    if ( do_set_hw ) {
339
        hal_clock_initialize( newp );
340
    }
341
}
342
 
343
// This routine is called during a clock interrupt.
344
 
345
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
346
{
347
    // to clear the timer interrupt, clear the timer interrupt
348
    // enable, then re-set the int. enable bit
349
    EXT_TIMER_INT_DISAB();
350
    EXT_TIMER_INT_ENAB();
351
}
352
 
353
// Read the current value of the clock, returning the number of hardware
354
// "ticks" that have occurred (i.e. how far away the current value is from
355
// the start)
356
 
357
void hal_clock_read(cyg_uint32 *pvalue)
358
{
359
    cyg_uint8  cnt0, cnt1, cnt2, cnt3;
360
    cyg_uint32 timer_val;;
361
 
362
    // first read latches the count
363
    // Actually, it looks like there is a hardware problem where
364
    // invalid counts get latched. This do while loop appears
365
    // to get around the problem.
366
    do {
367
        cnt0 = *TIMER_LA0_REG_ADDR & TIMER_COUNT_MASK;
368
    } while (cnt0 == 0);
369
    cnt1 = *TIMER_LA1_REG_ADDR & TIMER_COUNT_MASK;
370
    cnt2 = *TIMER_LA2_REG_ADDR & TIMER_COUNT_MASK;
371
    cnt3 = *TIMER_LA3_REG_ADDR & 0xf;   /* only 4 bits in most sig. */
372
 
373
    /* now build up the count value */
374
    timer_val  =  ((cnt0 & 0x40) >> 1) | (cnt0 & 0x1f);
375
    timer_val |= (((cnt1 & 0x40) >> 1) | (cnt1 & 0x1f)) << 6;
376
    timer_val |= (((cnt2 & 0x40) >> 1) | (cnt2 & 0x1f)) << 12;
377
    timer_val |= cnt3 << 18;
378
 
379
    *pvalue = timer_val;
380
}
381
 
382
// Delay for some usecs.
383
void hal_delay_us(cyg_uint32 delay)
384
{
385
#define _CNT_MASK 0x3fffff
386
#define _TICKS_PER_USEC (EXT_TIMER_CLK_FREQ / 1000000)
387
    cyg_uint32 now, last, diff, ticks;
388
 
389
    hal_clock_read(&last);
390
    diff = ticks = 0;
391
 
392
    while (delay > ticks) {
393
        hal_clock_read(&now);
394
 
395
        if (now < last)
396
            diff += ((_period - last) + now);
397
        else
398
            diff += (now - last);
399
 
400
        last = now;
401
 
402
        if (diff >= _TICKS_PER_USEC) {
403
            ticks += (diff / _TICKS_PER_USEC);
404
            diff %= _TICKS_PER_USEC;
405
        }
406
    }
407
}
408
 
409
#endif
410
 
411
// -------------------------------------------------------------------------
412
 
413
typedef cyg_uint32 cyg_ISR(cyg_uint32 vector, CYG_ADDRWORD data);
414
 
415
extern void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );
416
 
417
static inline cyg_uint32
418
hal_call_isr (cyg_uint32 vector)
419
{
420
    cyg_ISR *isr;
421
    CYG_ADDRWORD data;
422
    cyg_uint32 isr_ret;
423
 
424
    isr = (cyg_ISR*) hal_interrupt_handlers[vector];
425
    data = hal_interrupt_data[vector];
426
 
427
    isr_ret = (*isr) (vector, data);
428
 
429
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
430
    if (isr_ret & CYG_ISR_CALL_DSR) {
431
        cyg_interrupt_post_dsr (hal_interrupt_objects[vector]);
432
    }
433
#endif
434
 
435
    return isr_ret & ~CYG_ISR_CALL_DSR;
436
}
437
 
438
void _scrub_ecc(unsigned p)
439
{
440
    asm volatile ("ldrb r4, [%0]\n"
441
                  "strb r4, [%0]\n" : : "r"(p) );
442
}
443
 
444
static cyg_uint32 nmi_mcu_ISR(cyg_vector_t vector, cyg_addrword_t data)
445
{
446
    cyg_uint32 eccr_reg;
447
 
448
    // Read current state of ECC register
449
    eccr_reg = *ECCR_REG;
450
 
451
    // Turn off all ecc error reporting
452
    *ECCR_REG = 0x4;
453
 
454
    // Check for ECC Error 0
455
    if(*MCISR_REG & 0x1) {
456
 
457
#ifdef DEBUG_NMI
458
        diag_printf("ELOG0 = 0x%X\n", *ELOG0_REG);
459
        diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR0_REG);
460
#endif
461
 
462
        // Check for single-bit error
463
        if(!(*ELOG0_REG & 0x00000100)) {
464
            // call ECC restoration function
465
            _scrub_ecc(*ECAR0_REG);
466
 
467
            // Clear the MCISR
468
            *MCISR_REG = 0x1;
469
        } else {
470
#ifdef DEBUG_NMI
471
            diag_printf("Multi-bit or nibble error\n");
472
#endif
473
        }
474
    }
475
 
476
    // Check for ECC Error 1
477
    if(*MCISR_REG & 0x2) {
478
 
479
#ifdef DEBUG_NMI
480
        diag_printf("ELOG0 = 0x%X\n",*ELOG1_REG);
481
        diag_printf("ECC Error Detected at Address 0x%X\n",*ECAR1_REG);
482
#endif
483
 
484
        // Check for single-bit error
485
        if(!(*ELOG1_REG & 0x00000100))  {
486
            // call ECC restoration function
487
            _scrub_ecc(*ECAR1_REG);
488
 
489
            // Clear the MCISR
490
            *MCISR_REG = 0x2;
491
        }
492
        else {
493
#ifdef DEBUG_NMI
494
            diag_printf("Multi-bit or nibble error\n");
495
#endif
496
        }
497
    }
498
 
499
    // Check for ECC Error N
500
    if(*MCISR_REG & 0x4) {
501
        // Clear the MCISR
502
        *MCISR_REG = 0x4;
503
        diag_printf("Uncorrectable error during RMW\n");
504
    }
505
 
506
    // Restore ECCR register
507
    *ECCR_REG = eccr_reg;
508
 
509
    // clear the interrupt condition
510
    *MCISR_REG = *MCISR_REG & 7;
511
 
512
    return CYG_ISR_HANDLED;
513
}
514
 
515
static cyg_uint32 nmi_patu_ISR(cyg_vector_t vector, cyg_addrword_t data)
516
{
517
    cyg_uint32 status;
518
 
519
    status = *PATUISR_REG;
520
 
521
#ifdef DEBUG_NMI
522
    if (status & 0x001) diag_printf ("PPCI Master Parity Error\n");
523
    if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n");
524
    if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n");
525
    if (status & 0x008) diag_printf ("PPCI Master Abort\n");
526
    if (status & 0x010) diag_printf ("Primary P_SERR# Detected\n");
527
    if (status & 0x080) diag_printf ("Internal Bus Master Abort\n");
528
    if (status & 0x100) diag_printf ("PATU BIST Interrupt\n");
529
    if (status & 0x200) diag_printf ("PPCI Parity Error Detected\n");
530
    if (status & 0x400) diag_printf ("Primary P_SERR# Asserted\n");
531
#endif
532
 
533
    *PATUISR_REG = status & 0x79f;
534
    *PATUSR_REG |= 0xf900;
535
 
536
    return CYG_ISR_HANDLED;
537
}
538
 
539
 
540
static cyg_uint32 nmi_satu_ISR(cyg_vector_t vector, cyg_addrword_t data)
541
{
542
    cyg_uint32 status;
543
 
544
    status = *SATUISR_REG;
545
 
546
#ifdef DEBUG_NMI
547
    if (status & 0x001) diag_printf ("SPCI Master Parity Error\n");
548
    if (status & 0x002) diag_printf ("SPCI Target Abort (target)\n");
549
    if (status & 0x004) diag_printf ("SPCI Target Abort (master)\n");
550
    if (status & 0x008) diag_printf ("SPCI Master Abort\n");
551
    if (status & 0x010) diag_printf ("Secondary P_SERR# Detected\n");
552
    if (status & 0x080) diag_printf ("Internal Bus Master Abort\n");
553
    if (status & 0x200) diag_printf ("SPCI Parity Error Detected\n");
554
    if (status & 0x400) diag_printf ("Secondary P_SERR# Asserted\n");
555
#endif
556
 
557
    *SATUISR_REG = status & 0x69f;
558
    *SATUSR_REG |= 0xf900;
559
 
560
    return CYG_ISR_HANDLED;
561
}
562
 
563
static cyg_uint32 nmi_pb_ISR(cyg_vector_t vector, cyg_addrword_t data)
564
{
565
    cyg_uint32 status;
566
 
567
    status = *PBISR_REG;
568
 
569
#ifdef DEBUG_NMI
570
    if (status & 0x001) diag_printf ("PPCI Master Parity Error\n");
571
    if (status & 0x002) diag_printf ("PPCI Target Abort (target)\n");
572
    if (status & 0x004) diag_printf ("PPCI Target Abort (master)\n");
573
    if (status & 0x008) diag_printf ("PPCI Master Abort\n");
574
    if (status & 0x010) diag_printf ("Primary P_SERR# Asserted\n");
575
    if (status & 0x020) diag_printf ("PPCI Parity Error Detected\n");
576
#endif
577
 
578
    *PBISR_REG = status & 0x3f;
579
    *PSR_REG |= 0xf900;
580
 
581
    return CYG_ISR_HANDLED;
582
}
583
 
584
 
585
static cyg_uint32 nmi_sb_ISR(cyg_vector_t vector, cyg_addrword_t data)
586
{
587
    cyg_uint32 status;
588
 
589
    status = *SBISR_REG;
590
 
591
    *SBISR_REG = status & 0x7f;
592
    *SSR_REG |= 0xf900;
593
 
594
    return CYG_ISR_HANDLED;
595
}
596
 
597
 
598
static cyg_uint32 nfiq_ISR(cyg_vector_t vector, cyg_addrword_t data)
599
{
600
    cyg_uint32 sources;
601
    int i, isr_ret;
602
 
603
    // Check NMI
604
    sources = *NISR_REG;
605
    for (i = 0; i < 12; i++) {
606
        if (sources & (1<<i)) {
607
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MCU_ERR + i);
608
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "Interrupt not handled");
609
            return isr_ret;
610
        }
611
    }
612
    return 0;
613
}
614
 
615
static cyg_uint32 nirq_ISR(cyg_vector_t vector, cyg_addrword_t data)
616
{
617
    cyg_uint32 sources;
618
    int i, isr_ret;
619
    cyg_uint32 xint3_isr, xint3_mask;
620
 
621
    // Check XINT3
622
    sources = (xint3_isr = *X3ISR_REG) & ~(xint3_mask = *X3MASK_REG);
623
    for (i = 0; i <= CYGNUM_HAL_INTERRUPT_XINT3_BITS; i++) {
624
        if (sources & (1 << i)) {
625
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_XINT3_BIT0 + i);
626
            if ((isr_ret & CYG_ISR_HANDLED) == 0) {
627
                diag_printf("XINT3 int not handled - ISR: %02x, MASK: %02x\n", xint3_isr, ~xint3_mask);
628
            }
629
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "XINT3 Interrupt not handled");
630
            return isr_ret;
631
        }
632
    }
633
    // What to do about S_INTA-S_INTC?
634
 
635
    // Check XINT6
636
    sources = *X6ISR_REG;
637
    for (i = 0; i < 3; i++) {
638
        // check DMA irqs
639
        if (sources & (1<<i)) {
640
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DMA_0 + i);
641
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "DMA Interrupt not handled");
642
            return isr_ret;
643
        }
644
    }
645
    if (sources & 0x10) {
646
        // performance monitor
647
        _80312_EMISR = *EMISR_REG;
648
        if (_80312_EMISR & 1) {
649
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_GTSC);
650
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "GTSC Interrupt not handled");
651
        }
652
        if (_80312_EMISR & 0x7ffe) {
653
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_PEC);
654
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "PEC Interrupt not handled");
655
        }
656
        return 0;
657
    }
658
    if (sources & 0x20) {
659
        // Application Accelerator Unit
660
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_AAIP);
661
        CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "AAIP Interrupt not handled");
662
        return isr_ret;
663
    }
664
 
665
    // Check XINT7
666
    sources = *X7ISR_REG;
667
    if (sources & 2) {
668
        // I2C Unit
669
        cyg_uint32 i2c_sources = *ISR_REG;
670
 
671
        if (i2c_sources & (1<<7)) {
672
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_RX_FULL);
673
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C RX FULL Interrupt not handled");
674
        }
675
        if (i2c_sources & (1<<6)) {
676
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY);
677
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C TX EMPTY Interrupt not handled");
678
        }
679
        if (i2c_sources & (1<<10)) {
680
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_BUS_ERR);
681
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C BUS ERR Interrupt not handled");
682
        }
683
        if (i2c_sources & (1<<4)) {
684
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_STOP);
685
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C STOP Interrupt not handled");
686
        }
687
        if (i2c_sources & (1<<5)) {
688
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_LOSS);
689
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C LOSS Interrupt not handled");
690
        }
691
        if (i2c_sources & (1<<9)) {
692
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_I2C_ADDRESS);
693
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "I2C ADDRESS Interrupt not handled");
694
        }
695
        return 0;
696
    }
697
    if (sources & 4) {
698
        // Messaging Unit
699
        cyg_uint32 inb_sources = *IISR_REG;
700
 
701
        if (inb_sources & (1<<0)) {
702
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_0);
703
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "MESSAGE 0 Interrupt not handled");
704
        }
705
        if (inb_sources & (1<<1)) {
706
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_MESSAGE_1);
707
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "MESSAGE 1 Interrupt not handled");
708
        }
709
        if (inb_sources & (1<<2)) {
710
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_DOORBELL);
711
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "DOORBELL Interrupt not handled");
712
        }
713
        if (inb_sources & (1<<4)) {
714
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_QUEUE_POST);
715
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "QUEUE POST Interrupt not handled");
716
        }
717
        if (inb_sources & (1<<6)) {
718
            isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_INDEX_REGISTER);
719
            CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "INDEX REGISTER Interrupt not handled");
720
        }
721
        return 0;
722
    }
723
    if (sources & 8) {
724
        // BIST
725
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_BIST);
726
        CYG_ASSERT (isr_ret & CYG_ISR_HANDLED, "BIST Interrupt not handled");
727
    }
728
 
729
    return 0;
730
}
731
 
732
// This routine is called to respond to a hardware interrupt (IRQ).  It
733
// should interrogate the hardware and return the IRQ vector number.
734
int hal_IRQ_handler(void)
735
{
736
    int sources, masks;
737
 
738
    asm volatile ( // read the interrupt source reg INTSRC
739
        "mrc      p13,0,%0,c4,c0,0;"
740
        : "=r"(sources)
741
        :
742
      /*:*/
743
        );
744
    asm volatile ( // read the interrupt control reg INTCTL
745
        "mrc      p13,0,%0,c0,c0,0;"
746
        : "=r"(masks)
747
        :
748
      /*:*/
749
        );
750
    // is a source both unmasked and active?
751
    if ( (0 != (1 & masks)) && (0 != ((8 << 28) & sources)) )
752
        return CYGNUM_HAL_INTERRUPT_NFIQ;
753
    if ( (0 != (2 & masks)) && (0 != ((4 << 28) & sources)) )
754
        return CYGNUM_HAL_INTERRUPT_NIRQ;
755
    if ( (0 != (8 & masks)) && (0 != ((2 << 28) & sources)) )
756
        return CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT;
757
    if ( (0 != (4 & masks)) && (0 != ((1 << 28) & sources)) ) {
758
        // more complicated; it's the PMU.
759
        asm volatile ( // read the PMNC perfmon control reg
760
            "mrc      p14,0,%0,c0,c0,0;"
761
            : "=r"(sources)
762
            :
763
            /*:*/
764
            );
765
        // sources is now the PMNC performance monitor control register
766
        // enable bits are 4..6, status bits are 8..10
767
        sources = (sources >> 4) & (sources >> 8);
768
        if ( 1 & sources )
769
            return CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL;
770
        if ( 2 & sources )
771
            return CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL;
772
        if ( 4 & sources )
773
            return CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL;
774
    }
775
 
776
    return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
777
}
778
 
779
//
780
// Interrupt control
781
//
782
 
783
void hal_interrupt_mask(int vector)
784
{
785
    int mask = 0;
786
    int submask = 0;
787
    switch ( vector ) {
788
    case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL:
789
    case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL:
790
    case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL:
791
        submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2
792
        // select interrupt enable bit and also enable the perfmon per se
793
        submask = (1 << (submask + 4)); // bits 4-6 are masks
794
        asm volatile (
795
            "mrc      p14,0,r1,c0,c0,0;"
796
            "bic      r1, r1, #0x700;" // clear the overflow/interrupt flags
797
            "bic      r1, r1, #0x006;" // clear the reset bits
798
            "bic      %0, r1, %0;"     // preserve r1; better for debugging
799
            "tsts     %0, #0x070;"     // are all 3 sources now off?
800
            "biceq    %0, %0, #1;"     // if so, disable entirely.
801
            "mcr      p14,0,%0,c0,c0,0;"
802
            :
803
            : "r"(submask)
804
            : "r1"
805
            );
806
        mask = 4;
807
        break;
808
    case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT:
809
        // Nothing specific to do here
810
        mask = 8;
811
        break;
812
    case CYGNUM_HAL_INTERRUPT_NIRQ         :
813
        mask = 2;
814
        break;
815
    case CYGNUM_HAL_INTERRUPT_NFIQ         :
816
        mask = 1;
817
        break;
818
    case CYGNUM_HAL_INTERRUPT_GTSC:
819
        *GTMR_REG &= ~1;
820
        return;
821
    case CYGNUM_HAL_INTERRUPT_PEC:
822
        *ESR_REG &= ~(1<<16);
823
        return;
824
    case CYGNUM_HAL_INTERRUPT_AAIP:
825
        *ADCR_REG &= ~1;
826
        return;
827
    case CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY ... CYGNUM_HAL_INTERRUPT_I2C_ADDRESS:
828
        *ICR_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY));
829
        return;
830
    case CYGNUM_HAL_INTERRUPT_MESSAGE_0 ... CYGNUM_HAL_INTERRUPT_INDEX_REGISTER:
831
        *IIMR_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_MESSAGE_0));
832
        return;
833
    case CYGNUM_HAL_INTERRUPT_BIST:
834
        *ATUCR_REG &= ~(1<<3);
835
        return;
836
    case CYGNUM_HAL_INTERRUPT_P_SERR:  // FIQ
837
        *ATUCR_REG &= ~(1<<9);
838
        return;
839
    case CYGNUM_HAL_INTERRUPT_S_SERR:  // FIQ
840
        *ATUCR_REG &= ~(1<<10);
841
        return;
842
    case CYGNUM_HAL_INTERRUPT_XINT3_BIT0 ... CYGNUM_HAL_INTERRUPT_XINT3_BIT4:
843
        *X3MASK_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_XINT3_BIT0));
844
        return;
845
 
846
#ifdef CYGNUM_HAL_INTERRUPT_PCI_S_INTC  
847
    // The hardware doesn't (yet?) provide masking or status for these
848
    // even though they can trigger cpu interrupts. ISRs will need to
849
    // poll the device to see if the device actually triggered the
850
    // interrupt.
851
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTC:
852
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTB:
853
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTA:
854
    default:
855
        /* do nothing */
856
        return;
857
#endif
858
    }
859
    asm volatile (
860
        "mrc      p13,0,r1,c0,c0,0;"
861
        "bic      r1, r1, %0;"
862
        "mcr      p13,0,r1,c0,c0,0;"
863
        :
864
        : "r"(mask)
865
        : "r1"
866
        );
867
}
868
 
869
void hal_interrupt_unmask(int vector)
870
{
871
    int mask = 0;
872
    int submask = 0;
873
    switch ( vector ) {
874
    case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL:
875
    case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL:
876
    case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL:
877
        submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2
878
        // select interrupt enable bit and also enable the perfmon per se
879
        submask = 1 + (1 << (submask + 4)); // bits 4-6 are masks
880
        asm volatile (
881
            "mrc      p14,0,r1,c0,c0,0;"
882
            "bic      r1, r1, #0x700;"   // clear the overflow/interrupt flags
883
            "bic      r1, r1, #0x006;"   // clear the reset bits
884
            "orr      %0, r1, %0;"       // preserve r1; better for debugging
885
            "mcr      p14,0,%0,c0,c0,0;"
886
            "mrc      p13,0,r2,c8,c0,0;" // steer PMU interrupt to IRQ
887
            "and      r2, r2, #2;"       // preserve the other bit (BCU steer)
888
            "mcr      p13,0,r2,c8,c0,0;"
889
            :
890
            : "r"(submask)
891
            : "r1","r2"
892
            );
893
        mask = 4;
894
        break;
895
    case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT:
896
         asm volatile (
897
            "mrc      p13,0,r2,c8,c0,0;" // steer BCU interrupt to IRQ
898
            "and      r2, r2, #1;"       // preserve the other bit (PMU steer)
899
            "mcr      p13,0,r2,c8,c0,0;"
900
            :
901
            :
902
            : "r2"
903
            );
904
        mask = 8;
905
        break;
906
    case CYGNUM_HAL_INTERRUPT_NIRQ         :
907
        mask = 2;
908
        break;
909
    case CYGNUM_HAL_INTERRUPT_NFIQ         :
910
        mask = 1;
911
        break;
912
    case CYGNUM_HAL_INTERRUPT_GTSC:
913
        *GTMR_REG |= 1;
914
        return;
915
    case CYGNUM_HAL_INTERRUPT_PEC:
916
        *ESR_REG |= (1<<16);
917
        return;
918
    case CYGNUM_HAL_INTERRUPT_AAIP:
919
        *ADCR_REG |= 1;
920
        return;
921
    case CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY ... CYGNUM_HAL_INTERRUPT_I2C_ADDRESS:
922
        *ICR_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_I2C_TX_EMPTY));
923
        return;
924
    case CYGNUM_HAL_INTERRUPT_MESSAGE_0 ... CYGNUM_HAL_INTERRUPT_INDEX_REGISTER:
925
        *IIMR_REG |= (1<<(vector - CYGNUM_HAL_INTERRUPT_MESSAGE_0));
926
        return;
927
    case CYGNUM_HAL_INTERRUPT_BIST:
928
        *ATUCR_REG |= (1<<3);
929
        return;
930
    case CYGNUM_HAL_INTERRUPT_P_SERR:  // FIQ
931
        *ATUCR_REG |= (1<<9);
932
        return;
933
    case CYGNUM_HAL_INTERRUPT_S_SERR:  // FIQ
934
        *ATUCR_REG |= (1<<10);
935
        return;
936
    case CYGNUM_HAL_INTERRUPT_XINT3_BIT0 ... CYGNUM_HAL_INTERRUPT_XINT3_BIT4:
937
        *X3MASK_REG &= ~(1<<(vector - CYGNUM_HAL_INTERRUPT_XINT3_BIT0));
938
        return;
939
 
940
#ifdef CYGNUM_HAL_INTERRUPT_PCI_S_INTC  
941
    // The hardware doesn't (yet?) provide masking or status for these
942
    // even though they can trigger cpu interrupts. ISRs will need to
943
    // poll the device to see if the device actually triggered the
944
    // interrupt.
945
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTC:
946
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTB:
947
    case CYGNUM_HAL_INTERRUPT_PCI_S_INTA:
948
    default:
949
        /* do nothing */
950
        return;
951
#endif
952
    }
953
    asm volatile (
954
        "mrc      p13,0,r1,c0,c0,0;"
955
        "orr      %0, r1, %0;"
956
        "mcr      p13,0,%0,c0,c0,0;"
957
        :
958
        : "r"(mask)
959
        : "r1"
960
        );
961
}
962
 
963
void hal_interrupt_acknowledge(int vector)
964
{
965
    int submask = 0;
966
    switch ( vector ) {
967
    case CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL:
968
    case CYGNUM_HAL_INTERRUPT_PMU_PMN1_OVFL:
969
    case CYGNUM_HAL_INTERRUPT_PMU_CCNT_OVFL:
970
        submask = vector - CYGNUM_HAL_INTERRUPT_PMU_PMN0_OVFL; // 0 to 2
971
        // select interrupt enable bit and also enable the perfmon per se
972
        submask = (1 << (submask + 8)); // bits 8-10 are status; write 1 clr
973
        // Careful not to ack other interrupts or zero any counters:
974
        asm volatile (
975
            "mrc      p14,0,r1,c0,c0,0;"
976
            "bic      r1, r1, #0x700;" // clear the overflow/interrupt flags
977
            "bic      r1, r1, #0x006;" // clear the reset bits
978
            "orr      %0, r1, %0;"     // preserve r1; better for debugging
979
            "mcr      p14,0,%0,c0,c0,0;"
980
            :
981
            : "r"(submask)
982
            : "r1"
983
            );
984
        break;
985
    case CYGNUM_HAL_INTERRUPT_BCU_INTERRUPT:
986
    case CYGNUM_HAL_INTERRUPT_NIRQ         :
987
    case CYGNUM_HAL_INTERRUPT_NFIQ         :
988
    default:
989
        /* do nothing */
990
        return;
991
    }
992
}
993
 
994
void hal_interrupt_configure(int vector, int level, int up)
995
{
996
}
997
 
998
void hal_interrupt_set_level(int vector, int level)
999
{
1000
}
1001
 
1002
/*------------------------------------------------------------------------*/
1003
// EOF iop310_misc.c

powered by: WebSVN 2.1.0

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