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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [shared/] [openpic/] [openpic.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  openpic.c -- OpenPIC Interrupt Handling
3
 *
4
 *  Copyright (C) 1997 Geert Uytterhoeven
5
 *
6
 *  Modified to compile in RTEMS development environment
7
 *  by Eric Valette
8
 *
9
 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10
 *
11
 *  The license and distribution terms for this file may be
12
 *  found in found in the file LICENSE in this distribution or at
13
 *  http://www.OARcorp.com/rtems/license.html.
14
 *
15
 * $Id: openpic.c,v 1.2 2001-09-27 12:01:07 chris Exp $
16
 */
17
 
18
/*
19
 *  Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
20
 */
21
 
22
 
23
#include <bsp/openpic.h>
24
#include <bsp/pci.h>
25
#include <bsp/consoleIo.h>
26
#include <libcpu/io.h>
27
#include <libcpu/byteorder.h>
28
#include <bsp.h>
29
 
30
#define NULL 0
31
#define REGISTER_DEBUG
32
#undef REGISTER_DEBUG
33
 
34
 
35
volatile struct OpenPIC *OpenPIC = NULL;
36
unsigned int OpenPIC_NumInitSenses  = 0;
37
unsigned char *OpenPIC_InitSenses  = NULL;
38
 
39
static unsigned int NumProcessors;
40
static unsigned int NumSources;
41
 
42
 
43
    /*
44
     *  Accesses to the current processor's registers
45
     */
46
 
47
#define THIS_CPU                Processor[cpu]
48
#define CHECK_THIS_CPU          check_arg_cpu(cpu)
49
 
50
 
51
    /*
52
     *  Sanity checks
53
     */
54
 
55
#if 1
56
#define check_arg_ipi(ipi) \
57
    if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
58
        printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
59
#define check_arg_timer(timer) \
60
    if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
61
        printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
62
#define check_arg_vec(vec) \
63
    if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
64
        printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
65
#define check_arg_pri(pri) \
66
    if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
67
        printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
68
#define check_arg_irq(irq) \
69
    if (irq < 0 || irq >= NumSources) \
70
        printk("openpic.c:%d: illegal irq %d from %p,[%p],[[%p]]\n", \
71
               __LINE__, irq, __builtin_return_address(0), \
72
               __builtin_return_address(1), __builtin_return_address(2) \
73
               );
74
#define check_arg_cpu(cpu) \
75
    if (cpu < 0 || cpu >= NumProcessors) \
76
        printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
77
#else
78
#define check_arg_ipi(ipi)      do {} while (0)
79
#define check_arg_timer(timer)  do {} while (0)
80
#define check_arg_vec(vec)      do {} while (0)
81
#define check_arg_pri(pri)      do {} while (0)
82
#define check_arg_irq(irq)      do {} while (0)
83
#define check_arg_cpu(cpu)      do {} while (0)
84
#endif
85
 
86
 
87
 
88
    /*
89
     *  I/O functions
90
     */
91
 
92
static inline unsigned int openpic_read(volatile unsigned int *addr)
93
{
94
    unsigned int val;
95
 
96
    val = ld_le32(addr);
97
#ifdef REGISTER_DEBUG
98
    printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val);
99
#endif
100
    return val;
101
}
102
 
103
static inline void openpic_write(volatile unsigned int *addr, unsigned int val)
104
{
105
#ifdef REGISTER_DEBUG
106
    printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val);
107
#endif
108
    out_le32(addr, val);
109
}
110
 
111
 
112
static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask)
113
{
114
    unsigned int val = openpic_read(addr);
115
    return val & mask;
116
}
117
 
118
inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask,
119
                                      unsigned int field)
120
{
121
    unsigned int val = openpic_read(addr);
122
    openpic_write(addr, (val & ~mask) | (field & mask));
123
}
124
 
125
static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask)
126
{
127
    openpic_writefield(addr, mask, 0);
128
}
129
 
130
static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask)
131
{
132
    openpic_writefield(addr, mask, mask);
133
}
134
 
135
 
136
    /*
137
     *  Update a Vector/Priority register in a safe manner. The interrupt will
138
     *  be disabled.
139
     */
140
 
141
static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask,
142
                                    unsigned int field)
143
{
144
    openpic_setfield(addr, OPENPIC_MASK);
145
    /* wait until it's not in use */
146
    while (openpic_read(addr) & OPENPIC_ACTIVITY);
147
    openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
148
}
149
 
150
 
151
/* -------- Global Operations ---------------------------------------------- */
152
 
153
 
154
    /*
155
     *  Initialize the OpenPIC
156
     *
157
     * Add some kludge to use the Motorola Raven OpenPIC which does not
158
     * report vendor and device id, and gets the wrong number of interrupts.
159
     * (Motorola did a great job on that one!)
160
     */
161
 
162
void openpic_init(int main_pic)
163
{
164
    unsigned int t, i;
165
    unsigned int vendorid, devid, stepping, timerfreq;
166
    const char *version, *vendor, *device;
167
 
168
    if (!OpenPIC)
169
        BSP_panic("No OpenPIC found");
170
 
171
    t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
172
    switch (t & OPENPIC_FEATURE_VERSION_MASK) {
173
        case 1:
174
            version = "1.0";
175
            break;
176
        case 2:
177
            version = "1.2";
178
            break;
179
        default:
180
            version = "?";
181
            break;
182
    }
183
    NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
184
                     OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
185
    NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
186
                  OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
187
    t = openpic_read(&OpenPIC->Global.Vendor_Identification);
188
 
189
    vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK;
190
    devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >>
191
            OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT;
192
    stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >>
193
               OPENPIC_VENDOR_ID_STEPPING_SHIFT;
194
 
195
    /* Kludge for the Raven */
196
    pci_read_config_dword(0, 0, 0, 0, &t);
197
    if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
198
        vendor = "Motorola";
199
        device = "Raven";
200
        NumSources += 1;
201
    } else {
202
        switch (vendorid) {
203
            case OPENPIC_VENDOR_ID_APPLE:
204
                vendor = "Apple";
205
                break;
206
            default:
207
                vendor = "Unknown";
208
            break;
209
        }
210
        switch (devid) {
211
            case OPENPIC_DEVICE_ID_APPLE_HYDRA:
212
                device = "Hydra";
213
                break;
214
            default:
215
                device = "Unknown";
216
                break;
217
        }
218
    }
219
    printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
220
           NumProcessors, NumSources, OpenPIC);
221
 
222
    printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid,
223
           vendor, devid, device, stepping);
224
 
225
    timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
226
    printk("OpenPIC timer frequency is ");
227
    if (timerfreq)
228
        printk("%d Hz\n", timerfreq);
229
    else
230
        printk("not set\n");
231
 
232
    if ( main_pic )
233
    {
234
            /* Initialize timer interrupts */
235
            for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
236
                    /* Disabled, Priority 0 */
237
                    openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
238
                    /* No processor */
239
                    openpic_maptimer(i, 0);
240
            }
241
 
242
            /* Initialize IPI interrupts */
243
            for (i = 0; i < OPENPIC_NUM_IPI; i++) {
244
                    /* Disabled, Priority 0 */
245
                    openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
246
            }
247
 
248
            /* Initialize external interrupts */
249
            /* SIOint (8259 cascade) is special */
250
            openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
251
            /* Processor 0 */
252
            openpic_mapirq(0, 1<<0);
253
            for (i = 1; i < NumSources; i++) {
254
                    /* Enabled, Priority 8 */
255
                    openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
256
                                    i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
257
                    /* Processor 0 */
258
                    openpic_mapirq(i, 1<<0);
259
            }
260
 
261
            /* Initialize the spurious interrupt */
262
            openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
263
#if 0       
264
            if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
265
                            "82c59 cascade", NULL))
266
              printk("Unable to get OpenPIC IRQ 0 for cascade\n");
267
#endif      
268
            openpic_set_priority(0, 0);
269
            openpic_disable_8259_pass_through();
270
    }
271
}
272
 
273
 
274
    /*
275
     *  Reset the OpenPIC
276
     */
277
 
278
void openpic_reset(void)
279
{
280
    openpic_setfield(&OpenPIC->Global.Global_Configuration0,
281
                       OPENPIC_CONFIG_RESET);
282
}
283
 
284
 
285
    /*
286
     *  Enable/disable 8259 Pass Through Mode
287
     */
288
 
289
void openpic_enable_8259_pass_through(void)
290
{
291
    openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
292
                       OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
293
}
294
 
295
void openpic_disable_8259_pass_through(void)
296
{
297
    openpic_setfield(&OpenPIC->Global.Global_Configuration0,
298
                     OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
299
}
300
 
301
 
302
    /*
303
     *  Find out the current interrupt
304
     */
305
 
306
unsigned int openpic_irq(unsigned int cpu)
307
{
308
    unsigned int vec;
309
 
310
    check_arg_cpu(cpu);
311
    vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
312
                            OPENPIC_VECTOR_MASK);
313
    return vec;
314
}
315
 
316
 
317
    /*
318
     *  Signal end of interrupt (EOI) processing
319
     */
320
 
321
void openpic_eoi(unsigned int cpu)
322
{
323
    check_arg_cpu(cpu);
324
    openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
325
}
326
 
327
 
328
    /*
329
     *  Get/set the current task priority
330
     */
331
 
332
unsigned int openpic_get_priority(unsigned int cpu)
333
{
334
    CHECK_THIS_CPU;
335
    return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
336
                             OPENPIC_CURRENT_TASK_PRIORITY_MASK);
337
}
338
 
339
void openpic_set_priority(unsigned int cpu, unsigned int pri)
340
{
341
    CHECK_THIS_CPU;
342
    check_arg_pri(pri);
343
    openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
344
                       OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
345
}
346
 
347
    /*
348
     *  Get/set the spurious vector
349
     */
350
 
351
unsigned int openpic_get_spurious(void)
352
{
353
    return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
354
                             OPENPIC_VECTOR_MASK);
355
}
356
 
357
void openpic_set_spurious(unsigned int vec)
358
{
359
    check_arg_vec(vec);
360
    openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
361
                       vec);
362
}
363
 
364
 
365
    /*
366
     *  Initialize one or more CPUs
367
     */
368
 
369
void openpic_init_processor(unsigned int cpumask)
370
{
371
    openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
372
}
373
 
374
 
375
/* -------- Interprocessor Interrupts -------------------------------------- */
376
 
377
 
378
    /*
379
     *  Initialize an interprocessor interrupt (and disable it)
380
     *
381
     *  ipi: OpenPIC interprocessor interrupt number
382
     *  pri: interrupt source priority
383
     *  vec: the vector it will produce
384
     */
385
 
386
void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec)
387
{
388
    check_arg_timer(ipi);
389
    check_arg_pri(pri);
390
    check_arg_vec(vec);
391
    openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
392
                            OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
393
                            (pri << OPENPIC_PRIORITY_SHIFT) | vec);
394
}
395
 
396
 
397
    /*
398
     *  Send an IPI to one or more CPUs
399
     */
400
 
401
void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask)
402
{
403
    CHECK_THIS_CPU;
404
    check_arg_ipi(ipi);
405
    openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
406
}
407
 
408
 
409
/* -------- Timer Interrupts ----------------------------------------------- */
410
 
411
 
412
    /*
413
     *  Initialize a timer interrupt (and disable it)
414
     *
415
     *  timer: OpenPIC timer number
416
     *  pri: interrupt source priority
417
     *  vec: the vector it will produce
418
     */
419
 
420
void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec)
421
{
422
    check_arg_timer(timer);
423
    check_arg_pri(pri);
424
    check_arg_vec(vec);
425
    openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
426
                            OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
427
                            (pri << OPENPIC_PRIORITY_SHIFT) | vec);
428
}
429
 
430
 
431
    /*
432
     *  Map a timer interrupt to one or more CPUs
433
     */
434
 
435
void openpic_maptimer(unsigned int timer, unsigned int cpumask)
436
{
437
    check_arg_timer(timer);
438
    openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
439
}
440
 
441
 
442
/* -------- Interrupt Sources ---------------------------------------------- */
443
 
444
 
445
    /*
446
     *  Enable/disable an interrupt source
447
     */
448
 
449
void openpic_enable_irq(unsigned int irq)
450
{
451
    check_arg_irq(irq);
452
    openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
453
}
454
 
455
void openpic_disable_irq(unsigned int irq)
456
{
457
    check_arg_irq(irq);
458
    openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
459
}
460
 
461
 
462
    /*
463
     *  Initialize an interrupt source (and disable it!)
464
     *
465
     *  irq: OpenPIC interrupt number
466
     *  pri: interrupt source priority
467
     *  vec: the vector it will produce
468
     *  pol: polarity (1 for positive, 0 for negative)
469
     *  sense: 1 for level, 0 for edge
470
     */
471
 
472
void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense)
473
{
474
    check_arg_irq(irq);
475
    check_arg_pri(pri);
476
    check_arg_vec(vec);
477
    openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
478
                            OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
479
                            OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
480
                            (pri << OPENPIC_PRIORITY_SHIFT) | vec |
481
                            (pol ? OPENPIC_SENSE_POLARITY : 0) |
482
                            (sense ? OPENPIC_SENSE_LEVEL : 0));
483
}
484
 
485
 
486
    /*
487
     *  Map an interrupt source to one or more CPUs
488
     */
489
 
490
void openpic_mapirq(unsigned int irq, unsigned int cpumask)
491
{
492
    check_arg_irq(irq);
493
    openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
494
}
495
 
496
 
497
    /*
498
     *  Set the sense for an interrupt source (and disable it!)
499
     *
500
     *  sense: 1 for level, 0 for edge
501
     */
502
 
503
void openpic_set_sense(unsigned int irq, int sense)
504
{
505
    check_arg_irq(irq);
506
    openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
507
                            OPENPIC_SENSE_LEVEL,
508
                            (sense ? OPENPIC_SENSE_LEVEL : 0));
509
}

powered by: WebSVN 2.1.0

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