diff options
author | Hiroshi DOYU <hdoyu@nvidia.com> | 2011-11-16 11:47:51 +0200 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-02-09 12:53:53 -0800 |
commit | 1eb0ed48f5e7314afa002ae81a7016ff8e606a83 (patch) | |
tree | d8d5cab7716a309ddf76050bc5e5300bae39d4ef | |
parent | f9b820a55aa5f037a75e3adfcebb1c83c83a56e1 (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>
-rw-r--r-- | arch/arm/mach-tegra/iovmm-gart.c | 47 |
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); } |