1
2
3
4
5
6
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#include <linux/bitops.h>
16
17#include <asm/ptrace.h>
18#include <asm/dma.h>
19#include <asm/irq.h>
20#include <asm/mmu_context.h>
21#include <asm/io.h>
22#include <asm/pgtable.h>
23#include <asm/core_wildfire.h>
24#include <asm/hwrpb.h>
25#include <asm/tlbflush.h>
26
27#include "proto.h"
28#include "irq_impl.h"
29#include "pci_impl.h"
30#include "machvec_impl.h"
31
32static unsigned long cached_irq_mask[WILDFIRE_NR_IRQS/(sizeof(long)*8)];
33
34DEFINE_SPINLOCK(wildfire_irq_lock);
35
36static int doing_init_irq_hw = 0;
37
38static void
39wildfire_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
64static void __init
65wildfire_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
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
105static void
106wildfire_enable_irq(struct irq_data *d)
107{
108 unsigned int irq = d->irq;
109
110 if (irq < 16)
111 i8259a_enable_irq(d);
112
113 spin_lock(&wildfire_irq_lock);
114 set_bit(irq, &cached_irq_mask);
115 wildfire_update_irq_hw(irq);
116 spin_unlock(&wildfire_irq_lock);
117}
118
119static void
120wildfire_disable_irq(struct irq_data *d)
121{
122 unsigned int irq = d->irq;
123
124 if (irq < 16)
125 i8259a_disable_irq(d);
126
127 spin_lock(&wildfire_irq_lock);
128 clear_bit(irq, &cached_irq_mask);
129 wildfire_update_irq_hw(irq);
130 spin_unlock(&wildfire_irq_lock);
131}
132
133static void
134wildfire_mask_and_ack_irq(struct irq_data *d)
135{
136 unsigned int irq = d->irq;
137
138 if (irq < 16)
139 i8259a_mask_and_ack_irq(d);
140
141 spin_lock(&wildfire_irq_lock);
142 clear_bit(irq, &cached_irq_mask);
143 wildfire_update_irq_hw(irq);
144 spin_unlock(&wildfire_irq_lock);
145}
146
147static struct irq_chip wildfire_irq_type = {
148 .name = "WILDFIRE",
149 .irq_unmask = wildfire_enable_irq,
150 .irq_mask = wildfire_disable_irq,
151 .irq_mask_ack = wildfire_mask_and_ack_irq,
152};
153
154static void __init
155wildfire_init_irq_per_pca(int qbbno, int pcano)
156{
157 int i, irq_bias;
158 static struct irqaction isa_enable = {
159 .handler = no_action,
160 .name = "isa_enable",
161 };
162
163 irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
164 + pcano * WILDFIRE_IRQ_PER_PCA;
165
166#if 0
167 unsigned long io_bias;
168
169
170 io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
171
172 outb(0, DMA1_RESET_REG + io_bias);
173 outb(0, DMA2_RESET_REG + io_bias);
174 outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
175 outb(0, DMA2_MASK_REG + io_bias);
176#endif
177
178#if 0
179
180 init_i8259a_irqs();
181#endif
182
183 for (i = 0; i < 16; ++i) {
184 if (i == 2)
185 continue;
186 irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
187 handle_level_irq);
188 irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
189 }
190
191 irq_set_chip_and_handler(36 + irq_bias, &wildfire_irq_type,
192 handle_level_irq);
193 irq_set_status_flags(36 + irq_bias, IRQ_LEVEL);
194 for (i = 40; i < 64; ++i) {
195 irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
196 handle_level_irq);
197 irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
198 }
199
200 setup_irq(32+irq_bias, &isa_enable);
201}
202
203static void __init
204wildfire_init_irq(void)
205{
206 int qbbno, pcano;
207
208#if 1
209 wildfire_init_irq_hw();
210 init_i8259a_irqs();
211#endif
212
213 for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
214 if (WILDFIRE_QBB_EXISTS(qbbno)) {
215 for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
216 if (WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
217 wildfire_init_irq_per_pca(qbbno, pcano);
218 }
219 }
220 }
221 }
222}
223
224static void
225wildfire_device_interrupt(unsigned long vector)
226{
227 int irq;
228
229 irq = (vector - 0x800) >> 4;
230
231
232
233
234
235
236
237 handle_irq(irq);
238 return;
239}
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291static int __init
292wildfire_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
293{
294 static char irq_tab[8][5] __initdata = {
295
296 { -1, -1, -1, -1, -1},
297 { 36, 36, 36+1, 36+2, 36+3},
298 { 40, 40, 40+1, 40+2, 40+3},
299 { 44, 44, 44+1, 44+2, 44+3},
300 { 48, 48, 48+1, 48+2, 48+3},
301 { 52, 52, 52+1, 52+2, 52+3},
302 { 56, 56, 56+1, 56+2, 56+3},
303 { 60, 60, 60+1, 60+2, 60+3},
304 };
305 long min_idsel = 0, max_idsel = 7, irqs_per_slot = 5;
306
307 struct pci_controller *hose = dev->sysdata;
308 int irq = COMMON_TABLE_LOOKUP;
309
310 if (irq > 0) {
311 int qbbno = hose->index >> 3;
312 int pcano = (hose->index >> 1) & 3;
313 irq += (qbbno << 8) + (pcano << 6);
314 }
315 return irq;
316}
317
318
319
320
321
322
323struct alpha_machine_vector wildfire_mv __initmv = {
324 .vector_name = "WILDFIRE",
325 DO_EV6_MMU,
326 DO_DEFAULT_RTC,
327 DO_WILDFIRE_IO,
328 .machine_check = wildfire_machine_check,
329 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
330 .min_io_address = DEFAULT_IO_BASE,
331 .min_mem_address = DEFAULT_MEM_BASE,
332
333 .nr_irqs = WILDFIRE_NR_IRQS,
334 .device_interrupt = wildfire_device_interrupt,
335
336 .init_arch = wildfire_init_arch,
337 .init_irq = wildfire_init_irq,
338 .init_rtc = common_init_rtc,
339 .init_pci = common_init_pci,
340 .kill_arch = wildfire_kill_arch,
341 .pci_map_irq = wildfire_map_irq,
342 .pci_swizzle = common_swizzle,
343
344 .pa_to_nid = wildfire_pa_to_nid,
345 .cpuid_to_nid = wildfire_cpuid_to_nid,
346 .node_mem_start = wildfire_node_mem_start,
347 .node_mem_size = wildfire_node_mem_size,
348};
349ALIAS_MV(wildfire)
350