/* Fixup the IRQ for USB devices which is exist on XLP9XX SOC PCIE bus */ static void nlm_xlp9xx_usb_fixup_final(struct pci_dev *dev) { int node; node = xlp_socdev_to_node(dev); dev->dev.dma_mask = &xlp_usb_dmamask; dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); switch (dev->devfn) { case 0x21: dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_0_IRQ); break; case 0x22: dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_1_IRQ); break; case 0x23: dev->irq = nlm_irq_to_xirq(node, PIC_9XX_XHCI_2_IRQ); break; } }
/* * Allocate a MSI vector on a link */ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, struct msi_desc *desc) { struct xlp_msi_data *md; struct msi_msg msg; unsigned long flags; int msivec, irt, lirq, xirq, ret; uint64_t msiaddr; /* Get MSI data for the link */ lirq = PIC_PCIE_LINK_MSI_IRQ(link); xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); md = irq_get_handler_data(xirq); msiaddr = MSI_LINK_ADDR(node, link); spin_lock_irqsave(&md->msi_lock, flags); if (md->msi_alloc_mask == 0) { xlp_config_link_msi(lnkbase, lirq, msiaddr); /* switch the link IRQ to MSI range */ if (cpu_is_xlp9xx()) irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); else irt = PIC_IRT_PCIE_LINK_INDEX(link); nlm_setup_pic_irq(node, lirq, lirq, irt); nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, node * nlm_threads_per_node(), 1 /*en */); } /* allocate a MSI vec, and tell the bridge about it */ msivec = fls(md->msi_alloc_mask); if (msivec == XLP_MSIVEC_PER_LINK) { spin_unlock_irqrestore(&md->msi_lock, flags); return -ENOMEM; } md->msi_alloc_mask |= (1u << msivec); spin_unlock_irqrestore(&md->msi_lock, flags); msg.address_hi = msiaddr >> 32; msg.address_lo = msiaddr & 0xffffffff; msg.data = 0xc00 | msivec; xirq = xirq + msivec; /* msi mapped to global irq space */ ret = irq_set_msi_desc(xirq, desc); if (ret < 0) return ret; write_msi_msg(xirq, &msg); return 0; }
static void nlm_sata_fixup_final(struct pci_dev *dev) { u32 val; u64 regbase; int node; /* Find end bridge function to find node */ node = xlp_socdev_to_node(dev); regbase = nlm_get_sata_regbase(node); /* clear pending interrupts and then enable them */ val = nlm_read_sata_reg(regbase, SATA_INT); sata_set_glue_reg(regbase, SATA_INT, val); /* Enable only the core interrupt */ sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1); dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ); nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack); }