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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ppc64/] [kernel/] [i8259.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * c 2001 PPC64 Team, IBM Corp
3
 *
4
 * This program is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU General Public License
6
 * as published by the Free Software Foundation; either version
7
 * 2 of the License, or (at your option) any later version.
8
 */
9
#include <linux/stddef.h>
10
#include <linux/init.h>
11
#include <linux/sched.h>
12
#include <linux/signal.h>
13
#include <linux/cache.h>
14
#include <asm/io.h>
15
#include "i8259.h"
16
#include <linux/irq.h>
17
#include <asm/ppcdebug.h>
18
 
19
unsigned char cached_8259[2] = { 0xff, 0xff };
20
#define cached_A1 (cached_8259[0])
21
#define cached_21 (cached_8259[1])
22
 
23
static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
24
 
25
int i8259_pic_irq_offset;
26
 
27
int i8259_irq(int cpu)
28
{
29
        int irq;
30
 
31
        spin_lock/*_irqsave*/(&i8259_lock/*, flags*/);
32
        /*
33
         * Perform an interrupt acknowledge cycle on controller 1
34
         */
35
        outb(0x0C, 0x20);
36
        irq = inb(0x20) & 7;
37
        if (irq == 2)
38
        {
39
                /*
40
                 * Interrupt is cascaded so perform interrupt
41
                 * acknowledge on controller 2
42
                 */
43
                outb(0x0C, 0xA0);
44
                irq = (inb(0xA0) & 7) + 8;
45
        }
46
        else if (irq==7)
47
        {
48
                /*
49
                 * This may be a spurious interrupt
50
                 *
51
                 * Read the interrupt status register. If the most
52
                 * significant bit is not set then there is no valid
53
                 * interrupt
54
                 */
55
                outb(0x0b, 0x20);
56
                if(~inb(0x20)&0x80) {
57
                        spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
58
                        return -1;
59
                }
60
        }
61
        spin_unlock/*_irqrestore*/(&i8259_lock/*, flags*/);
62
        return irq;
63
}
64
 
65
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
66
{
67
        unsigned long flags;
68
 
69
        spin_lock_irqsave(&i8259_lock, flags);
70
        if ( irq_nr >= i8259_pic_irq_offset )
71
                irq_nr -= i8259_pic_irq_offset;
72
 
73
        if (irq_nr > 7) {
74
                cached_A1 |= 1 << (irq_nr-8);
75
                inb(0xA1);      /* DUMMY */
76
                outb(cached_A1,0xA1);
77
                outb(0x20,0xA0);        /* Non-specific EOI */
78
                outb(0x20,0x20);        /* Non-specific EOI to cascade */
79
        } else {
80
                cached_21 |= 1 << irq_nr;
81
                inb(0x21);      /* DUMMY */
82
                outb(cached_21,0x21);
83
                outb(0x20,0x20);        /* Non-specific EOI */
84
        }
85
        spin_unlock_irqrestore(&i8259_lock, flags);
86
}
87
 
88
static void i8259_set_irq_mask(int irq_nr)
89
{
90
        outb(cached_A1,0xA1);
91
        outb(cached_21,0x21);
92
}
93
 
94
static void i8259_mask_irq(unsigned int irq_nr)
95
{
96
        unsigned long flags;
97
 
98
        spin_lock_irqsave(&i8259_lock, flags);
99
        if ( irq_nr >= i8259_pic_irq_offset )
100
                irq_nr -= i8259_pic_irq_offset;
101
        if ( irq_nr < 8 )
102
                cached_21 |= 1 << irq_nr;
103
        else
104
                cached_A1 |= 1 << (irq_nr-8);
105
        i8259_set_irq_mask(irq_nr);
106
        spin_unlock_irqrestore(&i8259_lock, flags);
107
}
108
 
109
static void i8259_unmask_irq(unsigned int irq_nr)
110
{
111
        unsigned long flags;
112
 
113
        spin_lock_irqsave(&i8259_lock, flags);
114
        if ( irq_nr >= i8259_pic_irq_offset )
115
                irq_nr -= i8259_pic_irq_offset;
116
        if ( irq_nr < 8 )
117
                cached_21 &= ~(1 << irq_nr);
118
        else
119
                cached_A1 &= ~(1 << (irq_nr-8));
120
        i8259_set_irq_mask(irq_nr);
121
        spin_unlock_irqrestore(&i8259_lock, flags);
122
}
123
 
124
static void i8259_end_irq(unsigned int irq)
125
{
126
        if (!(irqdesc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
127
            irqdesc(irq)->action)
128
                i8259_unmask_irq(irq);
129
}
130
 
131
struct hw_interrupt_type i8259_pic = {
132
        " i8259    ",
133
        NULL,
134
        NULL,
135
        i8259_unmask_irq,
136
        i8259_mask_irq,
137
        i8259_mask_and_ack_irq,
138
        i8259_end_irq,
139
        NULL
140
};
141
 
142
void __init i8259_init(void)
143
{
144
        unsigned long flags;
145
 
146
        spin_lock_irqsave(&i8259_lock, flags);
147
        /* init master interrupt controller */
148
        outb(0x11, 0x20); /* Start init sequence */
149
        outb(0x00, 0x21); /* Vector base */
150
        outb(0x04, 0x21); /* edge triggered, Cascade (slave) on IRQ2 */
151
        outb(0x01, 0x21); /* Select 8086 mode */
152
        outb(0xFF, 0x21); /* Mask all */
153
        /* init slave interrupt controller */
154
        outb(0x11, 0xA0); /* Start init sequence */
155
        outb(0x08, 0xA1); /* Vector base */
156
        outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
157
        outb(0x01, 0xA1); /* Select 8086 mode */
158
        outb(0xFF, 0xA1); /* Mask all */
159
        outb(cached_A1, 0xA1);
160
        outb(cached_21, 0x21);
161
        spin_unlock_irqrestore(&i8259_lock, flags);
162
        request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
163
                     "82c59 secondary cascade", NULL );
164
 
165
}

powered by: WebSVN 2.1.0

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