diff options
Diffstat (limited to 'target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch')
-rw-r--r-- | target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch b/target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch new file mode 100644 index 0000000000..08de63d422 --- /dev/null +++ b/target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch @@ -0,0 +1,184 @@ +From 90b1f963b07d05e8243e5053a910e8a47222f7a1 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +Date: Fri, 5 Jul 2013 14:54:17 +0200 +Subject: [PATCH 047/203] PCI: mvebu: Adapt to the new device tree layout + +The new device tree layout encodes the window's target ID and attribute +in the PCIe controller node's ranges property. This allows to parse +such entries to obtain such information and use the recently introduced +MBus API to create the windows, instead of using the current name based +scheme. + +Acked-by: Bjorn Helgaas <bhelgaas@google.com> +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +Tested-by: Andrew Lunn <andrew@lunn.ch> +Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> +--- + drivers/pci/host/pci-mvebu.c | 113 ++++++++++++++++++++++++++++++++----------- + 1 file changed, 84 insertions(+), 29 deletions(-) + +--- a/drivers/pci/host/pci-mvebu.c ++++ b/drivers/pci/host/pci-mvebu.c +@@ -119,6 +119,10 @@ struct mvebu_pcie_port { + u32 port; + u32 lane; + int devfn; ++ unsigned int mem_target; ++ unsigned int mem_attr; ++ unsigned int io_target; ++ unsigned int io_attr; + struct clk *clk; + struct mvebu_sw_pci_bridge bridge; + struct device_node *dn; +@@ -303,10 +307,9 @@ static void mvebu_pcie_handle_iobase_cha + (port->bridge.iolimitupper << 16)) - + iobase); + +- mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base, +- port->iowin_size, +- iobase, +- MVEBU_MBUS_PCI_IO); ++ mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, ++ port->iowin_base, port->iowin_size, ++ iobase); + + pci_ioremap_io(iobase, port->iowin_base); + } +@@ -338,10 +341,8 @@ static void mvebu_pcie_handle_membase_ch + (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - + port->memwin_base; + +- mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base, +- port->memwin_size, +- MVEBU_MBUS_NO_REMAP, +- MVEBU_MBUS_PCI_MEM); ++ mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, ++ port->memwin_base, port->memwin_size); + } + + /* +@@ -730,12 +731,54 @@ mvebu_pcie_map_registers(struct platform + return devm_request_and_ioremap(&pdev->dev, ®s); + } + ++#define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) ++#define DT_TYPE_IO 0x1 ++#define DT_TYPE_MEM32 0x2 ++#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) ++#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) ++ ++static int mvebu_get_tgt_attr(struct device_node *np, int devfn, ++ unsigned long type, int *tgt, int *attr) ++{ ++ const int na = 3, ns = 2; ++ const __be32 *range; ++ int rlen, nranges, rangesz, pna, i; ++ ++ range = of_get_property(np, "ranges", &rlen); ++ if (!range) ++ return -EINVAL; ++ ++ pna = of_n_addr_cells(np); ++ rangesz = pna + na + ns; ++ nranges = rlen / sizeof(__be32) / rangesz; ++ ++ for (i = 0; i < nranges; i++) { ++ u32 flags = of_read_number(range, 1); ++ u32 slot = of_read_number(range, 2); ++ u64 cpuaddr = of_read_number(range + na, pna); ++ unsigned long rtype; ++ ++ if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO) ++ rtype = IORESOURCE_IO; ++ else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) ++ rtype = IORESOURCE_MEM; ++ ++ if (slot == PCI_SLOT(devfn) && type == rtype) { ++ *tgt = DT_CPUADDR_TO_TARGET(cpuaddr); ++ *attr = DT_CPUADDR_TO_ATTR(cpuaddr); ++ return 0; ++ } ++ ++ range += rangesz; ++ } ++ ++ return -ENOENT; ++} ++ + static int __init mvebu_pcie_probe(struct platform_device *pdev) + { + struct mvebu_pcie *pcie; + struct device_node *np = pdev->dev.of_node; +- struct of_pci_range range; +- struct of_pci_range_parser parser; + struct device_node *child; + int i, ret; + +@@ -746,29 +789,25 @@ static int __init mvebu_pcie_probe(struc + + pcie->pdev = pdev; + +- if (of_pci_range_parser_init(&parser, np)) ++ /* Get the PCIe memory and I/O aperture */ ++ mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); ++ if (resource_size(&pcie->mem) == 0) { ++ dev_err(&pdev->dev, "invalid memory aperture size\n"); + return -EINVAL; ++ } + +- /* Get the I/O and memory ranges from DT */ +- for_each_of_pci_range(&parser, &range) { +- unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; +- if (restype == IORESOURCE_IO) { +- of_pci_range_to_resource(&range, np, &pcie->io); +- of_pci_range_to_resource(&range, np, &pcie->realio); +- pcie->io.name = "I/O"; +- pcie->realio.start = max_t(resource_size_t, +- PCIBIOS_MIN_IO, +- range.pci_addr); +- pcie->realio.end = min_t(resource_size_t, +- IO_SPACE_LIMIT, +- range.pci_addr + range.size); +- } +- if (restype == IORESOURCE_MEM) { +- of_pci_range_to_resource(&range, np, &pcie->mem); +- pcie->mem.name = "MEM"; +- } ++ mvebu_mbus_get_pcie_io_aperture(&pcie->io); ++ if (resource_size(&pcie->io) == 0) { ++ dev_err(&pdev->dev, "invalid I/O aperture size\n"); ++ return -EINVAL; + } + ++ pcie->realio.flags = pcie->io.flags; ++ pcie->realio.start = PCIBIOS_MIN_IO; ++ pcie->realio.end = min_t(resource_size_t, ++ IO_SPACE_LIMIT, ++ resource_size(&pcie->io)); ++ + /* Get the bus range */ + ret = of_pci_parse_bus_range(np, &pcie->busn); + if (ret) { +@@ -816,6 +855,22 @@ static int __init mvebu_pcie_probe(struc + if (port->devfn < 0) + continue; + ++ ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM, ++ &port->mem_target, &port->mem_attr); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n", ++ port->port, port->lane); ++ continue; ++ } ++ ++ ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, ++ &port->io_target, &port->io_attr); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", ++ port->port, port->lane); ++ continue; ++ } ++ + port->base = mvebu_pcie_map_registers(pdev, child, port); + if (!port->base) { + dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", |