mvebu pcie driver (bridge) for v3.11
- mvebu - allow enumeration of devices beyond physical bridges - remove faking the slot location - fix status register emulation depends - mvebu/pcie -mvebu/of_pci -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQEcBAABAgAGBQJRpP2uAAoJEAi3KVZQDZAean8IAKvwIK5TzLB289GKL26NLgMs c7FxMseuTLzlc036BU85UhDJ62bjVcUCukWzGhF1YxGGr+46gdJ2/aRZ8cvAz3pu VDZCFo8V7A9VjoTZZ/MX3bzmdJbtgJD9G9PI69LX1sf+4WqlybVBhR9wFlyh9Zws iolfLGDpCqDwkI5YH1R3XI6KCcP5P+QC52gXb4Due0lRMULTfDiWUqfJs7nqSAnH AyM4SjImgXwWNVdKvK73uxbUmfG2pguvN20tq+ox5UHfSIfHOd9Uuj2EIEAC2SE7 eWbr7YV+Ba6fD/2Mfhuia7bCD8LrwrTPz8c7A4Xvjp7tMUW20K53PRAn+W4W6Wo= =TTX4 -----END PGP SIGNATURE----- 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
This commit is contained in:
Коммит
2dbefbf6a8
|
@ -51,6 +51,7 @@
|
||||||
#define PCIE_CTRL_X1_MODE 0x0001
|
#define PCIE_CTRL_X1_MODE 0x0001
|
||||||
#define PCIE_STAT_OFF 0x1a04
|
#define PCIE_STAT_OFF 0x1a04
|
||||||
#define PCIE_STAT_BUS 0xff00
|
#define PCIE_STAT_BUS 0xff00
|
||||||
|
#define PCIE_STAT_DEV 0x1f0000
|
||||||
#define PCIE_STAT_LINK_DOWN BIT(0)
|
#define PCIE_STAT_LINK_DOWN BIT(0)
|
||||||
#define PCIE_DEBUG_CTRL 0x1a60
|
#define PCIE_DEBUG_CTRL 0x1a60
|
||||||
#define PCIE_DEBUG_SOFT_RESET BIT(20)
|
#define PCIE_DEBUG_SOFT_RESET BIT(20)
|
||||||
|
@ -68,7 +69,6 @@ struct mvebu_sw_pci_bridge {
|
||||||
u16 vendor;
|
u16 vendor;
|
||||||
u16 device;
|
u16 device;
|
||||||
u16 command;
|
u16 command;
|
||||||
u16 status;
|
|
||||||
u16 class;
|
u16 class;
|
||||||
u8 interface;
|
u8 interface;
|
||||||
u8 revision;
|
u8 revision;
|
||||||
|
@ -148,6 +148,16 @@ static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
|
||||||
writel(stat, port->base + PCIE_STAT_OFF);
|
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:
|
* Setup PCIE BARs and Address Decode Wins:
|
||||||
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
|
* 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)
|
||||||
|
|
||||||
memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
|
memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
|
||||||
|
|
||||||
bridge->status = PCI_STATUS_CAP_LIST;
|
|
||||||
bridge->class = PCI_CLASS_BRIDGE_PCI;
|
bridge->class = PCI_CLASS_BRIDGE_PCI;
|
||||||
bridge->vendor = PCI_VENDOR_ID_MARVELL;
|
bridge->vendor = PCI_VENDOR_ID_MARVELL;
|
||||||
bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
|
bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
|
||||||
|
@ -375,7 +384,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_COMMAND:
|
case PCI_COMMAND:
|
||||||
*value = bridge->status << 16 | bridge->command;
|
*value = bridge->command;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_CLASS_REVISION:
|
case PCI_CLASS_REVISION:
|
||||||
|
@ -468,7 +477,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
|
||||||
switch (where & ~3) {
|
switch (where & ~3) {
|
||||||
case PCI_COMMAND:
|
case PCI_COMMAND:
|
||||||
bridge->command = value & 0xffff;
|
bridge->command = value & 0xffff;
|
||||||
bridge->status = value >> 16;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
|
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,
|
||||||
if (bus->number == 0 && port->devfn == devfn)
|
if (bus->number == 0 && port->devfn == devfn)
|
||||||
return port;
|
return port;
|
||||||
if (bus->number != 0 &&
|
if (bus->number != 0 &&
|
||||||
port->bridge.secondary_bus == bus->number)
|
bus->number >= port->bridge.secondary_bus &&
|
||||||
|
bus->number <= port->bridge.subordinate_bus)
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,13 +576,23 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
|
||||||
if (bus->number == 0)
|
if (bus->number == 0)
|
||||||
return mvebu_sw_pci_bridge_write(port, where, size, val);
|
return mvebu_sw_pci_bridge_write(port, where, size, val);
|
||||||
|
|
||||||
if (!port->haslink || PCI_SLOT(devfn) != 0)
|
if (!port->haslink)
|
||||||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On the secondary bus, we don't want to expose any other
|
||||||
|
* device than the device physically connected in the PCIe
|
||||||
|
* slot, visible in slot 0. In slot 1, there's a special
|
||||||
|
* Marvell device that only makes sense when the Armada is
|
||||||
|
* used as a PCIe endpoint.
|
||||||
|
*/
|
||||||
|
if (bus->number == port->bridge.secondary_bus &&
|
||||||
|
PCI_SLOT(devfn) != 0)
|
||||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
/* Access the real PCIe interface */
|
/* Access the real PCIe interface */
|
||||||
spin_lock_irqsave(&port->conf_lock, flags);
|
spin_lock_irqsave(&port->conf_lock, flags);
|
||||||
ret = mvebu_pcie_hw_wr_conf(port, bus,
|
ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
|
||||||
PCI_DEVFN(1, PCI_FUNC(devfn)),
|
|
||||||
where, size, val);
|
where, size, val);
|
||||||
spin_unlock_irqrestore(&port->conf_lock, flags);
|
spin_unlock_irqrestore(&port->conf_lock, flags);
|
||||||
|
|
||||||
|
@ -599,15 +618,27 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
||||||
if (bus->number == 0)
|
if (bus->number == 0)
|
||||||
return mvebu_sw_pci_bridge_read(port, where, size, val);
|
return mvebu_sw_pci_bridge_read(port, where, size, val);
|
||||||
|
|
||||||
if (!port->haslink || PCI_SLOT(devfn) != 0) {
|
if (!port->haslink) {
|
||||||
|
*val = 0xffffffff;
|
||||||
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On the secondary bus, we don't want to expose any other
|
||||||
|
* device than the device physically connected in the PCIe
|
||||||
|
* slot, visible in slot 0. In slot 1, there's a special
|
||||||
|
* Marvell device that only makes sense when the Armada is
|
||||||
|
* used as a PCIe endpoint.
|
||||||
|
*/
|
||||||
|
if (bus->number == port->bridge.secondary_bus &&
|
||||||
|
PCI_SLOT(devfn) != 0) {
|
||||||
*val = 0xffffffff;
|
*val = 0xffffffff;
|
||||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Access the real PCIe interface */
|
/* Access the real PCIe interface */
|
||||||
spin_lock_irqsave(&port->conf_lock, flags);
|
spin_lock_irqsave(&port->conf_lock, flags);
|
||||||
ret = mvebu_pcie_hw_rd_conf(port, bus,
|
ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
|
||||||
PCI_DEVFN(1, PCI_FUNC(devfn)),
|
|
||||||
where, size, val);
|
where, size, val);
|
||||||
spin_unlock_irqrestore(&port->conf_lock, flags);
|
spin_unlock_irqrestore(&port->conf_lock, flags);
|
||||||
|
|
||||||
|
@ -817,6 +848,8 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mvebu_pcie_set_local_dev_nr(port, 1);
|
||||||
|
|
||||||
if (mvebu_pcie_link_up(port)) {
|
if (mvebu_pcie_link_up(port)) {
|
||||||
port->haslink = 1;
|
port->haslink = 1;
|
||||||
dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
|
dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче