aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2013-11-26 13:02:55 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-11-26 13:36:32 -0500
commit641e674d6c0f974162c4c8cc0081c7ffc50b3911 (patch)
treef890659bf71b35ede986cff364b75f2c8c221680 /drivers
parent43a16f94445310800e39d54aaa534f2ce7dbe0a2 (diff)
PCI: mvebu: Support a bridge with no IO port window
Make pcie-io-aperture and the IO port MBUS ID in ranges optional. If not provided the bridge reports to Linux that IO space mapping is not supported and refuses to configure an IO MBUS window. This allows both complete disable (do not specify pcie-io-aperture) and per-port disable (do not specify a IO target ranges entry for the port). Most PCIe devices these days do not require IO support to function, so having an option to disable it in the driver is useful. Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/host/pci-mvebu.c63
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
153static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port)
154{
155 return port->io_target != -1 && port->io_attr != -1;
156}
157
153static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port) 158static 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
763static int mvebu_get_tgt_attr(struct device_node *np, int devfn, 782static 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,