From 1eb0ed48f5e7314afa002ae81a7016ff8e606a83 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Wed, 16 Nov 2011 11:47:51 +0200 Subject: 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 Reviewed-on: http://git-master/r/66358 (cherry picked from commit 4c68b93498ee4912e5f98ddb25d4511107d4d35a) Change-Id: I9e847624f7321bb36c1209340ff6e12b66f7e792 Signed-off-by: Pritesh Raithatha Reviewed-on: http://git-master/r/79987 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- arch/arm/mach-tegra/iovmm-gart.c | 47 +++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'arch/arm/mach-tegra/iovmm-gart.c') 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)<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); } -- cgit v1.2.3