Commit dda71892 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/host-mvebu' into next

* pci/host-mvebu:
  PCI: mvebu: Change delay after reset to the PCIe spec mandated 100ms
  PCI: mvebu: Handle changes to the bridge windows while enabled
parents e2dc4f22 8ed81ec8
...@@ -78,7 +78,8 @@ and the following optional properties: ...@@ -78,7 +78,8 @@ and the following optional properties:
multiple lanes. If this property is not found, we assume that the multiple lanes. If this property is not found, we assume that the
value is 0. value is 0.
- reset-gpios: optional gpio to PERST# - reset-gpios: optional gpio to PERST#
- reset-delay-us: delay in us to wait after reset de-assertion - reset-delay-us: delay in us to wait after reset de-assertion, if not
specified will default to 100ms, as required by the PCIe specification.
Example: Example:
......
...@@ -133,6 +133,12 @@ struct mvebu_pcie { ...@@ -133,6 +133,12 @@ struct mvebu_pcie {
int nports; int nports;
}; };
struct mvebu_pcie_window {
phys_addr_t base;
phys_addr_t remap;
size_t size;
};
/* Structure representing one PCIe interface */ /* Structure representing one PCIe interface */
struct mvebu_pcie_port { struct mvebu_pcie_port {
char *name; char *name;
...@@ -150,10 +156,8 @@ struct mvebu_pcie_port { ...@@ -150,10 +156,8 @@ struct mvebu_pcie_port {
struct mvebu_sw_pci_bridge bridge; struct mvebu_sw_pci_bridge bridge;
struct device_node *dn; struct device_node *dn;
struct mvebu_pcie *pcie; struct mvebu_pcie *pcie;
phys_addr_t memwin_base; struct mvebu_pcie_window memwin;
size_t memwin_size; struct mvebu_pcie_window iowin;
phys_addr_t iowin_base;
size_t iowin_size;
u32 saved_pcie_stat; u32 saved_pcie_stat;
}; };
...@@ -379,23 +383,45 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, ...@@ -379,23 +383,45 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
} }
} }
static void mvebu_pcie_set_window(struct mvebu_pcie_port *port,
unsigned int target, unsigned int attribute,
const struct mvebu_pcie_window *desired,
struct mvebu_pcie_window *cur)
{
if (desired->base == cur->base && desired->remap == cur->remap &&
desired->size == cur->size)
return;
if (cur->size != 0) {
mvebu_pcie_del_windows(port, cur->base, cur->size);
cur->size = 0;
cur->base = 0;
/*
* If something tries to change the window while it is enabled
* the change will not be done atomically. That would be
* difficult to do in the general case.
*/
}
if (desired->size == 0)
return;
mvebu_pcie_add_windows(port, target, attribute, desired->base,
desired->size, desired->remap);
*cur = *desired;
}
static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
{ {
phys_addr_t iobase; struct mvebu_pcie_window desired = {};
/* Are the new iobase/iolimit values invalid? */ /* Are the new iobase/iolimit values invalid? */
if (port->bridge.iolimit < port->bridge.iobase || if (port->bridge.iolimit < port->bridge.iobase ||
port->bridge.iolimitupper < port->bridge.iobaseupper || port->bridge.iolimitupper < port->bridge.iobaseupper ||
!(port->bridge.command & PCI_COMMAND_IO)) { !(port->bridge.command & PCI_COMMAND_IO)) {
mvebu_pcie_set_window(port, port->io_target, port->io_attr,
/* If a window was configured, remove it */ &desired, &port->iowin);
if (port->iowin_base) {
mvebu_pcie_del_windows(port, port->iowin_base,
port->iowin_size);
port->iowin_base = 0;
port->iowin_size = 0;
}
return; return;
} }
...@@ -412,32 +438,27 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) ...@@ -412,32 +438,27 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
* specifications. iobase is the bus address, port->iowin_base * specifications. iobase is the bus address, port->iowin_base
* is the CPU address. * is the CPU address.
*/ */
iobase = ((port->bridge.iobase & 0xF0) << 8) | desired.remap = ((port->bridge.iobase & 0xF0) << 8) |
(port->bridge.iobaseupper << 16); (port->bridge.iobaseupper << 16);
port->iowin_base = port->pcie->io.start + iobase; desired.base = port->pcie->io.start + desired.remap;
port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | desired.size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
(port->bridge.iolimitupper << 16)) - (port->bridge.iolimitupper << 16)) -
iobase) + 1; desired.remap) +
1;
mvebu_pcie_add_windows(port, port->io_target, port->io_attr,
port->iowin_base, port->iowin_size, mvebu_pcie_set_window(port, port->io_target, port->io_attr, &desired,
iobase); &port->iowin);
} }
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
{ {
struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP};
/* Are the new membase/memlimit values invalid? */ /* Are the new membase/memlimit values invalid? */
if (port->bridge.memlimit < port->bridge.membase || if (port->bridge.memlimit < port->bridge.membase ||
!(port->bridge.command & PCI_COMMAND_MEMORY)) { !(port->bridge.command & PCI_COMMAND_MEMORY)) {
mvebu_pcie_set_window(port, port->mem_target, port->mem_attr,
/* If a window was configured, remove it */ &desired, &port->memwin);
if (port->memwin_base) {
mvebu_pcie_del_windows(port, port->memwin_base,
port->memwin_size);
port->memwin_base = 0;
port->memwin_size = 0;
}
return; return;
} }
...@@ -447,14 +468,12 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) ...@@ -447,14 +468,12 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
* window to setup, according to the PCI-to-PCI bridge * window to setup, according to the PCI-to-PCI bridge
* specifications. * specifications.
*/ */
port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); desired.base = ((port->bridge.membase & 0xFFF0) << 16);
port->memwin_size = desired.size = (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
(((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - desired.base + 1;
port->memwin_base + 1;
mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, &desired,
mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, &port->memwin);
port->memwin_base, port->memwin_size,
MVEBU_MBUS_NO_REMAP);
} }
/* /*
...@@ -1162,7 +1181,7 @@ static int mvebu_pcie_powerup(struct mvebu_pcie_port *port) ...@@ -1162,7 +1181,7 @@ static int mvebu_pcie_powerup(struct mvebu_pcie_port *port)
return ret; return ret;
if (port->reset_gpio) { if (port->reset_gpio) {
u32 reset_udelay = 20000; u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000;
of_property_read_u32(port->dn, "reset-delay-us", of_property_read_u32(port->dn, "reset-delay-us",
&reset_udelay); &reset_udelay);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment