summaryrefslogtreecommitdiff
path: root/drivers/iommu/tegra-smmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r--drivers/iommu/tegra-smmu.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 720829724d86..c845d99ecf6b 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/iommu.h>
#include <linux/kernel.h>
@@ -24,6 +25,8 @@ struct tegra_smmu {
struct tegra_mc *mc;
const struct tegra_smmu_soc *soc;
+ unsigned long pfn_mask;
+
unsigned long *asids;
struct mutex lock;
@@ -110,8 +113,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
#define SMMU_PDE_SHIFT 22
#define SMMU_PTE_SHIFT 12
-#define SMMU_PFN_MASK 0x000fffff
-
#define SMMU_PD_READABLE (1 << 31)
#define SMMU_PD_WRITABLE (1 << 30)
#define SMMU_PD_NONSECURE (1 << 29)
@@ -271,6 +272,11 @@ static struct iommu_domain *tegra_smmu_domain_alloc(unsigned type)
for (i = 0; i < SMMU_NUM_PDE; i++)
pd[i] = 0;
+ /* setup aperture */
+ as->domain.geometry.aperture_start = 0;
+ as->domain.geometry.aperture_end = 0xffffffff;
+ as->domain.geometry.force_aperture = true;
+
return &as->domain;
}
@@ -486,7 +492,7 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova,
smmu_flush_tlb_section(smmu, as->id, iova);
smmu_flush(smmu);
} else {
- page = pfn_to_page(pd[pde] & SMMU_PFN_MASK);
+ page = pfn_to_page(pd[pde] & smmu->pfn_mask);
pt = page_address(page);
}
@@ -508,7 +514,7 @@ static void as_put_pte(struct tegra_smmu_as *as, dma_addr_t iova)
u32 *pd = page_address(as->pd), *pt;
struct page *page;
- page = pfn_to_page(pd[pde] & SMMU_PFN_MASK);
+ page = pfn_to_page(pd[pde] & as->smmu->pfn_mask);
pt = page_address(page);
/*
@@ -583,7 +589,7 @@ static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain,
u32 *pte;
pte = as_get_pte(as, iova, &page);
- pfn = *pte & SMMU_PFN_MASK;
+ pfn = *pte & as->smmu->pfn_mask;
return PFN_PHYS(pfn);
}
@@ -707,6 +713,10 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
smmu->dev = dev;
smmu->mc = mc;
+ smmu->pfn_mask = BIT_MASK(mc->soc->num_address_bits - PAGE_SHIFT) - 1;
+ dev_dbg(dev, "address bits: %u, PFN mask: %#lx\n",
+ mc->soc->num_address_bits, smmu->pfn_mask);
+
value = SMMU_PTC_CONFIG_ENABLE | SMMU_PTC_CONFIG_INDEX_MAP(0x3f);
if (soc->supports_request_limit)