]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/iommu/tegra-smmu.c
Merge branches 'iommu/fixes', 'x86/vt-d', 'x86/amd', 'arm/smmu', 'arm/tegra' and...
[karo-tx-linux.git] / drivers / iommu / tegra-smmu.c
index 720829724d8619e334577ed780313e813dee3f36..c845d99ecf6b8c50757998f08c86224c70064acb 100644 (file)
@@ -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)