iommu/msm: Add TLB sync operations

The hardware requires a TLB sync operation at the end of
each TLB maintenance operation.

Change-Id: I8102253cfc12af530216346efa5bb9760db25352
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index 26e967d..48edf96 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -67,6 +67,17 @@
 	clk_disable_unprepare(drvdata->pclk);
 }
 
+static void __sync_tlb(void __iomem *base, int ctx)
+{
+	SET_TLBSYNC(base, ctx, 0);
+
+	/* No barrier needed due to register proximity */
+	while (GET_CB_TLBSTATUS_SACTIVE(base, ctx))
+		cpu_relax();
+
+	/* No barrier needed due to read dependency */
+}
+
 static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
 {
 	struct msm_priv *priv = domain->priv;
@@ -92,6 +103,7 @@
 		SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
 			   asid | (va & CB_TLBIVA_VA));
 		mb();
+		__sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
 		__disable_clocks(iommu_drvdata);
 	}
 fail:
@@ -121,6 +133,7 @@
 
 		SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
 		mb();
+		__sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
 		__disable_clocks(iommu_drvdata);
 	}