summaryrefslogtreecommitdiff
path: root/drivers/iommu/tegra-smmu.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-07-27 13:29:36 +0100
committerThierry Reding <treding@nvidia.com>2015-08-13 16:06:40 +0200
commit4b3c7d10765403ab19628fb7d530b8ce1c50b81d (patch)
treed0dff12de7f9a34aa2b86479cc6d0180b6d7d642 /drivers/iommu/tegra-smmu.c
parent32924c76b0cbc67aa4cf0741f7bc6c37f097aaf3 (diff)
iommu/tegra-smmu: Move flush_dcache to tegra-smmu.c
Drivers should not be using __cpuc_* functions nor outer_cache_flush() directly. This change partly cleans up tegra-smmu.c. The only difference between cache handling of the tegra variants is Denver, which omits the call to outer_cache_flush(). This is due to Denver being an ARM64 CPU, and the ARM64 architecture does not provide this function. (This, in itself, is a good reason why these should not be used.) Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> [treding@nvidia.com: fix build failure on 64-bit ARM] Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r--drivers/iommu/tegra-smmu.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index d649b06cc4ca..42b13c07aeef 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -16,6 +16,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <asm/cacheflush.h>
+
#include <soc/tegra/ahb.h>
#include <soc/tegra/mc.h>
@@ -145,6 +147,24 @@ static unsigned int iova_pt_index(unsigned long iova)
return (iova >> SMMU_PTE_SHIFT) & (SMMU_NUM_PTE - 1);
}
+static void smmu_flush_dcache(struct page *page, unsigned long offset,
+ size_t size)
+{
+#ifdef CONFIG_ARM
+ phys_addr_t phys = page_to_phys(page) + offset;
+#endif
+ void *virt = page_address(page) + offset;
+
+#ifdef CONFIG_ARM
+ __cpuc_flush_dcache_area(virt, size);
+ outer_flush_range(phys, phys + size);
+#endif
+
+#ifdef CONFIG_ARM64
+ __flush_dcache_area(virt, size);
+#endif
+}
+
static inline void smmu_flush_ptc(struct tegra_smmu *smmu, struct page *page,
unsigned long offset)
{
@@ -392,7 +412,7 @@ static int tegra_smmu_as_prepare(struct tegra_smmu *smmu,
if (err < 0)
return err;
- smmu->soc->ops->flush_dcache(as->pd, 0, SMMU_SIZE_PD);
+ smmu_flush_dcache(as->pd, 0, SMMU_SIZE_PD);
smmu_flush_ptc(smmu, as->pd, 0);
smmu_flush_tlb_asid(smmu, as->id);
@@ -521,11 +541,11 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova,
as->pts[pde] = page;
- smmu->soc->ops->flush_dcache(page, 0, SMMU_SIZE_PT);
+ smmu_flush_dcache(page, 0, SMMU_SIZE_PT);
pd[pde] = SMMU_MK_PDE(page, SMMU_PDE_ATTR | SMMU_PDE_NEXT);
- smmu->soc->ops->flush_dcache(as->pd, pde << 2, 4);
+ smmu_flush_dcache(as->pd, pde << 2, 4);
smmu_flush_ptc(smmu, as->pd, pde << 2);
smmu_flush_tlb_section(smmu, as->id, iova);
smmu_flush(smmu);
@@ -562,7 +582,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova)
pd[pde] = 0;
/* Flush the page directory entry */
- smmu->soc->ops->flush_dcache(as->pd, offset, sizeof(*pd));
+ smmu_flush_dcache(as->pd, offset, sizeof(*pd));
smmu_flush_ptc(smmu, as->pd, offset);
smmu_flush_tlb_section(smmu, as->id, iova);
smmu_flush(smmu);
@@ -582,7 +602,7 @@ static void tegra_smmu_set_pte(struct tegra_smmu_as *as, unsigned long iova,
*pte = val;
- smmu->soc->ops->flush_dcache(pte_page, offset, 4);
+ smmu_flush_dcache(pte_page, offset, 4);
smmu_flush_ptc(smmu, pte_page, offset);
smmu_flush_tlb_group(smmu, as->id, iova);
smmu_flush(smmu);