summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/iovmm-gart.c
diff options
context:
space:
mode:
authorHiroshi DOYU <hdoyu@nvidia.com>2011-11-16 11:47:51 +0200
committerSimone Willett <swillett@nvidia.com>2012-02-09 12:53:53 -0800
commit1eb0ed48f5e7314afa002ae81a7016ff8e606a83 (patch)
treed8d5cab7716a309ddf76050bc5e5300bae39d4ef /arch/arm/mach-tegra/iovmm-gart.c
parentf9b820a55aa5f037a75e3adfcebb1c83c83a56e1 (diff)
ARM: tegra: gart: Replace memory barrier with register read-back
Any interaction between any block on PPSB and a block on APB or AHB must have these read-back to ensure the APB/AHB bus transaction is complete before initiating activity on the PPSB block. wmb() won't ensure the above transaction but only register read-back does. So now there's not much benefit ioremap_wc() + wmb() only for GART registers because the number of that access isn't so huge. Replaced memory barrier with register read-back, and also introduced gart_set_pte() for simplification of those register access. Signed-off-by: Hiroshi DOYU <hdoyu@nvidia.com> Reviewed-on: http://git-master/r/66358 (cherry picked from commit 4c68b93498ee4912e5f98ddb25d4511107d4d35a) Change-Id: I9e847624f7321bb36c1209340ff6e12b66f7e792 Signed-off-by: Pritesh Raithatha <praithatha@nvidia.com> Reviewed-on: http://git-master/r/79987 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/iovmm-gart.c')
-rw-r--r--arch/arm/mach-tegra/iovmm-gart.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/arch/arm/mach-tegra/iovmm-gart.c b/arch/arm/mach-tegra/iovmm-gart.c
index 9616af6672a1..fa4534d0167b 100644
--- a/arch/arm/mach-tegra/iovmm-gart.c
+++ b/arch/arm/mach-tegra/iovmm-gart.c
@@ -4,7 +4,7 @@
* Tegra I/O VMM implementation for GART devices in Tegra and Tegra 2 series
* systems-on-a-chip.
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,6 +54,20 @@ struct gart_device {
bool enable;
};
+/*
+ * Any interaction between any block on PPSB and a block on APB or AHB
+ * must have these read-back to ensure the APB/AHB bus transaction is
+ * complete before initiating activity on the PPSB block.
+ */
+#define FLUSH_GART_REGS(gart) (void)readl((gart)->regs + GART_CONFIG)
+
+static inline void gart_set_pte(struct gart_device *gart,
+ tegra_iovmm_addr_t offs, u32 pte)
+{
+ writel(offs, gart->regs + GART_ENTRY_ADDR);
+ writel(pte, gart->regs + GART_ENTRY_DATA);
+}
+
static int gart_map(struct tegra_iovmm_domain *, struct tegra_iovmm_area *);
static void gart_unmap(struct tegra_iovmm_domain *,
struct tegra_iovmm_area *, bool);
@@ -102,7 +116,6 @@ static int gart_suspend(struct tegra_iovmm_device *dev)
for (i = 0; i < gart->page_count; i++) {
writel(reg, gart->regs + GART_ENTRY_ADDR);
gart->savedata[i] = readl(gart->regs + GART_ENTRY_DATA);
- dmb();
reg += 1 << GART_PAGE_SHIFT;
}
spin_unlock(&gart->pte_lock);
@@ -118,11 +131,10 @@ static void do_gart_setup(struct gart_device *gart, const u32 *data)
reg = gart->iovmm_base;
for (i = 0; i < gart->page_count; i++) {
- writel(reg, gart->regs + GART_ENTRY_ADDR);
- writel((data) ? data[i] : 0, gart->regs + GART_ENTRY_DATA);
- wmb();
+ gart_set_pte(gart, reg, data ? data[i] : 0);
reg += 1 << GART_PAGE_SHIFT;
}
+ FLUSH_GART_REGS(gart);
}
static void gart_resume(struct tegra_iovmm_device *dev)
@@ -189,7 +201,7 @@ static int gart_probe(struct platform_device *pdev)
return -ENOMEM;
}
- gart_regs = ioremap_wc(res->start, res->end - res->start + 1);
+ gart_regs = ioremap(res->start, res->end - res->start + 1);
if (!gart_regs) {
pr_err(DRIVER_NAME ": failed to remap GART registers\n");
e = -ENXIO;
@@ -249,7 +261,7 @@ static void __exit gart_exit(void)
platform_driver_unregister(&tegra_iovmm_gart_drv);
}
-#define GART_PTE(_pfn) (0x80000000ul | ((_pfn)<<PAGE_SHIFT))
+#define GART_PTE(_pfn) (0x80000000ul | ((_pfn) << PAGE_SHIFT))
static int gart_map(struct tegra_iovmm_domain *domain,
@@ -272,11 +284,9 @@ static int gart_map(struct tegra_iovmm_domain *domain,
spin_lock(&gart->pte_lock);
- writel(gart_page, gart->regs + GART_ENTRY_ADDR);
- writel(GART_PTE(pfn), gart->regs + GART_ENTRY_DATA);
- wmb();
+ gart_set_pte(gart, gart_page, GART_PTE(pfn));
+ FLUSH_GART_REGS(gart);
gart_page += 1 << GART_PAGE_SHIFT;
-
spin_unlock(&gart->pte_lock);
}
@@ -287,10 +297,9 @@ fail:
while (i--) {
iovma->ops->release(iovma, i << PAGE_SHIFT);
gart_page -= 1 << GART_PAGE_SHIFT;
- writel(gart_page, gart->regs + GART_ENTRY_ADDR);
- writel(0, gart->regs + GART_ENTRY_DATA);
- wmb();
+ gart_set_pte(gart, gart_page, 0);
}
+ FLUSH_GART_REGS(gart);
spin_unlock(&gart->pte_lock);
return -ENOMEM;
@@ -312,11 +321,10 @@ static void gart_unmap(struct tegra_iovmm_domain *domain,
if (iovma->ops && iovma->ops->release)
iovma->ops->release(iovma, i << PAGE_SHIFT);
- writel(gart_page, gart->regs + GART_ENTRY_ADDR);
- writel(0, gart->regs + GART_ENTRY_DATA);
- wmb();
+ gart_set_pte(gart, gart_page, 0);
gart_page += 1 << GART_PAGE_SHIFT;
}
+ FLUSH_GART_REGS(gart);
spin_unlock(&gart->pte_lock);
}
@@ -329,9 +337,8 @@ static void gart_map_pfn(struct tegra_iovmm_domain *domain,
BUG_ON(!pfn_valid(pfn));
spin_lock(&gart->pte_lock);
- writel(offs, gart->regs + GART_ENTRY_ADDR);
- writel(GART_PTE(pfn), gart->regs + GART_ENTRY_DATA);
- wmb();
+ gart_set_pte(gart, offs, GART_PTE(pfn));
+ FLUSH_GART_REGS(gart);
spin_unlock(&gart->pte_lock);
}