diff options
Diffstat (limited to 'drivers/pci/host/pci-mvebu.c')
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 115 |
1 files changed, 86 insertions, 29 deletions
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index ce1543a584a3..729d5a101d62 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -119,6 +119,10 @@ struct mvebu_pcie_port { | |||
119 | u32 port; | 119 | u32 port; |
120 | u32 lane; | 120 | u32 lane; |
121 | int devfn; | 121 | int devfn; |
122 | unsigned int mem_target; | ||
123 | unsigned int mem_attr; | ||
124 | unsigned int io_target; | ||
125 | unsigned int io_attr; | ||
122 | struct clk *clk; | 126 | struct clk *clk; |
123 | struct mvebu_sw_pci_bridge bridge; | 127 | struct mvebu_sw_pci_bridge bridge; |
124 | struct device_node *dn; | 128 | struct device_node *dn; |
@@ -303,10 +307,9 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
303 | (port->bridge.iolimitupper << 16)) - | 307 | (port->bridge.iolimitupper << 16)) - |
304 | iobase); | 308 | iobase); |
305 | 309 | ||
306 | mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base, | 310 | mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, |
307 | port->iowin_size, | 311 | port->iowin_base, port->iowin_size, |
308 | iobase, | 312 | iobase); |
309 | MVEBU_MBUS_PCI_IO); | ||
310 | 313 | ||
311 | pci_ioremap_io(iobase, port->iowin_base); | 314 | pci_ioremap_io(iobase, port->iowin_base); |
312 | } | 315 | } |
@@ -338,10 +341,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
338 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - | 341 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - |
339 | port->memwin_base; | 342 | port->memwin_base; |
340 | 343 | ||
341 | mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base, | 344 | mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, |
342 | port->memwin_size, | 345 | port->memwin_base, port->memwin_size); |
343 | MVEBU_MBUS_NO_REMAP, | ||
344 | MVEBU_MBUS_PCI_MEM); | ||
345 | } | 346 | } |
346 | 347 | ||
347 | /* | 348 | /* |
@@ -636,6 +637,8 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
636 | 637 | ||
637 | for (i = 0; i < pcie->nports; i++) { | 638 | for (i = 0; i < pcie->nports; i++) { |
638 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 639 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
640 | if (!port->base) | ||
641 | continue; | ||
639 | mvebu_pcie_setup_hw(port); | 642 | mvebu_pcie_setup_hw(port); |
640 | } | 643 | } |
641 | 644 | ||
@@ -730,12 +733,54 @@ mvebu_pcie_map_registers(struct platform_device *pdev, | |||
730 | return devm_ioremap_resource(&pdev->dev, ®s); | 733 | return devm_ioremap_resource(&pdev->dev, ®s); |
731 | } | 734 | } |
732 | 735 | ||
736 | #define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) | ||
737 | #define DT_TYPE_IO 0x1 | ||
738 | #define DT_TYPE_MEM32 0x2 | ||
739 | #define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) | ||
740 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) | ||
741 | |||
742 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | ||
743 | unsigned long type, int *tgt, int *attr) | ||
744 | { | ||
745 | const int na = 3, ns = 2; | ||
746 | const __be32 *range; | ||
747 | int rlen, nranges, rangesz, pna, i; | ||
748 | |||
749 | range = of_get_property(np, "ranges", &rlen); | ||
750 | if (!range) | ||
751 | return -EINVAL; | ||
752 | |||
753 | pna = of_n_addr_cells(np); | ||
754 | rangesz = pna + na + ns; | ||
755 | nranges = rlen / sizeof(__be32) / rangesz; | ||
756 | |||
757 | for (i = 0; i < nranges; i++) { | ||
758 | u32 flags = of_read_number(range, 1); | ||
759 | u32 slot = of_read_number(range, 2); | ||
760 | u64 cpuaddr = of_read_number(range + na, pna); | ||
761 | unsigned long rtype; | ||
762 | |||
763 | if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO) | ||
764 | rtype = IORESOURCE_IO; | ||
765 | else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) | ||
766 | rtype = IORESOURCE_MEM; | ||
767 | |||
768 | if (slot == PCI_SLOT(devfn) && type == rtype) { | ||
769 | *tgt = DT_CPUADDR_TO_TARGET(cpuaddr); | ||
770 | *attr = DT_CPUADDR_TO_ATTR(cpuaddr); | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | range += rangesz; | ||
775 | } | ||
776 | |||
777 | return -ENOENT; | ||
778 | } | ||
779 | |||
733 | static int __init mvebu_pcie_probe(struct platform_device *pdev) | 780 | static int __init mvebu_pcie_probe(struct platform_device *pdev) |
734 | { | 781 | { |
735 | struct mvebu_pcie *pcie; | 782 | struct mvebu_pcie *pcie; |
736 | struct device_node *np = pdev->dev.of_node; | 783 | struct device_node *np = pdev->dev.of_node; |
737 | struct of_pci_range range; | ||
738 | struct of_pci_range_parser parser; | ||
739 | struct device_node *child; | 784 | struct device_node *child; |
740 | int i, ret; | 785 | int i, ret; |
741 | 786 | ||
@@ -746,29 +791,25 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
746 | 791 | ||
747 | pcie->pdev = pdev; | 792 | pcie->pdev = pdev; |
748 | 793 | ||
749 | if (of_pci_range_parser_init(&parser, np)) | 794 | /* Get the PCIe memory and I/O aperture */ |
795 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | ||
796 | if (resource_size(&pcie->mem) == 0) { | ||
797 | dev_err(&pdev->dev, "invalid memory aperture size\n"); | ||
750 | return -EINVAL; | 798 | return -EINVAL; |
799 | } | ||
751 | 800 | ||
752 | /* Get the I/O and memory ranges from DT */ | 801 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
753 | for_each_of_pci_range(&parser, &range) { | 802 | if (resource_size(&pcie->io) == 0) { |
754 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; | 803 | dev_err(&pdev->dev, "invalid I/O aperture size\n"); |
755 | if (restype == IORESOURCE_IO) { | 804 | return -EINVAL; |
756 | of_pci_range_to_resource(&range, np, &pcie->io); | ||
757 | of_pci_range_to_resource(&range, np, &pcie->realio); | ||
758 | pcie->io.name = "I/O"; | ||
759 | pcie->realio.start = max_t(resource_size_t, | ||
760 | PCIBIOS_MIN_IO, | ||
761 | range.pci_addr); | ||
762 | pcie->realio.end = min_t(resource_size_t, | ||
763 | IO_SPACE_LIMIT, | ||
764 | range.pci_addr + range.size); | ||
765 | } | ||
766 | if (restype == IORESOURCE_MEM) { | ||
767 | of_pci_range_to_resource(&range, np, &pcie->mem); | ||
768 | pcie->mem.name = "MEM"; | ||
769 | } | ||
770 | } | 805 | } |
771 | 806 | ||
807 | pcie->realio.flags = pcie->io.flags; | ||
808 | pcie->realio.start = PCIBIOS_MIN_IO; | ||
809 | pcie->realio.end = min_t(resource_size_t, | ||
810 | IO_SPACE_LIMIT, | ||
811 | resource_size(&pcie->io)); | ||
812 | |||
772 | /* Get the bus range */ | 813 | /* Get the bus range */ |
773 | ret = of_pci_parse_bus_range(np, &pcie->busn); | 814 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
774 | if (ret) { | 815 | if (ret) { |
@@ -816,6 +857,22 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
816 | if (port->devfn < 0) | 857 | if (port->devfn < 0) |
817 | continue; | 858 | continue; |
818 | 859 | ||
860 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM, | ||
861 | &port->mem_target, &port->mem_attr); | ||
862 | if (ret < 0) { | ||
863 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n", | ||
864 | port->port, port->lane); | ||
865 | continue; | ||
866 | } | ||
867 | |||
868 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | ||
869 | &port->io_target, &port->io_attr); | ||
870 | if (ret < 0) { | ||
871 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", | ||
872 | port->port, port->lane); | ||
873 | continue; | ||
874 | } | ||
875 | |||
819 | port->base = mvebu_pcie_map_registers(pdev, child, port); | 876 | port->base = mvebu_pcie_map_registers(pdev, child, port); |
820 | if (IS_ERR(port->base)) { | 877 | if (IS_ERR(port->base)) { |
821 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", | 878 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", |