diff options
author | Thiemo Seufer <ths@networkno.de> | 2005-08-31 11:55:16 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:32:13 -0400 |
commit | 37c8c642ea6deb4837c247de062e3f4c5ae2b282 (patch) | |
tree | c429ad5c7758883da9e90fb813b5b5bb1eff5c1e | |
parent | 7623debf267521771952870549f5c5d38c408ad1 (diff) |
IP22 EISA support update.
Signed-off-by: Thiemo Seufer <ths@networkno.de>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/sgi-ip22/ip22-eisa.c | 148 |
1 files changed, 67 insertions, 81 deletions
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index fa0e719c5bd1..b19820110aa3 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <asm/io.h> | ||
32 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
33 | #include <asm/mipsregs.h> | 34 | #include <asm/mipsregs.h> |
34 | #include <asm/addrspace.h> | 35 | #include <asm/addrspace.h> |
@@ -37,42 +38,29 @@ | |||
37 | #include <asm/sgi/mc.h> | 38 | #include <asm/sgi/mc.h> |
38 | #include <asm/sgi/ip22.h> | 39 | #include <asm/sgi/ip22.h> |
39 | 40 | ||
40 | #define EISA_MAX_SLOTS 4 | 41 | /* I2 has four EISA slots. */ |
42 | #define IP22_EISA_MAX_SLOTS 4 | ||
41 | #define EISA_MAX_IRQ 16 | 43 | #define EISA_MAX_IRQ 16 |
42 | 44 | ||
43 | #define EISA_TO_PHYS(x) (0x00080000 | (x)) | 45 | #define EIU_MODE_REG 0x0001ffc0 |
44 | #define EISA_TO_KSEG1(x) ((void *) KSEG1ADDR(EISA_TO_PHYS((x)))) | 46 | #define EIU_STAT_REG 0x0001ffc4 |
45 | 47 | #define EIU_PREMPT_REG 0x0001ffc8 | |
46 | #define EIU_MODE_REG 0x0009ffc0 | 48 | #define EIU_QUIET_REG 0x0001ffcc |
47 | #define EIU_STAT_REG 0x0009ffc4 | 49 | #define EIU_INTRPT_ACK 0x00010004 |
48 | #define EIU_PREMPT_REG 0x0009ffc8 | 50 | |
49 | #define EIU_QUIET_REG 0x0009ffcc | 51 | static char __init *decode_eisa_sig(unsigned long addr) |
50 | #define EIU_INTRPT_ACK 0x00090004 | ||
51 | |||
52 | #define EISA_DMA1_STATUS 8 | ||
53 | #define EISA_INT1_CTRL 0x20 | ||
54 | #define EISA_INT1_MASK 0x21 | ||
55 | #define EISA_INT2_CTRL 0xA0 | ||
56 | #define EISA_INT2_MASK 0xA1 | ||
57 | #define EISA_DMA2_STATUS 0xD0 | ||
58 | #define EISA_DMA2_WRITE_SINGLE 0xD4 | ||
59 | #define EISA_EXT_NMI_RESET_CTRL 0x461 | ||
60 | #define EISA_INT1_EDGE_LEVEL 0x4D0 | ||
61 | #define EISA_INT2_EDGE_LEVEL 0x4D1 | ||
62 | #define EISA_VENDOR_ID_OFFSET 0xC80 | ||
63 | |||
64 | #define EIU_WRITE_32(x,y) { *((u32 *) KSEG1ADDR(x)) = (u32) (y); mb(); } | ||
65 | #define EIU_READ_8(x) *((u8 *) KSEG1ADDR(x)) | ||
66 | #define EISA_WRITE_8(x,y) { *((u8 *) EISA_TO_KSEG1(x)) = (u8) (y); mb(); } | ||
67 | #define EISA_READ_8(x) *((u8 *) EISA_TO_KSEG1(x)) | ||
68 | |||
69 | static char *decode_eisa_sig(u8 * sig) | ||
70 | { | 52 | { |
71 | static char sig_str[8]; | 53 | static char sig_str[EISA_SIG_LEN]; |
72 | u16 rev; | 54 | u8 sig[4]; |
55 | u16 rev; | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < 4; i++) { | ||
59 | sig[i] = inb (addr + i); | ||
73 | 60 | ||
74 | if (sig[0] & 0x80) | 61 | if (!i && (sig[0] & 0x80)) |
75 | return NULL; | 62 | return NULL; |
63 | } | ||
76 | 64 | ||
77 | sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); | 65 | sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); |
78 | sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); | 66 | sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); |
@@ -83,23 +71,26 @@ static char *decode_eisa_sig(u8 * sig) | |||
83 | return sig_str; | 71 | return sig_str; |
84 | } | 72 | } |
85 | 73 | ||
86 | static void ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs) | 74 | static irqreturn_t ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs) |
87 | { | 75 | { |
88 | u8 eisa_irq; | 76 | u8 eisa_irq; |
89 | u8 dma1, dma2; | 77 | u8 dma1, dma2; |
90 | 78 | ||
91 | eisa_irq = EIU_READ_8(EIU_INTRPT_ACK); | 79 | eisa_irq = inb(EIU_INTRPT_ACK); |
92 | dma1 = EISA_READ_8(EISA_DMA1_STATUS); | 80 | dma1 = inb(EISA_DMA1_STATUS); |
93 | dma2 = EISA_READ_8(EISA_DMA2_STATUS); | 81 | dma2 = inb(EISA_DMA2_STATUS); |
94 | |||
95 | if (eisa_irq >= EISA_MAX_IRQ) { | ||
96 | /* Oops, Bad Stuff Happened... */ | ||
97 | printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq); | ||
98 | 82 | ||
99 | EISA_WRITE_8(EISA_INT2_CTRL, 0x20); | 83 | if (eisa_irq < EISA_MAX_IRQ) { |
100 | EISA_WRITE_8(EISA_INT1_CTRL, 0x20); | ||
101 | } else | ||
102 | do_IRQ(eisa_irq, regs); | 84 | do_IRQ(eisa_irq, regs); |
85 | return IRQ_HANDLED; | ||
86 | } | ||
87 | |||
88 | /* Oops, Bad Stuff Happened... */ | ||
89 | printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq); | ||
90 | |||
91 | outb(0x20, EISA_INT2_CTRL); | ||
92 | outb(0x20, EISA_INT1_CTRL); | ||
93 | return IRQ_NONE; | ||
103 | } | 94 | } |
104 | 95 | ||
105 | static void enable_eisa1_irq(unsigned int irq) | 96 | static void enable_eisa1_irq(unsigned int irq) |
@@ -109,9 +100,9 @@ static void enable_eisa1_irq(unsigned int irq) | |||
109 | 100 | ||
110 | local_irq_save(flags); | 101 | local_irq_save(flags); |
111 | 102 | ||
112 | mask = EISA_READ_8(EISA_INT1_MASK); | 103 | mask = inb(EISA_INT1_MASK); |
113 | mask &= ~((u8) (1 << irq)); | 104 | mask &= ~((u8) (1 << irq)); |
114 | EISA_WRITE_8(EISA_INT1_MASK, mask); | 105 | outb(mask, EISA_INT1_MASK); |
115 | 106 | ||
116 | local_irq_restore(flags); | 107 | local_irq_restore(flags); |
117 | } | 108 | } |
@@ -122,9 +113,9 @@ static unsigned int startup_eisa1_irq(unsigned int irq) | |||
122 | 113 | ||
123 | /* Only use edge interrupts for EISA */ | 114 | /* Only use edge interrupts for EISA */ |
124 | 115 | ||
125 | edge = EISA_READ_8(EISA_INT1_EDGE_LEVEL); | 116 | edge = inb(EISA_INT1_EDGE_LEVEL); |
126 | edge &= ~((u8) (1 << irq)); | 117 | edge &= ~((u8) (1 << irq)); |
127 | EISA_WRITE_8(EISA_INT1_EDGE_LEVEL, edge); | 118 | outb(edge, EISA_INT1_EDGE_LEVEL); |
128 | 119 | ||
129 | enable_eisa1_irq(irq); | 120 | enable_eisa1_irq(irq); |
130 | return 0; | 121 | return 0; |
@@ -134,9 +125,9 @@ static void disable_eisa1_irq(unsigned int irq) | |||
134 | { | 125 | { |
135 | u8 mask; | 126 | u8 mask; |
136 | 127 | ||
137 | mask = EISA_READ_8(EISA_INT1_MASK); | 128 | mask = inb(EISA_INT1_MASK); |
138 | mask |= ((u8) (1 << irq)); | 129 | mask |= ((u8) (1 << irq)); |
139 | EISA_WRITE_8(EISA_INT1_MASK, mask); | 130 | outb(mask, EISA_INT1_MASK); |
140 | } | 131 | } |
141 | 132 | ||
142 | #define shutdown_eisa1_irq disable_eisa1_irq | 133 | #define shutdown_eisa1_irq disable_eisa1_irq |
@@ -145,7 +136,7 @@ static void mask_and_ack_eisa1_irq(unsigned int irq) | |||
145 | { | 136 | { |
146 | disable_eisa1_irq(irq); | 137 | disable_eisa1_irq(irq); |
147 | 138 | ||
148 | EISA_WRITE_8(EISA_INT1_CTRL, 0x20); | 139 | outb(0x20, EISA_INT1_CTRL); |
149 | } | 140 | } |
150 | 141 | ||
151 | static void end_eisa1_irq(unsigned int irq) | 142 | static void end_eisa1_irq(unsigned int irq) |
@@ -171,9 +162,9 @@ static void enable_eisa2_irq(unsigned int irq) | |||
171 | 162 | ||
172 | local_irq_save(flags); | 163 | local_irq_save(flags); |
173 | 164 | ||
174 | mask = EISA_READ_8(EISA_INT2_MASK); | 165 | mask = inb(EISA_INT2_MASK); |
175 | mask &= ~((u8) (1 << (irq - 8))); | 166 | mask &= ~((u8) (1 << (irq - 8))); |
176 | EISA_WRITE_8(EISA_INT2_MASK, mask); | 167 | outb(mask, EISA_INT2_MASK); |
177 | 168 | ||
178 | local_irq_restore(flags); | 169 | local_irq_restore(flags); |
179 | } | 170 | } |
@@ -184,9 +175,9 @@ static unsigned int startup_eisa2_irq(unsigned int irq) | |||
184 | 175 | ||
185 | /* Only use edge interrupts for EISA */ | 176 | /* Only use edge interrupts for EISA */ |
186 | 177 | ||
187 | edge = EISA_READ_8(EISA_INT2_EDGE_LEVEL); | 178 | edge = inb(EISA_INT2_EDGE_LEVEL); |
188 | edge &= ~((u8) (1 << (irq - 8))); | 179 | edge &= ~((u8) (1 << (irq - 8))); |
189 | EISA_WRITE_8(EISA_INT2_EDGE_LEVEL, edge); | 180 | outb(edge, EISA_INT2_EDGE_LEVEL); |
190 | 181 | ||
191 | enable_eisa2_irq(irq); | 182 | enable_eisa2_irq(irq); |
192 | return 0; | 183 | return 0; |
@@ -196,9 +187,9 @@ static void disable_eisa2_irq(unsigned int irq) | |||
196 | { | 187 | { |
197 | u8 mask; | 188 | u8 mask; |
198 | 189 | ||
199 | mask = EISA_READ_8(EISA_INT2_MASK); | 190 | mask = inb(EISA_INT2_MASK); |
200 | mask |= ((u8) (1 << (irq - 8))); | 191 | mask |= ((u8) (1 << (irq - 8))); |
201 | EISA_WRITE_8(EISA_INT2_MASK, mask); | 192 | outb(mask, EISA_INT2_MASK); |
202 | } | 193 | } |
203 | 194 | ||
204 | #define shutdown_eisa2_irq disable_eisa2_irq | 195 | #define shutdown_eisa2_irq disable_eisa2_irq |
@@ -207,8 +198,7 @@ static void mask_and_ack_eisa2_irq(unsigned int irq) | |||
207 | { | 198 | { |
208 | disable_eisa2_irq(irq); | 199 | disable_eisa2_irq(irq); |
209 | 200 | ||
210 | EISA_WRITE_8(EISA_INT2_CTRL, 0x20); | 201 | outb(0x20, EISA_INT2_CTRL); |
211 | EISA_WRITE_8(EISA_INT1_CTRL, 0x20); | ||
212 | } | 202 | } |
213 | 203 | ||
214 | static void end_eisa2_irq(unsigned int irq) | 204 | static void end_eisa2_irq(unsigned int irq) |
@@ -241,7 +231,6 @@ int __init ip22_eisa_init(void) | |||
241 | { | 231 | { |
242 | int i, c; | 232 | int i, c; |
243 | char *str; | 233 | char *str; |
244 | u8 *slot_addr; | ||
245 | 234 | ||
246 | if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { | 235 | if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { |
247 | printk(KERN_INFO "EISA: bus not present.\n"); | 236 | printk(KERN_INFO "EISA: bus not present.\n"); |
@@ -249,11 +238,8 @@ int __init ip22_eisa_init(void) | |||
249 | } | 238 | } |
250 | 239 | ||
251 | printk(KERN_INFO "EISA: Probing bus...\n"); | 240 | printk(KERN_INFO "EISA: Probing bus...\n"); |
252 | for (c = 0, i = 1; i <= EISA_MAX_SLOTS; i++) { | 241 | for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) { |
253 | slot_addr = | 242 | if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) { |
254 | (u8 *) EISA_TO_KSEG1((0x1000 * i) + | ||
255 | EISA_VENDOR_ID_OFFSET); | ||
256 | if ((str = decode_eisa_sig(slot_addr))) { | ||
257 | printk(KERN_INFO "EISA: slot %d : %s detected.\n", | 243 | printk(KERN_INFO "EISA: slot %d : %s detected.\n", |
258 | i, str); | 244 | i, str); |
259 | c++; | 245 | c++; |
@@ -268,25 +254,25 @@ int __init ip22_eisa_init(void) | |||
268 | Please wave your favorite dead chicken over the busses */ | 254 | Please wave your favorite dead chicken over the busses */ |
269 | 255 | ||
270 | /* First say hello to the EIU */ | 256 | /* First say hello to the EIU */ |
271 | EIU_WRITE_32(EIU_PREMPT_REG, 0x0000FFFF); | 257 | outl(0x0000FFFF, EIU_PREMPT_REG); |
272 | EIU_WRITE_32(EIU_QUIET_REG, 1); | 258 | outl(1, EIU_QUIET_REG); |
273 | EIU_WRITE_32(EIU_MODE_REG, 0x40f3c07F); | 259 | outl(0x40f3c07F, EIU_MODE_REG); |
274 | 260 | ||
275 | /* Now be nice to the EISA chipset */ | 261 | /* Now be nice to the EISA chipset */ |
276 | EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 1); | 262 | outb(1, EISA_EXT_NMI_RESET_CTRL); |
277 | for (i = 0; i < 10000; i++); /* Wait long enough for the dust to settle */ | 263 | udelay(50); /* Wait long enough for the dust to settle */ |
278 | EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 0); | 264 | outb(0, EISA_EXT_NMI_RESET_CTRL); |
279 | EISA_WRITE_8(EISA_INT1_CTRL, 0x11); | 265 | outb(0x11, EISA_INT1_CTRL); |
280 | EISA_WRITE_8(EISA_INT2_CTRL, 0x11); | 266 | outb(0x11, EISA_INT2_CTRL); |
281 | EISA_WRITE_8(EISA_INT1_MASK, 0); | 267 | outb(0, EISA_INT1_MASK); |
282 | EISA_WRITE_8(EISA_INT2_MASK, 8); | 268 | outb(8, EISA_INT2_MASK); |
283 | EISA_WRITE_8(EISA_INT1_MASK, 4); | 269 | outb(4, EISA_INT1_MASK); |
284 | EISA_WRITE_8(EISA_INT2_MASK, 2); | 270 | outb(2, EISA_INT2_MASK); |
285 | EISA_WRITE_8(EISA_INT1_MASK, 1); | 271 | outb(1, EISA_INT1_MASK); |
286 | EISA_WRITE_8(EISA_INT2_MASK, 1); | 272 | outb(1, EISA_INT2_MASK); |
287 | EISA_WRITE_8(EISA_INT1_MASK, 0xfb); | 273 | outb(0xfb, EISA_INT1_MASK); |
288 | EISA_WRITE_8(EISA_INT2_MASK, 0xff); | 274 | outb(0xff, EISA_INT2_MASK); |
289 | EISA_WRITE_8(EISA_DMA2_WRITE_SINGLE, 0); | 275 | outb(0, EISA_DMA2_WRITE_SINGLE); |
290 | 276 | ||
291 | for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { | 277 | for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { |
292 | irq_desc[i].status = IRQ_DISABLED; | 278 | irq_desc[i].status = IRQ_DISABLED; |