[PATCH 3/3] PCI: imx6: ventana: fixup for IRQ mismapping

Tim Harvey tharvey at gateworks.com
Thu Feb 27 20:19:54 EST 2014


The TI XIO2001 PCIe-to-PCI bridge used on Ventana expansion boards
has its slot-to-bridge IRQ mapping reversed from the PCI specification:

  INTA->INTD
  INTB->INTC
  INTC->INTB
  INTD->INTA

Implement a custom swizzle function that does a fixup on the interrupt for
devices on the first TI XIO2001 bridge in the tree.

Signed-off-by: Tim Harvey <tharvey at gateworks.com>
Cc: Bjorn Helgaas <bhelgaas at google.com>
Cc: Richard Zhu <r65037 at freescale.com>
Cc: Shawn Guo <shawn.guo at linaro.org>
Cc: Lucas Stach <l.stach at pengutronix.de>
Cc: Sean Cross <xobs at kosagi.com>
Cc: Jingoo Han <jg1.han at samsung.com>
---
 drivers/pci/host/pci-imx6.c | 36 ++++++++++++++++++++++++++++++++++++
 include/linux/pci_ids.h     |  1 +
 2 files changed, 37 insertions(+)

diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index aaa05c8..b171a21 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -493,6 +493,39 @@ static int imx6_add_pcie_port(struct pcie_port *pp,
 	return 0;
 }
 
+/* TI XIO2001 PCIe-to-PCI bridge on GW16082 exp card has IRQs reversed */
+u8 ventana_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	u8 i = 0;
+	struct pci_dev *pdev = dev;
+
+	/* count number of TI XIO2001 bridges on bus */
+	while (!pci_is_root_bus(pdev->bus)) {
+		if (pdev->bus && pdev->bus->self &&
+		    (pdev->bus->self->vendor == PCI_VENDOR_ID_TI) &&
+		    (pdev->bus->self->device == PCI_DEVICE_ID_TI_XIO2001)) {
+			i++;
+		}
+		pdev = pdev->bus->self;
+	}
+	while (!pci_is_root_bus(dev->bus)) {
+		/* if we are directly downstream from 1st TI XIO2001 bridge */
+		if (dev->bus && dev->bus->self &&
+		    (dev->bus->self->vendor == PCI_VENDOR_ID_TI) &&
+		    (dev->bus->self->device == PCI_DEVICE_ID_TI_XIO2001)) {
+			if (--i == 0) {
+				/* swap IRQs and swizzle backwards */
+				*pin = (15 - PCI_SLOT(dev->devfn)) + 1;
+				dev = dev->bus->self;
+				continue;
+			}
+		}
+		*pin = pci_swizzle_interrupt_pin(dev, *pin);
+		dev = dev->bus->self;
+	}
+	return PCI_SLOT(dev->devfn);
+}
+
 static int __init imx6_pcie_probe(struct platform_device *pdev)
 {
 	struct imx6_pcie *imx6_pcie;
@@ -601,6 +634,9 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
 		return PTR_ERR(imx6_pcie->iomuxc_gpr);
 	}
 
+	if (of_machine_is_compatible("gw,ventana"))
+		pp->swizzle = ventana_swizzle;
+
 	ret = imx6_add_pcie_port(pp, pdev);
 	if (ret < 0)
 		return ret;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 97fbecd..4ca334f 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -822,6 +822,7 @@
 #define PCI_DEVICE_ID_TI_XX12		0x8039
 #define PCI_DEVICE_ID_TI_XX12_FM	0x803b
 #define PCI_DEVICE_ID_TI_XIO2000A	0x8231
+#define PCI_DEVICE_ID_TI_XIO2001	0x8240
 #define PCI_DEVICE_ID_TI_1130		0xac12
 #define PCI_DEVICE_ID_TI_1031		0xac13
 #define PCI_DEVICE_ID_TI_1131		0xac15
-- 
1.8.3.2




More information about the linux-arm-kernel mailing list