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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [parisc/] [eisa.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * eisa.c - provide support for EISA adapters in PA-RISC machines
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
 * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
10
 * Copyright (c) 2001 Daniel Engstrom <5116@telia.com>
11
 *
12
 * There are two distinct EISA adapters.  Mongoose is found in machines
13
 * before the 712; then the Wax ASIC is used.  To complicate matters, the
14
 * Wax ASIC also includes a PS/2 and RS-232 controller, but those are
15
 * dealt with elsewhere; this file is concerned only with the EISA portions
16
 * of Wax.
17
 *
18
 *
19
 * HINT:
20
 * -----
21
 * To allow an ISA card to work properly in the EISA slot you need to
22
 * set an edge trigger level. This may be done on the palo command line
23
 * by adding the kernel parameter "eisa_irq_edge=n,n2,[...]]", with
24
 * n and n2 as the irq levels you want to use.
25
 *
26
 * Example: "eisa_irq_edge=10,11" allows ISA cards to operate at
27
 * irq levels 10 and 11.
28
 */
29
 
30
#include <linux/init.h>
31
#include <linux/ioport.h>
32
#include <linux/interrupt.h>
33
#include <linux/kernel.h>
34
#include <linux/module.h>
35
#include <linux/pci.h>
36
#include <linux/spinlock.h>
37
#include <linux/eisa.h>
38
 
39
#include <asm/byteorder.h>
40
#include <asm/io.h>
41
#include <asm/hardware.h>
42
#include <asm/processor.h>
43
#include <asm/parisc-device.h>
44
#include <asm/delay.h>
45
#include <asm/eisa_bus.h>
46
#include <asm/eisa_eeprom.h>
47
 
48
#if 0
49
#define EISA_DBG(msg, arg... ) printk(KERN_DEBUG "eisa: " msg , ## arg )
50
#else
51
#define EISA_DBG(msg, arg... )  
52
#endif
53
 
54
#define SNAKES_EEPROM_BASE_ADDR 0xF0810400
55
#define MIRAGE_EEPROM_BASE_ADDR 0xF00C0400
56
 
57
static DEFINE_SPINLOCK(eisa_irq_lock);
58
 
59
void __iomem *eisa_eeprom_addr __read_mostly;
60
 
61
/* We can only have one EISA adapter in the system because neither
62
 * implementation can be flexed.
63
 */
64
static struct eisa_ba {
65
        struct pci_hba_data     hba;
66
        unsigned long eeprom_addr;
67
        struct eisa_root_device root;
68
} eisa_dev;
69
 
70
/* Port ops */
71
 
72
static inline unsigned long eisa_permute(unsigned short port)
73
{
74
        if (port & 0x300) {
75
                return 0xfc000000 | ((port & 0xfc00) >> 6)
76
                        | ((port & 0x3f8) << 9) | (port & 7);
77
        } else {
78
                return 0xfc000000 | port;
79
        }
80
}
81
 
82
unsigned char eisa_in8(unsigned short port)
83
{
84
        if (EISA_bus)
85
                return gsc_readb(eisa_permute(port));
86
        return 0xff;
87
}
88
 
89
unsigned short eisa_in16(unsigned short port)
90
{
91
        if (EISA_bus)
92
                return le16_to_cpu(gsc_readw(eisa_permute(port)));
93
        return 0xffff;
94
}
95
 
96
unsigned int eisa_in32(unsigned short port)
97
{
98
        if (EISA_bus)
99
                return le32_to_cpu(gsc_readl(eisa_permute(port)));
100
        return 0xffffffff;
101
}
102
 
103
void eisa_out8(unsigned char data, unsigned short port)
104
{
105
        if (EISA_bus)
106
                gsc_writeb(data, eisa_permute(port));
107
}
108
 
109
void eisa_out16(unsigned short data, unsigned short port)
110
{
111
        if (EISA_bus)
112
                gsc_writew(cpu_to_le16(data), eisa_permute(port));
113
}
114
 
115
void eisa_out32(unsigned int data, unsigned short port)
116
{
117
        if (EISA_bus)
118
                gsc_writel(cpu_to_le32(data), eisa_permute(port));
119
}
120
 
121
#ifndef CONFIG_PCI
122
/* We call these directly without PCI.  See asm/io.h. */
123
EXPORT_SYMBOL(eisa_in8);
124
EXPORT_SYMBOL(eisa_in16);
125
EXPORT_SYMBOL(eisa_in32);
126
EXPORT_SYMBOL(eisa_out8);
127
EXPORT_SYMBOL(eisa_out16);
128
EXPORT_SYMBOL(eisa_out32);
129
#endif
130
 
131
/* Interrupt handling */
132
 
133
/* cached interrupt mask registers */
134
static int master_mask;
135
static int slave_mask;
136
 
137
/* the trig level can be set with the
138
 * eisa_irq_edge=n,n,n commandline parameter
139
 * We should really read this from the EEPROM
140
 * in the furure.
141
 */
142
/* irq 13,8,2,1,0 must be edge */
143
static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered */
144
 
145
 
146
/* called by free irq */
147
static void eisa_disable_irq(unsigned int irq)
148
{
149
        unsigned long flags;
150
 
151
        EISA_DBG("disable irq %d\n", irq);
152
        /* just mask for now */
153
        spin_lock_irqsave(&eisa_irq_lock, flags);
154
        if (irq & 8) {
155
                slave_mask |= (1 << (irq&7));
156
                eisa_out8(slave_mask, 0xa1);
157
        } else {
158
                master_mask |= (1 << (irq&7));
159
                eisa_out8(master_mask, 0x21);
160
        }
161
        spin_unlock_irqrestore(&eisa_irq_lock, flags);
162
        EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21));
163
        EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1));
164
}
165
 
166
/* called by request irq */
167
static void eisa_enable_irq(unsigned int irq)
168
{
169
        unsigned long flags;
170
        EISA_DBG("enable irq %d\n", irq);
171
 
172
        spin_lock_irqsave(&eisa_irq_lock, flags);
173
        if (irq & 8) {
174
                slave_mask &= ~(1 << (irq&7));
175
                eisa_out8(slave_mask, 0xa1);
176
        } else {
177
                master_mask &= ~(1 << (irq&7));
178
                eisa_out8(master_mask, 0x21);
179
        }
180
        spin_unlock_irqrestore(&eisa_irq_lock, flags);
181
        EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21));
182
        EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1));
183
}
184
 
185
static unsigned int eisa_startup_irq(unsigned int irq)
186
{
187
        eisa_enable_irq(irq);
188
        return 0;
189
}
190
 
191
static struct hw_interrupt_type eisa_interrupt_type = {
192
        .typename =     "EISA",
193
        .startup =      eisa_startup_irq,
194
        .shutdown =     eisa_disable_irq,
195
        .enable =       eisa_enable_irq,
196
        .disable =      eisa_disable_irq,
197
        .ack =          no_ack_irq,
198
        .end =          no_end_irq,
199
};
200
 
201
static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
202
{
203
        int irq = gsc_readb(0xfc01f000); /* EISA supports 16 irqs */
204
        unsigned long flags;
205
 
206
        spin_lock_irqsave(&eisa_irq_lock, flags);
207
        /* read IRR command */
208
        eisa_out8(0x0a, 0x20);
209
        eisa_out8(0x0a, 0xa0);
210
 
211
        EISA_DBG("irq IAR %02x 8259-1 irr %02x 8259-2 irr %02x\n",
212
                   irq, eisa_in8(0x20), eisa_in8(0xa0));
213
 
214
        /* read ISR command */
215
        eisa_out8(0x0a, 0x20);
216
        eisa_out8(0x0a, 0xa0);
217
        EISA_DBG("irq 8259-1 isr %02x imr %02x 8259-2 isr %02x imr %02x\n",
218
                 eisa_in8(0x20), eisa_in8(0x21), eisa_in8(0xa0), eisa_in8(0xa1));
219
 
220
        irq &= 0xf;
221
 
222
        /* mask irq and write eoi */
223
        if (irq & 8) {
224
                slave_mask |= (1 << (irq&7));
225
                eisa_out8(slave_mask, 0xa1);
226
                eisa_out8(0x60 | (irq&7),0xa0);/* 'Specific EOI' to slave */
227
                eisa_out8(0x62,0x20);   /* 'Specific EOI' to master-IRQ2 */
228
 
229
        } else {
230
                master_mask |= (1 << (irq&7));
231
                eisa_out8(master_mask, 0x21);
232
                eisa_out8(0x60|irq,0x20);       /* 'Specific EOI' to master */
233
        }
234
        spin_unlock_irqrestore(&eisa_irq_lock, flags);
235
 
236
        __do_IRQ(irq);
237
 
238
        spin_lock_irqsave(&eisa_irq_lock, flags);
239
        /* unmask */
240
        if (irq & 8) {
241
                slave_mask &= ~(1 << (irq&7));
242
                eisa_out8(slave_mask, 0xa1);
243
        } else {
244
                master_mask &= ~(1 << (irq&7));
245
                eisa_out8(master_mask, 0x21);
246
        }
247
        spin_unlock_irqrestore(&eisa_irq_lock, flags);
248
        return IRQ_HANDLED;
249
}
250
 
251
static irqreturn_t dummy_irq2_handler(int _, void *dev)
252
{
253
        printk(KERN_ALERT "eisa: uhh, irq2?\n");
254
        return IRQ_HANDLED;
255
}
256
 
257
static struct irqaction irq2_action = {
258
        .handler = dummy_irq2_handler,
259
        .name = "cascade",
260
};
261
 
262
static void init_eisa_pic(void)
263
{
264
        unsigned long flags;
265
 
266
        spin_lock_irqsave(&eisa_irq_lock, flags);
267
 
268
        eisa_out8(0xff, 0x21); /* mask during init */
269
        eisa_out8(0xff, 0xa1); /* mask during init */
270
 
271
        /* master pic */
272
        eisa_out8(0x11,0x20); /* ICW1 */
273
        eisa_out8(0x00,0x21); /* ICW2 */
274
        eisa_out8(0x04,0x21); /* ICW3 */
275
        eisa_out8(0x01,0x21); /* ICW4 */
276
        eisa_out8(0x40,0x20); /* OCW2 */
277
 
278
        /* slave pic */
279
        eisa_out8(0x11,0xa0); /* ICW1 */
280
        eisa_out8(0x08,0xa1); /* ICW2 */
281
        eisa_out8(0x02,0xa1); /* ICW3 */
282
        eisa_out8(0x01,0xa1); /* ICW4 */
283
        eisa_out8(0x40,0xa0); /* OCW2 */
284
 
285
        udelay(100);
286
 
287
        slave_mask = 0xff;
288
        master_mask = 0xfb;
289
        eisa_out8(slave_mask, 0xa1); /* OCW1 */
290
        eisa_out8(master_mask, 0x21); /* OCW1 */
291
 
292
        /* setup trig level */
293
        EISA_DBG("EISA edge/level %04x\n", eisa_irq_level);
294
 
295
        eisa_out8(eisa_irq_level&0xff, 0x4d0); /* Set all irq's to edge  */
296
        eisa_out8((eisa_irq_level >> 8) & 0xff, 0x4d1);
297
 
298
        EISA_DBG("pic0 mask %02x\n", eisa_in8(0x21));
299
        EISA_DBG("pic1 mask %02x\n", eisa_in8(0xa1));
300
        EISA_DBG("pic0 edge/level %02x\n", eisa_in8(0x4d0));
301
        EISA_DBG("pic1 edge/level %02x\n", eisa_in8(0x4d1));
302
 
303
        spin_unlock_irqrestore(&eisa_irq_lock, flags);
304
}
305
 
306
/* Device initialisation */
307
 
308
#define is_mongoose(dev) (dev->id.sversion == 0x00076)
309
 
310
static int __init eisa_probe(struct parisc_device *dev)
311
{
312
        int i, result;
313
 
314
        char *name = is_mongoose(dev) ? "Mongoose" : "Wax";
315
 
316
        printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n",
317
                name, dev->hpa.start);
318
 
319
        eisa_dev.hba.dev = dev;
320
        eisa_dev.hba.iommu = ccio_get_iommu(dev);
321
 
322
        eisa_dev.hba.lmmio_space.name = "EISA";
323
        eisa_dev.hba.lmmio_space.start = F_EXTEND(0xfc000000);
324
        eisa_dev.hba.lmmio_space.end = F_EXTEND(0xffbfffff);
325
        eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM;
326
        result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space);
327
        if (result < 0) {
328
                printk(KERN_ERR "EISA: failed to claim EISA Bus address space!\n");
329
                return result;
330
        }
331
        eisa_dev.hba.io_space.name = "EISA";
332
        eisa_dev.hba.io_space.start = 0;
333
        eisa_dev.hba.io_space.end = 0xffff;
334
        eisa_dev.hba.lmmio_space.flags = IORESOURCE_IO;
335
        result = request_resource(&ioport_resource, &eisa_dev.hba.io_space);
336
        if (result < 0) {
337
                printk(KERN_ERR "EISA: failed to claim EISA Bus port space!\n");
338
                return result;
339
        }
340
        pcibios_register_hba(&eisa_dev.hba);
341
 
342
        result = request_irq(dev->irq, eisa_irq, IRQF_SHARED, "EISA", &eisa_dev);
343
        if (result) {
344
                printk(KERN_ERR "EISA: request_irq failed!\n");
345
                return result;
346
        }
347
 
348
        /* Reserve IRQ2 */
349
        irq_desc[2].action = &irq2_action;
350
 
351
        for (i = 0; i < 16; i++) {
352
                irq_desc[i].chip = &eisa_interrupt_type;
353
        }
354
 
355
        EISA_bus = 1;
356
 
357
        if (dev->num_addrs) {
358
                /* newer firmware hand out the eeprom address */
359
                eisa_dev.eeprom_addr = dev->addr[0];
360
        } else {
361
                /* old firmware, need to figure out the box */
362
                if (is_mongoose(dev)) {
363
                        eisa_dev.eeprom_addr = SNAKES_EEPROM_BASE_ADDR;
364
                } else {
365
                        eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR;
366
                }
367
        }
368
        eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
369
        result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space,
370
                        &eisa_dev.hba.lmmio_space);
371
        init_eisa_pic();
372
 
373
        if (result >= 0) {
374
                /* FIXME : Don't enumerate the bus twice. */
375
                eisa_dev.root.dev = &dev->dev;
376
                dev->dev.driver_data = &eisa_dev.root;
377
                eisa_dev.root.bus_base_addr = 0;
378
                eisa_dev.root.res = &eisa_dev.hba.io_space;
379
                eisa_dev.root.slots = result;
380
                eisa_dev.root.dma_mask = 0xffffffff; /* wild guess */
381
                if (eisa_root_register (&eisa_dev.root)) {
382
                        printk(KERN_ERR "EISA: Failed to register EISA root\n");
383
                        return -1;
384
                }
385
        }
386
 
387
        return 0;
388
}
389
 
390
static const struct parisc_device_id eisa_tbl[] = {
391
        { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */
392
        { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */
393
        { 0, }
394
};
395
 
396
MODULE_DEVICE_TABLE(parisc, eisa_tbl);
397
 
398
static struct parisc_driver eisa_driver = {
399
        .name =         "eisa_ba",
400
        .id_table =     eisa_tbl,
401
        .probe =        eisa_probe,
402
};
403
 
404
void __init eisa_init(void)
405
{
406
        register_parisc_driver(&eisa_driver);
407
}
408
 
409
 
410
static unsigned int eisa_irq_configured;
411
void eisa_make_irq_level(int num)
412
{
413
        if (eisa_irq_configured& (1<<num)) {
414
                printk(KERN_WARNING
415
                       "IRQ %d polarity configured twice (last to level)\n",
416
                       num);
417
        }
418
        eisa_irq_level |= (1<<num); /* set the corresponding bit */
419
        eisa_irq_configured |= (1<<num); /* set the corresponding bit */
420
}
421
 
422
void eisa_make_irq_edge(int num)
423
{
424
        if (eisa_irq_configured& (1<<num)) {
425
                printk(KERN_WARNING
426
                       "IRQ %d polarity configured twice (last to edge)\n",
427
                       num);
428
        }
429
        eisa_irq_level &= ~(1<<num); /* clear the corresponding bit */
430
        eisa_irq_configured |= (1<<num); /* set the corresponding bit */
431
}
432
 
433
static int __init eisa_irq_setup(char *str)
434
{
435
        char *cur = str;
436
        int val;
437
 
438
        EISA_DBG("IRQ setup\n");
439
        while (cur != NULL) {
440
                char *pe;
441
 
442
                val = (int) simple_strtoul(cur, &pe, 0);
443
                if (val > 15 || val < 0) {
444
                        printk(KERN_ERR "eisa: EISA irq value are 0-15\n");
445
                        continue;
446
                }
447
                if (val == 2) {
448
                        val = 9;
449
                }
450
                eisa_make_irq_edge(val); /* clear the corresponding bit */
451
                EISA_DBG("setting IRQ %d to edge-triggered mode\n", val);
452
 
453
                if ((cur = strchr(cur, ','))) {
454
                        cur++;
455
                } else {
456
                        break;
457
                }
458
        }
459
        return 1;
460
}
461
 
462
__setup("eisa_irq_edge=", eisa_irq_setup);
463
 

powered by: WebSVN 2.1.0

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