summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2016-02-09 15:52:32 +0100
committerBjorn Helgaas <bhelgaas@google.com>2016-03-08 15:42:07 -0600
commit56e75e2a15d0b28261503d415eb56bb4c2b92be5 (patch)
treec390e95da41ae6927f05d3448f4ce5690ba7d9cd /drivers
parent8493a952432bf00138b3d3c53a9300e353c18a6d (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/host/pci-tegra.c28
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";