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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [iop310/] [v2_0/] [src/] [iop310_misc.c] - Blame information for rev 307

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

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

powered by: WebSVN 2.1.0

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