aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-11-27 03:54:09 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-12-01 18:55:43 -0500
commit5106787a9e08dc2901d6b2513ed8f377671befa8 (patch)
tree0e41d4b0ad8d4291f72924add8c7eac3cf472d83
parent7fc986d8a9727e5d40da3c2c1c343da6142e82a9 (diff)
PCI: tegra: Use physical range for I/O mapping
Commit 0b0b0893d49b ("of/pci: Fix the conversion of IO ranges into IO resources") changed how I/O resources are parsed from DT. Rather than containing the physical address of the I/O region, the addresses will now be in I/O address space. On Tegra the union of all ranges is used to expose a top-level memory- mapped resource for the PCI host bridge. This helps to make /proc/iomem more readable. Combining both of the above, the union would now include the I/O space region. This causes a regression on Tegra20, where the physical base address of the PCIe controller (and therefore of the union) is located at physical address 0x80000000. Since I/O space starts at 0, the union will now include all of system RAM which starts at 0x00000000. This commit fixes this by keeping two copies of the I/O range: one that represents the range in the CPU's physical address space, the other for the range in the I/O address space. This allows the translation setup within the driver to reuse the physical addresses. The code registering the I/O region with the PCI core uses both ranges to establish the mapping. Fixes: 0b0b0893d49b ("of/pci: Fix the conversion of IO ranges into IO resources") Reported-by: Marc Zyngier <marc.zyngier@arm.com> Tested-by: Marc Zyngier <marc.zyngier@arm.com> Suggested-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--drivers/pci/host/pci-tegra.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 3d43874319be..19bb19c7db4a 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -276,6 +276,7 @@ struct tegra_pcie {
276 276
277 struct resource all; 277 struct resource all;
278 struct resource io; 278 struct resource io;
279 struct resource pio;
279 struct resource mem; 280 struct resource mem;
280 struct resource prefetch; 281 struct resource prefetch;
281 struct resource busn; 282 struct resource busn;
@@ -658,7 +659,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
658{ 659{
659 struct tegra_pcie *pcie = sys_to_pcie(sys); 660 struct tegra_pcie *pcie = sys_to_pcie(sys);
660 int err; 661 int err;
661 phys_addr_t io_start;
662 662
663 err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem); 663 err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
664 if (err < 0) 664 if (err < 0)
@@ -668,14 +668,12 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
668 if (err) 668 if (err)
669 return err; 669 return err;
670 670
671 io_start = pci_pio_to_address(pcie->io.start);
672
673 pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); 671 pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
674 pci_add_resource_offset(&sys->resources, &pcie->prefetch, 672 pci_add_resource_offset(&sys->resources, &pcie->prefetch,
675 sys->mem_offset); 673 sys->mem_offset);
676 pci_add_resource(&sys->resources, &pcie->busn); 674 pci_add_resource(&sys->resources, &pcie->busn);
677 675
678 pci_ioremap_io(nr * SZ_64K, io_start); 676 pci_ioremap_io(pcie->pio.start, pcie->io.start);
679 677
680 return 1; 678 return 1;
681} 679}
@@ -786,7 +784,6 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
786static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) 784static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
787{ 785{
788 u32 fpci_bar, size, axi_address; 786 u32 fpci_bar, size, axi_address;
789 phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
790 787
791 /* Bar 0: type 1 extended configuration space */ 788 /* Bar 0: type 1 extended configuration space */
792 fpci_bar = 0xfe100000; 789 fpci_bar = 0xfe100000;
@@ -799,7 +796,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
799 /* Bar 1: downstream IO bar */ 796 /* Bar 1: downstream IO bar */
800 fpci_bar = 0xfdfc0000; 797 fpci_bar = 0xfdfc0000;
801 size = resource_size(&pcie->io); 798 size = resource_size(&pcie->io);
802 axi_address = io_start; 799 axi_address = pcie->io.start;
803 afi_writel(pcie, axi_address, AFI_AXI_BAR1_START); 800 afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
804 afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); 801 afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
805 afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1); 802 afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
@@ -1690,8 +1687,23 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
1690 1687
1691 switch (res.flags & IORESOURCE_TYPE_BITS) { 1688 switch (res.flags & IORESOURCE_TYPE_BITS) {
1692 case IORESOURCE_IO: 1689 case IORESOURCE_IO:
1693 memcpy(&pcie->io, &res, sizeof(res)); 1690 memcpy(&pcie->pio, &res, sizeof(res));
1694 pcie->io.name = np->full_name; 1691 pcie->pio.name = np->full_name;
1692
1693 /*
1694 * The Tegra PCIe host bridge uses this to program the
1695 * mapping of the I/O space to the physical address,
1696 * so we override the .start and .end fields here that
1697 * of_pci_range_to_resource() converted to I/O space.
1698 * We also set the IORESOURCE_MEM type to clarify that
1699 * the resource is in the physical memory space.
1700 */
1701 pcie->io.start = range.cpu_addr;
1702 pcie->io.end = range.cpu_addr + range.size - 1;
1703 pcie->io.flags = IORESOURCE_MEM;
1704 pcie->io.name = "I/O";
1705
1706 memcpy(&res, &pcie->io, sizeof(res));
1695 break; 1707 break;
1696 1708
1697 case IORESOURCE_MEM: 1709 case IORESOURCE_MEM: