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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      linux/arch/alpha/kernel/sys_eiger.c
3
 *
4
 *      Copyright (C) 1995 David A Rusling
5
 *      Copyright (C) 1996, 1999 Jay A Estabrook
6
 *      Copyright (C) 1998, 1999 Richard Henderson
7
 *      Copyright (C) 1999 Iain Grant
8
 *
9
 * Code supporting the EIGER (EV6+TSUNAMI).
10
 */
11
 
12
#include <linux/kernel.h>
13
#include <linux/types.h>
14
#include <linux/mm.h>
15
#include <linux/sched.h>
16
#include <linux/pci.h>
17
#include <linux/init.h>
18
 
19
#include <asm/ptrace.h>
20
#include <asm/system.h>
21
#include <asm/dma.h>
22
#include <asm/irq.h>
23
#include <asm/bitops.h>
24
#include <asm/mmu_context.h>
25
#include <asm/io.h>
26
#include <asm/pci.h>
27
#include <asm/pgtable.h>
28
#include <asm/core_tsunami.h>
29
#include <asm/hwrpb.h>
30
 
31
#include "proto.h"
32
#include "irq_impl.h"
33
#include "pci_impl.h"
34
#include "machvec_impl.h"
35
 
36
 
37
/* Note that this interrupt code is identical to TAKARA.  */
38
 
39
/* Note mask bit is true for DISABLED irqs.  */
40
static unsigned long cached_irq_mask[2] = { -1, -1 };
41
 
42
static inline void
43
eiger_update_irq_hw(unsigned long irq, unsigned long mask)
44
{
45
        int regaddr;
46
 
47
        mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
48
        regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
49
        outl(mask & 0xffff0000UL, regaddr);
50
}
51
 
52
static inline void
53
eiger_enable_irq(unsigned int irq)
54
{
55
        unsigned long mask;
56
        mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
57
        eiger_update_irq_hw(irq, mask);
58
}
59
 
60
static void
61
eiger_disable_irq(unsigned int irq)
62
{
63
        unsigned long mask;
64
        mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
65
        eiger_update_irq_hw(irq, mask);
66
}
67
 
68
static unsigned int
69
eiger_startup_irq(unsigned int irq)
70
{
71
        eiger_enable_irq(irq);
72
        return 0; /* never anything pending */
73
}
74
 
75
static void
76
eiger_end_irq(unsigned int irq)
77
{
78
        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
79
                eiger_enable_irq(irq);
80
}
81
 
82
static struct hw_interrupt_type eiger_irq_type = {
83
        typename:       "EIGER",
84
        startup:        eiger_startup_irq,
85
        shutdown:       eiger_disable_irq,
86
        enable:         eiger_enable_irq,
87
        disable:        eiger_disable_irq,
88
        ack:            eiger_disable_irq,
89
        end:            eiger_end_irq,
90
};
91
 
92
static void
93
eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
94
{
95
        unsigned intstatus;
96
 
97
        /*
98
         * The PALcode will have passed us vectors 0x800 or 0x810,
99
         * which are fairly arbitrary values and serve only to tell
100
         * us whether an interrupt has come in on IRQ0 or IRQ1. If
101
         * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
102
         * probably ISA, but PCI interrupts can come through IRQ0
103
         * as well if the interrupt controller isn't in accelerated
104
         * mode.
105
         *
106
         * OTOH, the accelerator thing doesn't seem to be working
107
         * overly well, so what we'll do instead is try directly
108
         * examining the Master Interrupt Register to see if it's a
109
         * PCI interrupt, and if _not_ then we'll pass it on to the
110
         * ISA handler.
111
         */
112
 
113
        intstatus = inw(0x500) & 15;
114
        if (intstatus) {
115
                /*
116
                 * This is a PCI interrupt. Check each bit and
117
                 * despatch an interrupt if it's set.
118
                 */
119
 
120
                if (intstatus & 8) handle_irq(16+3, regs);
121
                if (intstatus & 4) handle_irq(16+2, regs);
122
                if (intstatus & 2) handle_irq(16+1, regs);
123
                if (intstatus & 1) handle_irq(16+0, regs);
124
        } else {
125
                isa_device_interrupt(vector, regs);
126
        }
127
}
128
 
129
static void
130
eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
131
{
132
        int irq = (vector - 0x800) >> 4;
133
        handle_irq(irq, regs);
134
}
135
 
136
static void __init
137
eiger_init_irq(void)
138
{
139
        long i;
140
 
141
        outb(0, DMA1_RESET_REG);
142
        outb(0, DMA2_RESET_REG);
143
        outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
144
        outb(0, DMA2_MASK_REG);
145
 
146
        if (alpha_using_srm)
147
                alpha_mv.device_interrupt = eiger_srm_device_interrupt;
148
 
149
        for (i = 16; i < 128; i += 16)
150
                eiger_update_irq_hw(i, -1);
151
 
152
        init_i8259a_irqs();
153
 
154
        for (i = 16; i < 128; ++i) {
155
                irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
156
                irq_desc[i].handler = &eiger_irq_type;
157
        }
158
}
159
 
160
static int __init
161
eiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
162
{
163
        u8 irq_orig;
164
 
165
        /* The SRM console has already calculated out the IRQ value's for
166
           option cards. As this works lets just read in the value already
167
           set and change it to a useable value by Linux.
168
 
169
           All the IRQ values generated by the console are greater than 90,
170
           so we subtract 80 because it is (90 - allocated ISA IRQ's).  */
171
 
172
        pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);
173
 
174
        return irq_orig - 0x80;
175
}
176
 
177
static u8 __init
178
eiger_swizzle(struct pci_dev *dev, u8 *pinp)
179
{
180
        struct pci_controller *hose = dev->sysdata;
181
        int slot, pin = *pinp;
182
        int bridge_count = 0;
183
 
184
        /* Find the number of backplane bridges.  */
185
        int backplane = inw(0x502) & 0x0f;
186
 
187
        switch (backplane)
188
        {
189
           case 0x00: bridge_count = 0; break; /* No bridges */
190
           case 0x01: bridge_count = 1; break; /* 1 */
191
           case 0x03: bridge_count = 2; break; /* 2 */
192
           case 0x07: bridge_count = 3; break; /* 3 */
193
           case 0x0f: bridge_count = 4; break; /* 4 */
194
        };
195
 
196
        /*  Check first for the built-in bridges on hose 0. */
197
        if (hose->index == 0
198
            && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {
199
                slot = PCI_SLOT(dev->devfn);
200
        } else {
201
                /* Must be a card-based bridge.  */
202
                do {
203
                        /* Check for built-in bridges on hose 0. */
204
                        if (hose->index == 0
205
                            && (PCI_SLOT(dev->bus->self->devfn)
206
                                > 20 - bridge_count)) {
207
                                slot = PCI_SLOT(dev->devfn);
208
                                break;
209
                        }
210
                        pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
211
 
212
                        /* Move up the chain of bridges.  */
213
                        dev = dev->bus->self;
214
                        /* Slot of the next bridge.  */
215
                        slot = PCI_SLOT(dev->devfn);
216
                } while (dev->bus->self);
217
        }
218
        *pinp = pin;
219
        return slot;
220
}
221
 
222
/*
223
 * The System Vectors
224
 */
225
 
226
struct alpha_machine_vector eiger_mv __initmv = {
227
        vector_name:            "Eiger",
228
        DO_EV6_MMU,
229
        DO_DEFAULT_RTC,
230
        DO_TSUNAMI_IO,
231
        DO_TSUNAMI_BUS,
232
        machine_check:          tsunami_machine_check,
233
        max_dma_address:        ALPHA_MAX_DMA_ADDRESS,
234
        min_io_address:         DEFAULT_IO_BASE,
235
        min_mem_address:        DEFAULT_MEM_BASE,
236
        pci_dac_offset:         TSUNAMI_DAC_OFFSET,
237
 
238
        nr_irqs:                128,
239
        device_interrupt:       eiger_device_interrupt,
240
 
241
        init_arch:              tsunami_init_arch,
242
        init_irq:               eiger_init_irq,
243
        init_rtc:               common_init_rtc,
244
        init_pci:               common_init_pci,
245
        kill_arch:              tsunami_kill_arch,
246
        pci_map_irq:            eiger_map_irq,
247
        pci_swizzle:            eiger_swizzle,
248
};
249
ALIAS_MV(eiger)

powered by: WebSVN 2.1.0

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