diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2017-09-07 21:24:11 +0300 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-09-07 21:24:11 +0300 |
commit | 99fd1b958cd36dc13fa441d63c4e93a39e17fb65 (patch) | |
tree | e00830594c9a980838f0bb6ea36f2cf2dd4331a6 /drivers/pci | |
parent | dd422a6f558cfb50d56d93a84adac149b2eaae7e (diff) | |
parent | 5fd4bf6a659e45251a91b04485318570554651b2 (diff) | |
download | linux-99fd1b958cd36dc13fa441d63c4e93a39e17fb65.tar.xz |
Merge branch 'pci/host-xilinx' into next
* pci/host-xilinx:
PCI: xilinx-nwl: Fix platform_get_irq() error handling
PCI: xilinx: Allow build on MIPS platforms
PCI: xilinx: Don't enable config completion interrupts
PCI: xilinx: Unify INTx & MSI interrupt decode
PCI: xilinx-nwl: Translate INTx range to hwirqs 0-3
PCI: xilinx: Translate INTx range to hwirqs 0-3
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-xilinx-nwl.c | 11 | ||||
-rw-r--r-- | drivers/pci/host/pcie-xilinx.c | 60 |
3 files changed, 28 insertions, 45 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 5b1ae9f8acdf..b868803792d8 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -71,7 +71,7 @@ config PCI_HOST_GENERIC config PCIE_XILINX bool "Xilinx AXI PCIe host bridge support" - depends on ARCH_ZYNQ || MICROBLAZE + depends on ARCH_ZYNQ || MICROBLAZE || (MIPS && PCI_DRIVERS_GENERIC) help Say 'Y' here if you want kernel to support the Xilinx AXI PCIe Host Bridge driver. diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index eec641a34fc5..65dea98b2643 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c @@ -133,7 +133,6 @@ #define CFG_DMA_REG_BAR GENMASK(2, 0) #define INT_PCI_MSI_NR (2 * 32) -#define INTX_NUM 4 /* Readin the PS_LINKUP */ #define PS_LINKUP_OFFSET 0x00000238 @@ -334,9 +333,8 @@ static void nwl_pcie_leg_handler(struct irq_desc *desc) while ((status = nwl_bridge_readl(pcie, MSGF_LEG_STATUS) & MSGF_LEG_SR_MASKALL) != 0) { - for_each_set_bit(bit, &status, INTX_NUM) { - virq = irq_find_mapping(pcie->legacy_irq_domain, - bit + 1); + for_each_set_bit(bit, &status, PCI_NUM_INTX) { + virq = irq_find_mapping(pcie->legacy_irq_domain, bit); if (virq) generic_handle_irq(virq); } @@ -436,6 +434,7 @@ static int nwl_legacy_map(struct irq_domain *domain, unsigned int irq, static const struct irq_domain_ops legacy_domain_ops = { .map = nwl_legacy_map, + .xlate = pci_irqd_intx_xlate, }; #ifdef CONFIG_PCI_MSI @@ -559,7 +558,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie) } pcie->legacy_irq_domain = irq_domain_add_linear(legacy_intc_node, - INTX_NUM, + PCI_NUM_INTX, &legacy_domain_ops, pcie); @@ -813,7 +812,7 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie, pcie->irq_intx = platform_get_irq_byname(pdev, "intx"); if (pcie->irq_intx < 0) { dev_err(dev, "failed to get intx IRQ %d\n", pcie->irq_intx); - return -EINVAL; + return pcie->irq_intx; } irq_set_chained_handler_and_data(pcie->irq_intx, diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index f63fa5e0278c..f30d03309c7f 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -60,6 +60,7 @@ #define XILINX_PCIE_INTR_MST_SLVERR BIT(27) #define XILINX_PCIE_INTR_MST_ERRP BIT(28) #define XILINX_PCIE_IMR_ALL_MASK 0x1FF30FED +#define XILINX_PCIE_IMR_ENABLE_MASK 0x1FF30F0D #define XILINX_PCIE_IDR_ALL_MASK 0xFFFFFFFF /* Root Port Error FIFO Read Register definitions */ @@ -369,6 +370,7 @@ static int xilinx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, /* INTx IRQ Domain operations */ static const struct irq_domain_ops intx_domain_ops = { .map = xilinx_pcie_intx_map, + .xlate = pci_irqd_intx_xlate, }; /* PCIe HW Functions */ @@ -384,7 +386,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) { struct xilinx_pcie_port *port = (struct xilinx_pcie_port *)data; struct device *dev = port->dev; - u32 val, mask, status, msi_data; + u32 val, mask, status; /* Read interrupt decode and mask registers */ val = pcie_read(port, XILINX_PCIE_REG_IDR); @@ -424,8 +426,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) xilinx_pcie_clear_err_interrupts(port); } - if (status & XILINX_PCIE_INTR_INTX) { - /* INTx interrupt received */ + if (status & (XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI)) { val = pcie_read(port, XILINX_PCIE_REG_RPIFR1); /* Check whether interrupt valid */ @@ -434,41 +435,24 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) goto error; } - if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) { - /* Clear interrupt FIFO register 1 */ - pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, - XILINX_PCIE_REG_RPIFR1); - - /* Handle INTx Interrupt */ - val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >> - XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1; - generic_handle_irq(irq_find_mapping(port->leg_domain, - val)); - } - } - - if (status & XILINX_PCIE_INTR_MSI) { - /* MSI Interrupt */ - val = pcie_read(port, XILINX_PCIE_REG_RPIFR1); - - if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { - dev_warn(dev, "RP Intr FIFO1 read error\n"); - goto error; - } - + /* Decode the IRQ number */ if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { - msi_data = pcie_read(port, XILINX_PCIE_REG_RPIFR2) & - XILINX_PCIE_RPIFR2_MSG_DATA; + val = pcie_read(port, XILINX_PCIE_REG_RPIFR2) & + XILINX_PCIE_RPIFR2_MSG_DATA; + } else { + val = (val & XILINX_PCIE_RPIFR1_INTR_MASK) >> + XILINX_PCIE_RPIFR1_INTR_SHIFT; + val = irq_find_mapping(port->leg_domain, val); + } - /* Clear interrupt FIFO register 1 */ - pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, - XILINX_PCIE_REG_RPIFR1); + /* Clear interrupt FIFO register 1 */ + pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, + XILINX_PCIE_REG_RPIFR1); - if (IS_ENABLED(CONFIG_PCI_MSI)) { - /* Handle MSI Interrupt */ - generic_handle_irq(msi_data); - } - } + /* Handle the interrupt */ + if (IS_ENABLED(CONFIG_PCI_MSI) || + !(val & XILINX_PCIE_RPIFR1_MSI_INTR)) + generic_handle_irq(val); } if (status & XILINX_PCIE_INTR_SLV_UNSUPP) @@ -524,7 +508,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port) return -ENODEV; } - port->leg_domain = irq_domain_add_linear(pcie_intc_node, 4, + port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, &intx_domain_ops, port); if (!port->leg_domain) { @@ -571,8 +555,8 @@ static void xilinx_pcie_init_port(struct xilinx_pcie_port *port) XILINX_PCIE_IMR_ALL_MASK, XILINX_PCIE_REG_IDR); - /* Enable all interrupts */ - pcie_write(port, XILINX_PCIE_IMR_ALL_MASK, XILINX_PCIE_REG_IMR); + /* Enable all interrupts we handle */ + pcie_write(port, XILINX_PCIE_IMR_ENABLE_MASK, XILINX_PCIE_REG_IMR); /* Enable the Bridge enable bit */ pcie_write(port, pcie_read(port, XILINX_PCIE_REG_RPSC) | |