Lines Matching +full:msi +full:- +full:cell
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 ** I/O Sapic Driver - PCI interrupt line support
6 ** (c) Copyright 1999 Hewlett-Packard Company
14 ** --------
21 ** MSI Message Signaled Interrupt. PCI 2.2 functionality.
28 ** -------------------------------------
29 ** MSI is a write transaction which targets a processor and is similar
33 ** PA only supports MSI. So I/O subsystems must either natively generate
34 ** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
38 ** MSI allows any I/O device to interrupt any processor. This makes
44 ** before the MSI is issued. I/O status can then safely be read from
49 ** -----------
50 ** PA-RISC platforms have two fundamentally different types of firmware.
58 ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
68 ** --------------------
77 ** ------------------
78 ** The IO-SAPIC can indicate to the CPU which interrupt was asserted.
79 ** So, unlike the GSC-ASIC and Dino, we allocate one CPU interrupt per
80 ** IO-SAPIC interrupt and call the device driver's handler directly.
81 ** The IO-SAPIC driver hijacks the CPU interrupt handler so it can
82 ** issue the End Of Interrupt command to the IO-SAPIC.
85 ** --------------------------------------
86 ** (caveat: code isn't finished yet - this is just the plan)
96 ** o initialize vector_info - read corresponding IRdT?
100 ** o if (device under PCI-PCI bridge)
110 ** intr_line = pcidev->irq
119 ** o enable IRdT - call enable_irq(vector[line]->processor_irq)
123 ** o disable IRdT - call disable_irq(vector[line]->processor_irq)
158 #define COMPARE_IRTE_ADDR(irte, hpa) ((irte)->dest_iosapic_addr == (hpa))
161 ((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
214 ** for them easy - not necessarily accurate (eg "cell").
228 * iosapic_load_irt - Fill in the interrupt routing table
229 * @cell_num: The cell number of the CPU we're currently executing on
234 * entries in the PCI interrupt routing table for the cell specified
235 * in the cell_number argument. The cell number must be for a cell
238 * The "Get PCI INT Routing Table" option returns, for the cell
265 DBG("calling get_irt_size (cell %ld)\n", cell_num); in iosapic_load_irt()
329 printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num); in iosapic_load_irt()
337 p->entry_type, p->entry_length, p->interrupt_type, in iosapic_load_irt()
338 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id, in iosapic_load_irt()
339 p->src_seg_id, p->dest_iosapic_intin, in iosapic_load_irt()
353 unsigned long cell = 0; in iosapic_init() local
362 cell = cell_info.cell_num; in iosapic_init()
367 /* get interrupt routing table for this cell */ in iosapic_init()
368 irt_num_entry = iosapic_load_irt(cell, &irt_cell); in iosapic_init()
385 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1); in irt_find_irqline()
398 if (i->entry_type != IRT_IOSAPIC_TYPE) { in irt_find_irqline()
399 …DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->en… in irt_find_irqline()
403 if (i->entry_length != IRT_IOSAPIC_LENGTH) { in irt_find_irqline()
404 …ARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length); in irt_find_irqline()
408 if (i->interrupt_type != IRT_VECTORED_INTR) { in irt_find_irqline()
409 …ULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type); in irt_find_irqline()
413 if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa)) in irt_find_irqline()
416 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno) in irt_find_irqline()
421 ** iosapic_info->isi_hpa on HP platforms. in irt_find_irqline()
431 isi->isi_hpa, slot, intr_pin); in irt_find_irqline()
443 ** (eg 4-port 100BT and SCSI/LAN "Combo Card")
448 ** o only support PCI-PCI Bridges.
458 pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin); in iosapic_xlate_pin()
466 if (pcidev->bus->parent) { in iosapic_xlate_pin()
475 ** This is architecturally "cleaner". HP-UX doesn't in iosapic_xlate_pin()
480 if (pci_bridge_funcs->xlate_intr_line) { in iosapic_xlate_pin()
481 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev); in iosapic_xlate_pin()
484 struct pci_bus *p = pcidev->bus; in iosapic_xlate_pin()
487 ** The "pin" is skewed ((pin + dev - 1) % 4). in iosapic_xlate_pin()
490 ** - all platforms only have PCI busses. in iosapic_xlate_pin()
491 ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA) in iosapic_xlate_pin()
492 ** - IRQ routing is only skewed once regardless of in iosapic_xlate_pin()
504 while (p->parent->parent) in iosapic_xlate_pin()
505 p = p->parent; in iosapic_xlate_pin()
507 intr_slot = PCI_SLOT(p->self->devfn); in iosapic_xlate_pin()
509 intr_slot = PCI_SLOT(pcidev->devfn); in iosapic_xlate_pin()
512 pcidev->bus->busn_res.start, intr_slot, intr_pin); in iosapic_xlate_pin()
519 struct iosapic_info *isp = vi->iosapic; in iosapic_rd_irt_entry()
520 u8 idx = vi->irqline; in iosapic_rd_irt_entry()
522 *dp0 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY(idx)); in iosapic_rd_irt_entry()
523 *dp1 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY_HI(idx)); in iosapic_rd_irt_entry()
529 struct iosapic_info *isp = vi->iosapic; in iosapic_wr_irt_entry()
532 vi->irqline, isp->isi_hpa, dp0, dp1); in iosapic_wr_irt_entry()
534 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0); in iosapic_wr_irt_entry()
537 dp0 = readl(isp->addr+IOSAPIC_REG_WINDOW); in iosapic_wr_irt_entry()
539 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1); in iosapic_wr_irt_entry()
542 dp1 = readl(isp->addr+IOSAPIC_REG_WINDOW); in iosapic_wr_irt_entry()
554 struct irt_entry *p = vi->irte; in iosapic_set_irt_data()
556 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO) in iosapic_set_irt_data()
559 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG) in iosapic_set_irt_data()
567 *dp0 = mode | (u32) vi->txn_data; in iosapic_set_irt_data()
578 *dp1 = (u32) (vi->txn_addr); in iosapic_set_irt_data()
584 ** eid 0x0ff00000 -> 0x00ff0000 in iosapic_set_irt_data()
585 ** id 0x000ff000 -> 0xff000000 in iosapic_set_irt_data()
587 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) | in iosapic_set_irt_data()
588 (((u32)vi->txn_addr & 0x000ff000) << 12); in iosapic_set_irt_data()
613 WARN_ON(vi->txn_irq == 0); in iosapic_unmask_irq()
620 u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL); in iosapic_unmask_irq()
621 printk("iosapic_enable_irq(): regs %p", vi->eoi_addr); in iosapic_unmask_irq()
622 for ( ; t < vi->eoi_addr; t++) in iosapic_unmask_irq()
629 struct iosapic_info *isp = vi->iosapic; in iosapic_unmask_irq()
632 d1 = iosapic_read(isp->addr, d0); in iosapic_unmask_irq()
645 DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq, in iosapic_unmask_irq()
646 vi->eoi_addr, vi->eoi_data); in iosapic_unmask_irq()
647 iosapic_eoi(vi->eoi_addr, vi->eoi_data); in iosapic_unmask_irq()
654 iosapic_eoi(vi->eoi_addr, vi->eoi_data); in iosapic_eoi_irq()
669 return -1; in iosapic_set_affinity_irq()
672 vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); in iosapic_set_affinity_irq()
687 .name = "IO-SAPIC-level",
707 return -1; in iosapic_fixup_irq()
712 * HACK ALERT! (non-compliant PCI device support) in iosapic_fixup_irq()
721 pcidev->irq = superio_fixup_irq(pcidev); in iosapic_fixup_irq()
724 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) in iosapic_fixup_irq()
725 return pcidev->irq; in iosapic_fixup_irq()
734 return -1; in iosapic_fixup_irq()
738 irte->entry_type, in iosapic_fixup_irq()
739 irte->entry_length, in iosapic_fixup_irq()
740 irte->polarity_trigger, in iosapic_fixup_irq()
741 irte->src_bus_irq_devno, in iosapic_fixup_irq()
742 irte->src_bus_id, in iosapic_fixup_irq()
743 irte->src_seg_id, in iosapic_fixup_irq()
744 irte->dest_iosapic_intin, in iosapic_fixup_irq()
745 (u32) irte->dest_iosapic_addr); in iosapic_fixup_irq()
746 isi_line = irte->dest_iosapic_intin; in iosapic_fixup_irq()
749 vi = isi->isi_vector + isi_line; in iosapic_fixup_irq()
753 if (vi->irte) in iosapic_fixup_irq()
756 vi->irte = irte; in iosapic_fixup_irq()
767 vi->txn_irq = txn_alloc_irq(8); in iosapic_fixup_irq()
769 if (vi->txn_irq < 0) in iosapic_fixup_irq()
773 vi->txn_addr = txn_alloc_addr(vi->txn_irq); in iosapic_fixup_irq()
774 vi->txn_data = txn_alloc_data(vi->txn_irq); in iosapic_fixup_irq()
776 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; in iosapic_fixup_irq()
777 vi->eoi_data = cpu_to_le32(vi->txn_data); in iosapic_fixup_irq()
779 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); in iosapic_fixup_irq()
782 pcidev->irq = vi->txn_irq; in iosapic_fixup_irq()
785 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn), in iosapic_fixup_irq()
786 pcidev->vendor, pcidev->device, isi_line, pcidev->irq); in iosapic_fixup_irq()
788 return pcidev->irq; in iosapic_fixup_irq()
802 intin = (dev->mod_info >> 24) & 15; in iosapic_serial_irq()
807 if (COMPARE_IRTE_ADDR(irte, dev->mod0) && in iosapic_serial_irq()
808 irte->dest_iosapic_intin == intin) in iosapic_serial_irq()
816 irte->entry_type, in iosapic_serial_irq()
817 irte->entry_length, in iosapic_serial_irq()
818 irte->polarity_trigger, in iosapic_serial_irq()
819 irte->src_bus_irq_devno, in iosapic_serial_irq()
820 irte->src_bus_id, in iosapic_serial_irq()
821 irte->src_seg_id, in iosapic_serial_irq()
822 irte->dest_iosapic_intin, in iosapic_serial_irq()
823 (u32) irte->dest_iosapic_addr); in iosapic_serial_irq()
826 for (isi = iosapic_list; isi; isi = isi->isi_next) in iosapic_serial_irq()
827 if (isi->isi_hpa == dev->mod0) in iosapic_serial_irq()
833 vi = isi->isi_vector + intin; in iosapic_serial_irq()
837 if (vi->irte) in iosapic_serial_irq()
840 vi->irte = irte; in iosapic_serial_irq()
851 vi->txn_irq = txn_alloc_irq(8); in iosapic_serial_irq()
853 if (vi->txn_irq < 0) in iosapic_serial_irq()
857 vi->txn_addr = txn_alloc_addr(vi->txn_irq); in iosapic_serial_irq()
858 vi->txn_data = txn_alloc_data(vi->txn_irq); in iosapic_serial_irq()
860 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; in iosapic_serial_irq()
861 vi->eoi_data = cpu_to_le32(vi->txn_data); in iosapic_serial_irq()
863 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); in iosapic_serial_irq()
867 return vi->txn_irq; in iosapic_serial_irq()
879 return iosapic_read(isi->addr, IOSAPIC_REG_VERSION); in iosapic_rd_version()
906 WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type); in iosapic_register()
922 isi->addr = vaddr; in iosapic_register()
923 isi->isi_hpa = hpa; in iosapic_register()
924 isi->isi_version = iosapic_rd_version(isi); in iosapic_register()
925 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; in iosapic_register()
927 vip = isi->isi_vector = kcalloc(isi->isi_num_vectors, in iosapic_register()
934 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { in iosapic_register()
935 vip->irqline = (unsigned char) cnt; in iosapic_register()
936 vip->iosapic = isi; in iosapic_register()
938 isi->isi_next = iosapic_list; in iosapic_register()
964 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi); in iosapic_prt_vi()
965 printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status); in iosapic_prt_vi()
966 printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq); in iosapic_prt_vi()
967 printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr); in iosapic_prt_vi()
968 printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data); in iosapic_prt_vi()
969 printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr); in iosapic_prt_vi()
970 printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data); in iosapic_prt_vi()
978 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa); in iosapic_prt_isi()
979 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status); in iosapic_prt_isi()
980 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version); in iosapic_prt_isi()
981 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector); in iosapic_prt_isi()