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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [verde/] [v2_0/] [src/] [verde_misc.c] - Blame information for rev 1773

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

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      verde_misc.c
4
//
5
//      HAL misc board support code for Intel Verde I/O Coprocessor
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 Red Hat, 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 version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    msalter
44
// Contributors: msalter
45
// Date:         2001-12-03
46
// Purpose:      HAL board support
47
// Description:  Implementations of HAL board interfaces
48
//
49
//####DESCRIPTIONEND####
50
//
51
//========================================================================*/
52
 
53
#include <pkgconf/hal.h>
54
#include <pkgconf/system.h>
55
#include CYGBLD_HAL_PLATFORM_H
56
#include CYGHWR_MEMORY_LAYOUT_H
57
 
58
#include <cyg/infra/cyg_type.h>         // base types
59
#include <cyg/infra/cyg_trac.h>         // tracing macros
60
#include <cyg/infra/cyg_ass.h>          // assertion macros
61
 
62
#include <cyg/hal/hal_io.h>             // IO macros
63
#include <cyg/hal/hal_stub.h>           // Stub macros
64
#include <cyg/hal/hal_if.h>             // calling interface API
65
#include <cyg/hal/hal_arch.h>           // Register state info
66
#include <cyg/hal/hal_diag.h>
67
#include <cyg/hal/hal_intr.h>           // Interrupt names
68
#include <cyg/hal/hal_cache.h>
69
#include <cyg/hal/plf_io.h>
70
#include <cyg/infra/diag.h>             // diag_printf
71
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
72
 
73
// Most initialization has already been done before we get here.
74
// All we do here is set up the interrupt environment.
75
// FIXME: some of the stuff in hal_platform_setup could be moved here.
76
 
77
externC void plf_hardware_init(void);
78
 
79
static cyg_uint32 mcu_ISR(cyg_vector_t vector, cyg_addrword_t data);
80
 
81
void
82
hal_hardware_init(void)
83
{
84
    hal_xscale_core_init();
85
 
86
    // Perform any platform specific initializations
87
    plf_hardware_init();
88
 
89
    // Let the timer run at a default rate (for delays)
90
    hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
91
 
92
    // Set up eCos/ROM interfaces
93
    hal_if_init();
94
 
95
    // Enable caches
96
    HAL_DCACHE_ENABLE();
97
    HAL_ICACHE_ENABLE();
98
 
99
    // attach interrupt handlers for MCU errors
100
    HAL_INTERRUPT_ATTACH (CYGNUM_HAL_INTERRUPT_MCU_ERR, &mcu_ISR, CYGNUM_HAL_INTERRUPT_MCU_ERR, 0);
101
    HAL_INTERRUPT_UNMASK (CYGNUM_HAL_INTERRUPT_MCU_ERR);
102
}
103
 
104
// -------------------------------------------------------------------------
105
// This routine is called to respond to a hardware interrupt (IRQ).  It
106
// should interrogate the hardware and return the IRQ vector number.
107
 
108
int
109
hal_IRQ_handler(void)
110
{
111
    cyg_uint32 sources, mask;
112
    int index;
113
 
114
    INTCTL_READ(mask);
115
    IINTSRC_READ(sources);
116
 
117
    sources &= mask; // just the unmasked ones
118
 
119
    if (sources) {
120
        HAL_LSBIT_INDEX( index, sources );
121
        return index;
122
    }
123
    return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
124
}
125
 
126
static inline void
127
_scrub_ecc(unsigned p)
128
{
129
    cyg_uint32 iacr;
130
 
131
    // The following ldr/str pair need to be atomic on the bus. Since
132
    // the XScale core doesn't support atomic RMW, we have to disable
133
    // arbitration to prevent other bus masters from taking the bus
134
    // between the the ldr and str.
135
 
136
    // Disable internal bus arbitration for everything except the CPU
137
    iacr = *ARB_IACR;
138
    *ARB_IACR = IACR_ATU(IACR_PRI_OFF)  | IACR_DMA0(IACR_PRI_OFF) |
139
                IACR_DMA1(IACR_PRI_OFF) | IACR_AAU(IACR_PRI_OFF)  |
140
                IACR_PBI(IACR_PRI_OFF)  | IACR_CORE(IACR_PRI_HIGH);
141
 
142
    // drain write buffer
143
    asm volatile ("mrc  p15,0,r1,c7,c10,4\n");
144
    CPWAIT();
145
 
146
    asm volatile ("ldrb r4, [%0]\n"
147
                  "strb r4, [%0]\n" : : "r"(p) : "r4");
148
 
149
    // Restore normal internal bus arbitration priorities
150
    *ARB_IACR = iacr;
151
}
152
 
153
static cyg_uint32
154
mcu_ISR(cyg_vector_t vector, cyg_addrword_t data)
155
{
156
    cyg_uint32 eccr_reg, mcisr_reg;
157
 
158
    // Read current state of ECC register
159
    eccr_reg = *MCU_ECCR;
160
 
161
    // and the interrupt status
162
    mcisr_reg = *MCU_MCISR;
163
 
164
    // Turn off all ecc error reporting
165
    *MCU_ECCR = 0xc;
166
 
167
#ifdef DEBUG_ECC
168
    diag_printf("mcu_ISR entry: ECCR = 0x%X, MCISR = 0x%X\n", eccr_reg, mcisr_reg);
169
#endif
170
 
171
    // Check for ECC Error 0
172
    if(mcisr_reg & 1) {
173
 
174
#ifdef DEBUG_ECC
175
        diag_printf("ELOG0 = 0x%X\n", *MCU_ELOG0);
176
        diag_printf("ECC Error Detected at Address 0x%X\n",*MCU_ECAR0);
177
#endif
178
 
179
        // Check for single-bit error
180
        if(!(*MCU_ELOG0 & 0x00000100)) {
181
            // call ECC restoration function
182
            _scrub_ecc((*MCU_ECAR0 - SDRAM_PHYS_BASE) + SDRAM_UNCACHED_BASE);
183
 
184
            // Clear the MCISR
185
            *MCU_MCISR = 1;
186
        } else {
187
#ifdef DEBUG_ECC
188
            diag_printf("Multi-bit or nibble error\n");
189
#endif
190
        }
191
    }
192
 
193
    // Check for ECC Error 1
194
    if(mcisr_reg & 2) {
195
 
196
#ifdef DEBUG_ECC
197
        diag_printf("ELOG1 = 0x%X\n",*MCU_ELOG1);
198
        diag_printf("ECC Error Detected at Address 0x%X\n",*MCU_ECAR1);
199
#endif
200
 
201
        // Check for single-bit error
202
        if(!(*MCU_ELOG1 & 0x00000100))  {
203
            // call ECC restoration function
204
            _scrub_ecc((*MCU_ECAR1 - SDRAM_PHYS_BASE) + SDRAM_UNCACHED_BASE);
205
 
206
            // Clear the MCISR
207
            *MCU_MCISR = 2;
208
        }
209
        else {
210
#ifdef DEBUG_ECC
211
            diag_printf("Multi-bit or nibble error\n");
212
#endif
213
        }
214
    }
215
 
216
    // Check for ECC Error N
217
    if(mcisr_reg & 4) {
218
        // Clear the MCISR
219
        *MCU_MCISR = 4;
220
        diag_printf("Uncorrectable error during RMW\n");
221
    }
222
 
223
    // Restore ECCR register
224
    *MCU_ECCR = eccr_reg;
225
 
226
#ifdef DEBUG_ECC
227
    diag_printf("mcu_ISR exit: MCISR = 0x%X\n", *MCU_MCISR);
228
#endif
229
 
230
    return CYG_ISR_HANDLED;
231
}
232
 
233
//
234
// Interrupt control
235
//
236
 
237
void
238
hal_interrupt_mask(int vector)
239
{
240
    if (vector <= CYGNUM_HAL_INTERRUPT_HPI) {
241
        int mask;
242
 
243
        INTCTL_READ(mask);
244
        mask &= ~(1 << vector);
245
        INTCTL_WRITE(mask);
246
        CPWAIT();
247
    }
248
}
249
 
250
void
251
hal_interrupt_unmask(int vector)
252
{
253
    if (vector <= CYGNUM_HAL_INTERRUPT_HPI) {
254
        int mask;
255
 
256
        INTCTL_READ(mask);
257
        mask |= (1 << vector);
258
        INTCTL_WRITE(mask);
259
        CPWAIT();
260
    }
261
}
262
 
263
void
264
hal_interrupt_acknowledge(int vector)
265
{
266
    // If this is a timer interrupt, write a 1 to the appropriate bit
267
    // in the TISR register.
268
    if( vector == CYGNUM_HAL_INTERRUPT_TIMER0 ||
269
        vector == CYGNUM_HAL_INTERRUPT_TIMER1 )
270
    {
271
        TISR_WRITE(1<<(vector-CYGNUM_HAL_INTERRUPT_TIMER0));
272
    }
273
}
274
 
275
 
276
void hal_interrupt_configure(int vector, int level, int up)
277
{
278
}
279
 
280
void hal_interrupt_set_level(int vector, int level)
281
{
282
}
283
 
284
 
285
/*------------------------------------------------------------------------*/
286
// RTC Support
287
 
288
static cyg_uint32 _period;
289
 
290
#define CLOCK_MULTIPLIER 200
291
 
292
void
293
hal_clock_initialize(cyg_uint32 period)
294
{
295
    cyg_uint32 val;
296
    cyg_uint32 tmr_period;
297
    _period = period;
298
 
299
    tmr_period = period * CLOCK_MULTIPLIER;
300
 
301
    // disable timer
302
    TMR0_WRITE(0);
303
 
304
    // clear interrupts
305
    TISR_WRITE(1);
306
 
307
    // set reload/count value
308
    TRR0_WRITE(tmr_period);
309
    TCR0_WRITE(tmr_period);
310
 
311
    // let it run
312
    TMR0_WRITE(TMR_ENABLE | TMR_RELOAD | TMR_CLK_1);
313
 
314
    TMR0_READ(val);
315
}
316
 
317
 
318
// Dynamically set the timer interrupt rate.
319
// Not for eCos application use at all, just special GPROF code in RedBoot.
320
 
321
void
322
hal_clock_reinitialize(          int *pfreq,    /* inout */
323
                        unsigned int *pperiod,  /* inout */
324
                        unsigned int old_hz )   /* in */
325
{
326
    unsigned int newp = 0, period, i = 0;
327
    int hz;
328
    int do_set_hw;
329
 
330
// Arbitrary choice somewhat - so the CPU can make
331
// progress with the clock set like this, we hope.
332
#define MIN_TICKS (2000)
333
#define MAX_TICKS  N/A: 32-bit counter
334
 
335
    if ( ! pfreq || ! pperiod )
336
        return; // we cannot even report a problem!
337
 
338
    hz = *pfreq;
339
    period = *pperiod;
340
 
341
// Requested HZ:
342
// 0         => tell me the current value (no change, implemented in caller)
343
// - 1       => tell me the slowest (no change)
344
// - 2       => tell me the default (no change, implemented in caller)
345
// -nnn      => tell me what you would choose for nnn (no change)
346
// MIN_INT   => tell me the fastest (no change)
347
//        
348
// 1         => tell me the slowest (sets the clock)
349
// MAX_INT   => tell me the fastest (sets the clock)
350
 
351
    do_set_hw = (hz > 0);
352
    if ( hz < 0 )
353
        hz = -hz;
354
 
355
    // Be paranoid about bad args, and very defensive about underflows
356
    if ( 0 < hz && 0 < period && 0 < old_hz ) {
357
 
358
        newp = period * old_hz / (unsigned)hz;
359
 
360
        if ( newp < MIN_TICKS ) {
361
            newp = MIN_TICKS;
362
            // recalculate to get the exact delay for this integral hz
363
            // and hunt hz down to an acceptable value if necessary
364
            i = period * old_hz / newp;
365
            if ( i ) do {
366
                newp = period * old_hz / i;
367
                i--;
368
            } while (newp < MIN_TICKS && i);
369
        }
370
        // So long as period * old_hz fits in 32 bits, there is no need to
371
        // worry about overflow; hz >= 1 in the initial divide.  If the
372
        // clock cannot do a whole second (period * old_hz >= 2^32), we
373
        // will get overflow here, and random returned HZ values.
374
 
375
        // Recalculate the actual value installed.
376
        i = period * old_hz / newp;
377
    }
378
 
379
    *pfreq = i;
380
    *pperiod = newp;
381
 
382
    if ( do_set_hw ) {
383
        hal_clock_initialize( newp );
384
    }
385
}
386
 
387
// This routine is called during a clock interrupt.
388
void
389
hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
390
{
391
}
392
 
393
// Read the current value of the clock, returning the number of hardware
394
// "ticks" that have occurred (i.e. how far away the current value is from
395
// the start)
396
void
397
hal_clock_read(cyg_uint32 *pvalue)
398
{
399
    cyg_uint32 timer_val;
400
 
401
    TCR0_READ(timer_val);
402
 
403
    // Translate timer value back into microseconds
404
 
405
    timer_val /= CLOCK_MULTIPLIER;
406
 
407
    *pvalue = _period - timer_val;
408
}
409
 
410
// Delay for some usecs.
411
void
412
hal_delay_us(cyg_int32 delay)
413
{
414
#define _TICKS_PER_USEC CLOCK_MULTIPLIER
415
    cyg_uint32 now, prev, diff, usecs;
416
    cyg_uint32 tmr_period = _period * CLOCK_MULTIPLIER;
417
 
418
    diff = usecs = 0;
419
    TCR0_READ(prev);
420
 
421
    while (delay > usecs) {
422
        TCR0_READ(now);
423
 
424
        if (prev < now)
425
            diff += (prev + (tmr_period - now));
426
        else
427
            diff += (prev - now);
428
 
429
        prev = now;
430
 
431
        if (diff >= _TICKS_PER_USEC) {
432
            usecs += (diff / _TICKS_PER_USEC);
433
            diff %= _TICKS_PER_USEC;
434
        }
435
    }
436
}
437
 
438
/*------------------------------------------------------------------------*/
439
// EOF verde_misc.c
440
 

powered by: WebSVN 2.1.0

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