diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-01 02:20:52 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-01 02:20:52 -0400 |
commit | 2dbefbf6a803d65f6327fe617f5e1960f218ce01 (patch) | |
tree | a128341f02fa1ea7ce3353a78397104162df04b4 /drivers/pci | |
parent | ed2670b334a1050aa122cd9ca53c7a545642c46b (diff) | |
parent | 6eb237c41acc1cf00b3b1176ad4a0ed3f221d630 (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.c | 55 |
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 | ||
151 | static 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", |