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

4.104.114.84.95
Last change on this file since e79a1947 was e79a1947, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 10, 2004 at 11:51:17 PM

2004-11-10 Richard Campbell <richard.campbell@…>

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