aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-cns3xxx/pcie.c
diff options
context:
space:
mode:
authorKrzysztof Hałasa <khalasa@piap.pl>2014-09-16 06:36:32 -0400
committerArnd Bergmann <arnd@arndb.de>2014-09-25 17:34:54 -0400
commitdefaa4d1dc97320ccc0ea83bc3851443b1c9083a (patch)
tree5287552f46160f10e45cedc700198a2899e656f0 /arch/arm/mach-cns3xxx/pcie.c
parentb125170a39ea35fe5ef93c894940feb6cf08ebd3 (diff)
CNS3xxx: Fix logical PCIe topology.
Without this patch, each root port and the device connected directly to it seem to be located on a shared (virtual) bus #0. It creates problems with enabling devices (the PCI code doesn't know that the root bridge must be enabled in order to access other devices). The PCIe topology shown by lspci doesn't reflect reality, e.g.: 0000:00:00.0 PCI bridge: Cavium Networks Device 3400 0000:00:01.0 PCI bridge: Texas Instruments XIO2001 PCI Express-to-PCI Bridge 0000:02:... 0001:00:00.0 PCI bridge: Cavium Networks Device 3400 (for the second lane/bus) -+-[0001:00]---00.0-[01]-- \-[0000:00]-+-00.0-[01]-- | ^^^^ root bridge \-01.0-[02]----... ^^^^ first external device With this patch, the first external PCIe device is connected to bus #1 (behind the root bridge). -+-[0001:00]---00.0-[01]-- \-[0000:00]---00.0-[01-02]----------00.0-[02]----... ^^^^ root bridge ^^^^ first external device Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-cns3xxx/pcie.c')
-rw-r--r--arch/arm/mach-cns3xxx/pcie.c29
1 files changed, 14 insertions, 15 deletions
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
index 70fd81ea1828..fbfe852286e8 100644
--- a/arch/arm/mach-cns3xxx/pcie.c
+++ b/arch/arm/mach-cns3xxx/pcie.c
@@ -60,11 +60,10 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
60 struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus); 60 struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus);
61 int busno = bus->number; 61 int busno = bus->number;
62 int slot = PCI_SLOT(devfn); 62 int slot = PCI_SLOT(devfn);
63 int offset;
64 void __iomem *base; 63 void __iomem *base;
65 64
66 /* If there is no link, just show the CNS PCI bridge. */ 65 /* If there is no link, just show the CNS PCI bridge. */
67 if (!cnspci->linked && (busno > 0 || slot > 0)) 66 if (!cnspci->linked && busno > 0)
68 return NULL; 67 return NULL;
69 68
70 /* 69 /*
@@ -72,22 +71,21 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus,
72 * we still want to access it. For this to work, we must place 71 * we still want to access it. For this to work, we must place
73 * the first device on the same bus as the CNS PCI bridge. 72 * the first device on the same bus as the CNS PCI bridge.
74 */ 73 */
75 if (busno == 0) { /* directly connected PCIe bus */ 74 if (busno == 0) { /* internal PCIe bus, host bridge device */
76 switch (slot) { 75 if (devfn == 0) /* device# and function# are ignored by hw */
77 case 0: /* host bridge device, function 0 only */
78 base = cnspci->host_regs; 76 base = cnspci->host_regs;
79 break; 77 else
80 case 1: /* directly connected device */ 78 return NULL; /* no such device */
79
80 } else if (busno == 1) { /* directly connected PCIe device */
81 if (slot == 0) /* device# is ignored by hw */
81 base = cnspci->cfg0_regs; 82 base = cnspci->cfg0_regs;
82 break; 83 else
83 default:
84 return NULL; /* no such device */ 84 return NULL; /* no such device */
85 }
86 } else /* remote PCI bus */ 85 } else /* remote PCI bus */
87 base = cnspci->cfg1_regs; 86 base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
88 87
89 offset = ((busno & 0xf) << 20) | (devfn << 12) | (where & 0xffc); 88 return base + (where & 0xffc) + (devfn << 12);
90 return base + offset;
91} 89}
92 90
93static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn, 91static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -167,7 +165,7 @@ static struct pci_ops cns3xxx_pcie_ops = {
167static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 165static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
168{ 166{
169 struct cns3xxx_pcie *cnspci = pdev_to_cnspci(dev); 167 struct cns3xxx_pcie *cnspci = pdev_to_cnspci(dev);
170 int irq = cnspci->irqs[slot]; 168 int irq = cnspci->irqs[!!dev->bus->number];
171 169
172 pr_info("PCIe map irq: %04d:%02x:%02x.%02x slot %d, pin %d, irq: %d\n", 170 pr_info("PCIe map irq: %04d:%02x:%02x.%02x slot %d, pin %d, irq: %d\n",
173 pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn), 171 pci_domain_nr(dev->bus), dev->bus->number, PCI_SLOT(dev->devfn),
@@ -297,7 +295,8 @@ static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
297 return; 295 return;
298 296
299 /* Set Device Max_Read_Request_Size to 128 byte */ 297 /* Set Device Max_Read_Request_Size to 128 byte */
300 devfn = PCI_DEVFN(1, 0); 298 bus.number = 1; /* directly connected PCIe device */
299 devfn = PCI_DEVFN(0, 0);
301 pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP); 300 pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
302 pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc); 301 pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
303 dc &= ~(0x3 << 12); /* Clear Device Control Register [14:12] */ 302 dc &= ~(0x3 << 12); /* Clear Device Control Register [14:12] */