Skip to contentSkip to conversation

i.MX6 MSI support

PATCH New Lucas Stach 2 participants 5 messages Feb 28, 2014 – Mar 3, 2014

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover i.MX6 MSI support

This adds MSI support to the i.MX6 PCIe host controller driver. We keep MSI optional in order to not break any existing DTs.

This series depends on the previous sent series "PCI irq mapping fixes and cleanups".

Lucas Stach (3):
ARM: dts: imx6: extend PCIe interrupt list for MSI
PCI: designware: make MSI isr shared irq aware
PCI: imx6: add support for MSI

 .../devicetree/bindings/pci/fsl,imx6q-pcie.txt     |  9 +++++++-
 arch/arm/boot/dts/imx6qdl.dtsi                     |  4 +++-
 drivers/pci/host/pci-exynos.c                      |  4 +---
 drivers/pci/host/pci-imx6.c                        | 26 ++++++++++++++++++++++
 drivers/pci/host/pcie-designware.c                 |  6 ++++-
 drivers/pci/host/pcie-designware.h                 |  2 +-
 6 files changed, 44 insertions(+), 7 deletions(-)
Signature · 1 line
1.8.5.3
#1 lore raw

PATCH 1/3 ARM: dts: imx6: extend PCIe interrupt list for MSI

Optional IRQ necessary for handling MSI.

---
 Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt | 9 ++++++++-
 arch/arm/boot/dts/imx6qdl.dtsi                           | 4 +++-
 2 files changed, 11 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +8 -1
index 93fbfd62f13c..0515183a6d96 100644
@@ -17,6 +17,11 @@ Required properties:
 	- "pcie_axi"
 
 Optional properties:
+- interrupts: Must contain an entry for each entry in the
+  interrupt-names property.
+- interrupt-names: May include the following entries:
+	- "inta"
+	- "msi" if not present the driver won't be able to handle MSI
 - power-on-gpio: gpio pin number of power-enable signal
 - wake-up-gpio:  gpio pin number of incoming wakeup signal
 - disable-gpio:  gpio pin number of outgoing rfkill/endpoint disable signal
@@ -34,7 +39,9 @@ Example:
 			  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>;
 		num-lanes = <1>;
 
-		interrupts = <0 123 0x04>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+		             <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "inta", "msi";
 
 		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 0 0x7>;
arch/arm/boot/dts/imx6qdl.dtsi +3 -1
index db3339e7d3a2..a3a3acd90964 100644
@@ -129,7 +129,9 @@
 				  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
 			num-lanes = <1>;
 
-			interrupts = <0 123 0x04>;
+			interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+			             <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "inta", "msi";
 
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0x7>;
Signature · 1 line
1.8.5.3
#2 lore raw

PATCH 1/3 ARM: dts: imx6: extend PCIe interrupt list for MSI

Quoted 6 lines · Lucas Stach

Optional IRQ necessary for handling MSI.

---
 Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt | 9 ++++++++-

Please have this change go with driver or a separate patch, not with dts update.

Shawn

Quoted 2 lines
 arch/arm/boot/dts/imx6qdl.dtsi                           | 4 +++-
 2 files changed, 11 insertions(+), 2 deletions(-)
#3 lore raw

PATCH 2/3 PCI: designware: make MSI isr shared irq aware

In reply to Lucas Stach

On i.MX6 the host controller MSI irq is shared with PCI legacy INTD. Make sure we don't bail too early from the irq handler.

The issue is fairly theoretical as it would require a system setup with a PCIe switch where one connected device is using legacy INTD and another one using MSI, but better fix it now.

---
 drivers/pci/host/pci-exynos.c      | 4 +---
 drivers/pci/host/pcie-designware.c | 6 +++++-
 drivers/pci/host/pcie-designware.h | 2 +-
 3 files changed, 7 insertions(+), 5 deletions(-)
drivers/pci/host/pci-exynos.c +1 -3
index 3de6bfbbe8e9..b616d34922d8 100644
@@ -415,9 +415,7 @@ static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
 {
 	struct pcie_port *pp = arg;
 
-	dw_handle_msi_irq(pp);
-
-	return IRQ_HANDLED;
+	return dw_handle_msi_irq(pp);
 }
 
 static void exynos_pcie_msi_init(struct pcie_port *pp)
drivers/pci/host/pcie-designware.c +5 -1
index 3e0c2af11528..f8c174a7d657 100644
@@ -156,15 +156,17 @@ static struct irq_chip dw_msi_irq_chip = {
 };
 
 /* MSI int handler */
-void dw_handle_msi_irq(struct pcie_port *pp)
+irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 {
 	unsigned long val;
 	int i, pos, irq;
+	irqreturn_t ret = IRQ_NONE;
 
 	for (i = 0; i < MAX_MSI_CTRLS; i++) {
 		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
 				(u32 *)&val);
 		if (val) {
+			ret = IRQ_HANDLED;
 			pos = 0;
 			while ((pos = find_next_bit(&val, 32, pos)) != 32) {
 				irq = irq_find_mapping(pp->irq_domain,
@@ -177,6 +179,8 @@ void dw_handle_msi_irq(struct pcie_port *pp)
 			}
 		}
 	}
+
+	return ret;
 }
 
 void dw_pcie_msi_init(struct pcie_port *pp)
drivers/pci/host/pcie-designware.h +1 -1
index 3063b3594d88..a169d22d517e 100644
@@ -68,7 +68,7 @@ struct pcie_host_ops {
 
 int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val);
 int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val);
-void dw_handle_msi_irq(struct pcie_port *pp);
+irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
 void dw_pcie_msi_init(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);
Signature · 1 line
1.8.5.3
#4 lore raw

PATCH 3/3 PCI: imx6: add support for MSI

In reply to Lucas Stach

This patch adds support for Message Signaled Interrupts in the imx6-pcie driver.

---
 drivers/pci/host/pci-imx6.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/pci/host/pci-imx6.c +26 -0
index e8663a8c3406..e038d47f1b01 100644
@@ -25,6 +25,7 @@
 #include <linux/resource.h>
 #include <linux/signal.h>
 #include <linux/types.h>
+#include <linux/interrupt.h>
 
 #include "pcie-designware.h"
 
@@ -329,6 +330,13 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp)
 	return 0;
 }
 
+static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
+{
+	struct pcie_port *pp = arg;
+
+	return dw_handle_msi_irq(pp);
+}
+
 static int imx6_pcie_start_link(struct pcie_port *pp)
 {
 	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
@@ -403,6 +411,9 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
 	dw_pcie_setup_rc(pp);
 
 	imx6_pcie_start_link(pp);
+
+	if (IS_ENABLED(CONFIG_PCI_MSI) && (pp->msi_irq > 0))
+		dw_pcie_msi_init(pp);
 }
 
 static void imx6_pcie_reset_phy(struct pcie_port *pp)
@@ -477,6 +488,21 @@ static int imx6_add_pcie_port(struct pcie_port *pp,
 		return -ENODEV;
 	}
 
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		pp->msi_irq = platform_get_irq_byname(pdev, "msi");
+		if (pp->msi_irq < 0) {
+			dev_info(&pdev->dev, "failed to get MSI irq, host will not support MSI\n");
+		} else {
+			ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+			                       imx6_pcie_msi_handler,
+			                       IRQF_SHARED, "mx6-pcie-msi", pp);
+			if (ret) {
+				dev_err(&pdev->dev, "failed to request MSI irq\n");
+				return -ENODEV;
+			}
+		}
+	}
+
 	pp->root_bus_nr = -1;
 	pp->ops = &imx6_pcie_host_ops;
 
Signature · 1 line
1.8.5.3