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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc/] [kernel/] [irq.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*  $Id: irq.c,v 1.114 2001/12/11 04:55:51 davem Exp $
2
 *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
3
 *                            Sparc the IRQs are basically 'cast in stone'
4
 *                            and you are supposed to probe the prom's device
5
 *                            node trees to find out who's got which IRQ.
6
 *
7
 *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
8
 *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
9
 *  Copyright (C) 1995,2002 Pete A. Zaitcev (zaitcev@yahoo.com)
10
 *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
11
 *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
12
 */
13
 
14
#include <linux/module.h>
15
#include <linux/sched.h>
16
#include <linux/ptrace.h>
17
#include <linux/errno.h>
18
#include <linux/linkage.h>
19
#include <linux/kernel_stat.h>
20
#include <linux/signal.h>
21
#include <linux/interrupt.h>
22
#include <linux/slab.h>
23
#include <linux/random.h>
24
#include <linux/init.h>
25
#include <linux/smp.h>
26
#include <linux/delay.h>
27
#include <linux/threads.h>
28
#include <linux/spinlock.h>
29
#include <linux/seq_file.h>
30
 
31
#include <asm/ptrace.h>
32
#include <asm/processor.h>
33
#include <asm/system.h>
34
#include <asm/psr.h>
35
#include <asm/smp.h>
36
#include <asm/vaddrs.h>
37
#include <asm/timer.h>
38
#include <asm/openprom.h>
39
#include <asm/oplib.h>
40
#include <asm/traps.h>
41
#include <asm/irq.h>
42
#include <asm/io.h>
43
#include <asm/pgalloc.h>
44
#include <asm/pgtable.h>
45
#include <asm/pcic.h>
46
#include <asm/cacheflush.h>
47
#include <asm/irq_regs.h>
48
 
49
#include "irq.h"
50
 
51
#ifdef CONFIG_SMP
52
#define SMP_NOP2 "nop; nop;\n\t"
53
#define SMP_NOP3 "nop; nop; nop;\n\t"
54
#else
55
#define SMP_NOP2
56
#define SMP_NOP3
57
#endif /* SMP */
58
unsigned long __raw_local_irq_save(void)
59
{
60
        unsigned long retval;
61
        unsigned long tmp;
62
 
63
        __asm__ __volatile__(
64
                "rd     %%psr, %0\n\t"
65
                SMP_NOP3        /* Sun4m + Cypress + SMP bug */
66
                "or     %0, %2, %1\n\t"
67
                "wr     %1, 0, %%psr\n\t"
68
                "nop; nop; nop\n"
69
                : "=&r" (retval), "=r" (tmp)
70
                : "i" (PSR_PIL)
71
                : "memory");
72
 
73
        return retval;
74
}
75
 
76
void raw_local_irq_enable(void)
77
{
78
        unsigned long tmp;
79
 
80
        __asm__ __volatile__(
81
                "rd     %%psr, %0\n\t"
82
                SMP_NOP3        /* Sun4m + Cypress + SMP bug */
83
                "andn   %0, %1, %0\n\t"
84
                "wr     %0, 0, %%psr\n\t"
85
                "nop; nop; nop\n"
86
                : "=&r" (tmp)
87
                : "i" (PSR_PIL)
88
                : "memory");
89
}
90
 
91
void raw_local_irq_restore(unsigned long old_psr)
92
{
93
        unsigned long tmp;
94
 
95
        __asm__ __volatile__(
96
                "rd     %%psr, %0\n\t"
97
                "and    %2, %1, %2\n\t"
98
                SMP_NOP2        /* Sun4m + Cypress + SMP bug */
99
                "andn   %0, %1, %0\n\t"
100
                "wr     %0, %2, %%psr\n\t"
101
                "nop; nop; nop\n"
102
                : "=&r" (tmp)
103
                : "i" (PSR_PIL), "r" (old_psr)
104
                : "memory");
105
}
106
 
107
EXPORT_SYMBOL(__raw_local_irq_save);
108
EXPORT_SYMBOL(raw_local_irq_enable);
109
EXPORT_SYMBOL(raw_local_irq_restore);
110
 
111
/*
112
 * Dave Redman (djhr@tadpole.co.uk)
113
 *
114
 * IRQ numbers.. These are no longer restricted to 15..
115
 *
116
 * this is done to enable SBUS cards and onboard IO to be masked
117
 * correctly. using the interrupt level isn't good enough.
118
 *
119
 * For example:
120
 *   A device interrupting at sbus level6 and the Floppy both come in
121
 *   at IRQ11, but enabling and disabling them requires writing to
122
 *   different bits in the SLAVIO/SEC.
123
 *
124
 * As a result of these changes sun4m machines could now support
125
 * directed CPU interrupts using the existing enable/disable irq code
126
 * with tweaks.
127
 *
128
 */
129
 
130
static void irq_panic(void)
131
{
132
    extern char *cputypval;
133
    prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval);
134
    prom_halt();
135
}
136
 
137
void (*sparc_init_timers)(irq_handler_t ) =
138
    (void (*)(irq_handler_t )) irq_panic;
139
 
140
/*
141
 * Dave Redman (djhr@tadpole.co.uk)
142
 *
143
 * There used to be extern calls and hard coded values here.. very sucky!
144
 * instead, because some of the devices attach very early, I do something
145
 * equally sucky but at least we'll never try to free statically allocated
146
 * space or call kmalloc before kmalloc_init :(.
147
 *
148
 * In fact it's the timer10 that attaches first.. then timer14
149
 * then kmalloc_init is called.. then the tty interrupts attach.
150
 * hmmm....
151
 *
152
 */
153
#define MAX_STATIC_ALLOC        4
154
struct irqaction static_irqaction[MAX_STATIC_ALLOC];
155
int static_irq_count;
156
 
157
struct {
158
        struct irqaction *action;
159
        int flags;
160
} sparc_irq[NR_IRQS];
161
#define SPARC_IRQ_INPROGRESS 1
162
 
163
/* Used to protect the IRQ action lists */
164
DEFINE_SPINLOCK(irq_action_lock);
165
 
166
int show_interrupts(struct seq_file *p, void *v)
167
{
168
        int i = *(loff_t *) v;
169
        struct irqaction * action;
170
        unsigned long flags;
171
#ifdef CONFIG_SMP
172
        int j;
173
#endif
174
 
175
        if (sparc_cpu_model == sun4d) {
176
                extern int show_sun4d_interrupts(struct seq_file *, void *);
177
 
178
                return show_sun4d_interrupts(p, v);
179
        }
180
        spin_lock_irqsave(&irq_action_lock, flags);
181
        if (i < NR_IRQS) {
182
                action = sparc_irq[i].action;
183
                if (!action)
184
                        goto out_unlock;
185
                seq_printf(p, "%3d: ", i);
186
#ifndef CONFIG_SMP
187
                seq_printf(p, "%10u ", kstat_irqs(i));
188
#else
189
                for_each_online_cpu(j) {
190
                        seq_printf(p, "%10u ",
191
                                    kstat_cpu(j).irqs[i]);
192
                }
193
#endif
194
                seq_printf(p, " %c %s",
195
                        (action->flags & IRQF_DISABLED) ? '+' : ' ',
196
                        action->name);
197
                for (action=action->next; action; action = action->next) {
198
                        seq_printf(p, ",%s %s",
199
                                (action->flags & IRQF_DISABLED) ? " +" : "",
200
                                action->name);
201
                }
202
                seq_putc(p, '\n');
203
        }
204
out_unlock:
205
        spin_unlock_irqrestore(&irq_action_lock, flags);
206
        return 0;
207
}
208
 
209
void free_irq(unsigned int irq, void *dev_id)
210
{
211
        struct irqaction * action;
212
        struct irqaction **actionp;
213
        unsigned long flags;
214
        unsigned int cpu_irq;
215
 
216
        if (sparc_cpu_model == sun4d) {
217
                extern void sun4d_free_irq(unsigned int, void *);
218
 
219
                sun4d_free_irq(irq, dev_id);
220
                return;
221
        }
222
        cpu_irq = irq & (NR_IRQS - 1);
223
        if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
224
                printk("Trying to free bogus IRQ %d\n", irq);
225
                return;
226
        }
227
 
228
        spin_lock_irqsave(&irq_action_lock, flags);
229
 
230
        actionp = &sparc_irq[cpu_irq].action;
231
        action = *actionp;
232
 
233
        if (!action->handler) {
234
                printk("Trying to free free IRQ%d\n",irq);
235
                goto out_unlock;
236
        }
237
        if (dev_id) {
238
                for (; action; action = action->next) {
239
                        if (action->dev_id == dev_id)
240
                                break;
241
                        actionp = &action->next;
242
                }
243
                if (!action) {
244
                        printk("Trying to free free shared IRQ%d\n",irq);
245
                        goto out_unlock;
246
                }
247
        } else if (action->flags & IRQF_SHARED) {
248
                printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
249
                goto out_unlock;
250
        }
251
        if (action->flags & SA_STATIC_ALLOC)
252
        {
253
                /* This interrupt is marked as specially allocated
254
                 * so it is a bad idea to free it.
255
                 */
256
                printk("Attempt to free statically allocated IRQ%d (%s)\n",
257
                       irq, action->name);
258
                goto out_unlock;
259
        }
260
 
261
        *actionp = action->next;
262
 
263
        spin_unlock_irqrestore(&irq_action_lock, flags);
264
 
265
        synchronize_irq(irq);
266
 
267
        spin_lock_irqsave(&irq_action_lock, flags);
268
 
269
        kfree(action);
270
 
271
        if (!sparc_irq[cpu_irq].action)
272
                __disable_irq(irq);
273
 
274
out_unlock:
275
        spin_unlock_irqrestore(&irq_action_lock, flags);
276
}
277
 
278
EXPORT_SYMBOL(free_irq);
279
 
280
/*
281
 * This is called when we want to synchronize with
282
 * interrupts. We may for example tell a device to
283
 * stop sending interrupts: but to make sure there
284
 * are no interrupts that are executing on another
285
 * CPU we need to call this function.
286
 */
287
#ifdef CONFIG_SMP
288
void synchronize_irq(unsigned int irq)
289
{
290
        unsigned int cpu_irq;
291
 
292
        cpu_irq = irq & (NR_IRQS - 1);
293
        while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
294
                cpu_relax();
295
}
296
#endif /* SMP */
297
 
298
void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
299
{
300
        int i;
301
        struct irqaction * action;
302
        unsigned int cpu_irq;
303
 
304
        cpu_irq = irq & (NR_IRQS - 1);
305
        action = sparc_irq[cpu_irq].action;
306
 
307
        printk("IO device interrupt, irq = %d\n", irq);
308
        printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
309
                    regs->npc, regs->u_regs[14]);
310
        if (action) {
311
                printk("Expecting: ");
312
                for (i = 0; i < 16; i++)
313
                        if (action->handler)
314
                                printk("[%s:%d:0x%x] ", action->name,
315
                                       (int) i, (unsigned int) action->handler);
316
        }
317
        printk("AIEEE\n");
318
        panic("bogus interrupt received");
319
}
320
 
321
void handler_irq(int irq, struct pt_regs * regs)
322
{
323
        struct pt_regs *old_regs;
324
        struct irqaction * action;
325
        int cpu = smp_processor_id();
326
#ifdef CONFIG_SMP
327
        extern void smp4m_irq_rotate(int cpu);
328
#endif
329
 
330
        old_regs = set_irq_regs(regs);
331
        irq_enter();
332
        disable_pil_irq(irq);
333
#ifdef CONFIG_SMP
334
        /* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */
335
        if((sparc_cpu_model==sun4m) && (irq < 10))
336
                smp4m_irq_rotate(cpu);
337
#endif
338
        action = sparc_irq[irq].action;
339
        sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
340
        kstat_cpu(cpu).irqs[irq]++;
341
        do {
342
                if (!action || !action->handler)
343
                        unexpected_irq(irq, NULL, regs);
344
                action->handler(irq, action->dev_id);
345
                action = action->next;
346
        } while (action);
347
        sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
348
        enable_pil_irq(irq);
349
        irq_exit();
350
        set_irq_regs(old_regs);
351
}
352
 
353
#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
354
 
355
/* Fast IRQs on the Sparc can only have one routine attached to them,
356
 * thus no sharing possible.
357
 */
358
static int request_fast_irq(unsigned int irq,
359
                            void (*handler)(void),
360
                            unsigned long irqflags, const char *devname)
361
{
362
        struct irqaction *action;
363
        unsigned long flags;
364
        unsigned int cpu_irq;
365
        int ret;
366
#ifdef CONFIG_SMP
367
        struct tt_entry *trap_table;
368
        extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;
369
#endif
370
 
371
        cpu_irq = irq & (NR_IRQS - 1);
372
        if(cpu_irq > 14) {
373
                ret = -EINVAL;
374
                goto out;
375
        }
376
        if(!handler) {
377
                ret = -EINVAL;
378
                goto out;
379
        }
380
 
381
        spin_lock_irqsave(&irq_action_lock, flags);
382
 
383
        action = sparc_irq[cpu_irq].action;
384
        if(action) {
385
                if(action->flags & IRQF_SHARED)
386
                        panic("Trying to register fast irq when already shared.\n");
387
                if(irqflags & IRQF_SHARED)
388
                        panic("Trying to register fast irq as shared.\n");
389
 
390
                /* Anyway, someone already owns it so cannot be made fast. */
391
                printk("request_fast_irq: Trying to register yet already owned.\n");
392
                ret = -EBUSY;
393
                goto out_unlock;
394
        }
395
 
396
        /* If this is flagged as statically allocated then we use our
397
         * private struct which is never freed.
398
         */
399
        if (irqflags & SA_STATIC_ALLOC) {
400
            if (static_irq_count < MAX_STATIC_ALLOC)
401
                action = &static_irqaction[static_irq_count++];
402
            else
403
                printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
404
                       irq, devname);
405
        }
406
 
407
        if (action == NULL)
408
            action = kmalloc(sizeof(struct irqaction),
409
                                                 GFP_ATOMIC);
410
 
411
        if (!action) {
412
                ret = -ENOMEM;
413
                goto out_unlock;
414
        }
415
 
416
        /* Dork with trap table if we get this far. */
417
#define INSTANTIATE(table) \
418
        table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
419
        table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
420
                SPARC_BRANCH((unsigned long) handler, \
421
                             (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
422
        table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
423
        table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
424
 
425
        INSTANTIATE(sparc_ttable)
426
#ifdef CONFIG_SMP
427
        trap_table = &trapbase_cpu1; INSTANTIATE(trap_table)
428
        trap_table = &trapbase_cpu2; INSTANTIATE(trap_table)
429
        trap_table = &trapbase_cpu3; INSTANTIATE(trap_table)
430
#endif
431
#undef INSTANTIATE
432
        /*
433
         * XXX Correct thing whould be to flush only I- and D-cache lines
434
         * which contain the handler in question. But as of time of the
435
         * writing we have no CPU-neutral interface to fine-grained flushes.
436
         */
437
        flush_cache_all();
438
 
439
        action->flags = irqflags;
440
        cpus_clear(action->mask);
441
        action->name = devname;
442
        action->dev_id = NULL;
443
        action->next = NULL;
444
 
445
        sparc_irq[cpu_irq].action = action;
446
 
447
        __enable_irq(irq);
448
 
449
        ret = 0;
450
out_unlock:
451
        spin_unlock_irqrestore(&irq_action_lock, flags);
452
out:
453
        return ret;
454
}
455
 
456
/* These variables are used to access state from the assembler
457
 * interrupt handler, floppy_hardint, so we cannot put these in
458
 * the floppy driver image because that would not work in the
459
 * modular case.
460
 */
461
volatile unsigned char *fdc_status;
462
EXPORT_SYMBOL(fdc_status);
463
 
464
char *pdma_vaddr;
465
EXPORT_SYMBOL(pdma_vaddr);
466
 
467
unsigned long pdma_size;
468
EXPORT_SYMBOL(pdma_size);
469
 
470
volatile int doing_pdma;
471
EXPORT_SYMBOL(doing_pdma);
472
 
473
char *pdma_base;
474
EXPORT_SYMBOL(pdma_base);
475
 
476
unsigned long pdma_areasize;
477
EXPORT_SYMBOL(pdma_areasize);
478
 
479
extern void floppy_hardint(void);
480
 
481
static irq_handler_t floppy_irq_handler;
482
 
483
void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
484
{
485
        struct pt_regs *old_regs;
486
        int cpu = smp_processor_id();
487
 
488
        old_regs = set_irq_regs(regs);
489
        disable_pil_irq(irq);
490
        irq_enter();
491
        kstat_cpu(cpu).irqs[irq]++;
492
        floppy_irq_handler(irq, dev_id);
493
        irq_exit();
494
        enable_pil_irq(irq);
495
        set_irq_regs(old_regs);
496
        // XXX Eek, it's totally changed with preempt_count() and such
497
        // if (softirq_pending(cpu))
498
        //      do_softirq();
499
}
500
 
501
int sparc_floppy_request_irq(int irq, unsigned long flags,
502
                             irq_handler_t irq_handler)
503
{
504
        floppy_irq_handler = irq_handler;
505
        return request_fast_irq(irq, floppy_hardint, flags, "floppy");
506
}
507
EXPORT_SYMBOL(sparc_floppy_request_irq);
508
 
509
#endif
510
 
511
int request_irq(unsigned int irq,
512
                irq_handler_t handler,
513
                unsigned long irqflags, const char * devname, void *dev_id)
514
{
515
        struct irqaction * action, **actionp;
516
        unsigned long flags;
517
        unsigned int cpu_irq;
518
        int ret;
519
 
520
        if (sparc_cpu_model == sun4d) {
521
                extern int sun4d_request_irq(unsigned int,
522
                                             irq_handler_t ,
523
                                             unsigned long, const char *, void *);
524
                return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
525
        }
526
        cpu_irq = irq & (NR_IRQS - 1);
527
        if(cpu_irq > 14) {
528
                ret = -EINVAL;
529
                goto out;
530
        }
531
        if (!handler) {
532
                ret = -EINVAL;
533
                goto out;
534
        }
535
 
536
        spin_lock_irqsave(&irq_action_lock, flags);
537
 
538
        actionp = &sparc_irq[cpu_irq].action;
539
        action = *actionp;
540
        if (action) {
541
                if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) {
542
                        ret = -EBUSY;
543
                        goto out_unlock;
544
                }
545
                if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
546
                        printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
547
                        ret = -EBUSY;
548
                        goto out_unlock;
549
                }
550
                for ( ; action; action = *actionp)
551
                        actionp = &action->next;
552
        }
553
 
554
        /* If this is flagged as statically allocated then we use our
555
         * private struct which is never freed.
556
         */
557
        if (irqflags & SA_STATIC_ALLOC) {
558
                if (static_irq_count < MAX_STATIC_ALLOC)
559
                        action = &static_irqaction[static_irq_count++];
560
                else
561
                        printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
562
        }
563
 
564
        if (action == NULL)
565
                action = kmalloc(sizeof(struct irqaction),
566
                                                     GFP_ATOMIC);
567
 
568
        if (!action) {
569
                ret = -ENOMEM;
570
                goto out_unlock;
571
        }
572
 
573
        action->handler = handler;
574
        action->flags = irqflags;
575
        cpus_clear(action->mask);
576
        action->name = devname;
577
        action->next = NULL;
578
        action->dev_id = dev_id;
579
 
580
        *actionp = action;
581
 
582
        __enable_irq(irq);
583
 
584
        ret = 0;
585
out_unlock:
586
        spin_unlock_irqrestore(&irq_action_lock, flags);
587
out:
588
        return ret;
589
}
590
 
591
EXPORT_SYMBOL(request_irq);
592
 
593
void disable_irq_nosync(unsigned int irq)
594
{
595
        return __disable_irq(irq);
596
}
597
EXPORT_SYMBOL(disable_irq_nosync);
598
 
599
void disable_irq(unsigned int irq)
600
{
601
        return __disable_irq(irq);
602
}
603
EXPORT_SYMBOL(disable_irq);
604
 
605
void enable_irq(unsigned int irq)
606
{
607
        return __enable_irq(irq);
608
}
609
 
610
EXPORT_SYMBOL(enable_irq);
611
 
612
/* We really don't need these at all on the Sparc.  We only have
613
 * stubs here because they are exported to modules.
614
 */
615
unsigned long probe_irq_on(void)
616
{
617
        return 0;
618
}
619
 
620
EXPORT_SYMBOL(probe_irq_on);
621
 
622
int probe_irq_off(unsigned long mask)
623
{
624
        return 0;
625
}
626
 
627
EXPORT_SYMBOL(probe_irq_off);
628
 
629
/* djhr
630
 * This could probably be made indirect too and assigned in the CPU
631
 * bits of the code. That would be much nicer I think and would also
632
 * fit in with the idea of being able to tune your kernel for your machine
633
 * by removing unrequired machine and device support.
634
 *
635
 */
636
 
637
void __init init_IRQ(void)
638
{
639
        extern void sun4c_init_IRQ( void );
640
        extern void sun4m_init_IRQ( void );
641
        extern void sun4d_init_IRQ( void );
642
 
643
        switch(sparc_cpu_model) {
644
        case sun4c:
645
        case sun4:
646
                sun4c_init_IRQ();
647
                break;
648
 
649
        case sun4m:
650
#ifdef CONFIG_PCI
651
                pcic_probe();
652
                if (pcic_present()) {
653
                        sun4m_pci_init_IRQ();
654
                        break;
655
                }
656
#endif
657
                sun4m_init_IRQ();
658
                break;
659
 
660
        case sun4d:
661
                sun4d_init_IRQ();
662
                break;
663
 
664
        default:
665
                prom_printf("Cannot initialize IRQs on this Sun machine...");
666
                break;
667
        }
668
        btfixup();
669
}
670
 
671
void init_irq_proc(void)
672
{
673
        /* For now, nothing... */
674
}

powered by: WebSVN 2.1.0

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