diff options
author | Thierry Reding <treding@nvidia.com> | 2016-02-09 15:52:32 +0100 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-03-08 15:42:07 -0600 |
commit | 56e75e2a15d0b28261503d415eb56bb4c2b92be5 (patch) | |
tree | c390e95da41ae6927f05d3448f4ce5690ba7d9cd | |
parent | 8493a952432bf00138b3d3c53a9300e353c18a6d (diff) |
PCI: tegra: Track bus -> CPU mapping
Track the offsets of the bus -> CPU mapping for I/O and memory. This is
cosmetic for current Tegra chips because the offset is always 0. But to
properly support legacy use-cases, like VGA, this would be needed so that
PCI bus addresses can be relocated.
While at it, also request the I/O resource both in physical memory and I/O
space to make /proc/iomem consistent, as well as add the I/O region to the
list of host bridge resources.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 0ca1dae16603..7bda73bf7c5e 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -281,6 +281,11 @@ struct tegra_pcie { struct resource prefetch; struct resource busn; + struct { + resource_size_t mem; + resource_size_t io; + } offset; + struct clk *pex_clk; struct clk *afi_clk; struct clk *pll_e; @@ -611,6 +616,17 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) struct tegra_pcie *pcie = sys_to_pcie(sys); int err; + sys->mem_offset = pcie->offset.mem; + sys->io_offset = pcie->offset.io; + + err = devm_request_resource(pcie->dev, &pcie->all, &pcie->io); + if (err < 0) + return err; + + err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio); + if (err < 0) + return err; + err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem); if (err < 0) return err; @@ -619,6 +635,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) if (err) return err; + pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); pci_add_resource_offset(&sys->resources, &pcie->prefetch, sys->mem_offset); @@ -1614,6 +1631,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) switch (res.flags & IORESOURCE_TYPE_BITS) { case IORESOURCE_IO: + /* Track the bus -> CPU I/O mapping offset. */ + pcie->offset.io = res.start - range.pci_addr; + memcpy(&pcie->pio, &res, sizeof(res)); pcie->pio.name = np->full_name; @@ -1634,6 +1654,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) break; case IORESOURCE_MEM: + /* + * Track the bus -> CPU memory mapping offset. This + * assumes that the prefetchable and non-prefetchable + * regions will be the last of type IORESOURCE_MEM in + * the ranges property. + * */ + pcie->offset.mem = res.start - range.pci_addr; + if (res.flags & IORESOURCE_PREFETCH) { memcpy(&pcie->prefetch, &res, sizeof(res)); pcie->prefetch.name = "prefetchable"; |