|
@@ -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) {
|
|
|
|
- /* INTx interrupt received */
|
|
|
|
|
|
+ if (status & (XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI)) {
|
|
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)) {
|
|
|
|
- /* 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) {
|
|
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)
|
|
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 */
|
|
|
|
- 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 */
|
|
/* 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) |
|