xref: /linux/arch/alpha/kernel/sys_cabriolet.c (revision 9b031c86506cef9acae45e61339fcf9deaabb793)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *	linux/arch/alpha/kernel/sys_cabriolet.c
4  *
5  *	Copyright (C) 1995 David A Rusling
6  *	Copyright (C) 1996 Jay A Estabrook
7  *	Copyright (C) 1998, 1999, 2000 Richard Henderson
8  *
9  * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
10  * PC164 and LX164.
11  */
12 
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/mm.h>
16 #include <linux/sched.h>
17 #include <linux/pci.h>
18 #include <linux/init.h>
19 #include <linux/bitops.h>
20 
21 #include <asm/ptrace.h>
22 #include <asm/dma.h>
23 #include <asm/irq.h>
24 #include <asm/mmu_context.h>
25 #include <asm/io.h>
26 #include <asm/pgtable.h>
27 #include <asm/core_apecs.h>
28 #include <asm/core_cia.h>
29 #include <asm/core_lca.h>
30 #include <asm/tlbflush.h>
31 
32 #include "proto.h"
33 #include "irq_impl.h"
34 #include "pci_impl.h"
35 #include "machvec_impl.h"
36 #include "pc873xx.h"
37 
38 /* Note mask bit is true for DISABLED irqs.  */
39 static unsigned long cached_irq_mask = ~0UL;
40 
41 static inline void
42 cabriolet_update_irq_hw(unsigned int irq, unsigned long mask)
43 {
44 	int ofs = (irq - 16) / 8;
45 	outb(mask >> (16 + ofs * 8), 0x804 + ofs);
46 }
47 
48 static inline void
49 cabriolet_enable_irq(struct irq_data *d)
50 {
51 	cabriolet_update_irq_hw(d->irq, cached_irq_mask &= ~(1UL << d->irq));
52 }
53 
54 static void
55 cabriolet_disable_irq(struct irq_data *d)
56 {
57 	cabriolet_update_irq_hw(d->irq, cached_irq_mask |= 1UL << d->irq);
58 }
59 
60 static struct irq_chip cabriolet_irq_type = {
61 	.name		= "CABRIOLET",
62 	.irq_unmask	= cabriolet_enable_irq,
63 	.irq_mask	= cabriolet_disable_irq,
64 	.irq_mask_ack	= cabriolet_disable_irq,
65 };
66 
67 static void
68 cabriolet_device_interrupt(unsigned long v)
69 {
70 	unsigned long pld;
71 	unsigned int i;
72 
73 	/* Read the interrupt summary registers */
74 	pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
75 
76 	/*
77 	 * Now for every possible bit set, work through them and call
78 	 * the appropriate interrupt handler.
79 	 */
80 	while (pld) {
81 		i = ffz(~pld);
82 		pld &= pld - 1;	/* clear least bit set */
83 		if (i == 4) {
84 			isa_device_interrupt(v);
85 		} else {
86 			handle_irq(16 + i);
87 		}
88 	}
89 }
90 
91 static void __init
92 common_init_irq(void (*srm_dev_int)(unsigned long v))
93 {
94 	init_i8259a_irqs();
95 
96 	if (alpha_using_srm) {
97 		alpha_mv.device_interrupt = srm_dev_int;
98 		init_srm_irqs(35, 0);
99 	}
100 	else {
101 		long i;
102 
103 		outb(0xff, 0x804);
104 		outb(0xff, 0x805);
105 		outb(0xff, 0x806);
106 
107 		for (i = 16; i < 35; ++i) {
108 			irq_set_chip_and_handler(i, &cabriolet_irq_type,
109 						 handle_level_irq);
110 			irq_set_status_flags(i, IRQ_LEVEL);
111 		}
112 	}
113 
114 	common_init_isa_dma();
115 	if (request_irq(16 + 4, no_action, 0, "isa-cascade", NULL))
116 		pr_err("Failed to register isa-cascade interrupt\n");
117 }
118 
119 #ifndef CONFIG_ALPHA_PC164
120 static void __init
121 cabriolet_init_irq(void)
122 {
123 	common_init_irq(srm_device_interrupt);
124 }
125 #endif
126 
127 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
128 /* In theory, the PC164 has the same interrupt hardware as the other
129    Cabriolet based systems.  However, something got screwed up late
130    in the development cycle which broke the interrupt masking hardware.
131    Repeat, it is not possible to mask and ack interrupts.  At all.
132 
133    In an attempt to work around this, while processing interrupts,
134    we do not allow the IPL to drop below what it is currently.  This
135    prevents the possibility of recursion.
136 
137    ??? Another option might be to force all PCI devices to use edge
138    triggered rather than level triggered interrupts.  That might be
139    too invasive though.  */
140 
141 static void
142 pc164_srm_device_interrupt(unsigned long v)
143 {
144 	__min_ipl = getipl();
145 	srm_device_interrupt(v);
146 	__min_ipl = 0;
147 }
148 
149 static void
150 pc164_device_interrupt(unsigned long v)
151 {
152 	__min_ipl = getipl();
153 	cabriolet_device_interrupt(v);
154 	__min_ipl = 0;
155 }
156 
157 static void __init
158 pc164_init_irq(void)
159 {
160 	common_init_irq(pc164_srm_device_interrupt);
161 }
162 #endif
163 
164 /*
165  * The EB66+ is very similar to the EB66 except that it does not have
166  * the on-board NCR and Tulip chips.  In the code below, I have used
167  * slot number to refer to the id select line and *not* the slot
168  * number used in the EB66+ documentation.  However, in the table,
169  * I've given the slot number, the id select line and the Jxx number
170  * that's printed on the board.  The interrupt pins from the PCI slots
171  * are wired into 3 interrupt summary registers at 0x804, 0x805 and
172  * 0x806 ISA.
173  *
174  * In the table, -1 means don't assign an IRQ number.  This is usually
175  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
176  */
177 
178 static inline int
179 eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
180 {
181 	static char irq_tab[5][5] = {
182 		/*INT  INTA  INTB  INTC   INTD */
183 		{16+0, 16+0, 16+5,  16+9, 16+13},  /* IdSel 6,  slot 0, J25 */
184 		{16+1, 16+1, 16+6, 16+10, 16+14},  /* IdSel 7,  slot 1, J26 */
185 		{  -1,   -1,   -1,    -1,    -1},  /* IdSel 8,  SIO         */
186 		{16+2, 16+2, 16+7, 16+11, 16+15},  /* IdSel 9,  slot 2, J27 */
187 		{16+3, 16+3, 16+8, 16+12,  16+6}   /* IdSel 10, slot 3, J28 */
188 	};
189 	const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5;
190 	return COMMON_TABLE_LOOKUP;
191 }
192 
193 
194 /*
195  * The AlphaPC64 is very similar to the EB66+ except that its slots
196  * are numbered differently.  In the code below, I have used slot
197  * number to refer to the id select line and *not* the slot number
198  * used in the AlphaPC64 documentation.  However, in the table, I've
199  * given the slot number, the id select line and the Jxx number that's
200  * printed on the board.  The interrupt pins from the PCI slots are
201  * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
202  * ISA.
203  *
204  * In the table, -1 means don't assign an IRQ number.  This is usually
205  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
206  */
207 
208 static inline int
209 cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
210 {
211 	static char irq_tab[5][5] = {
212 		/*INT   INTA  INTB  INTC   INTD */
213 		{ 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5,  slot 2, J21 */
214 		{ 16+0, 16+0, 16+5,  16+9, 16+13}, /* IdSel 6,  slot 0, J19 */
215 		{ 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7,  slot 1, J20 */
216 		{   -1,   -1,   -1,    -1,    -1}, /* IdSel 8,  SIO         */
217 		{ 16+3, 16+3, 16+8, 16+12, 16+16}  /* IdSel 9,  slot 3, J22 */
218 	};
219 	const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
220 	return COMMON_TABLE_LOOKUP;
221 }
222 
223 static inline void __init
224 cabriolet_enable_ide(void)
225 {
226 	if (pc873xx_probe() == -1) {
227 		printk(KERN_ERR "Probing for PC873xx Super IO chip failed.\n");
228 	 } else {
229 		printk(KERN_INFO "Found %s Super IO chip at 0x%x\n",
230 			pc873xx_get_model(), pc873xx_get_base());
231 
232 		pc873xx_enable_ide();
233 	}
234 }
235 
236 static inline void __init
237 cabriolet_init_pci(void)
238 {
239 	common_init_pci();
240 	cabriolet_enable_ide();
241 }
242 
243 static inline void __init
244 cia_cab_init_pci(void)
245 {
246 	cia_init_pci();
247 	cabriolet_enable_ide();
248 }
249 
250 /*
251  * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
252  * PCI slots, the SIO, PCI/IDE, and USB.
253  *
254  * Each of the interrupts can be individually masked. This is
255  * accomplished by setting the appropriate bit in the mask register.
256  * A bit is set by writing a "1" to the desired position in the mask
257  * register and cleared by writing a "0". There are 3 mask registers
258  * located at ISA address 804h, 805h and 806h.
259  *
260  * An I/O read at ISA address 804h, 805h, 806h will return the
261  * state of the 11 PCI interrupts and not the state of the MASKED
262  * interrupts.
263  *
264  * Note: A write to I/O 804h, 805h, and 806h the mask register will be
265  * updated.
266  *
267  *
268  * 				ISA DATA<7:0>
269  * ISA     +--------------------------------------------------------------+
270  * ADDRESS |   7   |   6   |   5   |   4   |   3   |   2  |   1   |   0   |
271  *         +==============================================================+
272  * 0x804   | INTB0 |  USB  |  IDE  |  SIO  | INTA3 |INTA2 | INTA1 | INTA0 |
273  *         +--------------------------------------------------------------+
274  * 0x805   | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
275  *         +--------------------------------------------------------------+
276  * 0x806   | Rsrv  | Rsrv  | Rsrv  | Rsrv  | Rsrv  |INTD3 | INTD2 | INTD1 |
277  *         +--------------------------------------------------------------+
278  *         * Rsrv = reserved bits
279  *         Note: The mask register is write-only.
280  *
281  * IdSel
282  *   5	 32 bit PCI option slot 2
283  *   6	 64 bit PCI option slot 0
284  *   7	 64 bit PCI option slot 1
285  *   8	 Saturn I/O
286  *   9	 32 bit PCI option slot 3
287  *  10	 USB
288  *  11	 IDE
289  *
290  */
291 
292 static inline int
293 alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
294 {
295 	static char irq_tab[7][5] = {
296 		/*INT   INTA  INTB   INTC   INTD */
297 		{ 16+2, 16+2, 16+9,  16+13, 16+17}, /* IdSel  5, slot 2, J20 */
298 		{ 16+0, 16+0, 16+7,  16+11, 16+15}, /* IdSel  6, slot 0, J29 */
299 		{ 16+1, 16+1, 16+8,  16+12, 16+16}, /* IdSel  7, slot 1, J26 */
300 		{   -1,   -1,   -1,    -1,    -1},  /* IdSel  8, SIO */
301 		{ 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel  9, slot 3, J19 */
302 		{ 16+6, 16+6, 16+6,  16+6,  16+6},  /* IdSel 10, USB */
303 		{ 16+5, 16+5, 16+5,  16+5,  16+5}   /* IdSel 11, IDE */
304 	};
305 	const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5;
306 	return COMMON_TABLE_LOOKUP;
307 }
308 
309 static inline void __init
310 alphapc164_init_pci(void)
311 {
312 	cia_init_pci();
313 	SMC93x_Init();
314 }
315 
316 
317 /*
318  * The System Vector
319  */
320 
321 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
322 struct alpha_machine_vector cabriolet_mv __initmv = {
323 	.vector_name		= "Cabriolet",
324 	DO_EV4_MMU,
325 	DO_DEFAULT_RTC,
326 	DO_APECS_IO,
327 	.machine_check		= apecs_machine_check,
328 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
329 	.min_io_address		= DEFAULT_IO_BASE,
330 	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,
331 
332 	.nr_irqs		= 35,
333 	.device_interrupt	= cabriolet_device_interrupt,
334 
335 	.init_arch		= apecs_init_arch,
336 	.init_irq		= cabriolet_init_irq,
337 	.init_rtc		= common_init_rtc,
338 	.init_pci		= cabriolet_init_pci,
339 	.pci_map_irq		= cabriolet_map_irq,
340 	.pci_swizzle		= common_swizzle,
341 };
342 #ifndef CONFIG_ALPHA_EB64P
343 ALIAS_MV(cabriolet)
344 #endif
345 #endif
346 
347 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
348 struct alpha_machine_vector eb164_mv __initmv = {
349 	.vector_name		= "EB164",
350 	DO_EV5_MMU,
351 	DO_DEFAULT_RTC,
352 	DO_CIA_IO,
353 	.machine_check		= cia_machine_check,
354 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
355 	.min_io_address		= DEFAULT_IO_BASE,
356 	.min_mem_address	= CIA_DEFAULT_MEM_BASE,
357 
358 	.nr_irqs		= 35,
359 	.device_interrupt	= cabriolet_device_interrupt,
360 
361 	.init_arch		= cia_init_arch,
362 	.init_irq		= cabriolet_init_irq,
363 	.init_rtc		= common_init_rtc,
364 	.init_pci		= cia_cab_init_pci,
365 	.kill_arch		= cia_kill_arch,
366 	.pci_map_irq		= cabriolet_map_irq,
367 	.pci_swizzle		= common_swizzle,
368 };
369 ALIAS_MV(eb164)
370 #endif
371 
372 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P)
373 struct alpha_machine_vector eb66p_mv __initmv = {
374 	.vector_name		= "EB66+",
375 	DO_EV4_MMU,
376 	DO_DEFAULT_RTC,
377 	DO_LCA_IO,
378 	.machine_check		= lca_machine_check,
379 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
380 	.min_io_address		= DEFAULT_IO_BASE,
381 	.min_mem_address	= APECS_AND_LCA_DEFAULT_MEM_BASE,
382 
383 	.nr_irqs		= 35,
384 	.device_interrupt	= cabriolet_device_interrupt,
385 
386 	.init_arch		= lca_init_arch,
387 	.init_irq		= cabriolet_init_irq,
388 	.init_rtc		= common_init_rtc,
389 	.init_pci		= cabriolet_init_pci,
390 	.pci_map_irq		= eb66p_map_irq,
391 	.pci_swizzle		= common_swizzle,
392 };
393 ALIAS_MV(eb66p)
394 #endif
395 
396 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164)
397 struct alpha_machine_vector lx164_mv __initmv = {
398 	.vector_name		= "LX164",
399 	DO_EV5_MMU,
400 	DO_DEFAULT_RTC,
401 	DO_PYXIS_IO,
402 	.machine_check		= cia_machine_check,
403 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
404 	.min_io_address		= DEFAULT_IO_BASE,
405 	.min_mem_address	= DEFAULT_MEM_BASE,
406 	.pci_dac_offset		= PYXIS_DAC_OFFSET,
407 
408 	.nr_irqs		= 35,
409 	.device_interrupt	= cabriolet_device_interrupt,
410 
411 	.init_arch		= pyxis_init_arch,
412 	.init_irq		= cabriolet_init_irq,
413 	.init_rtc		= common_init_rtc,
414 	.init_pci		= alphapc164_init_pci,
415 	.kill_arch		= cia_kill_arch,
416 	.pci_map_irq		= alphapc164_map_irq,
417 	.pci_swizzle		= common_swizzle,
418 };
419 ALIAS_MV(lx164)
420 #endif
421 
422 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
423 struct alpha_machine_vector pc164_mv __initmv = {
424 	.vector_name		= "PC164",
425 	DO_EV5_MMU,
426 	DO_DEFAULT_RTC,
427 	DO_CIA_IO,
428 	.machine_check		= cia_machine_check,
429 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
430 	.min_io_address		= DEFAULT_IO_BASE,
431 	.min_mem_address	= CIA_DEFAULT_MEM_BASE,
432 
433 	.nr_irqs		= 35,
434 	.device_interrupt	= pc164_device_interrupt,
435 
436 	.init_arch		= cia_init_arch,
437 	.init_irq		= pc164_init_irq,
438 	.init_rtc		= common_init_rtc,
439 	.init_pci		= alphapc164_init_pci,
440 	.kill_arch		= cia_kill_arch,
441 	.pci_map_irq		= alphapc164_map_irq,
442 	.pci_swizzle		= common_swizzle,
443 };
444 ALIAS_MV(pc164)
445 #endif
446