2 ** I/O Sapic Driver - PCI interrupt line support
4 ** (c) Copyright 1999 Grant Grundler
5 ** (c) Copyright 1999 Hewlett-Packard Company
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.
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).
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.
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.
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.
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.
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.
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.
67 ** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
68 ** Routing Table for the entire platform.
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().
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).
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().
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.
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.
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.
109 ** Overview of exported iosapic functions
110 ** --------------------------------------
111 ** (caveat: code isn't finished yet - this is just the plan)
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.
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?
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
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)?
135 ** intr_line = pcidev->irq
136 ** IRT pointer = NULL
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;
143 ** iosapic_interrupt:
144 ** o call do_irq(vector->isi->irq_region, vector->irq_line, regs)
145 ** o assume level triggered and write EOI
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.
152 ** iosapic_disable_irq:
153 ** o disable IRdT - call disable_irq(vector[line]->processor_irq)
155 ** FIXME: mask/unmask
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 */
170 #include <asm/byteorder.h> /* get in-line asm for swab */
172 #include <asm/page.h>
173 #include <asm/segment.h>
174 #include <asm/system.h>
175 #include <asm/io.h> /* gsc_read/write functions */
176 #ifdef CONFIG_SUPERIO
177 #include <asm/superio.h>
180 #include <asm/iosapic.h>
181 #include "./iosapic_private.h"
183 #define MODULE_NAME "iosapic"
185 /* "local" compile flags */
186 #undef PCI_BRIDGE_FUNCS
188 #undef DEBUG_IOSAPIC_IRT
192 static char assert_buf[128];
195 assert_failed (char *a, char *f, int l)
198 "ASSERT(%s) failed!\nline %d in %s\n",
199 a, /* assertion text */
207 #define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
209 #define DBG(x...) printk(x)
211 #else /* DEBUG_IOSAPIC */
217 #endif /* DEBUG_IOSAPIC */
219 #ifdef DEBUG_IOSAPIC_IRT
220 #define DBG_IRT(x...) printk(x)
222 #define DBG_IRT(x...)
226 #define READ_U8(addr) gsc_readb(addr)
227 #define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
228 #define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
229 #define READ_REG16(addr) gsc_readw((u16 *) (addr))
230 #define READ_REG32(addr) gsc_readl((u32 *) (addr))
231 #define WRITE_U8(value, addr) gsc_writeb(value, addr)
232 #define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
233 #define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
234 #define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
235 #define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
238 #define IOSAPIC_REG_SELECT 0
239 #define IOSAPIC_REG_WINDOW 0x10
240 #define IOSAPIC_REG_EOI 0x40
242 #define IOSAPIC_REG_VERSION 0x1
244 #define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
245 #define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
248 ** FIXME: revisit which GFP flags we should really be using.
249 ** GFP_KERNEL includes __GFP_WAIT flag and that may not
250 ** be acceptable. Since this is boot time, we shouldn't have
251 ** to wait ever and this code should (will?) never get called
252 ** from the interrrupt context.
254 #define IOSAPIC_KALLOC(a_type, cnt) \
255 (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
256 #define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
259 #define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags)
260 #define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
263 #define IOSAPIC_VERSION_MASK 0x000000ff
264 #define IOSAPIC_VERSION_SHIFT 0x0
265 #define IOSAPIC_VERSION(ver) \
266 (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
268 #define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
270 #define IOSAPIC_MAX_ENTRY_SHIFT 0x10
271 #define IOSAPIC_IRDT_MAX_ENTRY(ver) \
272 (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
274 /* bits in the "low" I/O Sapic IRdT entry */
275 #define IOSAPIC_IRDT_ENABLE 0x10000
276 #define IOSAPIC_IRDT_PO_LOW 0x02000
277 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
278 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
280 /* bits in the "high" I/O Sapic IRdT entry */
281 #define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
285 #define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
287 static struct iosapic_info *iosapic_list;
288 static spinlock_t iosapic_lock;
289 static int iosapic_count;
293 ** REVISIT: future platforms may have more than one IRT.
294 ** If so, the following three fields form a structure which
295 ** then be linked into a list. Names are chosen to make searching
296 ** for them easy - not necessarily accurate (eg "cell").
298 ** Alternative: iosapic_info could point to the IRT it's in.
299 ** iosapic_register() could search a list of IRT's.
301 static struct irt_entry *irt_cell;
302 static size_t irt_num_entry;
309 ** The "Get PCI INT Routing Table Size" option returns the number of
310 ** entries in the PCI interrupt routing table for the cell specified
311 ** in the cell_number argument. The cell number must be for a cell
312 ** within the caller's protection domain.
314 ** The "Get PCI INT Routing Table" option returns, for the cell
315 ** specified in the cell_number argument, the PCI interrupt routing
316 ** table in the caller allocated memory pointed to by mem_addr.
317 ** We assume the IRT only contains entries for I/O SAPIC and
318 ** calculate the size based on the size of I/O sapic entries.
320 ** The PCI interrupt routing table entry format is derived from the
321 ** IA64 SAL Specification 2.4. The PCI interrupt routing table defines
322 ** the routing of PCI interrupt signals between the PCI device output
323 ** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
324 ** devices). This table does NOT include information for devices/slots
325 ** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
326 ** for the architected method of routing of IRQ's behind PPB's.
330 static int __init /* return number of entries as success/fail flag */
331 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
333 long status; /* PDC return value status */
334 struct irt_entry *table; /* start of interrupt routing tbl */
335 unsigned long num_entries = 0UL;
341 /* Use pat pdc routine to get interrupt routing table size */
342 DBG("calling get_irt_size (cell %ld)\n", cell_num);
343 status = pdc_pat_get_irt_size(&num_entries, cell_num);
344 DBG("get_irt_size: %ld\n", status);
346 ASSERT(status == PDC_OK);
348 /* save the number of entries in the table */
349 ASSERT(0UL != num_entries);
352 ** allocate memory for interrupt routing table
353 ** This interface isn't really right. We are assuming
354 ** the contents of the table are exclusively
355 ** for I/O sapic devices.
357 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
359 printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
363 /* get PCI INT routing table */
364 status = pdc_pat_get_irt(table, cell_num);
365 DBG("pdc_pat_get_irt: %ld\n", status);
366 ASSERT(status == PDC_OK);
369 ** C3000/J5000 (and similar) platforms with Sprockets PDC
370 ** will return exactly one IRT for all iosapics.
371 ** So if we have one, don't need to get it again.
373 if (NULL != irt_cell)
376 /* Should be using the Elroy's HPA, but it's ignored anyway */
377 status = pdc_pci_irt_size(&num_entries, 0);
378 DBG("pdc_pci_irt_size: %ld\n", status);
380 if (PDC_OK != status) {
381 /* Not a "legacy" system with I/O SAPIC either */
385 ASSERT(0UL != num_entries);
387 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
389 printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
393 /* HPA ignored by this call too. */
394 status = pdc_pci_irt(num_entries, 0, table);
395 ASSERT(PDC_OK == status);
398 /* return interrupt table address */
401 #ifdef DEBUG_IOSAPIC_IRT
403 struct irt_entry *p = table;
406 printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
407 printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
410 (int) sizeof(struct irt_entry));
412 for (i = 0 ; i < num_entries ; i++, p++) {
413 printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
414 p->entry_type, p->entry_length, p->interrupt_type,
415 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
416 p->src_seg_id, p->dest_iosapic_intin,
422 #endif /* DEBUG_IOSAPIC_IRT */
432 unsigned long cell = 0;
434 /* init global data */
435 iosapic_lock = SPIN_LOCK_UNLOCKED;
436 iosapic_list = (struct iosapic_info *) NULL;
439 DBG("iosapic_init()\n");
444 struct pdc_pat_cell_num cell_info;
446 status = pdc_pat_cell_get_number(&cell_info);
447 if (status == PDC_OK) {
448 cell = cell_info.cell_num;
454 ** get IRT for this cell.
456 irt_num_entry = iosapic_load_irt(cell, &irt_cell);
457 if (0 == irt_num_entry)
458 irt_cell = NULL; /* old PDC w/o iosapic */
463 ** Return the IRT entry in case we need to look something else up.
465 static struct irt_entry *
466 irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
468 struct irt_entry *i = irt_cell;
469 int cnt; /* track how many entries we've looked at */
470 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
472 DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
474 for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
477 ** Validate: entry_type, entry_length, interrupt_type
479 ** Difference between validate vs compare is the former
480 ** should print debug info and is not expected to "fail"
481 ** on current platforms.
483 if (i->entry_type != IRT_IOSAPIC_TYPE) {
484 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
488 if (i->entry_length != IRT_IOSAPIC_LENGTH) {
489 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
493 if (i->interrupt_type != IRT_VECTORED_INTR) {
494 DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
499 ** Compare: dest_iosapic_addr, src_bus_irq_devno
501 if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
504 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
508 ** Ignore: src_bus_id and rc_seg_id correlate with
509 ** iosapic_info->isi_hpa on HP platforms.
510 ** If needed, pass in "PFA" (aka config space addr)
518 printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
519 isi->isi_hpa, slot, intr_pin);
525 ** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
526 ** Legacy PDC already does this translation for us and stores it in INTR_LINE.
528 ** PAT PDC needs to basically do what legacy PDC does:
530 ** o adjust PIN in case device is "behind" a PPB
531 ** (eg 4-port 100BT and SCSI/LAN "Combo Card")
532 ** o convert slot/pin to I/O SAPIC input line.
534 ** HP platforms only support:
535 ** o one level of skewing for any number of PPBs
536 ** o only support PCI-PCI Bridges.
538 static struct irt_entry *
539 iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
541 u8 intr_pin, intr_slot;
543 pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
545 DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
546 PCI_SLOT(pcidev->devfn), intr_pin);
549 /* The device does NOT support/use IRQ lines. */
553 /* Check if pcidev behind a PPB */
554 if (NULL != pcidev->bus->self) {
555 /* Convert pcidev INTR_PIN into something we
556 ** can lookup in the IRT.
558 #ifdef PCI_BRIDGE_FUNCS
562 ** call implementation specific translation function
563 ** This is architecturally "cleaner". HP-UX doesn't
564 ** support other secondary bus types (eg. E/ISA) directly.
565 ** May be needed for other processor (eg IA64) architectures
566 ** or by some ambitous soul who wants to watch TV.
568 if (pci_bridge_funcs->xlate_intr_line) {
569 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
571 #else /* PCI_BRIDGE_FUNCS */
572 struct pci_bus *p = pcidev->bus;
575 ** The "pin" is skewed ((pin + dev - 1) % 4).
577 ** This isn't very clean since I/O SAPIC must assume:
578 ** - all platforms only have PCI busses.
579 ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
580 ** - IRQ routing is only skewed once regardless of
581 ** the number of PPB's between iosapic and device.
582 ** (Bit3 expansion chassis follows this rule)
584 ** Advantage is it's really easy to implement.
586 intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
587 intr_pin++; /* convert back to INTA-D (1-4) */
588 #endif /* PCI_BRIDGE_FUNCS */
591 ** Locate the host slot the PPB nearest the Host bus
594 while (NULL != p->parent->self)
597 intr_slot = PCI_SLOT(p->self->devfn);
599 intr_slot = PCI_SLOT(pcidev->devfn);
601 DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
602 pcidev->bus->secondary, intr_slot, intr_pin);
604 return irt_find_irqline(isi, intr_slot, intr_pin);
609 iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
611 struct vector_info *vi = (struct vector_info *)dev_id;
612 extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
613 int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline;
615 DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
616 irq, vi->irqline, vi->eoi_addr);
618 /* FIXME: Need to mask/unmask? processor IRQ is already masked... */
619 do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs);
622 ** PCI only supports level triggered in order to share IRQ lines.
623 ** I/O SAPIC must always issue EOI.
625 IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
632 iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
634 struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
635 struct irt_entry *irte = NULL; /* only used if PAT PDC */
636 struct vector_info *vi;
637 int isi_line; /* line used by device */
641 printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
646 #ifdef CONFIG_SUPERIO
648 * HACK ALERT! (non-compliant PCI device support)
650 * All SuckyIO interrupts are routed through the PIC's on function 1.
651 * But SuckyIO OHCI USB controller gets an IRT entry anyway because
652 * it advertises INT D for INT_PIN. Use that IRT entry to get the
653 * SuckyIO interrupt routing for PICs on function 1 (*BLEECCHH*).
655 if (is_superio_device(pcidev)) {
656 /* We must call superio_fixup_irq() to register the pdev */
657 pcidev->irq = superio_fixup_irq(pcidev);
659 /* Don't return if need to program the IOSAPIC's IRT... */
660 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
663 #endif /* CONFIG_SUPERIO */
665 /* lookup IRT entry for isi/slot/pin set */
666 irte = iosapic_xlate_pin(isi, pcidev);
668 printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
672 DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
676 irte->polarity_trigger,
677 irte->src_bus_irq_devno,
680 irte->dest_iosapic_intin,
681 (u32) irte->dest_iosapic_addr);
682 isi_line = irte->dest_iosapic_intin;
683 pcidev->irq = isi->isi_region->data.irqbase + isi_line;
685 /* get vector info for this input line */
686 ASSERT(NULL != isi->isi_vector);
687 vi = &(isi->isi_vector[isi_line]);
688 DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
690 /* If this IRQ line has already been setup, skip it */
696 /* Allocate processor IRQ */
697 vi->txn_irq = txn_alloc_irq();
699 /* XXX/FIXME The txn_alloc_irq() code and related code should be moved
700 ** to enable_irq(). That way we only allocate processor IRQ bits
701 ** for devices that actually have drivers claiming them.
702 ** Right now we assign an IRQ to every PCI device present regardless
703 ** of whether it's used or not.
706 panic("I/O sapic: couldn't get TXN IRQ\n");
708 /* enable_irq() will use txn_* to program IRdT */
709 vi->txn_addr = txn_alloc_addr(vi->txn_irq);
710 vi->txn_data = txn_alloc_data(vi->txn_irq, 8);
711 ASSERT(vi->txn_data < 256); /* matches 8 above */
713 tmp = request_irq(vi->txn_irq, iosapic_interrupt, 0,
717 vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
718 vi->eoi_data = cpu_to_le32(vi->irqline);
720 ASSERT(NULL != isi->isi_region);
722 DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
723 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->irq),
724 pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
731 iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
733 struct iosapic_info *isp = vi->iosapic;
734 u8 idx = vi->irqline;
736 /* point the window register to the lower word */
737 WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
738 *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
740 /* point the window register to the higher word */
741 WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
742 *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
747 iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
749 struct iosapic_info *isp = vi->iosapic;
752 ASSERT(0 != isp->isi_hpa);
753 DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n",
755 isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
758 /* point the window register to the lower word */
759 WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
760 WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
762 /* Read the window register to flush the writes down to HW */
763 dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
765 /* point the window register to the higher word */
766 WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
767 WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
769 /* Read the window register to flush the writes down to HW */
770 dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
775 ** set_irt prepares the data (dp0, dp1) according to the vector_info
776 ** and target cpu (id_eid). dp0/dp1 are then used to program I/O SAPIC
777 ** IRdT for the given "vector" (aka IRQ line).
780 iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
783 struct irt_entry *p = vi->irte;
784 ASSERT(NULL != vi->irte);
786 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
787 mode |= IOSAPIC_IRDT_PO_LOW;
789 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
790 mode |= IOSAPIC_IRDT_LEVEL_TRIG;
794 ** PA doesn't support EXTINT or LPRIO bits.
797 ASSERT(vi->txn_data);
798 *dp0 = mode | (u32) vi->txn_data;
801 ** Extracting id_eid isn't a real clean way of getting it.
802 ** But the encoding is the same for both PA and IA64 platforms.
806 ** PAT PDC just hands it to us "right".
807 ** txn_addr comes from cpu_data[x].txn_addr.
809 *dp1 = (u32) (vi->txn_addr);
812 ** eg if base_addr == 0xfffa0000),
813 ** we want to get 0xa0ff0000.
815 ** eid 0x0ff00000 -> 0x00ff0000
816 ** id 0x000ff000 -> 0xff000000
818 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) |
819 (((u32)vi->txn_addr & 0x000ff000) << 12);
821 DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
826 iosapic_disable_irq(void *irq_dev, int irq)
829 struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]);
834 IOSAPIC_LOCK(&iosapic_lock);
836 #ifdef REVISIT_DESIGN_ISSUE
840 disable_irq()/enable_irq(): drawback of using IRQ as a "handle"
842 Current disable_irq interface only allows the irq_region support routines
843 to manage sharing of "irq" objects. The problem is the disable_irq()
844 interface specifies which IRQ line needs to be disabled but does not
845 identify the particular ISR which needs to be disabled. IO sapic
846 (and similar code in Dino) can only support one handler per IRQ
847 since they don't further encode the meaning of the IRQ number.
848 irq_region support has to hide it's implementation of "shared IRQ"
849 behind a function call.
851 Encoding the IRQ would be possible by I/O SAPIC but makes life really
852 complicated for the IRQ handler and not help performance.
854 Need more info on how Linux supports shared IRQ lines on a PC.
856 #endif /* REVISIT_DESIGN_ISSUE */
858 iosapic_rd_irt_entry(vi, &d0, &d1);
859 d0 |= IOSAPIC_IRDT_ENABLE;
860 iosapic_wr_irt_entry(vi, d0, d1);
862 IOSAPIC_UNLOCK(&iosapic_lock);
864 /* disable ISR for parent */
865 disable_irq(vi->txn_irq);
870 iosapic_enable_irq(void *dev, int irq)
872 struct vector_info *vi = &(((struct vector_info *) dev)[irq]);
876 ASSERT(NULL != vi->irte);
878 /* data is initialized by fixup_irq */
879 ASSERT(0 < vi->txn_irq);
880 ASSERT(0UL != vi->txn_data);
882 iosapic_set_irt_data(vi, &d0, &d1);
883 iosapic_wr_irt_entry(vi, d0, d1);
886 #ifdef DEBUG_IOSAPIC_IRT
888 u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
889 printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
890 while (t < vi->eoi_addr) printk(" %x", READ_U32(t++));
894 printk("iosapic_enable_irq(): sel ");
896 struct iosapic_info *isp = vi->iosapic;
898 for (d0=0x10; d0<0x1e; d0++) {
899 /* point the window register to the lower word */
900 WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
903 d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
911 ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
912 ** PCI supports level triggered in order to share IRQ lines.
914 ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
917 IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
922 iosapic_mask_irq(void *dev, int irq)
929 iosapic_unmask_irq(void *dev, int irq)
935 static struct irq_region_ops iosapic_irq_ops = {
936 .disable_irq = iosapic_disable_irq,
937 .enable_irq = iosapic_enable_irq,
938 .mask_irq = iosapic_mask_irq,
939 .unmask_irq = iosapic_unmask_irq
944 ** squirrel away the I/O Sapic Version
947 iosapic_rd_version(struct iosapic_info *isi)
950 ASSERT(isi->isi_hpa);
952 /* point window to the version register */
953 WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
955 /* now read the version register */
956 return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
961 ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
962 ** Caller must be certain they have an I/O SAPIC and know its MMIO address.
964 ** o allocate iosapic_info and add it to the list
965 ** o read iosapic version and squirrel that away
966 ** o read size of IRdT.
967 ** o allocate and initialize isi_vector[]
968 ** o allocate isi_region (registers region handlers)
971 iosapic_register(unsigned long hpa)
973 struct iosapic_info *isi = NULL;
974 struct irt_entry *irte = irt_cell;
975 struct vector_info *vip;
976 int cnt; /* track how many entries we've looked at */
979 ** Astro based platforms can't support PCI OLARD if they
980 ** implement the legacy PDC (not PAT). Though Legacy PDC
981 ** supports an IRT, LBA's with no device under them
982 ** are *not* listed in the IRT.
983 ** Search the IRT and ignore iosapic's which aren't
986 ASSERT(NULL != irte); /* always have built-in devices */
987 for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
988 ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
990 ** We need sign extension of the hpa on 32-bit kernels.
991 ** The address in the IRT is *always* 64 bit and really
992 ** is an unsigned quantity (like all physical addresses).
994 if (irte->dest_iosapic_addr == (s64) ((long) hpa))
998 if (cnt >= irt_num_entry)
1001 if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
1006 memset(isi, 0, sizeof(struct iosapic_info));
1009 isi->isi_version = iosapic_rd_version(isi);
1010 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
1012 vip = isi->isi_vector =
1013 IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
1016 IOSAPIC_FREE(isi, struct iosapic_info, 1);
1020 memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
1021 sprintf(isi->isi_name, "IO-SAPIC%02d", iosapic_count++);
1024 ** Initialize vector array
1026 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
1027 vip->irqline = (unsigned char) cnt;
1029 sprintf(vip->name, "%s-L%d", isi->isi_name, cnt);
1032 isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
1033 &iosapic_irq_ops, isi->isi_name,
1034 (void *) isi->isi_vector);
1036 ASSERT(NULL != isi->isi_region);
1037 return ((void *) isi);
1041 #ifdef DEBUG_IOSAPIC
1044 iosapic_prt_irt(void *irt, long num_entry)
1046 unsigned int i, *irp = (unsigned int *) irt;
1048 ASSERT(NULL != irt);
1050 printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
1052 for (i=0; i<num_entry; i++, irp += 4) {
1053 printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
1054 irp, i, irp[0], irp[1], irp[2], irp[3]);
1060 iosapic_prt_vi(struct vector_info *vi)
1064 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
1065 printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status);
1066 printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq);
1067 printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr);
1068 printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data);
1069 printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr);
1070 printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data);
1075 iosapic_prt_isi(struct iosapic_info *isi)
1077 ASSERT(NULL != isi);
1078 printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
1079 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa);
1080 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
1081 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
1082 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
1084 #endif /* DEBUG_IOSAPIC */