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
This commit is contained in:
Bjorn Helgaas 2017-09-07 13:24:11 -05:00
commit 99fd1b958c
3 changed files with 29 additions and 46 deletions

View File

@ -71,7 +71,7 @@ config PCI_HOST_GENERIC
config PCIE_XILINX config PCIE_XILINX
bool "Xilinx AXI PCIe host bridge support" bool "Xilinx AXI PCIe host bridge support"
depends on ARCH_ZYNQ || MICROBLAZE depends on ARCH_ZYNQ || MICROBLAZE || (MIPS && PCI_DRIVERS_GENERIC)
help help
Say 'Y' here if you want kernel to support the Xilinx AXI PCIe Say 'Y' here if you want kernel to support the Xilinx AXI PCIe
Host Bridge driver. Host Bridge driver.

View File

@ -133,7 +133,6 @@
#define CFG_DMA_REG_BAR GENMASK(2, 0) #define CFG_DMA_REG_BAR GENMASK(2, 0)
#define INT_PCI_MSI_NR (2 * 32) #define INT_PCI_MSI_NR (2 * 32)
#define INTX_NUM 4
/* Readin the PS_LINKUP */ /* Readin the PS_LINKUP */
#define PS_LINKUP_OFFSET 0x00000238 #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) & while ((status = nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
MSGF_LEG_SR_MASKALL) != 0) { MSGF_LEG_SR_MASKALL) != 0) {
for_each_set_bit(bit, &status, INTX_NUM) { for_each_set_bit(bit, &status, PCI_NUM_INTX) {
virq = irq_find_mapping(pcie->legacy_irq_domain, virq = irq_find_mapping(pcie->legacy_irq_domain, bit);
bit + 1);
if (virq) if (virq)
generic_handle_irq(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 = { static const struct irq_domain_ops legacy_domain_ops = {
.map = nwl_legacy_map, .map = nwl_legacy_map,
.xlate = pci_irqd_intx_xlate,
}; };
#ifdef CONFIG_PCI_MSI #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, pcie->legacy_irq_domain = irq_domain_add_linear(legacy_intc_node,
INTX_NUM, PCI_NUM_INTX,
&legacy_domain_ops, &legacy_domain_ops,
pcie); pcie);
@ -813,7 +812,7 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
pcie->irq_intx = platform_get_irq_byname(pdev, "intx"); pcie->irq_intx = platform_get_irq_byname(pdev, "intx");
if (pcie->irq_intx < 0) { if (pcie->irq_intx < 0) {
dev_err(dev, "failed to get intx IRQ %d\n", pcie->irq_intx); 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, irq_set_chained_handler_and_data(pcie->irq_intx,

View File

@ -60,6 +60,7 @@
#define XILINX_PCIE_INTR_MST_SLVERR BIT(27) #define XILINX_PCIE_INTR_MST_SLVERR BIT(27)
#define XILINX_PCIE_INTR_MST_ERRP BIT(28) #define XILINX_PCIE_INTR_MST_ERRP BIT(28)
#define XILINX_PCIE_IMR_ALL_MASK 0x1FF30FED #define XILINX_PCIE_IMR_ALL_MASK 0x1FF30FED
#define XILINX_PCIE_IMR_ENABLE_MASK 0x1FF30F0D
#define XILINX_PCIE_IDR_ALL_MASK 0xFFFFFFFF #define XILINX_PCIE_IDR_ALL_MASK 0xFFFFFFFF
/* Root Port Error FIFO Read Register definitions */ /* 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 */ /* INTx IRQ Domain operations */
static const struct irq_domain_ops intx_domain_ops = { static const struct irq_domain_ops intx_domain_ops = {
.map = xilinx_pcie_intx_map, .map = xilinx_pcie_intx_map,
.xlate = pci_irqd_intx_xlate,
}; };
/* PCIe HW Functions */ /* 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 xilinx_pcie_port *port = (struct xilinx_pcie_port *)data;
struct device *dev = port->dev; struct device *dev = port->dev;
u32 val, mask, status, msi_data; u32 val, mask, status;
/* Read interrupt decode and mask registers */ /* Read interrupt decode and mask registers */
val = pcie_read(port, XILINX_PCIE_REG_IDR); 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); xilinx_pcie_clear_err_interrupts(port);
} }
if (status & XILINX_PCIE_INTR_INTX) { if (status & (XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI)) {
/* INTx interrupt received */
val = pcie_read(port, XILINX_PCIE_REG_RPIFR1); val = pcie_read(port, XILINX_PCIE_REG_RPIFR1);
/* Check whether interrupt valid */ /* Check whether interrupt valid */
@ -434,41 +435,24 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
goto error; goto error;
} }
if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) { /* Decode the IRQ number */
/* 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;
}
if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { if (val & XILINX_PCIE_RPIFR1_MSI_INTR) {
msi_data = pcie_read(port, XILINX_PCIE_REG_RPIFR2) & val = pcie_read(port, XILINX_PCIE_REG_RPIFR2) &
XILINX_PCIE_RPIFR2_MSG_DATA; XILINX_PCIE_RPIFR2_MSG_DATA;
} else {
/* Clear interrupt FIFO register 1 */ val = (val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK, XILINX_PCIE_RPIFR1_INTR_SHIFT;
XILINX_PCIE_REG_RPIFR1); val = irq_find_mapping(port->leg_domain, val);
if (IS_ENABLED(CONFIG_PCI_MSI)) {
/* Handle MSI Interrupt */
generic_handle_irq(msi_data);
}
} }
/* Clear interrupt FIFO register 1 */
pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
XILINX_PCIE_REG_RPIFR1);
/* 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) 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; 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, &intx_domain_ops,
port); port);
if (!port->leg_domain) { 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_IMR_ALL_MASK,
XILINX_PCIE_REG_IDR); XILINX_PCIE_REG_IDR);
/* Enable all interrupts */ /* Enable all interrupts we handle */
pcie_write(port, XILINX_PCIE_IMR_ALL_MASK, XILINX_PCIE_REG_IMR); pcie_write(port, XILINX_PCIE_IMR_ENABLE_MASK, XILINX_PCIE_REG_IMR);
/* Enable the Bridge enable bit */ /* Enable the Bridge enable bit */
pcie_write(port, pcie_read(port, XILINX_PCIE_REG_RPSC) | pcie_write(port, pcie_read(port, XILINX_PCIE_REG_RPSC) |