diff options
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 94294123e7bd..abd560e46757 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); |
@@ -314,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
314 | return; | 319 | return; |
315 | } | 320 | } |
316 | 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 | |||
317 | /* | 328 | /* |
318 | * We read the PCI-to-PCI bridge emulated registers, and | 329 | * We read the PCI-to-PCI bridge emulated registers, and |
319 | * calculate the base address and size of the address decoding | 330 | * calculate the base address and size of the address decoding |
@@ -428,9 +439,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, | |||
428 | break; | 439 | break; |
429 | 440 | ||
430 | case PCI_IO_BASE: | 441 | case PCI_IO_BASE: |
431 | *value = (bridge->secondary_status << 16 | | 442 | if (!mvebu_has_ioport(port)) |
432 | bridge->iolimit << 8 | | 443 | *value = bridge->secondary_status << 16; |
433 | bridge->iobase); | 444 | else |
445 | *value = (bridge->secondary_status << 16 | | ||
446 | bridge->iolimit << 8 | | ||
447 | bridge->iobase); | ||
434 | break; | 448 | break; |
435 | 449 | ||
436 | case PCI_MEMORY_BASE: | 450 | case PCI_MEMORY_BASE: |
@@ -490,6 +504,9 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, | |||
490 | { | 504 | { |
491 | u32 old = bridge->command; | 505 | u32 old = bridge->command; |
492 | 506 | ||
507 | if (!mvebu_has_ioport(port)) | ||
508 | value &= ~PCI_COMMAND_IO; | ||
509 | |||
493 | bridge->command = value & 0xffff; | 510 | bridge->command = value & 0xffff; |
494 | if ((old ^ bridge->command) & PCI_COMMAND_IO) | 511 | if ((old ^ bridge->command) & PCI_COMMAND_IO) |
495 | mvebu_pcie_handle_iobase_change(port); | 512 | mvebu_pcie_handle_iobase_change(port); |
@@ -660,7 +677,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
660 | struct mvebu_pcie *pcie = sys_to_pcie(sys); | 677 | struct mvebu_pcie *pcie = sys_to_pcie(sys); |
661 | int i; | 678 | int i; |
662 | 679 | ||
663 | pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset); | 680 | if (resource_size(&pcie->realio) != 0) |
681 | pci_add_resource_offset(&sys->resources, &pcie->realio, | ||
682 | sys->io_offset); | ||
664 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); | 683 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); |
665 | pci_add_resource(&sys->resources, &pcie->busn); | 684 | pci_add_resource(&sys->resources, &pcie->busn); |
666 | 685 | ||
@@ -761,12 +780,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, | |||
761 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) | 780 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) |
762 | 781 | ||
763 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | 782 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, |
764 | unsigned long type, int *tgt, int *attr) | 783 | unsigned long type, |
784 | unsigned int *tgt, | ||
785 | unsigned int *attr) | ||
765 | { | 786 | { |
766 | const int na = 3, ns = 2; | 787 | const int na = 3, ns = 2; |
767 | const __be32 *range; | 788 | const __be32 *range; |
768 | int rlen, nranges, rangesz, pna, i; | 789 | int rlen, nranges, rangesz, pna, i; |
769 | 790 | ||
791 | *tgt = -1; | ||
792 | *attr = -1; | ||
793 | |||
770 | range = of_get_property(np, "ranges", &rlen); | 794 | range = of_get_property(np, "ranges", &rlen); |
771 | if (!range) | 795 | if (!range) |
772 | return -EINVAL; | 796 | return -EINVAL; |
@@ -836,16 +860,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
836 | } | 860 | } |
837 | 861 | ||
838 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); | 862 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
839 | if (resource_size(&pcie->io) == 0) { | ||
840 | dev_err(&pdev->dev, "invalid I/O aperture size\n"); | ||
841 | return -EINVAL; | ||
842 | } | ||
843 | 863 | ||
844 | pcie->realio.flags = pcie->io.flags; | 864 | if (resource_size(&pcie->io) != 0) { |
845 | pcie->realio.start = PCIBIOS_MIN_IO; | 865 | pcie->realio.flags = pcie->io.flags; |
846 | pcie->realio.end = min_t(resource_size_t, | 866 | pcie->realio.start = PCIBIOS_MIN_IO; |
847 | IO_SPACE_LIMIT, | 867 | pcie->realio.end = min_t(resource_size_t, |
848 | resource_size(&pcie->io)); | 868 | IO_SPACE_LIMIT, |
869 | resource_size(&pcie->io)); | ||
870 | } else | ||
871 | pcie->realio = pcie->io; | ||
849 | 872 | ||
850 | /* Get the bus range */ | 873 | /* Get the bus range */ |
851 | ret = of_pci_parse_bus_range(np, &pcie->busn); | 874 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
@@ -904,12 +927,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
904 | continue; | 927 | continue; |
905 | } | 928 | } |
906 | 929 | ||
907 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | 930 | if (resource_size(&pcie->io) != 0) |
908 | &port->io_target, &port->io_attr); | 931 | mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, |
909 | if (ret < 0) { | 932 | &port->io_target, &port->io_attr); |
910 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", | 933 | else { |
911 | port->port, port->lane); | 934 | port->io_target = -1; |
912 | continue; | 935 | port->io_attr = -1; |
913 | } | 936 | } |
914 | 937 | ||
915 | port->reset_gpio = of_get_named_gpio_flags(child, | 938 | port->reset_gpio = of_get_named_gpio_flags(child, |