File: /usr/src/linux/arch/alpha/kernel/sys_sable.c
1 /*
2 * linux/arch/alpha/kernel/sys_sable.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the Sable and Sable-Gamma systems.
9 */
10
11 #include <linux/config.h>
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/mmu_context.h>
24 #include <asm/io.h>
25 #include <asm/pgtable.h>
26 #include <asm/core_t2.h>
27
28 #include "proto.h"
29 #include "irq_impl.h"
30 #include "pci_impl.h"
31 #include "machvec_impl.h"
32
33 spinlock_t sable_irq_lock = SPIN_LOCK_UNLOCKED;
34
35 /*
36 * For SABLE, which is really baroque, we manage 40 IRQ's, but the
37 * hardware really only supports 24, not via normal ISA PIC,
38 * but cascaded custom 8259's, etc.
39 * 0-7 (char at 536)
40 * 8-15 (char at 53a)
41 * 16-23 (char at 53c)
42 *
43 * Summary Registers (536/53a/53c):
44 *
45 * Bit Meaning Kernel IRQ
46 *------------------------------------------
47 * 0 PCI slot 0 34
48 * 1 NCR810 (builtin) 33
49 * 2 TULIP (builtin) 32
50 * 3 mouse 12
51 * 4 PCI slot 1 35
52 * 5 PCI slot 2 36
53 * 6 keyboard 1
54 * 7 floppy 6
55 * 8 COM2 3
56 * 9 parallel port 7
57 *10 EISA irq 3 -
58 *11 EISA irq 4 -
59 *12 EISA irq 5 5
60 *13 EISA irq 6 -
61 *14 EISA irq 7 -
62 *15 COM1 4
63 *16 EISA irq 9 9
64 *17 EISA irq 10 10
65 *18 EISA irq 11 11
66 *19 EISA irq 12 -
67 *20 EISA irq 13 -
68 *21 EISA irq 14 14
69 *22 NC 15
70 *23 IIC -
71 */
72
73 static struct
74 {
75 char irq_to_mask[40];
76 char mask_to_irq[40];
77
78 /* Note mask bit is true for DISABLED irqs. */
79 unsigned long shadow_mask;
80 } sable_irq_swizzle = {
81 {
82 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
83 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
84 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
85 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
86 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
87 },
88 {
89 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
90 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
91 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
92 },
93 -1
94 };
95
96 static inline void
97 sable_update_irq_hw(unsigned long bit, unsigned long mask)
98 {
99 int port = 0x537;
100
101 if (bit >= 16) {
102 port = 0x53d;
103 mask >>= 16;
104 } else if (bit >= 8) {
105 port = 0x53b;
106 mask >>= 8;
107 }
108
109 outb(mask, port);
110 }
111
112 static inline void
113 sable_ack_irq_hw(unsigned long bit)
114 {
115 int port, val1, val2;
116
117 if (bit >= 16) {
118 port = 0x53c;
119 val1 = 0xE0 | (bit - 16);
120 val2 = 0xE0 | 4;
121 } else if (bit >= 8) {
122 port = 0x53a;
123 val1 = 0xE0 | (bit - 8);
124 val2 = 0xE0 | 3;
125 } else {
126 port = 0x536;
127 val1 = 0xE0 | (bit - 0);
128 val2 = 0xE0 | 1;
129 }
130
131 outb(val1, port); /* ack the slave */
132 outb(val2, 0x534); /* ack the master */
133 }
134
135 static inline void
136 sable_enable_irq(unsigned int irq)
137 {
138 unsigned long bit, mask;
139
140 bit = sable_irq_swizzle.irq_to_mask[irq];
141 spin_lock(&sable_irq_lock);
142 mask = sable_irq_swizzle.shadow_mask &= ~(1UL << bit);
143 sable_update_irq_hw(bit, mask);
144 spin_unlock(&sable_irq_lock);
145 }
146
147 static void
148 sable_disable_irq(unsigned int irq)
149 {
150 unsigned long bit, mask;
151
152 bit = sable_irq_swizzle.irq_to_mask[irq];
153 spin_lock(&sable_irq_lock);
154 mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
155 sable_update_irq_hw(bit, mask);
156 spin_unlock(&sable_irq_lock);
157 }
158
159 static unsigned int
160 sable_startup_irq(unsigned int irq)
161 {
162 sable_enable_irq(irq);
163 return 0;
164 }
165
166 static void
167 sable_end_irq(unsigned int irq)
168 {
169 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
170 sable_enable_irq(irq);
171 }
172
173 static void
174 sable_mask_and_ack_irq(unsigned int irq)
175 {
176 unsigned long bit, mask;
177
178 bit = sable_irq_swizzle.irq_to_mask[irq];
179 spin_lock(&sable_irq_lock);
180 mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
181 sable_update_irq_hw(bit, mask);
182 sable_ack_irq_hw(bit);
183 spin_unlock(&sable_irq_lock);
184 }
185
186 static struct hw_interrupt_type sable_irq_type = {
187 typename: "SABLE",
188 startup: sable_startup_irq,
189 shutdown: sable_disable_irq,
190 enable: sable_enable_irq,
191 disable: sable_disable_irq,
192 ack: sable_mask_and_ack_irq,
193 end: sable_end_irq,
194 };
195
196 static void
197 sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
198 {
199 /* Note that the vector reported by the SRM PALcode corresponds
200 to the interrupt mask bits, but we have to manage via more
201 normal IRQs. */
202
203 int bit, irq;
204
205 bit = (vector - 0x800) >> 4;
206 irq = sable_irq_swizzle.mask_to_irq[bit];
207 handle_irq(irq, regs);
208 }
209
210 static void __init
211 sable_init_irq(void)
212 {
213 long i;
214
215 outb(-1, 0x537); /* slave 0 */
216 outb(-1, 0x53b); /* slave 1 */
217 outb(-1, 0x53d); /* slave 2 */
218 outb(0x44, 0x535); /* enable cascades in master */
219
220 for (i = 0; i < 40; ++i) {
221 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
222 irq_desc[i].handler = &sable_irq_type;
223 }
224
225 common_init_isa_dma();
226 }
227
228
229 /*
230 * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
231 *
232 * The device to slot mapping looks like:
233 *
234 * Slot Device
235 * 0 TULIP
236 * 1 SCSI
237 * 2 PCI-EISA bridge
238 * 3 none
239 * 4 none
240 * 5 none
241 * 6 PCI on board slot 0
242 * 7 PCI on board slot 1
243 * 8 PCI on board slot 2
244 *
245 *
246 * This two layered interrupt approach means that we allocate IRQ 16 and
247 * above for PCI interrupts. The IRQ relates to which bit the interrupt
248 * comes in on. This makes interrupt processing much easier.
249 */
250 /*
251 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
252 * with the values in the irq swizzling tables above.
253 */
254
255 static int __init
256 sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
257 {
258 static char irq_tab[9][5] __initdata = {
259 /*INT INTA INTB INTC INTD */
260 { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
261 { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
262 { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
263 { -1, -1, -1, -1, -1}, /* IdSel 3, none */
264 { -1, -1, -1, -1, -1}, /* IdSel 4, none */
265 { -1, -1, -1, -1, -1}, /* IdSel 5, none */
266 { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
267 { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
268 { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
269 };
270 const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
271 return COMMON_TABLE_LOOKUP;
272 }
273
274
275 /*
276 * The System Vectors
277 *
278 * In order that T2_HAE_ADDRESS should be a constant, we play
279 * these games with GAMMA_BIAS.
280 */
281
282 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA)
283 #undef GAMMA_BIAS
284 #define GAMMA_BIAS 0
285 struct alpha_machine_vector sable_mv __initmv = {
286 vector_name: "Sable",
287 DO_EV4_MMU,
288 DO_DEFAULT_RTC,
289 DO_T2_IO,
290 DO_T2_BUS,
291 machine_check: t2_machine_check,
292 max_dma_address: ALPHA_MAX_DMA_ADDRESS,
293 min_io_address: EISA_DEFAULT_IO_BASE,
294 min_mem_address: DEFAULT_MEM_BASE,
295
296 nr_irqs: 40,
297 device_interrupt: sable_srm_device_interrupt,
298
299 init_arch: t2_init_arch,
300 init_irq: sable_init_irq,
301 init_rtc: common_init_rtc,
302 init_pci: common_init_pci,
303 kill_arch: NULL,
304 pci_map_irq: sable_map_irq,
305 pci_swizzle: common_swizzle,
306
307 sys: { t2: {
308 gamma_bias: 0
309 } }
310 };
311 ALIAS_MV(sable)
312 #endif
313
314 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA)
315 #undef GAMMA_BIAS
316 #define GAMMA_BIAS _GAMMA_BIAS
317 struct alpha_machine_vector sable_gamma_mv __initmv = {
318 vector_name: "Sable-Gamma",
319 DO_EV5_MMU,
320 DO_DEFAULT_RTC,
321 DO_T2_IO,
322 DO_T2_BUS,
323 machine_check: t2_machine_check,
324 max_dma_address: ALPHA_MAX_DMA_ADDRESS,
325 min_io_address: EISA_DEFAULT_IO_BASE,
326 min_mem_address: DEFAULT_MEM_BASE,
327
328 nr_irqs: 40,
329 device_interrupt: sable_srm_device_interrupt,
330
331 init_arch: t2_init_arch,
332 init_irq: sable_init_irq,
333 init_rtc: common_init_rtc,
334 init_pci: common_init_pci,
335 pci_map_irq: sable_map_irq,
336 pci_swizzle: common_swizzle,
337
338 sys: { t2: {
339 gamma_bias: _GAMMA_BIAS
340 } }
341 };
342 ALIAS_MV(sable_gamma)
343 #endif
344