source: rtems/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c @ 20603d1

4.104.114.84.95
Last change on this file since 20603d1 was 20603d1, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 3, 2002 at 2:22:16 PM

2002-04-02 Ralf Corsepius <corsepiu@…>

  • residual/residual.c: Include <string.h>.
  • vectors/vectors_init.c: Include <rtems/bspIo.h> for printk.
  • bootloader/mm.c: Ditto.
  • bootloader/pci.c: Ditto.
  • console/console.c: Ditto.
  • openpic/openpic.c: Ditto.
  • Property mode set to 100644
File size: 12.7 KB
Line 
1/*
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$
16 */
17
18/*
19 *  Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
20 */
21
22#include <rtems/bspIo.h>
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
35volatile struct OpenPIC *OpenPIC = NULL;
36unsigned int OpenPIC_NumInitSenses  = 0;
37unsigned char *OpenPIC_InitSenses  = NULL;
38
39static unsigned int NumProcessors;
40static 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
92static 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
103static 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
112static 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
118inline 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
125static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask)
126{
127    openpic_writefield(addr, mask, 0);
128}
129
130static 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
141static 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
162void 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
278void 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
289void openpic_enable_8259_pass_through(void)
290{
291    openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
292                       OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
293}
294
295void 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
306unsigned 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
321void 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
332unsigned 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
339void 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
351unsigned int openpic_get_spurious(void)
352{
353    return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
354                             OPENPIC_VECTOR_MASK);
355}
356
357void 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
369void 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
386void 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
401void 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
420void 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
435void 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
449void openpic_enable_irq(unsigned int irq)
450{
451    check_arg_irq(irq);
452    openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
453}
454
455void 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
472void 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
490void 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
503void 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}
Note: See TracBrowser for help on using the repository browser.