aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-06-01 02:20:52 -0400
committerOlof Johansson <olof@lixom.net>2013-06-01 02:20:52 -0400
commit2dbefbf6a803d65f6327fe617f5e1960f218ce01 (patch)
treea128341f02fa1ea7ce3353a78397104162df04b4 /drivers/pci
parented2670b334a1050aa122cd9ca53c7a545642c46b (diff)
parent6eb237c41acc1cf00b3b1176ad4a0ed3f221d630 (diff)
Merge tag 'pcie_bridge-3.11' of git://git.infradead.org/users/jcooper/linux into next/soc
From Jason Cooper: mvebu pcie driver (bridge) for v3.11 - mvebu - allow enumeration of devices beyond physical bridges - remove faking the slot location - fix status register emulation Signed-off-by: Olof Johansson <olof@lixom.net> * tag 'pcie_bridge-3.11' of git://git.infradead.org/users/jcooper/linux: pci: mvebu: fix the emulation of the status register pci: mvebu: allow the enumeration of devices beyond physical bridges pci: mvebu: no longer fake the slot location of downstream devices
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/host/pci-mvebu.c55
1 files changed, 44 insertions, 11 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index c8397c416a71..13a633b1612e 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -51,6 +51,7 @@
51#define PCIE_CTRL_X1_MODE 0x0001 51#define PCIE_CTRL_X1_MODE 0x0001
52#define PCIE_STAT_OFF 0x1a04 52#define PCIE_STAT_OFF 0x1a04
53#define PCIE_STAT_BUS 0xff00 53#define PCIE_STAT_BUS 0xff00
54#define PCIE_STAT_DEV 0x1f0000
54#define PCIE_STAT_LINK_DOWN BIT(0) 55#define PCIE_STAT_LINK_DOWN BIT(0)
55#define PCIE_DEBUG_CTRL 0x1a60 56#define PCIE_DEBUG_CTRL 0x1a60
56#define PCIE_DEBUG_SOFT_RESET BIT(20) 57#define PCIE_DEBUG_SOFT_RESET BIT(20)
@@ -68,7 +69,6 @@ struct mvebu_sw_pci_bridge {
68 u16 vendor; 69 u16 vendor;
69 u16 device; 70 u16 device;
70 u16 command; 71 u16 command;
71 u16 status;
72 u16 class; 72 u16 class;
73 u8 interface; 73 u8 interface;
74 u8 revision; 74 u8 revision;
@@ -148,6 +148,16 @@ static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
148 writel(stat, port->base + PCIE_STAT_OFF); 148 writel(stat, port->base + PCIE_STAT_OFF);
149} 149}
150 150
151static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
152{
153 u32 stat;
154
155 stat = readl(port->base + PCIE_STAT_OFF);
156 stat &= ~PCIE_STAT_DEV;
157 stat |= nr << 16;
158 writel(stat, port->base + PCIE_STAT_OFF);
159}
160
151/* 161/*
152 * Setup PCIE BARs and Address Decode Wins: 162 * Setup PCIE BARs and Address Decode Wins:
153 * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks 163 * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
@@ -348,7 +358,6 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
348 358
349 memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge)); 359 memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
350 360
351 bridge->status = PCI_STATUS_CAP_LIST;
352 bridge->class = PCI_CLASS_BRIDGE_PCI; 361 bridge->class = PCI_CLASS_BRIDGE_PCI;
353 bridge->vendor = PCI_VENDOR_ID_MARVELL; 362 bridge->vendor = PCI_VENDOR_ID_MARVELL;
354 bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID; 363 bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
@@ -375,7 +384,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
375 break; 384 break;
376 385
377 case PCI_COMMAND: 386 case PCI_COMMAND:
378 *value = bridge->status << 16 | bridge->command; 387 *value = bridge->command;
379 break; 388 break;
380 389
381 case PCI_CLASS_REVISION: 390 case PCI_CLASS_REVISION:
@@ -468,7 +477,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
468 switch (where & ~3) { 477 switch (where & ~3) {
469 case PCI_COMMAND: 478 case PCI_COMMAND:
470 bridge->command = value & 0xffff; 479 bridge->command = value & 0xffff;
471 bridge->status = value >> 16;
472 break; 480 break;
473 481
474 case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: 482 case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
@@ -543,7 +551,8 @@ mvebu_pcie_find_port(struct mvebu_pcie *pcie, struct pci_bus *bus,
543 if (bus->number == 0 && port->devfn == devfn) 551 if (bus->number == 0 && port->devfn == devfn)
544 return port; 552 return port;
545 if (bus->number != 0 && 553 if (bus->number != 0 &&
546 port->bridge.secondary_bus == bus->number) 554 bus->number >= port->bridge.secondary_bus &&
555 bus->number <= port->bridge.subordinate_bus)
547 return port; 556 return port;
548 } 557 }
549 558
@@ -567,13 +576,23 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
567 if (bus->number == 0) 576 if (bus->number == 0)
568 return mvebu_sw_pci_bridge_write(port, where, size, val); 577 return mvebu_sw_pci_bridge_write(port, where, size, val);
569 578
570 if (!port->haslink || PCI_SLOT(devfn) != 0) 579 if (!port->haslink)
580 return PCIBIOS_DEVICE_NOT_FOUND;
581
582 /*
583 * On the secondary bus, we don't want to expose any other
584 * device than the device physically connected in the PCIe
585 * slot, visible in slot 0. In slot 1, there's a special
586 * Marvell device that only makes sense when the Armada is
587 * used as a PCIe endpoint.
588 */
589 if (bus->number == port->bridge.secondary_bus &&
590 PCI_SLOT(devfn) != 0)
571 return PCIBIOS_DEVICE_NOT_FOUND; 591 return PCIBIOS_DEVICE_NOT_FOUND;
572 592
573 /* Access the real PCIe interface */ 593 /* Access the real PCIe interface */
574 spin_lock_irqsave(&port->conf_lock, flags); 594 spin_lock_irqsave(&port->conf_lock, flags);
575 ret = mvebu_pcie_hw_wr_conf(port, bus, 595 ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
576 PCI_DEVFN(1, PCI_FUNC(devfn)),
577 where, size, val); 596 where, size, val);
578 spin_unlock_irqrestore(&port->conf_lock, flags); 597 spin_unlock_irqrestore(&port->conf_lock, flags);
579 598
@@ -599,15 +618,27 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
599 if (bus->number == 0) 618 if (bus->number == 0)
600 return mvebu_sw_pci_bridge_read(port, where, size, val); 619 return mvebu_sw_pci_bridge_read(port, where, size, val);
601 620
602 if (!port->haslink || PCI_SLOT(devfn) != 0) { 621 if (!port->haslink) {
622 *val = 0xffffffff;
623 return PCIBIOS_DEVICE_NOT_FOUND;
624 }
625
626 /*
627 * On the secondary bus, we don't want to expose any other
628 * device than the device physically connected in the PCIe
629 * slot, visible in slot 0. In slot 1, there's a special
630 * Marvell device that only makes sense when the Armada is
631 * used as a PCIe endpoint.
632 */
633 if (bus->number == port->bridge.secondary_bus &&
634 PCI_SLOT(devfn) != 0) {
603 *val = 0xffffffff; 635 *val = 0xffffffff;
604 return PCIBIOS_DEVICE_NOT_FOUND; 636 return PCIBIOS_DEVICE_NOT_FOUND;
605 } 637 }
606 638
607 /* Access the real PCIe interface */ 639 /* Access the real PCIe interface */
608 spin_lock_irqsave(&port->conf_lock, flags); 640 spin_lock_irqsave(&port->conf_lock, flags);
609 ret = mvebu_pcie_hw_rd_conf(port, bus, 641 ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
610 PCI_DEVFN(1, PCI_FUNC(devfn)),
611 where, size, val); 642 where, size, val);
612 spin_unlock_irqrestore(&port->conf_lock, flags); 643 spin_unlock_irqrestore(&port->conf_lock, flags);
613 644
@@ -817,6 +848,8 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
817 continue; 848 continue;
818 } 849 }
819 850
851 mvebu_pcie_set_local_dev_nr(port, 1);
852
820 if (mvebu_pcie_link_up(port)) { 853 if (mvebu_pcie_link_up(port)) {
821 port->haslink = 1; 854 port->haslink = 1;
822 dev_info(&pdev->dev, "PCIe%d.%d: link up\n", 855 dev_info(&pdev->dev, "PCIe%d.%d: link up\n",