1 /*
2 ** I/O Sapic Driver - PCI interrupt line support
3 **
4 ** (c) Copyright 1999 Grant Grundler
5 ** (c) Copyright 1999 Hewlett-Packard Company
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** The I/O sapic driver manages the Interrupt Redirection Table which is
13 ** the control logic to convert PCI line based interrupts into a Message
14 ** Signaled Interrupt (aka Transaction Based Interrupt, TBI).
15 **
16 ** Acronyms
17 ** --------
18 ** HPA Hard Physical Address (aka MMIO address)
19 ** IRQ Interrupt ReQuest. Implies Line based interrupt.
20 ** IRT Interrupt Routing Table (provided by PAT firmware)
21 ** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA
22 ** table which is implemented in I/O SAPIC.
23 ** ISR Interrupt Service Routine. aka Interrupt handler.
24 ** MSI Message Signaled Interrupt. PCI 2.2 functionality.
25 ** aka Transaction Based Interrupt (or TBI).
26 ** PA Precision Architecture. HP's RISC architecture.
27 ** RISC Reduced Instruction Set Computer.
28 **
29 **
30 ** What's a Message Signalled Interrupt?
31 ** -------------------------------------
32 ** MSI is a write transaction which targets a processor and is similar
33 ** to a processor write to memory or MMIO. MSIs can be generated by I/O
34 ** devices as well as processors and require *architecture* to work.
35 **
36 ** PA only supports MSI. So I/O subsystems must either natively generate
37 ** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
38 ** (e.g. PCI and EISA). IA64 supports MSIs via a "local SAPIC" which
39 ** acts on behalf of a processor.
40 **
41 ** MSI allows any I/O device to interrupt any processor. This makes
42 ** load balancing of the interrupt processing possible on an SMP platform.
43 ** Interrupts are also ordered WRT to DMA data. It's possible on I/O
44 ** coherent systems to completely eliminate PIO reads from the interrupt
45 ** path. The device and driver must be designed and implemented to
46 ** guarantee all DMA has been issued (issues about atomicity here)
47 ** before the MSI is issued. I/O status can then safely be read from
48 ** DMA'd data by the ISR.
49 **
50 **
51 ** PA Firmware
52 ** -----------
53 ** PA-RISC platforms have two fundementally different types of firmware.
54 ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
55 ** and BARs similar to a traditional PC BIOS.
56 ** The newer "PAT" firmware supports PDC calls which return tables.
57 ** PAT firmware only initializes PCI Console and Boot interface.
58 ** With these tables, the OS can progam all other PCI devices.
59 **
60 ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
61 ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
62 ** input line. If the IRT is not available, this driver assumes
63 ** INTERRUPT_LINE register has been programmed by firmware. The latter
64 ** case also means online addition of PCI cards can NOT be supported
65 ** even if HW support is present.
66 **
67 ** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
68 ** Routing Table for the entire platform.
69 **
70 ** Where's the iosapic?
71 ** --------------------
72 ** I/O sapic is part of the "Core Electronics Complex". And on HP platforms
73 ** it's integrated as part of the PCI bus adapter, "lba". So no bus walk
74 ** will discover I/O Sapic. I/O Sapic driver learns about each device
75 ** when lba driver advertises the presence of the I/O sapic by calling
76 ** iosapic_register().
77 **
78 **
79 ** IRQ region notes
80 ** ----------------
81 ** The data passed to iosapic_interrupt() is per IRQ line.
82 ** Each IRQ line will get one txn_addr/data pair. Thus each IRQ region,
83 ** will have several txn_addr/data pairs (up to 7 for current I/O SAPIC
84 ** implementations). The IRQ region "sysdata" will NOT be directly passed
85 ** to the interrupt handler like GSCtoPCI (dino.c).
86 **
87 ** iosapic interrupt handler will NOT call do_irq_mask().
88 ** It doesn't need to read a bit mask to determine which IRQ line was pulled
89 ** since it already knows based on vector_info passed to iosapic_interrupt().
90 **
91 ** One IRQ number represents both an IRQ line and a driver ISR.
92 ** The I/O sapic driver can't manage shared IRQ lines because
93 ** additional data besides the IRQ number must be passed via
94 ** irq_region_ops. do_irq() and request_irq() must manage
95 ** a sharing a bit in the mask.
96 **
97 ** iosapic_interrupt() replaces do_irq_mask() and calls do_irq().
98 ** Which IRQ line was asserted is already known since each
99 ** line has unique data associated with it. We could omit
100 ** iosapic_interrupt() from the calling path if it did NOT need
101 ** to write EOI. For unshared lines, it really doesn't.
102 **
103 ** Unfortunately, can't optimize out EOI if IRQ line isn't "shared".
104 ** N-class console "device" and some sort of heartbeat actually share
105 ** one line though only one driver is registered...<sigh>...this was
106 ** true for HP-UX at least. May not be true for parisc-linux.
107 **
108 **
109 ** Overview of exported iosapic functions
110 ** --------------------------------------
111 ** (caveat: code isn't finished yet - this is just the plan)
112 **
113 ** iosapic_init:
114 ** o initialize globals (lock, etc)
115 ** o try to read IRT. Presence of IRT determines if this is
116 ** a PAT platform or not.
117 **
118 ** iosapic_register():
119 ** o create iosapic_info instance data structure
120 ** o allocate vector_info array for this iosapic
121 ** o initialize vector_info - read corresponding IRdT?
122 **
123 ** iosapic_xlate_pin: (only called by fixup_irq for PAT platform)
124 ** o intr_pin = read cfg (INTERRUPT_PIN);
125 ** o if (device under PCI-PCI bridge)
126 ** translate slot/pin
127 **
128 ** iosapic_fixup_irq:
129 ** o if PAT platform (IRT present)
130 ** intr_pin = iosapic_xlate_pin(isi,pcidev):
131 ** intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
132 ** save IRT entry into vector_info later
133 ** write cfg INTERRUPT_LINE (with intr_line)?
134 ** else
135 ** intr_line = pcidev->irq
136 ** IRT pointer = NULL
137 ** endif
138 ** o locate vector_info (needs: isi, intr_line)
139 ** o allocate processor "irq" and get txn_addr/data
140 ** o request_irq(processor_irq, iosapic_interrupt, vector_info,...)
141 ** o pcidev->irq = isi->isi_region...base + intr_line;
142 **
143 ** iosapic_interrupt:
144 ** o call do_irq(vector->isi->irq_region, vector->irq_line, regs)
145 ** o assume level triggered and write EOI
146 **
147 ** iosapic_enable_irq:
148 ** o clear any pending IRQ on that line
149 ** o enable IRdT - call enable_irq(vector[line]->processor_irq)
150 ** o write EOI in case line is already asserted.
151 **
152 ** iosapic_disable_irq:
153 ** o disable IRdT - call disable_irq(vector[line]->processor_irq)
154 **
155 ** FIXME: mask/unmask
156 */
157
158
159 /* FIXME: determine which include files are really needed */
160 #include <linux/types.h>
161 #include <linux/kernel.h>
162 #include <linux/spinlock.h>
163 #include <linux/pci.h> /* pci cfg accessor functions */
164 #include <linux/init.h>
165 #include <linux/slab.h>
166 #include <linux/smp_lock.h>
167 #include <linux/interrupt.h> /* irqaction */
168 #include <linux/irq.h> /* irq_region support */
169
170 #include <asm/byteorder.h> /* get in-line asm for swab */
171 #include <asm/pdc.h>
172 #include <asm/page.h>
173 #include <asm/segment.h>
174 #include <asm/system.h>
175 #include <asm/gsc.h> /* gsc_read/write functions */
176 #ifdef CONFIG_SUPERIO
177 #include <asm/superio.h>
178 #endif
179
180 #include <asm/iosapic.h>
181 #include "./iosapic_private.h"
182
183 #define MODULE_NAME "iosapic"
184
185 /* "local" compile flags */
186 #undef PCI_BRIDGE_FUNCS
187 #undef DEBUG_IOSAPIC
188 #undef DEBUG_IOSAPIC_IRT
189
190
191 #ifdef DEBUG_IOSAPIC
192 static char assert_buf[128];
193
194 static int
assert_failed(char * a,char * f,int l)195 assert_failed (char *a, char *f, int l)
196 {
197 sprintf(assert_buf,
198 "ASSERT(%s) failed!\nline %d in %s\n",
199 a, /* assertion text */
200 l, /* line number */
201 f); /* file name */
202 panic(assert_buf);
203 return 0;
204 }
205
206 #undef ASSERT
207 #define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
208
209 #define DBG(x...) printk(x)
210
211 #else /* DEBUG_IOSAPIC */
212
213 #define DBG(x...)
214 #define ASSERT(EX)
215
216 #endif /* DEBUG_IOSAPIC */
217
218 #ifdef DEBUG_IOSAPIC_IRT
219 #define DBG_IRT(x...) printk(x)
220 #else
221 #define DBG_IRT(x...)
222 #endif
223
224
225 #define READ_U8(addr) gsc_readb(addr)
226 #define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
227 #define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
228 #define READ_REG16(addr) gsc_readw((u16 *) (addr))
229 #define READ_REG32(addr) gsc_readl((u32 *) (addr))
230 #define WRITE_U8(value, addr) gsc_writeb(value, addr)
231 #define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
232 #define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
233 #define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
234 #define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
235
236
237 #define IOSAPIC_REG_SELECT 0
238 #define IOSAPIC_REG_WINDOW 0x10
239 #define IOSAPIC_REG_EOI 0x40
240
241 #define IOSAPIC_REG_VERSION 0x1
242
243 #define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
244 #define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
245
246 /*
247 ** FIXME: revisit which GFP flags we should really be using.
248 ** GFP_KERNEL includes __GFP_WAIT flag and that may not
249 ** be acceptable. Since this is boot time, we shouldn't have
250 ** to wait ever and this code should (will?) never get called
251 ** from the interrrupt context.
252 */
253 #define IOSAPIC_KALLOC(a_type, cnt) \
254 (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
255 #define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
256
257
258 #define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags)
259 #define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
260
261
262 #define IOSAPIC_VERSION_MASK 0x000000ff
263 #define IOSAPIC_VERSION_SHIFT 0x0
264 #define IOSAPIC_VERSION(ver) \
265 (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
266
267 #define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
268
269 #define IOSAPIC_MAX_ENTRY_SHIFT 0x10
270 #define IOSAPIC_IRDT_MAX_ENTRY(ver) \
271 (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
272
273 /* bits in the "low" I/O Sapic IRdT entry */
274 #define IOSAPIC_IRDT_ENABLE 0x10000
275 #define IOSAPIC_IRDT_PO_LOW 0x02000
276 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
277 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
278
279 /* bits in the "high" I/O Sapic IRdT entry */
280 #define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
281
282
283
284 #define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
285
286 static struct iosapic_info *iosapic_list;
287 static spinlock_t iosapic_lock;
288 static int iosapic_count;
289
290
291 /*
292 ** REVISIT: future platforms may have more than one IRT.
293 ** If so, the following three fields form a structure which
294 ** then be linked into a list. Names are chosen to make searching
295 ** for them easy - not necessarily accurate (eg "cell").
296 **
297 ** Alternative: iosapic_info could point to the IRT it's in.
298 ** iosapic_register() could search a list of IRT's.
299 */
300 static struct irt_entry *irt_cell;
301 static size_t irt_num_entry;
302
303
304
305 /*
306 ** iosapic_load_irt
307 **
308 ** The "Get PCI INT Routing Table Size" option returns the number of
309 ** entries in the PCI interrupt routing table for the cell specified
310 ** in the cell_number argument. The cell number must be for a cell
311 ** within the caller's protection domain.
312 **
313 ** The "Get PCI INT Routing Table" option returns, for the cell
314 ** specified in the cell_number argument, the PCI interrupt routing
315 ** table in the caller allocated memory pointed to by mem_addr.
316 ** We assume the IRT only contains entries for I/O SAPIC and
317 ** calculate the size based on the size of I/O sapic entries.
318 **
319 ** The PCI interrupt routing table entry format is derived from the
320 ** IA64 SAL Specification 2.4. The PCI interrupt routing table defines
321 ** the routing of PCI interrupt signals between the PCI device output
322 ** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
323 ** devices). This table does NOT include information for devices/slots
324 ** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
325 ** for the architected method of routing of IRQ's behind PPB's.
326 */
327
328
329 static int __init /* return number of entries as success/fail flag */
iosapic_load_irt(unsigned long cell_num,struct irt_entry ** irt)330 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
331 {
332 long status; /* PDC return value status */
333 struct irt_entry *table; /* start of interrupt routing tbl */
334 unsigned long num_entries = 0UL;
335
336 ASSERT(NULL != irt);
337
338 if (is_pdc_pat()) {
339
340 /* Use pat pdc routine to get interrupt routing table size */
341 DBG("calling get_irt_size (cell %ld)\n", cell_num);
342 status = pdc_pat_get_irt_size(&num_entries, cell_num);
343 DBG("get_irt_size: %ld\n", status);
344
345 ASSERT(status == PDC_OK);
346
347 /* save the number of entries in the table */
348 ASSERT(0UL != num_entries);
349
350 /*
351 ** allocate memory for interrupt routing table
352 ** This interface isn't really right. We are assuming
353 ** the contents of the table are exclusively
354 ** for I/O sapic devices.
355 */
356 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
357 if (table == NULL) {
358 printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
359 return 0;
360 }
361
362 /* get PCI INT routing table */
363 status = pdc_pat_get_irt(table, cell_num);
364 DBG("pdc_pat_get_irt: %ld\n", status);
365 ASSERT(status == PDC_OK);
366 } else {
367 /*
368 ** C3000/J5000 (and similar) platforms with Sprockets PDC
369 ** will return exactly one IRT for all iosapics.
370 ** So if we have one, don't need to get it again.
371 */
372 if (NULL != irt_cell)
373 return 0;
374
375 /* Should be using the Elroy's HPA, but it's ignored anyway */
376 status = pdc_pci_irt_size(&num_entries, 0);
377 DBG("pdc_pci_irt_size: %ld\n", status);
378
379 if (PDC_OK != status) {
380 /* Not a "legacy" system with I/O SAPIC either */
381 return 0;
382 }
383
384 ASSERT(0UL != num_entries);
385
386 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
387 if (table == NULL) {
388 printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
389 return 0;
390 }
391
392 /* HPA ignored by this call too. */
393 status = pdc_pci_irt(num_entries, 0, table);
394 ASSERT(PDC_OK == status);
395 }
396
397 /* return interrupt table address */
398 *irt = table;
399
400 #ifdef DEBUG_IOSAPIC_IRT
401 {
402 struct irt_entry *p = table;
403 int i;
404
405 printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
406 printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
407 table,
408 num_entries,
409 (int) sizeof(struct irt_entry));
410
411 for (i = 0 ; i < num_entries ; i++, p++) {
412 printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
413 p->entry_type, p->entry_length, p->interrupt_type,
414 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
415 p->src_seg_id, p->dest_iosapic_intin,
416 ((u32 *) p)[2],
417 ((u32 *) p)[3]
418 );
419 }
420 }
421 #endif /* DEBUG_IOSAPIC_IRT */
422
423 return num_entries;
424 }
425
426
427
428 void __init
iosapic_init(void)429 iosapic_init(void)
430 {
431 unsigned long cell = 0;
432
433 /* init global data */
434 iosapic_lock = SPIN_LOCK_UNLOCKED;
435 iosapic_list = (struct iosapic_info *) NULL;
436 iosapic_count = 0;
437
438 DBG("iosapic_init()\n");
439
440 #ifdef __LP64__
441 if (is_pdc_pat()) {
442 int status;
443 struct pdc_pat_cell_num cell_info;
444
445 status = pdc_pat_cell_get_number(&cell_info);
446 if (status == PDC_OK) {
447 cell = cell_info.cell_num;
448 }
449 }
450 #endif
451
452 /*
453 ** get IRT for this cell.
454 */
455 irt_num_entry = iosapic_load_irt(cell, &irt_cell);
456 if (0 == irt_num_entry)
457 irt_cell = NULL; /* old PDC w/o iosapic */
458 }
459
460
461 /*
462 ** Return the IRT entry in case we need to look something else up.
463 */
464 static struct irt_entry *
irt_find_irqline(struct iosapic_info * isi,u8 slot,u8 intr_pin)465 irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
466 {
467 struct irt_entry *i = irt_cell;
468 int cnt; /* track how many entries we've looked at */
469 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
470
471 DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
472
473 for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
474
475 /*
476 ** Validate: entry_type, entry_length, interrupt_type
477 **
478 ** Difference between validate vs compare is the former
479 ** should print debug info and is not expected to "fail"
480 ** on current platforms.
481 */
482 if (i->entry_type != IRT_IOSAPIC_TYPE) {
483 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
484 continue;
485 }
486
487 if (i->entry_length != IRT_IOSAPIC_LENGTH) {
488 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
489 continue;
490 }
491
492 if (i->interrupt_type != IRT_VECTORED_INTR) {
493 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
494 continue;
495 }
496
497 /*
498 ** Compare: dest_iosapic_addr, src_bus_irq_devno
499 */
500 if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
501 continue;
502
503 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
504 continue;
505
506 /*
507 ** Ignore: src_bus_id and rc_seg_id correlate with
508 ** iosapic_info->isi_hpa on HP platforms.
509 ** If needed, pass in "PFA" (aka config space addr)
510 ** instead of slot.
511 */
512
513 /* Found it! */
514 return i;
515 }
516
517 printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
518 isi->isi_hpa, slot, intr_pin);
519 return NULL;
520 }
521
522
523 /*
524 ** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
525 ** Legacy PDC already does this translation for us and stores it in INTR_LINE.
526 **
527 ** PAT PDC needs to basically do what legacy PDC does:
528 ** o read PIN
529 ** o adjust PIN in case device is "behind" a PPB
530 ** (eg 4-port 100BT and SCSI/LAN "Combo Card")
531 ** o convert slot/pin to I/O SAPIC input line.
532 **
533 ** HP platforms only support:
534 ** o one level of skewing for any number of PPBs
535 ** o only support PCI-PCI Bridges.
536 */
537 static struct irt_entry *
iosapic_xlate_pin(struct iosapic_info * isi,struct pci_dev * pcidev)538 iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
539 {
540 u8 intr_pin, intr_slot;
541
542 pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
543
544 DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
545 PCI_SLOT(pcidev->devfn), intr_pin);
546
547 if (0 == intr_pin) {
548 /* The device does NOT support/use IRQ lines. */
549 return NULL;
550 }
551
552 /* Check if pcidev behind a PPB */
553 if (NULL != pcidev->bus->self) {
554 /* Convert pcidev INTR_PIN into something we
555 ** can lookup in the IRT.
556 */
557 #ifdef PCI_BRIDGE_FUNCS
558 /*
559 ** Proposal #1:
560 **
561 ** call implementation specific translation function
562 ** This is architecturally "cleaner". HP-UX doesn't
563 ** support other secondary bus types (eg. E/ISA) directly.
564 ** May be needed for other processor (eg IA64) architectures
565 ** or by some ambitous soul who wants to watch TV.
566 */
567 if (pci_bridge_funcs->xlate_intr_line) {
568 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
569 }
570 #else /* PCI_BRIDGE_FUNCS */
571 struct pci_bus *p = pcidev->bus;
572 /*
573 ** Proposal #2:
574 ** The "pin" is skewed ((pin + dev - 1) % 4).
575 **
576 ** This isn't very clean since I/O SAPIC must assume:
577 ** - all platforms only have PCI busses.
578 ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
579 ** - IRQ routing is only skewed once regardless of
580 ** the number of PPB's between iosapic and device.
581 ** (Bit3 expansion chassis follows this rule)
582 **
583 ** Advantage is it's really easy to implement.
584 */
585 intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
586 intr_pin++; /* convert back to INTA-D (1-4) */
587 #endif /* PCI_BRIDGE_FUNCS */
588
589 /*
590 ** Locate the host slot the PPB nearest the Host bus
591 ** adapter.
592 */
593 while (NULL != p->parent->self)
594 p = p->parent;
595
596 intr_slot = PCI_SLOT(p->self->devfn);
597 } else {
598 intr_slot = PCI_SLOT(pcidev->devfn);
599 }
600 DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
601 pcidev->bus->secondary, intr_slot, intr_pin);
602
603 return irt_find_irqline(isi, intr_slot, intr_pin);
604 }
605
606
607 static void
iosapic_interrupt(int irq,void * dev_id,struct pt_regs * regs)608 iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
609 {
610 struct vector_info *vi = (struct vector_info *)dev_id;
611 extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
612 int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline;
613
614 DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
615 irq, vi->vi_irqline, vi->vi_eoi_addr);
616
617 /* FIXME: Need to mask/unmask? processor IRQ is already masked... */
618 do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs);
619
620 /*
621 ** PCI only supports level triggered in order to share IRQ lines.
622 ** I/O SAPIC must always issue EOI.
623 */
624 IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
625 }
626
627
628 int
iosapic_fixup_irq(void * isi_obj,struct pci_dev * pcidev)629 iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
630 {
631 struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
632 struct irt_entry *irte = NULL; /* only used if PAT PDC */
633 struct vector_info *vi;
634 int isi_line; /* line used by device */
635 int tmp;
636 int return_irq;
637 #ifdef CONFIG_SUPERIO
638 int superio_irq = -1;
639 #endif
640
641 if (NULL == isi) {
642 printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
643 pcidev->name);
644 return(-1);
645 }
646
647 #ifdef CONFIG_SUPERIO
648 if (is_superio_device(pcidev)) {
649 superio_irq = superio_fixup_irq(pcidev);
650 if (superio_irq == -1)
651 return(-1);
652
653 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) {
654
655 /*
656 * SuperIO USB controller has an irt entry.
657 * Only let the USB controller hookup the rest
658 * of the interrupt routing when it comes through.
659 * Note that interrupts for all three functions
660 * actually come through the PIC's on function 1!
661 */
662
663 pcidev->irq = superio_irq;
664 return superio_irq;
665 }
666 }
667 #endif /* CONFIG_SUPERIO */
668
669 /* lookup IRT entry for isi/slot/pin set */
670 irte = iosapic_xlate_pin(isi, pcidev);
671 if (NULL == irte) {
672 return(-1);
673 }
674 DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
675 irte,
676 irte->entry_type,
677 irte->entry_length,
678 irte->polarity_trigger,
679 irte->src_bus_irq_devno,
680 irte->src_bus_id,
681 irte->src_seg_id,
682 irte->dest_iosapic_intin,
683 (u32) irte->dest_iosapic_addr);
684 isi_line = irte->dest_iosapic_intin;
685
686 /* get vector info for this input line */
687 ASSERT(NULL != isi->isi_vector);
688 vi = &(isi->isi_vector[isi_line]);
689 DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
690 vi->vi_irte = irte;
691
692 /* Allocate processor IRQ */
693 vi->vi_txn_irq = txn_alloc_irq();
694
695 /* XXX/FIXME The txn_alloc_irq() code and related code should be moved
696 ** to enable_irq(). That way we only allocate processor IRQ bits
697 ** for devices that actually have drivers claiming them.
698 ** Right now we assign an IRQ to every PCI device present regardless
699 ** of whether it's used or not.
700 */
701 if (vi->vi_txn_irq < 0)
702 panic("I/O sapic: couldn't get TXN IRQ\n");
703
704 /* enable_irq() will use txn_* to program IRdT */
705 vi->vi_txn_addr = txn_alloc_addr(vi->vi_txn_irq);
706 vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8);
707 ASSERT(vi->vi_txn_data < 256); /* matches 8 above */
708
709 tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0,
710 vi->vi_name, vi);
711 ASSERT(tmp == 0);
712
713 vi->vi_eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
714 vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline);
715
716 ASSERT(NULL != isi->isi_region);
717 /* pcidev->irq still needs to be virtualized. */
718
719 return_irq = isi->isi_region->data.irqbase + isi_line;
720
721 #ifdef CONFIG_SUPERIO
722 if (superio_irq != -1) {
723 superio_inform_irq(return_irq);
724 return_irq = superio_irq;
725 }
726 #endif
727 pcidev->irq = return_irq;
728
729 DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
730 PCI_SLOT(pcidev->devfn),
731 PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, return_irq);
732
733 return return_irq;
734 }
735
736
737 static void
iosapic_rd_irt_entry(struct vector_info * vi,u32 * dp0,u32 * dp1)738 iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
739 {
740 struct iosapic_info *isp = vi->vi_ios;
741 u8 idx = vi->vi_irqline;
742
743 /* point the window register to the lower word */
744 WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
745 *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
746
747 /* point the window register to the higher word */
748 WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
749 *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
750 }
751
752
753 static void
iosapic_wr_irt_entry(struct vector_info * vi,u32 dp0,u32 dp1)754 iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
755 {
756 struct iosapic_info *isp = vi->vi_ios;
757
758 ASSERT(NULL != isp);
759 ASSERT(0 != isp->isi_hpa);
760 DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n",
761 vi->vi_irqline,
762 isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
763 dp0, dp1);
764
765 /* point the window register to the lower word */
766 WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
767 WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
768
769 /* Read the window register to flush the writes down to HW */
770 dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
771
772 /* point the window register to the higher word */
773 WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
774 WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
775
776 /* Read the window register to flush the writes down to HW */
777 dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
778 }
779
780
781 /*
782 ** set_irt prepares the data (dp0, dp1) according to the vector_info
783 ** and target cpu (id_eid). dp0/dp1 are then used to program I/O SAPIC
784 ** IRdT for the given "vector" (aka IRQ line).
785 */
786 static void
iosapic_set_irt_data(struct vector_info * vi,u32 * dp0,u32 * dp1)787 iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
788 {
789 u32 mode = 0;
790 struct irt_entry *p = vi->vi_irte;
791 ASSERT(NULL != vi->vi_irte);
792
793 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
794 mode |= IOSAPIC_IRDT_PO_LOW;
795
796 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
797 mode |= IOSAPIC_IRDT_LEVEL_TRIG;
798
799 /*
800 ** IA64 REVISIT
801 ** PA doesn't support EXTINT or LPRIO bits.
802 */
803
804 ASSERT(vi->vi_txn_data);
805 *dp0 = mode | (u32) vi->vi_txn_data;
806
807 /*
808 ** Extracting id_eid isn't a real clean way of getting it.
809 ** But the encoding is the same for both PA and IA64 platforms.
810 */
811 if (is_pdc_pat()) {
812 /*
813 ** PAT PDC just hands it to us "right".
814 ** vi_txn_addr comes from cpu_data[x].txn_addr.
815 */
816 *dp1 = (u32) (vi->vi_txn_addr);
817 } else {
818 /*
819 ** eg if base_addr == 0xfffa0000),
820 ** we want to get 0xa0ff0000.
821 **
822 ** eid 0x0ff00000 -> 0x00ff0000
823 ** id 0x000ff000 -> 0xff000000
824 */
825 *dp1 = (((u32)vi->vi_txn_addr & 0x0ff00000) >> 4) |
826 (((u32)vi->vi_txn_addr & 0x000ff000) << 12);
827 }
828 DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
829 }
830
831
832 static void
iosapic_disable_irq(void * irq_dev,int irq)833 iosapic_disable_irq(void *irq_dev, int irq)
834 {
835 ulong irqflags;
836 struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]);
837 u32 d0, d1;
838
839 ASSERT(NULL != vi);
840
841 IOSAPIC_LOCK(&iosapic_lock);
842
843 #ifdef REVISIT_DESIGN_ISSUE
844 /*
845 ** XXX/FIXME
846
847 disable_irq()/enable_irq(): drawback of using IRQ as a "handle"
848
849 Current disable_irq interface only allows the irq_region support routines
850 to manage sharing of "irq" objects. The problem is the disable_irq()
851 interface specifies which IRQ line needs to be disabled but does not
852 identify the particular ISR which needs to be disabled. IO sapic
853 (and similar code in Dino) can only support one handler per IRQ
854 since they don't further encode the meaning of the IRQ number.
855 irq_region support has to hide it's implementation of "shared IRQ"
856 behind a function call.
857
858 Encoding the IRQ would be possible by I/O SAPIC but makes life really
859 complicated for the IRQ handler and not help performance.
860
861 Need more info on how Linux supports shared IRQ lines on a PC.
862 */
863 #endif /* REVISIT_DESIGN_ISSUE */
864
865 iosapic_rd_irt_entry(vi, &d0, &d1);
866 d0 |= IOSAPIC_IRDT_ENABLE;
867 iosapic_wr_irt_entry(vi, d0, d1);
868
869 IOSAPIC_UNLOCK(&iosapic_lock);
870
871 /* disable ISR for parent */
872 disable_irq(vi->vi_txn_irq);
873 }
874
875
876 static void
iosapic_enable_irq(void * dev,int irq)877 iosapic_enable_irq(void *dev, int irq)
878 {
879 struct vector_info *vi = &(((struct vector_info *) dev)[irq]);
880 u32 d0, d1;
881
882 ASSERT(NULL != vi);
883 ASSERT(NULL != vi->vi_irte);
884
885 /* data is initialized by fixup_irq */
886 ASSERT(0 < vi->vi_txn_irq);
887 ASSERT(0UL != vi->vi_txn_data);
888
889 iosapic_set_irt_data(vi, &d0, &d1);
890 iosapic_wr_irt_entry(vi, d0, d1);
891
892
893 #ifdef DEBUG_IOSAPIC_IRT
894 {
895 u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL);
896 printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr);
897 while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++));
898 printk("\n");
899 }
900
901 printk("iosapic_enable_irq(): sel ");
902 {
903 struct iosapic_info *isp = vi->vi_ios;
904
905 for (d0=0x10; d0<0x1e; d0++) {
906 /* point the window register to the lower word */
907 WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
908
909 /* read the word */
910 d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
911 printk(" %x", d1);
912 }
913 }
914 printk("\n");
915 #endif
916
917 /*
918 ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
919 ** PCI supports level triggered in order to share IRQ lines.
920 **
921 ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
922 ** asserted.
923 */
924 IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
925 }
926
927
928 static void
iosapic_mask_irq(void * dev,int irq)929 iosapic_mask_irq(void *dev, int irq)
930 {
931 BUG();
932 }
933
934
935 static void
iosapic_unmask_irq(void * dev,int irq)936 iosapic_unmask_irq(void *dev, int irq)
937 {
938 BUG();
939 }
940
941
942 static struct irq_region_ops iosapic_irq_ops = {
943 disable_irq: iosapic_disable_irq,
944 enable_irq: iosapic_enable_irq,
945 mask_irq: iosapic_mask_irq,
946 unmask_irq: iosapic_unmask_irq
947 };
948
949
950 /*
951 ** squirrel away the I/O Sapic Version
952 */
953 static unsigned int
iosapic_rd_version(struct iosapic_info * isi)954 iosapic_rd_version(struct iosapic_info *isi)
955 {
956 ASSERT(isi);
957 ASSERT(isi->isi_hpa);
958
959 /* point window to the version register */
960 WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
961
962 /* now read the version register */
963 return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
964 }
965
966
967 /*
968 ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
969 ** Caller must be certain they have an I/O SAPIC and know its MMIO address.
970 **
971 ** o allocate iosapic_info and add it to the list
972 ** o read iosapic version and squirrel that away
973 ** o read size of IRdT.
974 ** o allocate and initialize isi_vector[]
975 ** o allocate isi_region (registers region handlers)
976 */
977 void *
iosapic_register(unsigned long hpa)978 iosapic_register(unsigned long hpa)
979 {
980 struct iosapic_info *isi = NULL;
981 struct irt_entry *irte = irt_cell;
982 struct vector_info *vip;
983 int cnt; /* track how many entries we've looked at */
984
985 /*
986 ** Astro based platforms can't support PCI OLARD if they
987 ** implement the legacy PDC (not PAT). Though Legacy PDC
988 ** supports an IRT, LBA's with no device under them
989 ** are *not* listed in the IRT.
990 ** Search the IRT and ignore iosapic's which aren't
991 ** in the IRT.
992 */
993 ASSERT(NULL != irte); /* always have built-in devices */
994 for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
995 ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
996 /*
997 ** We need sign extension of the hpa on 32-bit kernels.
998 ** The address in the IRT is *always* 64 bit and really
999 ** is an unsigned quantity (like all physical addresses).
1000 */
1001 if (irte->dest_iosapic_addr == (s64) ((long) hpa))
1002 break;
1003 }
1004
1005 if (cnt >= irt_num_entry)
1006 return (NULL);
1007
1008 if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
1009 BUG();
1010 return (NULL);
1011 }
1012
1013 memset(isi, 0, sizeof(struct iosapic_info));
1014
1015 isi->isi_hpa = hpa;
1016 isi->isi_version = iosapic_rd_version(isi);
1017 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
1018
1019 vip = isi->isi_vector =
1020 IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
1021
1022 if (vip == NULL) {
1023 IOSAPIC_FREE(isi, struct iosapic_info, 1);
1024 return (NULL);
1025 }
1026
1027 memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
1028 sprintf(isi->isi_name, "IO-SAPIC%02d", iosapic_count++);
1029
1030 /*
1031 ** Initialize vector array
1032 */
1033 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
1034 vip->vi_irqline = (unsigned char) cnt;
1035 vip->vi_ios = isi;
1036 sprintf(vip->vi_name, "%s-L%d", isi->isi_name, cnt);
1037 }
1038
1039 isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
1040 &iosapic_irq_ops, isi->isi_name,
1041 (void *) isi->isi_vector);
1042
1043 ASSERT(NULL != isi->isi_region);
1044 return ((void *) isi);
1045 }
1046
1047
1048 #ifdef DEBUG_IOSAPIC
1049
1050 static void
iosapic_prt_irt(void * irt,long num_entry)1051 iosapic_prt_irt(void *irt, long num_entry)
1052 {
1053 unsigned int i, *irp = (unsigned int *) irt;
1054
1055 ASSERT(NULL != irt);
1056
1057 printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
1058
1059 for (i=0; i<num_entry; i++, irp += 4) {
1060 printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
1061 irp, i, irp[0], irp[1], irp[2], irp[3]);
1062 }
1063 }
1064
1065
1066 static void
iosapic_prt_vi(struct vector_info * vi)1067 iosapic_prt_vi(struct vector_info *vi)
1068 {
1069 ASSERT(NULL != vi);
1070
1071 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->vi_irqline, vi);
1072 printk(KERN_DEBUG "\t\tvi_status: %.4x\n", vi->vi_status);
1073 printk(KERN_DEBUG "\t\tvi_txn_irq: %d\n", vi->vi_txn_irq);
1074 printk(KERN_DEBUG "\t\tvi_txn_addr: %lx\n", vi->vi_txn_addr);
1075 printk(KERN_DEBUG "\t\tvi_txn_data: %lx\n", vi->vi_txn_data);
1076 printk(KERN_DEBUG "\t\tvi_eoi_addr: %p\n", vi->vi_eoi_addr);
1077 printk(KERN_DEBUG "\t\tvi_eoi_data: %x\n", vi->vi_eoi_data);
1078 }
1079
1080
1081 static void
iosapic_prt_isi(struct iosapic_info * isi)1082 iosapic_prt_isi(struct iosapic_info *isi)
1083 {
1084 ASSERT(NULL != isi);
1085 printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
1086 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa);
1087 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
1088 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
1089 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
1090 }
1091 #endif /* DEBUG_IOSAPIC */
1092