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").
226 /* The IRT needs to be 8-byte aligned for the PDC call. in iosapic_alloc_irt()
229 * 4-byte alignment on 32-bit kernels in iosapic_alloc_irt()
237 * iosapic_load_irt - Fill in the interrupt routing table
238 * @cell_num: The cell number of the CPU we're currently executing on
243 * entries in the PCI interrupt routing table for the cell specified
244 * in the cell_number argument. The cell number must be for a cell
247 * The "Get PCI INT Routing Table" option returns, for the cell
274 DBG("calling get_irt_size (cell %ld)\n", cell_num); in iosapic_load_irt()
338 printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num); in iosapic_load_irt()
346 p->entry_type, p->entry_length, p->interrupt_type, in iosapic_load_irt()
347 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id, in iosapic_load_irt()
348 p->src_seg_id, p->dest_iosapic_intin, in iosapic_load_irt()
363 unsigned long cell = 0; in iosapic_init() local
374 cell = cell_info.cell_num; in iosapic_init()
379 /* get interrupt routing table for this cell */ in iosapic_init()
380 irt_num_entry = iosapic_load_irt(cell, &irt_cell); in iosapic_init()
394 u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1); in irt_find_irqline()
407 if (i->entry_type != IRT_IOSAPIC_TYPE) { in irt_find_irqline()
408 …DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->en… in irt_find_irqline()
412 if (i->entry_length != IRT_IOSAPIC_LENGTH) { in irt_find_irqline()
413 …ARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length); in irt_find_irqline()
417 if (i->interrupt_type != IRT_VECTORED_INTR) { in irt_find_irqline()
418 …ULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type); in irt_find_irqline()
422 if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa)) in irt_find_irqline()
425 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno) in irt_find_irqline()
430 ** iosapic_info->isi_hpa on HP platforms. in irt_find_irqline()
440 isi->isi_hpa, slot, intr_pin); in irt_find_irqline()
452 ** (eg 4-port 100BT and SCSI/LAN "Combo Card")
457 ** o only support PCI-PCI Bridges.
467 pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin); in iosapic_xlate_pin()
475 if (pcidev->bus->parent) { in iosapic_xlate_pin()
484 ** This is architecturally "cleaner". HP-UX doesn't in iosapic_xlate_pin()
489 if (pci_bridge_funcs->xlate_intr_line) { in iosapic_xlate_pin()
490 intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev); in iosapic_xlate_pin()
493 struct pci_bus *p = pcidev->bus; in iosapic_xlate_pin()
496 ** The "pin" is skewed ((pin + dev - 1) % 4). in iosapic_xlate_pin()
499 ** - all platforms only have PCI busses. in iosapic_xlate_pin()
500 ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA) in iosapic_xlate_pin()
501 ** - IRQ routing is only skewed once regardless of in iosapic_xlate_pin()
513 while (p->parent->parent) in iosapic_xlate_pin()
514 p = p->parent; in iosapic_xlate_pin()
516 intr_slot = PCI_SLOT(p->self->devfn); in iosapic_xlate_pin()
518 intr_slot = PCI_SLOT(pcidev->devfn); in iosapic_xlate_pin()
521 pcidev->bus->busn_res.start, intr_slot, intr_pin); in iosapic_xlate_pin()
528 struct iosapic_info *isp = vi->iosapic; in iosapic_rd_irt_entry()
529 u8 idx = vi->irqline; in iosapic_rd_irt_entry()
531 *dp0 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY(idx)); in iosapic_rd_irt_entry()
532 *dp1 = iosapic_read(isp->addr, IOSAPIC_IRDT_ENTRY_HI(idx)); in iosapic_rd_irt_entry()
538 struct iosapic_info *isp = vi->iosapic; in iosapic_wr_irt_entry()
541 vi->irqline, isp->isi_hpa, dp0, dp1); in iosapic_wr_irt_entry()
543 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY(vi->irqline), dp0); in iosapic_wr_irt_entry()
546 dp0 = readl(isp->addr+IOSAPIC_REG_WINDOW); in iosapic_wr_irt_entry()
548 iosapic_write(isp->addr, IOSAPIC_IRDT_ENTRY_HI(vi->irqline), dp1); in iosapic_wr_irt_entry()
551 dp1 = readl(isp->addr+IOSAPIC_REG_WINDOW); in iosapic_wr_irt_entry()
563 struct irt_entry *p = vi->irte; in iosapic_set_irt_data()
565 if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO) in iosapic_set_irt_data()
568 if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG) in iosapic_set_irt_data()
576 *dp0 = mode | (u32) vi->txn_data; in iosapic_set_irt_data()
587 *dp1 = (u32) (vi->txn_addr); in iosapic_set_irt_data()
593 ** eid 0x0ff00000 -> 0x00ff0000 in iosapic_set_irt_data()
594 ** id 0x000ff000 -> 0xff000000 in iosapic_set_irt_data()
596 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) | in iosapic_set_irt_data()
597 (((u32)vi->txn_addr & 0x000ff000) << 12); in iosapic_set_irt_data()
622 WARN_ON(vi->txn_irq == 0); in iosapic_unmask_irq()
629 u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL); in iosapic_unmask_irq()
630 printk("iosapic_enable_irq(): regs %p", vi->eoi_addr); in iosapic_unmask_irq()
631 for ( ; t < vi->eoi_addr; t++) in iosapic_unmask_irq()
638 struct iosapic_info *isp = vi->iosapic; in iosapic_unmask_irq()
641 d1 = iosapic_read(isp->addr, d0); in iosapic_unmask_irq()
654 DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq, in iosapic_unmask_irq()
655 vi->eoi_addr, vi->eoi_data); in iosapic_unmask_irq()
656 iosapic_eoi(vi->eoi_addr, vi->eoi_data); in iosapic_unmask_irq()
663 iosapic_eoi(vi->eoi_addr, vi->eoi_data); in iosapic_eoi_irq()
678 return -1; in iosapic_set_affinity_irq()
681 vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); in iosapic_set_affinity_irq()
696 .name = "IO-SAPIC-level",
716 return -1; in iosapic_fixup_irq()
721 * HACK ALERT! (non-compliant PCI device support) in iosapic_fixup_irq()
730 pcidev->irq = superio_fixup_irq(pcidev); in iosapic_fixup_irq()
733 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) in iosapic_fixup_irq()
734 return pcidev->irq; in iosapic_fixup_irq()
743 return -1; in iosapic_fixup_irq()
747 irte->entry_type, in iosapic_fixup_irq()
748 irte->entry_length, in iosapic_fixup_irq()
749 irte->polarity_trigger, in iosapic_fixup_irq()
750 irte->src_bus_irq_devno, in iosapic_fixup_irq()
751 irte->src_bus_id, in iosapic_fixup_irq()
752 irte->src_seg_id, in iosapic_fixup_irq()
753 irte->dest_iosapic_intin, in iosapic_fixup_irq()
754 (u32) irte->dest_iosapic_addr); in iosapic_fixup_irq()
755 isi_line = irte->dest_iosapic_intin; in iosapic_fixup_irq()
758 vi = isi->isi_vector + isi_line; in iosapic_fixup_irq()
762 if (vi->irte) in iosapic_fixup_irq()
765 vi->irte = irte; in iosapic_fixup_irq()
776 vi->txn_irq = txn_alloc_irq(8); in iosapic_fixup_irq()
778 if (vi->txn_irq < 0) in iosapic_fixup_irq()
782 vi->txn_addr = txn_alloc_addr(vi->txn_irq); in iosapic_fixup_irq()
783 vi->txn_data = txn_alloc_data(vi->txn_irq); in iosapic_fixup_irq()
785 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; in iosapic_fixup_irq()
786 vi->eoi_data = cpu_to_le32(vi->txn_data); in iosapic_fixup_irq()
788 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); in iosapic_fixup_irq()
791 pcidev->irq = vi->txn_irq; in iosapic_fixup_irq()
794 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn), in iosapic_fixup_irq()
795 pcidev->vendor, pcidev->device, isi_line, pcidev->irq); in iosapic_fixup_irq()
797 return pcidev->irq; in iosapic_fixup_irq()
811 intin = (dev->mod_info >> 24) & 15; in iosapic_serial_irq()
816 if (COMPARE_IRTE_ADDR(irte, dev->mod0) && in iosapic_serial_irq()
817 irte->dest_iosapic_intin == intin) in iosapic_serial_irq()
825 irte->entry_type, in iosapic_serial_irq()
826 irte->entry_length, in iosapic_serial_irq()
827 irte->polarity_trigger, in iosapic_serial_irq()
828 irte->src_bus_irq_devno, in iosapic_serial_irq()
829 irte->src_bus_id, in iosapic_serial_irq()
830 irte->src_seg_id, in iosapic_serial_irq()
831 irte->dest_iosapic_intin, in iosapic_serial_irq()
832 (u32) irte->dest_iosapic_addr); in iosapic_serial_irq()
835 for (isi = iosapic_list; isi; isi = isi->isi_next) in iosapic_serial_irq()
836 if (isi->isi_hpa == dev->mod0) in iosapic_serial_irq()
842 vi = isi->isi_vector + intin; in iosapic_serial_irq()
846 if (vi->irte) in iosapic_serial_irq()
849 vi->irte = irte; in iosapic_serial_irq()
860 vi->txn_irq = txn_alloc_irq(8); in iosapic_serial_irq()
862 if (vi->txn_irq < 0) in iosapic_serial_irq()
866 vi->txn_addr = txn_alloc_addr(vi->txn_irq); in iosapic_serial_irq()
867 vi->txn_data = txn_alloc_data(vi->txn_irq); in iosapic_serial_irq()
869 vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI; in iosapic_serial_irq()
870 vi->eoi_data = cpu_to_le32(vi->txn_data); in iosapic_serial_irq()
872 cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi); in iosapic_serial_irq()
876 return vi->txn_irq; in iosapic_serial_irq()
887 return iosapic_read(isi->addr, IOSAPIC_REG_VERSION); in iosapic_rd_version()
914 WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type); in iosapic_register()
930 isi->addr = ioremap(hpa, 4096); in iosapic_register()
931 isi->isi_hpa = hpa; in iosapic_register()
932 isi->isi_version = iosapic_rd_version(isi); in iosapic_register()
933 isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; in iosapic_register()
935 vip = isi->isi_vector = kcalloc(isi->isi_num_vectors, in iosapic_register()
942 for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { in iosapic_register()
943 vip->irqline = (unsigned char) cnt; in iosapic_register()
944 vip->iosapic = isi; in iosapic_register()
946 isi->isi_next = iosapic_list; in iosapic_register()
972 printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi); in iosapic_prt_vi()
973 printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status); in iosapic_prt_vi()
974 printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq); in iosapic_prt_vi()
975 printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr); in iosapic_prt_vi()
976 printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data); in iosapic_prt_vi()
977 printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr); in iosapic_prt_vi()
978 printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data); in iosapic_prt_vi()
986 printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa); in iosapic_prt_isi()
987 printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status); in iosapic_prt_isi()
988 printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version); in iosapic_prt_isi()
989 printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector); in iosapic_prt_isi()