From 9d826428b7c8a8f8167f71f3995bacc5a61efc22 Mon Sep 17 00:00:00 2001 From: Luka Perkov Date: Mon, 11 Aug 2014 20:35:06 +0000 Subject: [PATCH] imx6: kernel: add GW16082 miniPCI Expansion Mezzanine support The GW16082 miniPCI Expansion Mezzanine has the INTA/B/C/D IRQ's reversed from the PCI standard. This will soon be resolved in the bootloader via devicetree, but in the meantime this will work around the issue. Signed-off-by: Tim Harvey SVN-Revision: 42146 --- ...nware_add-ability-for-custom-swizzle.patch | 33 ++++++++ ...mx6_ventana_fixup-for-IRQ-mismapping.patch | 81 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 target/linux/imx6/patches-3.14/200-pci_designware_add-ability-for-custom-swizzle.patch create mode 100644 target/linux/imx6/patches-3.14/201-pci_imx6_ventana_fixup-for-IRQ-mismapping.patch diff --git a/target/linux/imx6/patches-3.14/200-pci_designware_add-ability-for-custom-swizzle.patch b/target/linux/imx6/patches-3.14/200-pci_designware_add-ability-for-custom-swizzle.patch new file mode 100644 index 000000000000..b17437686058 --- /dev/null +++ b/target/linux/imx6/patches-3.14/200-pci_designware_add-ability-for-custom-swizzle.patch @@ -0,0 +1,33 @@ +commit e84634dc6c7f3f6af9b8ef1fb36f0d85c476ab95 +Author: Tim Harvey +Date: Thu Feb 27 01:02:23 2014 -0800 + + PCI: designware: add ability for custom swizzle + + Add the ability for a platform driver to provide a platform-specific + swizzle function. + + Signed-off-by: Tim Harvey + +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -481,6 +481,9 @@ int __init dw_pcie_host_init(struct pcie + if (pp->ops->host_init) + pp->ops->host_init(pp); + ++ if (pp->swizzle) ++ dw_pci.swizzle = pp->swizzle; ++ + dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); + + /* program correct class for RC */ +--- a/drivers/pci/host/pcie-designware.h ++++ b/drivers/pci/host/pcie-designware.h +@@ -53,6 +53,7 @@ struct pcie_port { + struct irq_domain *irq_domain; + unsigned long msi_data; + DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); ++ u8 (*swizzle)(struct pci_dev *, u8 *); + }; + + struct pcie_host_ops { diff --git a/target/linux/imx6/patches-3.14/201-pci_imx6_ventana_fixup-for-IRQ-mismapping.patch b/target/linux/imx6/patches-3.14/201-pci_imx6_ventana_fixup-for-IRQ-mismapping.patch new file mode 100644 index 000000000000..c8e2a0e0e3d9 --- /dev/null +++ b/target/linux/imx6/patches-3.14/201-pci_imx6_ventana_fixup-for-IRQ-mismapping.patch @@ -0,0 +1,81 @@ +commit 2c0d0491438433a1f327f2e754c7b6b55fec51c4 +Author: Tim Harvey +Date: Thu Feb 27 00:59:53 2014 -0800 + + PCI: imx6: ventana: fixup for IRQ mismapping + + The TI XIO2001 PCIe-to-PCI bridge used on several 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 a TI XIO2001 bridge. + + Signed-off-by: Tim Harvey + +--- a/drivers/pci/host/pci-imx6.c ++++ b/drivers/pci/host/pci-imx6.c +@@ -540,6 +540,39 @@ static int imx6_add_pcie_port(struct pci + 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; +@@ -648,6 +681,9 @@ static int __init imx6_pcie_probe(struct + 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; +--- 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 -- 2.30.2