diff options
Diffstat (limited to 'drivers/pci/host/pci-mvebu.c')
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 102 |
1 files changed, 78 insertions, 24 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index d3d1cfd51e09..7f450322f397 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -113,7 +113,6 @@ struct mvebu_pcie { | |||
113 | struct mvebu_pcie_port { | 113 | struct mvebu_pcie_port { |
114 | char *name; | 114 | char *name; |
115 | void __iomem *base; | 115 | void __iomem *base; |
116 | spinlock_t conf_lock; | ||
117 | u32 port; | 116 | u32 port; |
118 | u32 lane; | 117 | u32 lane; |
119 | int devfn; | 118 | int devfn; |
@@ -293,6 +292,60 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, | |||
293 | return PCIBIOS_SUCCESSFUL; | 292 | return PCIBIOS_SUCCESSFUL; |
294 | } | 293 | } |
295 | 294 | ||
295 | /* | ||
296 | * Remove windows, starting from the largest ones to the smallest | ||
297 | * ones. | ||
298 | */ | ||
299 | static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, | ||
300 | phys_addr_t base, size_t size) | ||
301 | { | ||
302 | while (size) { | ||
303 | size_t sz = 1 << (fls(size) - 1); | ||
304 | |||
305 | mvebu_mbus_del_window(base, sz); | ||
306 | base += sz; | ||
307 | size -= sz; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * MBus windows can only have a power of two size, but PCI BARs do not | ||
313 | * have this constraint. Therefore, we have to split the PCI BAR into | ||
314 | * areas each having a power of two size. We start from the largest | ||
315 | * one (i.e highest order bit set in the size). | ||
316 | */ | ||
317 | static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, | ||
318 | unsigned int target, unsigned int attribute, | ||
319 | phys_addr_t base, size_t size, | ||
320 | phys_addr_t remap) | ||
321 | { | ||
322 | size_t size_mapped = 0; | ||
323 | |||
324 | while (size) { | ||
325 | size_t sz = 1 << (fls(size) - 1); | ||
326 | int ret; | ||
327 | |||
328 | ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base, | ||
329 | sz, remap); | ||
330 | if (ret) { | ||
331 | phys_addr_t end = base + sz - 1; | ||
332 | |||
333 | dev_err(&port->pcie->pdev->dev, | ||
334 | "Could not create MBus window at [mem %pa-%pa]: %d\n", | ||
335 | &base, &end, ret); | ||
336 | mvebu_pcie_del_windows(port, base - size_mapped, | ||
337 | size_mapped); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | size -= sz; | ||
342 | size_mapped += sz; | ||
343 | base += sz; | ||
344 | if (remap != MVEBU_MBUS_NO_REMAP) | ||
345 | remap += sz; | ||
346 | } | ||
347 | } | ||
348 | |||
296 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | 349 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) |
297 | { | 350 | { |
298 | phys_addr_t iobase; | 351 | phys_addr_t iobase; |
@@ -304,8 +357,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
304 | 357 | ||
305 | /* If a window was configured, remove it */ | 358 | /* If a window was configured, remove it */ |
306 | if (port->iowin_base) { | 359 | if (port->iowin_base) { |
307 | mvebu_mbus_del_window(port->iowin_base, | 360 | mvebu_pcie_del_windows(port, port->iowin_base, |
308 | port->iowin_size); | 361 | port->iowin_size); |
309 | port->iowin_base = 0; | 362 | port->iowin_base = 0; |
310 | port->iowin_size = 0; | 363 | port->iowin_size = 0; |
311 | } | 364 | } |
@@ -331,11 +384,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
331 | port->iowin_base = port->pcie->io.start + iobase; | 384 | port->iowin_base = port->pcie->io.start + iobase; |
332 | port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | | 385 | port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | |
333 | (port->bridge.iolimitupper << 16)) - | 386 | (port->bridge.iolimitupper << 16)) - |
334 | iobase); | 387 | iobase) + 1; |
335 | 388 | ||
336 | mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, | 389 | mvebu_pcie_add_windows(port, port->io_target, port->io_attr, |
337 | port->iowin_base, port->iowin_size, | 390 | port->iowin_base, port->iowin_size, |
338 | iobase); | 391 | iobase); |
339 | } | 392 | } |
340 | 393 | ||
341 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | 394 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) |
@@ -346,8 +399,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
346 | 399 | ||
347 | /* If a window was configured, remove it */ | 400 | /* If a window was configured, remove it */ |
348 | if (port->memwin_base) { | 401 | if (port->memwin_base) { |
349 | mvebu_mbus_del_window(port->memwin_base, | 402 | mvebu_pcie_del_windows(port, port->memwin_base, |
350 | port->memwin_size); | 403 | port->memwin_size); |
351 | port->memwin_base = 0; | 404 | port->memwin_base = 0; |
352 | port->memwin_size = 0; | 405 | port->memwin_size = 0; |
353 | } | 406 | } |
@@ -364,10 +417,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
364 | port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); | 417 | port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); |
365 | port->memwin_size = | 418 | port->memwin_size = |
366 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - | 419 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - |
367 | port->memwin_base; | 420 | port->memwin_base + 1; |
368 | 421 | ||
369 | mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, | 422 | mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, |
370 | port->memwin_base, port->memwin_size); | 423 | port->memwin_base, port->memwin_size, |
424 | MVEBU_MBUS_NO_REMAP); | ||
371 | } | 425 | } |
372 | 426 | ||
373 | /* | 427 | /* |
@@ -585,7 +639,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
585 | { | 639 | { |
586 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 640 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); |
587 | struct mvebu_pcie_port *port; | 641 | struct mvebu_pcie_port *port; |
588 | unsigned long flags; | ||
589 | int ret; | 642 | int ret; |
590 | 643 | ||
591 | port = mvebu_pcie_find_port(pcie, bus, devfn); | 644 | port = mvebu_pcie_find_port(pcie, bus, devfn); |
@@ -611,10 +664,8 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
611 | return PCIBIOS_DEVICE_NOT_FOUND; | 664 | return PCIBIOS_DEVICE_NOT_FOUND; |
612 | 665 | ||
613 | /* Access the real PCIe interface */ | 666 | /* Access the real PCIe interface */ |
614 | spin_lock_irqsave(&port->conf_lock, flags); | ||
615 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, | 667 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, |
616 | where, size, val); | 668 | where, size, val); |
617 | spin_unlock_irqrestore(&port->conf_lock, flags); | ||
618 | 669 | ||
619 | return ret; | 670 | return ret; |
620 | } | 671 | } |
@@ -625,7 +676,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
625 | { | 676 | { |
626 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 677 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); |
627 | struct mvebu_pcie_port *port; | 678 | struct mvebu_pcie_port *port; |
628 | unsigned long flags; | ||
629 | int ret; | 679 | int ret; |
630 | 680 | ||
631 | port = mvebu_pcie_find_port(pcie, bus, devfn); | 681 | port = mvebu_pcie_find_port(pcie, bus, devfn); |
@@ -657,10 +707,8 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
657 | } | 707 | } |
658 | 708 | ||
659 | /* Access the real PCIe interface */ | 709 | /* Access the real PCIe interface */ |
660 | spin_lock_irqsave(&port->conf_lock, flags); | ||
661 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, | 710 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, |
662 | where, size, val); | 711 | where, size, val); |
663 | spin_unlock_irqrestore(&port->conf_lock, flags); | ||
664 | 712 | ||
665 | return ret; | 713 | return ret; |
666 | } | 714 | } |
@@ -743,14 +791,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | |||
743 | 791 | ||
744 | /* | 792 | /* |
745 | * On the PCI-to-PCI bridge side, the I/O windows must have at | 793 | * On the PCI-to-PCI bridge side, the I/O windows must have at |
746 | * least a 64 KB size and be aligned on their size, and the | 794 | * least a 64 KB size and the memory windows must have at |
747 | * memory windows must have at least a 1 MB size and be | 795 | * least a 1 MB size. Moreover, MBus windows need to have a |
748 | * aligned on their size | 796 | * base address aligned on their size, and their size must be |
797 | * a power of two. This means that if the BAR doesn't have a | ||
798 | * power of two size, several MBus windows will actually be | ||
799 | * created. We need to ensure that the biggest MBus window | ||
800 | * (which will be the first one) is aligned on its size, which | ||
801 | * explains the rounddown_pow_of_two() being done here. | ||
749 | */ | 802 | */ |
750 | if (res->flags & IORESOURCE_IO) | 803 | if (res->flags & IORESOURCE_IO) |
751 | return round_up(start, max_t(resource_size_t, SZ_64K, size)); | 804 | return round_up(start, max_t(resource_size_t, SZ_64K, |
805 | rounddown_pow_of_two(size))); | ||
752 | else if (res->flags & IORESOURCE_MEM) | 806 | else if (res->flags & IORESOURCE_MEM) |
753 | return round_up(start, max_t(resource_size_t, SZ_1M, size)); | 807 | return round_up(start, max_t(resource_size_t, SZ_1M, |
808 | rounddown_pow_of_two(size))); | ||
754 | else | 809 | else |
755 | return start; | 810 | return start; |
756 | } | 811 | } |
@@ -1000,7 +1055,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1000 | mvebu_pcie_set_local_dev_nr(port, 1); | 1055 | mvebu_pcie_set_local_dev_nr(port, 1); |
1001 | 1056 | ||
1002 | port->dn = child; | 1057 | port->dn = child; |
1003 | spin_lock_init(&port->conf_lock); | ||
1004 | mvebu_sw_pci_bridge_init(port); | 1058 | mvebu_sw_pci_bridge_init(port); |
1005 | i++; | 1059 | i++; |
1006 | } | 1060 | } |