diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-18 16:04:09 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-18 16:04:09 -0500 |
commit | 7160266a2679ad35222b55330d425f5e113ab165 (patch) | |
tree | 1fcb8c27b12b8d05dff75d5add56a56d9e8dc4b4 | |
parent | ed00f97d4129cea9d4c034e6d3171d073a48307a (diff) | |
parent | 84f47190d6be1cb99cd4a680e1018080d93800a8 (diff) |
Merge branch 'pci/host-mvebu' into next
* pci/host-mvebu:
PCI: mvebu: Remove duplicate of_clk_get_by_name() call
PCI: mvebu: Support a bridge with no IO port window
PCI: mvebu: Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits
PCI: mvebu: Drop writes to bridge Secondary Status register
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 2aa7b77c7c88..533e0df02718 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -150,6 +150,11 @@ static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg) | |||
150 | return readl(port->base + reg); | 150 | return readl(port->base + reg); |
151 | } | 151 | } |
152 | 152 | ||
153 | static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port) | ||
154 | { | ||
155 | return port->io_target != -1 && port->io_attr != -1; | ||
156 | } | ||
157 | |||
153 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) | 158 | static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) |
154 | { | 159 | { |
155 | return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); | 160 | return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); |
@@ -300,7 +305,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
300 | 305 | ||
301 | /* Are the new iobase/iolimit values invalid? */ | 306 | /* Are the new iobase/iolimit values invalid? */ |
302 | if (port->bridge.iolimit < port->bridge.iobase || | 307 | if (port->bridge.iolimit < port->bridge.iobase || |
303 | port->bridge.iolimitupper < port->bridge.iobaseupper) { | 308 | port->bridge.iolimitupper < port->bridge.iobaseupper || |
309 | !(port->bridge.command & PCI_COMMAND_IO)) { | ||
304 | 310 | ||
305 | /* If a window was configured, remove it */ | 311 | /* If a window was configured, remove it */ |
306 | if (port->iowin_base) { | 312 | if (port->iowin_base) { |
@@ -313,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
313 | return; | 319 | return; |
314 | } | 320 | } |
315 | 321 | ||
322 | if (!mvebu_has_ioport(port)) { | ||
323 | dev_WARN(&port->pcie->pdev->dev, | ||
324 | "Attempt to set IO when IO is disabled\n"); | ||
325 | return; | ||
326 | } | ||
327 | |||
316 | /* | 328 | /* |
317 | * We read the PCI-to-PCI bridge emulated registers, and | 329 | * We read the PCI-to-PCI bridge emulated registers, and |
318 | * calculate the base address and size of the address decoding | 330 | * calculate the base address and size of the address decoding |
@@ -337,7 +349,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
337 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | 349 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) |
338 | { | 350 | { |
339 | /* Are the new membase/memlimit values invalid? */ | 351 | /* Are the new membase/memlimit values invalid? */ |
340 | if (port->bridge.memlimit < port->bridge.membase) { | 352 | if (port->bridge.memlimit < port->bridge.membase || |
353 | !(port->bridge.command & PCI_COMMAND_MEMORY)) { | ||
341 | 354 | ||
342 | /* If a window was configured, remove it */ | 355 | /* If a window was configured, remove it */ |
343 | if (port->memwin_base) { | 356 | if (port->memwin_base) { |
@@ -426,9 +439,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, | |||
426 | break; | 439 | break; |
427 | 440 | ||
428 | case PCI_IO_BASE: | 441 | case PCI_IO_BASE: |
429 | *value = (bridge->secondary_status << 16 | | 442 | if (!mvebu_has_ioport(port)) |
430 | bridge->iolimit << 8 | | 443 | *value = bridge->secondary_status << 16; |
431 | bridge->iobase); | 444 | else |
445 | *value = (bridge->secondary_status << 16 | | ||
446 | bridge->iolimit << 8 | | ||
447 | bridge->iobase); | ||
432 | break; | 448 | break; |
433 | 449 | ||
434 | case PCI_MEMORY_BASE: | 450 | case PCI_MEMORY_BASE: |
@@ -490,8 +506,19 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, | |||
490 | 506 | ||
491 | switch (where & ~3) { | 507 | switch (where & ~3) { |
492 | case PCI_COMMAND: | 508 | case PCI_COMMAND: |
509 | { | ||
510 | u32 old = bridge->command; | ||
511 | |||
512 | if (!mvebu_has_ioport(port)) | ||
513 | value &= ~PCI_COMMAND_IO; | ||
514 | |||
493 | bridge->command = value & 0xffff; | 515 | bridge->command = value & 0xffff; |
516 | if ((old ^ bridge->command) & PCI_COMMAND_IO) | ||
517 | mvebu_pcie_handle_iobase_change(port); | ||
518 | if ((old ^ bridge->command) & PCI_COMMAND_MEMORY) | ||
519 | mvebu_pcie_handle_membase_change(port); | ||
494 | break; | 520 | break; |
521 | } | ||
495 | 522 | ||
496 | case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: | 523 | case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1: |
497 | bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value; | 524 | bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value; |
@@ -505,7 +532,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, | |||
505 | */ | 532 | */ |
506 | bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32; | 533 | bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32; |
507 | bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32; | 534 | bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32; |
508 | bridge->secondary_status = value >> 16; | ||
509 | mvebu_pcie_handle_iobase_change(port); | 535 | mvebu_pcie_handle_iobase_change(port); |
510 | break; | 536 | break; |
511 | 537 | ||
@@ -656,7 +682,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
656 | struct mvebu_pcie *pcie = sys_to_pcie(sys); | 682 | struct mvebu_pcie *pcie = sys_to_pcie(sys); |
657 | int i; | 683 | int i; |
658 | 684 | ||
659 | pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset); | 685 | if (resource_size(&pcie->realio) != 0) |
686 | pci_add_resource_offset(&sys->resources, &pcie->realio, | ||
687 | sys->io_offset); | ||
660 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); | 688 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); |
661 | pci_add_resource(&sys->resources, &pcie->busn); | 689 | pci_add_resource(&sys->resources, &pcie->busn); |
662 | 690 | ||
@@ -757,12 +785,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, | |||
757 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) | 785 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) |
758 | 786 | ||
759 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | 787 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, |
760 | unsigned long type, int *tgt, int *attr) | 788 | unsigned long type, |
789 | unsigned int *tgt, | ||
790 | unsigned int *attr) | ||
761 | { | 791 | { |
762 | const int na = 3, ns = 2; | 792 | const int na = 3, ns = 2; |
763 | const __be32 *range; | 793 | const __be32 *range; |
764 | int rlen, nranges, rangesz, pna, i; | 794 | int rlen, nranges, rangesz, pna, i; |
765 | 795 | ||
796 | *tgt = -1; | ||
797 | *attr = -1; | ||
798 | |||
766 | range = of_get_property(np, "ranges", &rlen); | 799 | range = of_get_property(np, "ranges", &rlen); |
767 | if (!range) | 800 | if (!range) |
768 | return -EINVAL; | 801 | return -EINVAL; |
@@ -832,16 +865,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
832 | } | 865 | } |
833 | 866 | ||
834 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); | 867 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
835 | if (resource_size(&pcie->io) == 0) { | ||
836 | dev_err(&pdev->dev, "invalid I/O aperture size\n"); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | 868 | ||
840 | pcie->realio.flags = pcie->io.flags; | 869 | if (resource_size(&pcie->io) != 0) { |
841 | pcie->realio.start = PCIBIOS_MIN_IO; | 870 | pcie->realio.flags = pcie->io.flags; |
842 | pcie->realio.end = min_t(resource_size_t, | 871 | pcie->realio.start = PCIBIOS_MIN_IO; |
843 | IO_SPACE_LIMIT, | 872 | pcie->realio.end = min_t(resource_size_t, |
844 | resource_size(&pcie->io)); | 873 | IO_SPACE_LIMIT, |
874 | resource_size(&pcie->io)); | ||
875 | } else | ||
876 | pcie->realio = pcie->io; | ||
845 | 877 | ||
846 | /* Get the bus range */ | 878 | /* Get the bus range */ |
847 | ret = of_pci_parse_bus_range(np, &pcie->busn); | 879 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
@@ -900,12 +932,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
900 | continue; | 932 | continue; |
901 | } | 933 | } |
902 | 934 | ||
903 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | 935 | if (resource_size(&pcie->io) != 0) |
904 | &port->io_target, &port->io_attr); | 936 | mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, |
905 | if (ret < 0) { | 937 | &port->io_target, &port->io_attr); |
906 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", | 938 | else { |
907 | port->port, port->lane); | 939 | port->io_target = -1; |
908 | continue; | 940 | port->io_attr = -1; |
909 | } | 941 | } |
910 | 942 | ||
911 | port->reset_gpio = of_get_named_gpio_flags(child, | 943 | port->reset_gpio = of_get_named_gpio_flags(child, |
@@ -954,14 +986,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
954 | 986 | ||
955 | mvebu_pcie_set_local_dev_nr(port, 1); | 987 | mvebu_pcie_set_local_dev_nr(port, 1); |
956 | 988 | ||
957 | port->clk = of_clk_get_by_name(child, NULL); | ||
958 | if (IS_ERR(port->clk)) { | ||
959 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | ||
960 | port->port, port->lane); | ||
961 | iounmap(port->base); | ||
962 | continue; | ||
963 | } | ||
964 | |||
965 | port->dn = child; | 989 | port->dn = child; |
966 | spin_lock_init(&port->conf_lock); | 990 | spin_lock_init(&port->conf_lock); |
967 | mvebu_sw_pci_bridge_init(port); | 991 | mvebu_sw_pci_bridge_init(port); |