98 lines
3.5 KiB
Diff
98 lines
3.5 KiB
Diff
From 34361044442206dd7d10ff3309f8e0713e0fd856 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
|
Date: Thu, 23 May 2013 16:32:51 +0200
|
|
Subject: [PATCH 015/203] pci: mvebu: no longer fake the slot location of
|
|
downstream devices
|
|
|
|
By default, the Marvell hardware, for each PCIe interface, exhibits
|
|
the following devices:
|
|
|
|
* On slot 0, a "Marvell Memory controller", identical on all PCIe
|
|
interfaces, and which isn't useful when the Marvell SoC is the PCIe
|
|
root complex (i.e, the normal case when we run Linux on the Marvell
|
|
SoC).
|
|
|
|
* On slot 1, the real PCIe card connected into the PCIe slot of the
|
|
board.
|
|
|
|
So, what the Marvell PCIe driver was doing in its PCI-to-PCI bridge
|
|
emulation is that when the Linux PCI core was trying to access the
|
|
device in slot 0, we were in fact forwarding the configuration
|
|
transaction to the device in slot 1. For all other slots, we were
|
|
telling the Linux PCI core that there was no device connected.
|
|
|
|
However, new versions of bootloaders from Marvell change the default
|
|
PCIe configuration, and make the real device appear in slot 0, and the
|
|
"Marvell Memory controller" in slot 1.
|
|
|
|
Therefore, this commit modifies the Marvell PCIe driver to adjust the
|
|
PCIe hardware configuration to make sure that this behavior (real
|
|
device in slot 0, "Marvell Memory controller" in slot 1) is the one
|
|
we'll see regardless of what the bootloader has done. It allows to
|
|
remove the little hack that was forwarding configuration transactions
|
|
on slot 0 to slot 1, which is nice.
|
|
|
|
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
|
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
|
|
---
|
|
drivers/pci/host/pci-mvebu.c | 19 +++++++++++++++----
|
|
1 file changed, 15 insertions(+), 4 deletions(-)
|
|
|
|
--- a/drivers/pci/host/pci-mvebu.c
|
|
+++ b/drivers/pci/host/pci-mvebu.c
|
|
@@ -51,6 +51,7 @@
|
|
#define PCIE_CTRL_X1_MODE 0x0001
|
|
#define PCIE_STAT_OFF 0x1a04
|
|
#define PCIE_STAT_BUS 0xff00
|
|
+#define PCIE_STAT_DEV 0x1f0000
|
|
#define PCIE_STAT_LINK_DOWN BIT(0)
|
|
#define PCIE_DEBUG_CTRL 0x1a60
|
|
#define PCIE_DEBUG_SOFT_RESET BIT(20)
|
|
@@ -148,6 +149,16 @@ static void mvebu_pcie_set_local_bus_nr(
|
|
writel(stat, port->base + PCIE_STAT_OFF);
|
|
}
|
|
|
|
+static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
|
|
+{
|
|
+ u32 stat;
|
|
+
|
|
+ stat = readl(port->base + PCIE_STAT_OFF);
|
|
+ stat &= ~PCIE_STAT_DEV;
|
|
+ stat |= nr << 16;
|
|
+ writel(stat, port->base + PCIE_STAT_OFF);
|
|
+}
|
|
+
|
|
/*
|
|
* Setup PCIE BARs and Address Decode Wins:
|
|
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
|
|
@@ -572,8 +583,7 @@ static int mvebu_pcie_wr_conf(struct pci
|
|
|
|
/* Access the real PCIe interface */
|
|
spin_lock_irqsave(&port->conf_lock, flags);
|
|
- ret = mvebu_pcie_hw_wr_conf(port, bus,
|
|
- PCI_DEVFN(1, PCI_FUNC(devfn)),
|
|
+ ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
|
|
where, size, val);
|
|
spin_unlock_irqrestore(&port->conf_lock, flags);
|
|
|
|
@@ -606,8 +616,7 @@ static int mvebu_pcie_rd_conf(struct pci
|
|
|
|
/* Access the real PCIe interface */
|
|
spin_lock_irqsave(&port->conf_lock, flags);
|
|
- ret = mvebu_pcie_hw_rd_conf(port, bus,
|
|
- PCI_DEVFN(1, PCI_FUNC(devfn)),
|
|
+ ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
|
|
where, size, val);
|
|
spin_unlock_irqrestore(&port->conf_lock, flags);
|
|
|
|
@@ -817,6 +826,8 @@ static int __init mvebu_pcie_probe(struc
|
|
continue;
|
|
}
|
|
|
|
+ mvebu_pcie_set_local_dev_nr(port, 1);
|
|
+
|
|
if (mvebu_pcie_link_up(port)) {
|
|
port->haslink = 1;
|
|
dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
|