Thread (29 messages) 29 messages, 7 authors, 2014-03-04
STALE4473d
Revisions (5)
  1. rfc [diff vs current]
  2. rfc current
  3. rfc [diff vs current]
  4. rfc [diff vs current]
  5. rfc [diff vs current]

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

From: Jingoo Han <hidden>
Date: 2014-02-28 02:10:52

On Friday, February 28, 2014 10:20 AM, Tim Harvey wrote:
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
(+cc Marek Vasut, Pratyush Anand, Kishon Vijay Abraham I, Mohit KUMAR DCG)

As I mention earlier, 'i.MX6 PCIe IP' is not a culprit.
The 'TI XIO2001 PCIe-to-PCI bridge' is the culprit, right?

Then, './drivers/pci/host/pci-imx6.c' is not a good place
to fix the board problems.

Look at other i.MX6 boards. They don't have the 'TI XIO2001
PCIe-to-PCI bridge'. Please don't add this board specific 
code to SoC specific driver code.

Best regards,
Jingoo Han
quoted hunk ↗ jump to hunk
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@gateworks.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Richard Zhu <redacted>
Cc: Shawn Guo <redacted>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Sean Cross <redacted>
Cc: Jingoo Han <redacted>
---
 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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help