diff options
author | Thierry Reding <treding@nvidia.com> | 2014-11-27 03:54:09 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-12-01 18:55:43 -0500 |
commit | 5106787a9e08dc2901d6b2513ed8f377671befa8 (patch) | |
tree | 0e41d4b0ad8d4291f72924add8c7eac3cf472d83 | |
parent | 7fc986d8a9727e5d40da3c2c1c343da6142e82a9 (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.c | 28 |
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) | |||
786 | static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) | 784 | static 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: |