diff options
Diffstat (limited to 'arch/mips/sgi-ip22/ip22-eisa.c')
-rw-r--r-- | arch/mips/sgi-ip22/ip22-eisa.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c new file mode 100644 index 000000000..f3b0e90e0 --- /dev/null +++ b/arch/mips/sgi-ip22/ip22-eisa.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Basic EISA bus support for the SGI Indigo-2. | ||
3 | * | ||
4 | * (C) 2002 Pascal Dameme <netinet@freesurf.fr> | ||
5 | * and Marc Zyngier <mzyngier@freesurf.fr> | ||
6 | * | ||
7 | * This code is released under both the GPL version 2 and BSD | ||
8 | * licenses. Either license may be used. | ||
9 | * | ||
10 | * This code offers a very basic support for this EISA bus present in | ||
11 | * the SGI Indigo-2. It currently only supports PIO (forget about DMA | ||
12 | * for the time being). This is enough for a low-end ethernet card, | ||
13 | * but forget about your favorite SCSI card... | ||
14 | * | ||
15 | * TODO : | ||
16 | * - Fix bugs... | ||
17 | * - Add ISA support | ||
18 | * - Add DMA (yeah, right...). | ||
19 | * - Fix more bugs. | ||
20 | */ | ||
21 | |||
22 | #include <linux/eisa.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/kernel_stat.h> | ||
27 | #include <linux/signal.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/irq.h> | ||
33 | #include <asm/mipsregs.h> | ||
34 | #include <asm/addrspace.h> | ||
35 | #include <asm/processor.h> | ||
36 | #include <asm/sgi/ioc.h> | ||
37 | #include <asm/sgi/mc.h> | ||
38 | #include <asm/sgi/ip22.h> | ||
39 | #include <asm/i8259.h> | ||
40 | |||
41 | /* I2 has four EISA slots. */ | ||
42 | #define IP22_EISA_MAX_SLOTS 4 | ||
43 | #define EISA_MAX_IRQ 16 | ||
44 | |||
45 | #define EIU_MODE_REG 0x0001ffc0 | ||
46 | #define EIU_STAT_REG 0x0001ffc4 | ||
47 | #define EIU_PREMPT_REG 0x0001ffc8 | ||
48 | #define EIU_QUIET_REG 0x0001ffcc | ||
49 | #define EIU_INTRPT_ACK 0x00010004 | ||
50 | |||
51 | static char __init *decode_eisa_sig(unsigned long addr) | ||
52 | { | ||
53 | static char sig_str[EISA_SIG_LEN] __initdata; | ||
54 | u8 sig[4]; | ||
55 | u16 rev; | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < 4; i++) { | ||
59 | sig[i] = inb(addr + i); | ||
60 | |||
61 | if (!i && (sig[0] & 0x80)) | ||
62 | return NULL; | ||
63 | } | ||
64 | |||
65 | sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); | ||
66 | sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); | ||
67 | sig_str[2] = (sig[1] & 0x1f) + ('A' - 1); | ||
68 | rev = (sig[2] << 8) | sig[3]; | ||
69 | sprintf(sig_str + 3, "%04X", rev); | ||
70 | |||
71 | return sig_str; | ||
72 | } | ||
73 | |||
74 | static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) | ||
75 | { | ||
76 | u8 eisa_irq = inb(EIU_INTRPT_ACK); | ||
77 | |||
78 | inb(EISA_DMA1_STATUS); | ||
79 | inb(EISA_DMA2_STATUS); | ||
80 | |||
81 | if (eisa_irq < EISA_MAX_IRQ) { | ||
82 | do_IRQ(eisa_irq); | ||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | |||
86 | /* Oops, Bad Stuff Happened... */ | ||
87 | printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq); | ||
88 | |||
89 | outb(0x20, EISA_INT2_CTRL); | ||
90 | outb(0x20, EISA_INT1_CTRL); | ||
91 | |||
92 | return IRQ_NONE; | ||
93 | } | ||
94 | |||
95 | int __init ip22_eisa_init(void) | ||
96 | { | ||
97 | int i, c; | ||
98 | char *str; | ||
99 | |||
100 | if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { | ||
101 | printk(KERN_INFO "EISA: bus not present.\n"); | ||
102 | return 1; | ||
103 | } | ||
104 | |||
105 | printk(KERN_INFO "EISA: Probing bus...\n"); | ||
106 | for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) { | ||
107 | if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) { | ||
108 | printk(KERN_INFO "EISA: slot %d : %s detected.\n", | ||
109 | i, str); | ||
110 | c++; | ||
111 | } | ||
112 | } | ||
113 | printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s"); | ||
114 | #ifdef CONFIG_ISA | ||
115 | printk(KERN_INFO "ISA support compiled in.\n"); | ||
116 | #endif | ||
117 | |||
118 | /* Warning : BlackMagicAhead(tm). | ||
119 | Please wave your favorite dead chicken over the busses */ | ||
120 | |||
121 | /* First say hello to the EIU */ | ||
122 | outl(0x0000FFFF, EIU_PREMPT_REG); | ||
123 | outl(1, EIU_QUIET_REG); | ||
124 | outl(0x40f3c07F, EIU_MODE_REG); | ||
125 | |||
126 | /* Now be nice to the EISA chipset */ | ||
127 | outb(1, EISA_EXT_NMI_RESET_CTRL); | ||
128 | udelay(50); /* Wait long enough for the dust to settle */ | ||
129 | outb(0, EISA_EXT_NMI_RESET_CTRL); | ||
130 | outb(0, EISA_DMA2_WRITE_SINGLE); | ||
131 | |||
132 | init_i8259_irqs(); | ||
133 | |||
134 | if (request_irq(SGI_EISA_IRQ, ip22_eisa_intr, 0, "EISA", NULL)) | ||
135 | pr_err("Failed to request irq %d (EISA)\n", SGI_EISA_IRQ); | ||
136 | |||
137 | EISA_bus = 1; | ||
138 | return 0; | ||
139 | } | ||