1
2
3
4
5
6
7
8
9
10
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/mce.h>
23#include <asm/dma.h>
24#include <asm/irq.h>
25#include <asm/mmu_context.h>
26#include <asm/io.h>
27#include <asm/core_apecs.h>
28#include <asm/core_cia.h>
29#include <asm/tlbflush.h>
30
31#include "proto.h"
32#include "irq_impl.h"
33#include "pci_impl.h"
34#include "machvec_impl.h"
35
36
37static int cached_irq_mask;
38
39static inline void
40noritake_update_irq_hw(int irq, int mask)
41{
42 int port = 0x54a;
43 if (irq >= 32) {
44 mask >>= 16;
45 port = 0x54c;
46 }
47 outw(mask, port);
48}
49
50static void
51noritake_enable_irq(struct irq_data *d)
52{
53 noritake_update_irq_hw(d->irq, cached_irq_mask |= 1 << (d->irq - 16));
54}
55
56static void
57noritake_disable_irq(struct irq_data *d)
58{
59 noritake_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << (d->irq - 16)));
60}
61
62static struct irq_chip noritake_irq_type = {
63 .name = "NORITAKE",
64 .irq_unmask = noritake_enable_irq,
65 .irq_mask = noritake_disable_irq,
66 .irq_mask_ack = noritake_disable_irq,
67};
68
69static void
70noritake_device_interrupt(unsigned long vector)
71{
72 unsigned long pld;
73 unsigned int i;
74
75
76 pld = (((unsigned long) inw(0x54c) << 32)
77 | ((unsigned long) inw(0x54a) << 16)
78 | ((unsigned long) inb(0xa0) << 8)
79 | inb(0x20));
80
81
82
83
84
85 while (pld) {
86 i = ffz(~pld);
87 pld &= pld - 1;
88 if (i < 16) {
89 isa_device_interrupt(vector);
90 } else {
91 handle_irq(i);
92 }
93 }
94}
95
96static void
97noritake_srm_device_interrupt(unsigned long vector)
98{
99 int irq;
100
101 irq = (vector - 0x800) >> 4;
102
103
104
105
106
107
108
109
110
111
112 if (irq >= 16)
113 irq = irq + 1;
114
115 handle_irq(irq);
116}
117
118static void __init
119noritake_init_irq(void)
120{
121 long i;
122
123 if (alpha_using_srm)
124 alpha_mv.device_interrupt = noritake_srm_device_interrupt;
125
126 outw(0, 0x54a);
127 outw(0, 0x54c);
128
129 for (i = 16; i < 48; ++i) {
130 irq_set_chip_and_handler(i, &noritake_irq_type,
131 handle_level_irq);
132 irq_set_status_flags(i, IRQ_LEVEL);
133 }
134
135 init_i8259a_irqs();
136 common_init_isa_dma();
137}
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196static int
197noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
198{
199 static char irq_tab[15][5] = {
200
201
202 { 16+1, 16+1, 16+1, 16+1, 16+1},
203 { -1, -1, -1, -1, -1},
204 { -1, -1, -1, -1, -1},
205 { -1, -1, -1, -1, -1},
206 { -1, -1, -1, -1, -1},
207 { -1, -1, -1, -1, -1},
208 { 16+2, 16+2, 16+3, 32+2, 32+3},
209 { 16+4, 16+4, 16+5, 32+4, 32+5},
210 { 16+6, 16+6, 16+7, 32+6, 32+7},
211 { 16+8, 16+8, 16+9, 32+8, 32+9},
212
213
214 { 16+1, 16+1, 16+1, 16+1, 16+1},
215 { 16+8, 16+8, 16+9, 32+8, 32+9},
216 {16+10, 16+10, 16+11, 32+10, 32+11},
217 {16+12, 16+12, 16+13, 32+12, 32+13},
218 {16+14, 16+14, 16+15, 32+14, 32+15},
219 };
220 const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
221 return COMMON_TABLE_LOOKUP;
222}
223
224static u8
225noritake_swizzle(struct pci_dev *dev, u8 *pinp)
226{
227 int slot, pin = *pinp;
228
229 if (dev->bus->number == 0) {
230 slot = PCI_SLOT(dev->devfn);
231 }
232
233 else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
234 slot = PCI_SLOT(dev->devfn) + 15;
235 }
236 else
237 {
238
239 do {
240 if (PCI_SLOT(dev->bus->self->devfn) == 8) {
241 slot = PCI_SLOT(dev->devfn) + 15;
242 break;
243 }
244 pin = pci_swizzle_interrupt_pin(dev, pin);
245
246
247 dev = dev->bus->self;
248
249 slot = PCI_SLOT(dev->devfn);
250 } while (dev->bus->self);
251 }
252 *pinp = pin;
253 return slot;
254}
255
256#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
257static void
258noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr)
259{
260#define MCHK_NO_DEVSEL 0x205U
261#define MCHK_NO_TABT 0x204U
262
263 struct el_common *mchk_header;
264 unsigned int code;
265
266 mchk_header = (struct el_common *)la_ptr;
267
268
269 mb();
270 mb();
271 draina();
272 apecs_pci_clr_err();
273 wrmces(0x7);
274 mb();
275
276 code = mchk_header->code;
277 process_mcheck_info(vector, la_ptr, "NORITAKE APECS",
278 (mcheck_expected(0)
279 && (code == MCHK_NO_DEVSEL
280 || code == MCHK_NO_TABT)));
281}
282#endif
283
284
285
286
287
288
289#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
290struct alpha_machine_vector noritake_mv __initmv = {
291 .vector_name = "Noritake",
292 DO_EV4_MMU,
293 DO_DEFAULT_RTC,
294 DO_APECS_IO,
295 .machine_check = noritake_apecs_machine_check,
296 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
297 .min_io_address = EISA_DEFAULT_IO_BASE,
298 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
299
300 .nr_irqs = 48,
301 .device_interrupt = noritake_device_interrupt,
302
303 .init_arch = apecs_init_arch,
304 .init_irq = noritake_init_irq,
305 .init_rtc = common_init_rtc,
306 .init_pci = common_init_pci,
307 .pci_map_irq = noritake_map_irq,
308 .pci_swizzle = noritake_swizzle,
309};
310ALIAS_MV(noritake)
311#endif
312
313#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
314struct alpha_machine_vector noritake_primo_mv __initmv = {
315 .vector_name = "Noritake-Primo",
316 DO_EV5_MMU,
317 DO_DEFAULT_RTC,
318 DO_CIA_IO,
319 .machine_check = cia_machine_check,
320 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
321 .min_io_address = EISA_DEFAULT_IO_BASE,
322 .min_mem_address = CIA_DEFAULT_MEM_BASE,
323
324 .nr_irqs = 48,
325 .device_interrupt = noritake_device_interrupt,
326
327 .init_arch = cia_init_arch,
328 .init_irq = noritake_init_irq,
329 .init_rtc = common_init_rtc,
330 .init_pci = cia_init_pci,
331 .kill_arch = cia_kill_arch,
332 .pci_map_irq = noritake_map_irq,
333 .pci_swizzle = noritake_swizzle,
334};
335ALIAS_MV(noritake_primo)
336#endif
337