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:
commit
99fd1b958c
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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) |
|
||||||
|
Loading…
Reference in New Issue
Block a user