1 /*
2  *  linux/arch/alpha/kernel/sys_wildfire.c
3  *
4  *  Wildfire support.
5  *
6  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 
16 #include <asm/ptrace.h>
17 #include <asm/system.h>
18 #include <asm/dma.h>
19 #include <asm/irq.h>
20 #include <asm/bitops.h>
21 #include <asm/mmu_context.h>
22 #include <asm/io.h>
23 #include <asm/pgtable.h>
24 #include <asm/core_wildfire.h>
25 #include <asm/hwrpb.h>
26 
27 #include "proto.h"
28 #include "irq_impl.h"
29 #include "pci_impl.h"
30 #include "machvec_impl.h"
31 
32 static unsigned long cached_irq_mask[WILDFIRE_NR_IRQS/(sizeof(long)*8)];
33 
34 spinlock_t wildfire_irq_lock = SPIN_LOCK_UNLOCKED;
35 
36 static int doing_init_irq_hw = 0;
37 
38 static void
wildfire_update_irq_hw(unsigned int irq)39 wildfire_update_irq_hw(unsigned int irq)
40 {
41 	int qbbno = (irq >> 8) & (WILDFIRE_MAX_QBB - 1);
42 	int pcano = (irq >> 6) & (WILDFIRE_PCA_PER_QBB - 1);
43 	wildfire_pca *pca;
44 	volatile unsigned long * enable0;
45 
46 	if (!WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
47 		if (!doing_init_irq_hw) {
48 			printk(KERN_ERR "wildfire_update_irq_hw:"
49 			       " got irq %d for non-existent PCA %d"
50 			       " on QBB %d.\n",
51 			       irq, pcano, qbbno);
52 		}
53 		return;
54 	}
55 
56 	pca = WILDFIRE_pca(qbbno, pcano);
57 	enable0 = (unsigned long *) &pca->pca_int[0].enable; /* ??? */
58 
59 	*enable0 = cached_irq_mask[qbbno * WILDFIRE_PCA_PER_QBB + pcano];
60 	mb();
61 	*enable0;
62 }
63 
64 static void __init
wildfire_init_irq_hw(void)65 wildfire_init_irq_hw(void)
66 {
67 #if 0
68 	register wildfire_pca * pca = WILDFIRE_pca(0, 0);
69 	volatile unsigned long * enable0, * enable1, * enable2, *enable3;
70 	volatile unsigned long * target0, * target1, * target2, *target3;
71 
72 	enable0 = (unsigned long *) &pca->pca_int[0].enable;
73 	enable1 = (unsigned long *) &pca->pca_int[1].enable;
74 	enable2 = (unsigned long *) &pca->pca_int[2].enable;
75 	enable3 = (unsigned long *) &pca->pca_int[3].enable;
76 
77 	target0 = (unsigned long *) &pca->pca_int[0].target;
78 	target1 = (unsigned long *) &pca->pca_int[1].target;
79 	target2 = (unsigned long *) &pca->pca_int[2].target;
80 	target3 = (unsigned long *) &pca->pca_int[3].target;
81 
82 	*enable0 = *enable1 = *enable2 = *enable3 = 0;
83 
84 	*target0 = (1UL<<8) | WILDFIRE_QBB(0);
85 	*target1 = *target2 = *target3 = 0;
86 
87 	mb();
88 
89 	*enable0; *enable1; *enable2; *enable3;
90 	*target0; *target1; *target2; *target3;
91 
92 #else
93 	int i;
94 
95 	doing_init_irq_hw = 1;
96 
97 	/* Need to update only once for every possible PCA. */
98 	for (i = 0; i < WILDFIRE_NR_IRQS; i+=WILDFIRE_IRQ_PER_PCA)
99 		wildfire_update_irq_hw(i);
100 
101 	doing_init_irq_hw = 0;
102 #endif
103 }
104 
105 static void
wildfire_enable_irq(unsigned int irq)106 wildfire_enable_irq(unsigned int irq)
107 {
108 	if (irq < 16)
109 		i8259a_enable_irq(irq);
110 
111 	spin_lock(&wildfire_irq_lock);
112 	set_bit(irq, &cached_irq_mask);
113 	wildfire_update_irq_hw(irq);
114 	spin_unlock(&wildfire_irq_lock);
115 }
116 
117 static void
wildfire_disable_irq(unsigned int irq)118 wildfire_disable_irq(unsigned int irq)
119 {
120 	if (irq < 16)
121 		i8259a_disable_irq(irq);
122 
123 	spin_lock(&wildfire_irq_lock);
124 	clear_bit(irq, &cached_irq_mask);
125 	wildfire_update_irq_hw(irq);
126 	spin_unlock(&wildfire_irq_lock);
127 }
128 
129 static void
wildfire_mask_and_ack_irq(unsigned int irq)130 wildfire_mask_and_ack_irq(unsigned int irq)
131 {
132 	if (irq < 16)
133 		i8259a_mask_and_ack_irq(irq);
134 
135 	spin_lock(&wildfire_irq_lock);
136 	clear_bit(irq, &cached_irq_mask);
137 	wildfire_update_irq_hw(irq);
138 	spin_unlock(&wildfire_irq_lock);
139 }
140 
141 static unsigned int
wildfire_startup_irq(unsigned int irq)142 wildfire_startup_irq(unsigned int irq)
143 {
144 	wildfire_enable_irq(irq);
145 	return 0; /* never anything pending */
146 }
147 
148 static void
wildfire_end_irq(unsigned int irq)149 wildfire_end_irq(unsigned int irq)
150 {
151 #if 0
152 	if (!irq_desc[irq].action)
153 		printk("got irq %d\n", irq);
154 #endif
155 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
156 		wildfire_enable_irq(irq);
157 }
158 
159 static struct hw_interrupt_type wildfire_irq_type = {
160 	typename:	"WILDFIRE",
161 	startup:	wildfire_startup_irq,
162 	shutdown:	wildfire_disable_irq,
163 	enable:		wildfire_enable_irq,
164 	disable:	wildfire_disable_irq,
165 	ack:		wildfire_mask_and_ack_irq,
166 	end:		wildfire_end_irq,
167 };
168 
169 static void __init
wildfire_init_irq_per_pca(int qbbno,int pcano)170 wildfire_init_irq_per_pca(int qbbno, int pcano)
171 {
172 	int i, irq_bias;
173 	unsigned long io_bias;
174 	static struct irqaction isa_enable = {
175 		handler:	no_action,
176 		name:		"isa_enable",
177 	};
178 
179 	irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
180 		 + pcano * WILDFIRE_IRQ_PER_PCA;
181 
182 	/* Only need the following for first PCI bus per PCA. */
183 	io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
184 
185 #if 0
186 	outb(0, DMA1_RESET_REG + io_bias);
187 	outb(0, DMA2_RESET_REG + io_bias);
188 	outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
189 	outb(0, DMA2_MASK_REG + io_bias);
190 #endif
191 
192 #if 0
193 	/* ??? Not sure how to do this, yet... */
194 	init_i8259a_irqs(); /* ??? */
195 #endif
196 
197 	for (i = 0; i < 16; ++i) {
198 		if (i == 2)
199 			continue;
200 		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
201 		irq_desc[i+irq_bias].handler = &wildfire_irq_type;
202 	}
203 
204 	irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
205 	irq_desc[36+irq_bias].handler = &wildfire_irq_type;
206 	for (i = 40; i < 64; ++i) {
207 		irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
208 		irq_desc[i+irq_bias].handler = &wildfire_irq_type;
209 	}
210 
211 	setup_irq(32+irq_bias, &isa_enable);
212 }
213 
214 static void __init
wildfire_init_irq(void)215 wildfire_init_irq(void)
216 {
217 	int qbbno, pcano;
218 
219 #if 1
220 	wildfire_init_irq_hw();
221 	init_i8259a_irqs();
222 #endif
223 
224 	for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
225 	  if (WILDFIRE_QBB_EXISTS(qbbno)) {
226 	    for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
227 	      if (WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
228 		wildfire_init_irq_per_pca(qbbno, pcano);
229 	      }
230 	    }
231 	  }
232 	}
233 }
234 
235 static void
wildfire_device_interrupt(unsigned long vector,struct pt_regs * regs)236 wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
237 {
238 	int irq;
239 
240 	irq = (vector - 0x800) >> 4;
241 
242 	/*
243 	 * bits 10-8:	source QBB ID
244 	 * bits 7-6:	PCA
245 	 * bits 5-0:	irq in PCA
246 	 */
247 
248 	handle_irq(irq, regs);
249 	return;
250 }
251 
252 /*
253  * PCI Fixup configuration.
254  *
255  * Summary per PCA (2 PCI or HIPPI buses):
256  *
257  * Bit      Meaning
258  * 0-15     ISA
259  *
260  *32        ISA summary
261  *33        SMI
262  *34        NMI
263  *36        builtin QLogic SCSI (or slot 0 if no IO module)
264  *40        Interrupt Line A from slot 2 PCI0
265  *41        Interrupt Line B from slot 2 PCI0
266  *42        Interrupt Line C from slot 2 PCI0
267  *43        Interrupt Line D from slot 2 PCI0
268  *44        Interrupt Line A from slot 3 PCI0
269  *45        Interrupt Line B from slot 3 PCI0
270  *46        Interrupt Line C from slot 3 PCI0
271  *47        Interrupt Line D from slot 3 PCI0
272  *
273  *48        Interrupt Line A from slot 4 PCI1
274  *49        Interrupt Line B from slot 4 PCI1
275  *50        Interrupt Line C from slot 4 PCI1
276  *51        Interrupt Line D from slot 4 PCI1
277  *52        Interrupt Line A from slot 5 PCI1
278  *53        Interrupt Line B from slot 5 PCI1
279  *54        Interrupt Line C from slot 5 PCI1
280  *55        Interrupt Line D from slot 5 PCI1
281  *56        Interrupt Line A from slot 6 PCI1
282  *57        Interrupt Line B from slot 6 PCI1
283  *58        Interrupt Line C from slot 6 PCI1
284  *50        Interrupt Line D from slot 6 PCI1
285  *60        Interrupt Line A from slot 7 PCI1
286  *61        Interrupt Line B from slot 7 PCI1
287  *62        Interrupt Line C from slot 7 PCI1
288  *63        Interrupt Line D from slot 7 PCI1
289  *
290  *
291  * IdSel
292  *   0	 Cypress Bridge I/O (ISA summary interrupt)
293  *   1	 64 bit PCI 0 option slot 1 (SCSI QLogic builtin)
294  *   2	 64 bit PCI 0 option slot 2
295  *   3	 64 bit PCI 0 option slot 3
296  *   4	 64 bit PCI 1 option slot 4
297  *   5	 64 bit PCI 1 option slot 5
298  *   6	 64 bit PCI 1 option slot 6
299  *   7	 64 bit PCI 1 option slot 7
300  */
301 
302 static int __init
wildfire_map_irq(struct pci_dev * dev,u8 slot,u8 pin)303 wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
304 {
305 	static char irq_tab[8][5] __initdata = {
306 		/*INT    INTA   INTB   INTC   INTD */
307 		{ -1,    -1,    -1,    -1,    -1}, /* IdSel 0 ISA Bridge */
308 		{ 36,    36,    36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */
309 		{ 40,    40,    40+1, 40+2, 40+3}, /* IdSel 2 PCI 0 slot 2 */
310 		{ 44,    44,    44+1, 44+2, 44+3}, /* IdSel 3 PCI 0 slot 3 */
311 		{ 48,    48,    48+1, 48+2, 48+3}, /* IdSel 4 PCI 1 slot 4 */
312 		{ 52,    52,    52+1, 52+2, 52+3}, /* IdSel 5 PCI 1 slot 5 */
313 		{ 56,    56,    56+1, 56+2, 56+3}, /* IdSel 6 PCI 1 slot 6 */
314 		{ 60,    60,    60+1, 60+2, 60+3}, /* IdSel 7 PCI 1 slot 7 */
315 	};
316 	const long min_idsel = 0, max_idsel = 7, irqs_per_slot = 5;
317 
318 	struct pci_controller *hose = dev->sysdata;
319 	int irq = COMMON_TABLE_LOOKUP;
320 
321 	if (irq > 0) {
322 		int qbbno = hose->index >> 3;
323 		int pcano = (hose->index >> 1) & 3;
324 		irq += (qbbno << 8) + (pcano << 6);
325 	}
326 	return irq;
327 }
328 
329 
330 /*
331  * The System Vectors
332  */
333 
334 struct alpha_machine_vector wildfire_mv __initmv = {
335 	vector_name:		"WILDFIRE",
336 	DO_EV6_MMU,
337 	DO_DEFAULT_RTC,
338 	DO_WILDFIRE_IO,
339 	DO_WILDFIRE_BUS,
340 	machine_check:		wildfire_machine_check,
341 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
342 	min_io_address:		DEFAULT_IO_BASE,
343 	min_mem_address:	DEFAULT_MEM_BASE,
344 
345 	nr_irqs:		WILDFIRE_NR_IRQS,
346 	device_interrupt:	wildfire_device_interrupt,
347 
348 	init_arch:		wildfire_init_arch,
349 	init_irq:		wildfire_init_irq,
350 	init_rtc:		common_init_rtc,
351 	init_pci:		common_init_pci,
352 	kill_arch:		wildfire_kill_arch,
353 	pci_map_irq:		wildfire_map_irq,
354 	pci_swizzle:		common_swizzle,
355 
356 	pa_to_nid:		wildfire_pa_to_nid,
357 	cpuid_to_nid:		wildfire_cpuid_to_nid,
358 	node_mem_start:		wildfire_node_mem_start,
359 	node_mem_size:		wildfire_node_mem_size,
360 };
361 ALIAS_MV(wildfire)
362