diff options
author | Olof Johansson <olof@lixom.net> | 2013-08-16 02:10:31 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-08-16 02:10:31 -0400 |
commit | f668adebf43556df9834f254479a44a20294dcf1 (patch) | |
tree | 1db70c6f513da3c4c2fdc0341ef0d8ffdffa07f5 /drivers/pci/host | |
parent | fac2e57742d9aa3dbe41860280352efda9d5566e (diff) | |
parent | a0cec7867ffdf5d153d29b3a8243911ea8dfd366 (diff) |
Merge tag 'drivers-3.12' of git://git.infradead.org/linux-mvebu into next/soc
From Jason Cooper:
mvebu drivers changes for v3.12
- MBus devicetree bindings
- devbus update for address decoding window, cleanup
* tag 'drivers-3.12' of git://git.infradead.org/linux-mvebu: (35 commits)
memory: mvebu-devbus: Remove unused variable
ARM: mvebu: Relocate PCIe node in Armada 370 RD board
ARM: mvebu: Fix AXP-WiFi-AP DT for MBUS DT binding
ARM: mvebu: add support for the AXP WiFi AP board
ARM: mvebu: use dts pre-processor for mv78230
PCI: mvebu: Adapt to the new device tree layout
bus: mvebu-mbus: Add devicetree binding
ARM: kirkwood: Relocate PCIe device tree nodes
ARM: kirkwood: Introduce MBUS_ID
ARM: kirkwood: Introduce MBus DT node
ARM: kirkwood: Use the preprocessor on device tree files
ARM: kirkwood: Split DT and legacy MBus initialization
ARM: mvebu: Relocate Armada 370/XP PCIe device tree nodes
ARM: mvebu: Relocate Armada 370/XP DeviceBus device tree nodes
ARM: mvebu: Add BootROM to Armada 370/XP device tree
ARM: mvebu: Add MBus to Armada 370/XP device tree
ARM: mvebu: Use the preprocessor on Armada 370/XP device tree files
ARM: mvebu: Initialize MBus using the DT binding
ARM: mvebu: Remove the harcoded BootROM window allocation
bus: mvebu-mbus: Factorize Armada 370/XP data structures
...
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/pci/host')
-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 13a633b1612e..338691b616d9 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -123,6 +123,10 @@ struct mvebu_pcie_port { | |||
123 | u32 port; | 123 | u32 port; |
124 | u32 lane; | 124 | u32 lane; |
125 | int devfn; | 125 | int devfn; |
126 | unsigned int mem_target; | ||
127 | unsigned int mem_attr; | ||
128 | unsigned int io_target; | ||
129 | unsigned int io_attr; | ||
126 | struct clk *clk; | 130 | struct clk *clk; |
127 | struct mvebu_sw_pci_bridge bridge; | 131 | struct mvebu_sw_pci_bridge bridge; |
128 | struct device_node *dn; | 132 | struct device_node *dn; |
@@ -307,10 +311,9 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
307 | (port->bridge.iolimitupper << 16)) - | 311 | (port->bridge.iolimitupper << 16)) - |
308 | iobase); | 312 | iobase); |
309 | 313 | ||
310 | mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base, | 314 | mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, |
311 | port->iowin_size, | 315 | port->iowin_base, port->iowin_size, |
312 | iobase, | 316 | iobase); |
313 | MVEBU_MBUS_PCI_IO); | ||
314 | 317 | ||
315 | pci_ioremap_io(iobase, port->iowin_base); | 318 | pci_ioremap_io(iobase, port->iowin_base); |
316 | } | 319 | } |
@@ -342,10 +345,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
342 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - | 345 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - |
343 | port->memwin_base; | 346 | port->memwin_base; |
344 | 347 | ||
345 | mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base, | 348 | mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, |
346 | port->memwin_size, | 349 | port->memwin_base, port->memwin_size); |
347 | MVEBU_MBUS_NO_REMAP, | ||
348 | MVEBU_MBUS_PCI_MEM); | ||
349 | } | 350 | } |
350 | 351 | ||
351 | /* | 352 | /* |
@@ -661,6 +662,8 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) | |||
661 | 662 | ||
662 | for (i = 0; i < pcie->nports; i++) { | 663 | for (i = 0; i < pcie->nports; i++) { |
663 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 664 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
665 | if (!port->base) | ||
666 | continue; | ||
664 | mvebu_pcie_setup_hw(port); | 667 | mvebu_pcie_setup_hw(port); |
665 | } | 668 | } |
666 | 669 | ||
@@ -755,12 +758,54 @@ mvebu_pcie_map_registers(struct platform_device *pdev, | |||
755 | return devm_request_and_ioremap(&pdev->dev, ®s); | 758 | return devm_request_and_ioremap(&pdev->dev, ®s); |
756 | } | 759 | } |
757 | 760 | ||
761 | #define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) | ||
762 | #define DT_TYPE_IO 0x1 | ||
763 | #define DT_TYPE_MEM32 0x2 | ||
764 | #define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) | ||
765 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) | ||
766 | |||
767 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | ||
768 | unsigned long type, int *tgt, int *attr) | ||
769 | { | ||
770 | const int na = 3, ns = 2; | ||
771 | const __be32 *range; | ||
772 | int rlen, nranges, rangesz, pna, i; | ||
773 | |||
774 | range = of_get_property(np, "ranges", &rlen); | ||
775 | if (!range) | ||
776 | return -EINVAL; | ||
777 | |||
778 | pna = of_n_addr_cells(np); | ||
779 | rangesz = pna + na + ns; | ||
780 | nranges = rlen / sizeof(__be32) / rangesz; | ||
781 | |||
782 | for (i = 0; i < nranges; i++) { | ||
783 | u32 flags = of_read_number(range, 1); | ||
784 | u32 slot = of_read_number(range, 2); | ||
785 | u64 cpuaddr = of_read_number(range + na, pna); | ||
786 | unsigned long rtype; | ||
787 | |||
788 | if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO) | ||
789 | rtype = IORESOURCE_IO; | ||
790 | else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) | ||
791 | rtype = IORESOURCE_MEM; | ||
792 | |||
793 | if (slot == PCI_SLOT(devfn) && type == rtype) { | ||
794 | *tgt = DT_CPUADDR_TO_TARGET(cpuaddr); | ||
795 | *attr = DT_CPUADDR_TO_ATTR(cpuaddr); | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | range += rangesz; | ||
800 | } | ||
801 | |||
802 | return -ENOENT; | ||
803 | } | ||
804 | |||
758 | static int __init mvebu_pcie_probe(struct platform_device *pdev) | 805 | static int __init mvebu_pcie_probe(struct platform_device *pdev) |
759 | { | 806 | { |
760 | struct mvebu_pcie *pcie; | 807 | struct mvebu_pcie *pcie; |
761 | struct device_node *np = pdev->dev.of_node; | 808 | struct device_node *np = pdev->dev.of_node; |
762 | struct of_pci_range range; | ||
763 | struct of_pci_range_parser parser; | ||
764 | struct device_node *child; | 809 | struct device_node *child; |
765 | int i, ret; | 810 | int i, ret; |
766 | 811 | ||
@@ -771,29 +816,25 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
771 | 816 | ||
772 | pcie->pdev = pdev; | 817 | pcie->pdev = pdev; |
773 | 818 | ||
774 | if (of_pci_range_parser_init(&parser, np)) | 819 | /* Get the PCIe memory and I/O aperture */ |
820 | mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); | ||
821 | if (resource_size(&pcie->mem) == 0) { | ||
822 | dev_err(&pdev->dev, "invalid memory aperture size\n"); | ||
775 | return -EINVAL; | 823 | return -EINVAL; |
824 | } | ||
776 | 825 | ||
777 | /* Get the I/O and memory ranges from DT */ | 826 | mvebu_mbus_get_pcie_io_aperture(&pcie->io); |
778 | for_each_of_pci_range(&parser, &range) { | 827 | if (resource_size(&pcie->io) == 0) { |
779 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; | 828 | dev_err(&pdev->dev, "invalid I/O aperture size\n"); |
780 | if (restype == IORESOURCE_IO) { | 829 | return -EINVAL; |
781 | of_pci_range_to_resource(&range, np, &pcie->io); | ||
782 | of_pci_range_to_resource(&range, np, &pcie->realio); | ||
783 | pcie->io.name = "I/O"; | ||
784 | pcie->realio.start = max_t(resource_size_t, | ||
785 | PCIBIOS_MIN_IO, | ||
786 | range.pci_addr); | ||
787 | pcie->realio.end = min_t(resource_size_t, | ||
788 | IO_SPACE_LIMIT, | ||
789 | range.pci_addr + range.size); | ||
790 | } | ||
791 | if (restype == IORESOURCE_MEM) { | ||
792 | of_pci_range_to_resource(&range, np, &pcie->mem); | ||
793 | pcie->mem.name = "MEM"; | ||
794 | } | ||
795 | } | 830 | } |
796 | 831 | ||
832 | pcie->realio.flags = pcie->io.flags; | ||
833 | pcie->realio.start = PCIBIOS_MIN_IO; | ||
834 | pcie->realio.end = min_t(resource_size_t, | ||
835 | IO_SPACE_LIMIT, | ||
836 | resource_size(&pcie->io)); | ||
837 | |||
797 | /* Get the bus range */ | 838 | /* Get the bus range */ |
798 | ret = of_pci_parse_bus_range(np, &pcie->busn); | 839 | ret = of_pci_parse_bus_range(np, &pcie->busn); |
799 | if (ret) { | 840 | if (ret) { |
@@ -841,6 +882,22 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev) | |||
841 | if (port->devfn < 0) | 882 | if (port->devfn < 0) |
842 | continue; | 883 | continue; |
843 | 884 | ||
885 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM, | ||
886 | &port->mem_target, &port->mem_attr); | ||
887 | if (ret < 0) { | ||
888 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n", | ||
889 | port->port, port->lane); | ||
890 | continue; | ||
891 | } | ||
892 | |||
893 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | ||
894 | &port->io_target, &port->io_attr); | ||
895 | if (ret < 0) { | ||
896 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", | ||
897 | port->port, port->lane); | ||
898 | continue; | ||
899 | } | ||
900 | |||
844 | port->base = mvebu_pcie_map_registers(pdev, child, port); | 901 | port->base = mvebu_pcie_map_registers(pdev, child, port); |
845 | if (!port->base) { | 902 | if (!port->base) { |
846 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", | 903 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", |