| From b9898c7dd8ece4d4a9abbd8a8ddf16cd6d2faa6c Mon Sep 17 00:00:00 2001 |
| From: Richard Zhu <hongxing.zhu@nxp.com> |
| Date: Fri, 21 Dec 2018 04:33:38 +0000 |
| Subject: PCI: imx: Enable MSI from downstream components |
| |
| [ Upstream commit 75cb8d20c112aba70f23d98e3f8d0a38ace16006 ] |
| |
| The MSI Enable bit in the MSI Capability (PCIe r4.0, sec 7.7.1.2) controls |
| whether a Function can request service using MSI. |
| |
| i.MX6 Root Ports implement the MSI Capability and may use MSI to request |
| service for events like PME, hotplug, AER, etc. In addition, on i.MX6, the |
| MSI Enable bit controls delivery of MSI interrupts from components below |
| the Root Port. |
| |
| Prior to f3fdfc4ac3a2 ("PCI: Remove host driver Kconfig selection of |
| CONFIG_PCIEPORTBUS"), enabling CONFIG_PCI_IMX6 automatically also enabled |
| CONFIG_PCIEPORTBUS, and when portdrv claimed the Root Ports, it set the MSI |
| Enable bit so it could use PME, hotplug, AER, etc. As a side effect, that |
| also enabled delivery of MSI interrupts from downstream components. |
| |
| The imx6q-pcie driver itself does not depend on portdrv, so set MSI Enable |
| in imx6q-pcie so MSI from downstream components works even if nobody uses |
| MSI for the Root Port events. |
| |
| Fixes: f3fdfc4ac3a2 ("PCI: Remove host driver Kconfig selection of CONFIG_PCIEPORTBUS") |
| Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Tested-by: Sven Van Asbroeck <TheSven73@googlemail.com> |
| Tested-by: Trent Piepho <tpiepho@impinj.com> |
| Reviewed-by: Lucas Stach <l.stach@pengutronix.de> |
| Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/pci/controller/dwc/pci-imx6.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c |
| index 975050a69494..3826b444298c 100644 |
| --- a/drivers/pci/controller/dwc/pci-imx6.c |
| +++ b/drivers/pci/controller/dwc/pci-imx6.c |
| @@ -66,6 +66,7 @@ struct imx6_pcie { |
| #define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200 |
| |
| /* PCIe Root Complex registers (memory-mapped) */ |
| +#define PCIE_RC_IMX6_MSI_CAP 0x50 |
| #define PCIE_RC_LCR 0x7c |
| #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 |
| #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 |
| @@ -682,6 +683,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) |
| struct resource *dbi_base; |
| struct device_node *node = dev->of_node; |
| int ret; |
| + u16 val; |
| |
| imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL); |
| if (!imx6_pcie) |
| @@ -816,6 +818,14 @@ static int imx6_pcie_probe(struct platform_device *pdev) |
| if (ret < 0) |
| return ret; |
| |
| + if (pci_msi_enabled()) { |
| + val = dw_pcie_readw_dbi(pci, PCIE_RC_IMX6_MSI_CAP + |
| + PCI_MSI_FLAGS); |
| + val |= PCI_MSI_FLAGS_ENABLE; |
| + dw_pcie_writew_dbi(pci, PCIE_RC_IMX6_MSI_CAP + PCI_MSI_FLAGS, |
| + val); |
| + } |
| + |
| return 0; |
| } |
| |
| -- |
| 2.19.1 |
| |