@@ -39,6 +39,7 @@ struct ipmmu_features {
bool has_eight_ctx;
bool setup_imbuscr;
bool twobit_imttbcr_sl0;
+ bool imctr_va64;
};
struct ipmmu_vmsa_device {
@@ -117,6 +118,7 @@ static void set_archdata(struct device *
#define IM_CTX_SIZE 0x40
#define IMCTR 0x0000
+#define IMCTR_VA64 (1 << 29)
#define IMCTR_TRE (1 << 17)
#define IMCTR_AFE (1 << 16)
#define IMCTR_RTSEL_MASK (3 << 4)
@@ -430,8 +432,9 @@ static int ipmmu_domain_init_context(str
*/
domain->cfg.iommu_dev = domain->root->dev;
- domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
- domain);
+ domain->iop = alloc_io_pgtable_ops(domain->root->features->imctr_va64 ?
+ ARM_64_LPAE_S1 : ARM_32_LPAE_S1,
+ &domain->cfg, domain);
if (!domain->iop)
return -EINVAL;
@@ -462,6 +465,12 @@ static int ipmmu_domain_init_context(str
else
tmp = IMTTBCR_SL0_LVL_1;
+ /*
+ * For IMCTR_VA64 and ARM_64_LPAE_S1 we need lowest bits of TTBCR
+ */
+ if (domain->root->features->imctr_va64)
+ tmp |= 32;
+
ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
IMTTBCR_IRGN0_WB_WA | tmp);
@@ -488,7 +497,8 @@ static int ipmmu_domain_init_context(str
* required when modifying the context registers.
*/
ipmmu_ctx_write2(domain, IMCTR,
- IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+ (domain->root->features->imctr_va64 ? IMCTR_VA64 : 0)
+ | IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
return 0;
}
@@ -1098,6 +1108,7 @@ static const struct ipmmu_features ipmmu
.has_eight_ctx = false,
.setup_imbuscr = true,
.twobit_imttbcr_sl0 = false,
+ .imctr_va64 = false,
};
static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
@@ -1106,6 +1117,7 @@ static const struct ipmmu_features ipmmu
.has_eight_ctx = true,
.setup_imbuscr = false,
.twobit_imttbcr_sl0 = true,
+ .imctr_va64 = true,
};
static const struct of_device_id ipmmu_of_ids[] = {