提交 ebe85a44 编写于 作者: K Kishon Vijay Abraham I 提交者: Bjorn Helgaas

PCI: dra7xx: Enable MSI and legacy interrupts simultaneously

pci-dra7xx driver had a bug in that if CONFIG_PCI_MSI config is enabled, it
doesn't support legacy interrupt.  Fix it here so that both MSI and legacy
interrupts can be enabled simultaneously and the interrupt mechanism
supported by the endpoint device will be used.
Signed-off-by: NKishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
上级 ab5fe4f4
...@@ -72,6 +72,7 @@ struct dra7xx_pcie { ...@@ -72,6 +72,7 @@ struct dra7xx_pcie {
int phy_count; /* DT phy-names count */ int phy_count; /* DT phy-names count */
struct phy **phy; struct phy **phy;
int link_gen; int link_gen;
struct irq_domain *irq_domain;
}; };
#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp) #define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp)
...@@ -142,14 +143,8 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx) ...@@ -142,14 +143,8 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS); PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS);
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
~LEG_EP_INTERRUPTS & ~MSI); ~LEG_EP_INTERRUPTS & ~MSI);
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
if (IS_ENABLED(CONFIG_PCI_MSI)) MSI | LEG_EP_INTERRUPTS);
dra7xx_pcie_writel(dra7xx,
PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI);
else
dra7xx_pcie_writel(dra7xx,
PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
LEG_EP_INTERRUPTS);
} }
static void dra7xx_pcie_host_init(struct pcie_port *pp) static void dra7xx_pcie_host_init(struct pcie_port *pp)
...@@ -164,8 +159,7 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp) ...@@ -164,8 +159,7 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
dw_pcie_setup_rc(pp); dw_pcie_setup_rc(pp);
dra7xx_pcie_establish_link(dra7xx); dra7xx_pcie_establish_link(dra7xx);
if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp);
dw_pcie_msi_init(pp);
dra7xx_pcie_enable_interrupts(dra7xx); dra7xx_pcie_enable_interrupts(dra7xx);
} }
...@@ -190,6 +184,7 @@ static const struct irq_domain_ops intx_domain_ops = { ...@@ -190,6 +184,7 @@ static const struct irq_domain_ops intx_domain_ops = {
static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
{ {
struct device *dev = pp->dev; struct device *dev = pp->dev;
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
struct device_node *pcie_intc_node = of_get_next_child(node, NULL); struct device_node *pcie_intc_node = of_get_next_child(node, NULL);
...@@ -198,9 +193,9 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) ...@@ -198,9 +193,9 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
return -ENODEV; return -ENODEV;
} }
pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
&intx_domain_ops, pp); &intx_domain_ops, pp);
if (!pp->irq_domain) { if (!dra7xx->irq_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n"); dev_err(dev, "Failed to get a INTx IRQ domain\n");
return -ENODEV; return -ENODEV;
} }
...@@ -224,7 +219,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) ...@@ -224,7 +219,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
case INTB: case INTB:
case INTC: case INTC:
case INTD: case INTD:
generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg))); generic_handle_irq(irq_find_mapping(dra7xx->irq_domain,
ffs(reg)));
break; break;
} }
...@@ -310,11 +306,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, ...@@ -310,11 +306,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
return ret; return ret;
} }
if (!IS_ENABLED(CONFIG_PCI_MSI)) { ret = dra7xx_pcie_init_irq_domain(pp);
ret = dra7xx_pcie_init_irq_domain(pp); if (ret < 0)
if (ret < 0) return ret;
return ret;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics");
pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res)); pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册