From d57b64dfb0ba45e5da17cf145c54bd8ad85caf52 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@openwrt.org>
Date: Thu, 27 Nov 2014 15:02:05 +0000
Subject: [PATCH] cns3xxx: fix pcie root bridge topology

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

SVN-Revision: 43403
---
 .../110-pci_isolated_interrupts.patch         |  4 +-
 .../120-backport_pcie_topology_fix.patch      | 53 +++++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/cns3xxx/patches-3.14/120-backport_pcie_topology_fix.patch

diff --git a/target/linux/cns3xxx/patches-3.14/110-pci_isolated_interrupts.patch b/target/linux/cns3xxx/patches-3.14/110-pci_isolated_interrupts.patch
index 3e4cc67979..4aeb2102b2 100644
--- a/target/linux/cns3xxx/patches-3.14/110-pci_isolated_interrupts.patch
+++ b/target/linux/cns3xxx/patches-3.14/110-pci_isolated_interrupts.patch
@@ -30,7 +30,7 @@
  #include <linux/gpio.h>
  #include <linux/dma-mapping.h>
  #include <linux/serial_core.h>
-@@ -868,12 +869,42 @@ static int laguna_register_gpio(struct g
+@@ -873,12 +874,42 @@ static int laguna_register_gpio(struct g
  	return ret;
  }
  
@@ -74,7 +74,7 @@
  }
  subsys_initcall(laguna_pcie_init);
  
-@@ -888,8 +919,33 @@ static int __init laguna_model_setup(voi
+@@ -893,8 +924,33 @@ static int __init laguna_model_setup(voi
  	printk("Running on Gateworks Laguna %s\n", laguna_info.model);
  	cns3xxx_gpio_init( 0, 32, CNS3XXX_GPIOA_BASE_VIRT, IRQ_CNS3XXX_GPIOA,
  		NR_IRQS_CNS3XXX);
diff --git a/target/linux/cns3xxx/patches-3.14/120-backport_pcie_topology_fix.patch b/target/linux/cns3xxx/patches-3.14/120-backport_pcie_topology_fix.patch
new file mode 100644
index 0000000000..4f68e6fb14
--- /dev/null
+++ b/target/linux/cns3xxx/patches-3.14/120-backport_pcie_topology_fix.patch
@@ -0,0 +1,53 @@
+--- a/arch/arm/mach-cns3xxx/pcie.c
++++ b/arch/arm/mach-cns3xxx/pcie.c
+@@ -71,7 +71,7 @@ static void __iomem *cns3xxx_pci_cfg_bas
+ 	void __iomem *base;
+ 
+ 	/* If there is no link, just show the CNS PCI bridge. */
+-	if (!cnspci->linked && (busno > 0 || slot > 0))
++	if (!cnspci->linked && (busno > 0))
+ 		return NULL;
+ 
+ 	/*
+@@ -80,15 +80,19 @@ static void __iomem *cns3xxx_pci_cfg_bas
+ 	 * the first device on the same bus as the CNS PCI bridge.
+ 	 */
+ 	if (busno == 0) {
+-		if (slot > 1)
++		type = CNS3XXX_HOST_TYPE;
++		if (devfn)
++			return NULL;
++	} else if (busno == 1) {
++		type = CNS3XXX_CFG0_TYPE;
++		if (slot)
+ 			return NULL;
+-		type = slot;
+ 	} else {
+ 		type = CNS3XXX_CFG1_TYPE;
+ 	}
+ 
+ 	base = (void __iomem *)cnspci->cfg_bases[type].virtual;
+-	offset = ((busno & 0xf) << 20) | (devfn << 12) | (where & 0xffc);
++	offset = (devfn << 12) | (where & 0xffc);
+ 
+ 	return base + offset;
+ }
+@@ -256,7 +260,7 @@ static struct pci_ops cns3xxx_pcie_ops =
+ static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+ {
+ 	struct cns3xxx_pcie *cnspci = pdev_to_cnspci(dev);
+-	int irq = cnspci->irqs[slot+pin-1];
++	int irq = cnspci->irqs[!!dev->bus->number+pin-1];
+ 
+ 	pr_info("PCIe map irq: %04d:%02x:%02x.%02x slot %d, pin %d, irq: %d\n",
+ 		pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn),
+@@ -434,7 +438,8 @@ static void __init cns3xxx_pcie_hw_init(
+ 		return;
+ 
+ 	/* Set Device Max_Read_Request_Size to 128 byte */
+-	devfn = PCI_DEVFN(1, 0);
++	bus.number = 1;
++	devfn = PCI_DEVFN(0, 0);
+ 	pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
+ 	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
+ 	dc &= ~(0x3 << 12);	/* Clear Device Control Register [14:12] */
-- 
2.30.2