iommu: msm: Only program registers once

Certain operations need to be performed only once per
IOMMU. Ensure that this is the case for both secure and non-secure
IOMMUs.

Change-Id: If16220fc5807a55daadd1c5e13a1117148445e0c
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 923e4da..c5c4988 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -97,6 +97,7 @@
  * @clk_reg_virt: Optional clock register virtual address.
  * @halt_enabled: Set to 1 if IOMMU halt is supported in the IOMMU, 0 otherwise.
  * @asid:         List of ASID and their usage count (index is ASID value).
+ * @ctx_attach_count: Count of how many context are attached.
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -119,6 +120,7 @@
 	void __iomem *clk_reg_virt;
 	int halt_enabled;
 	int *asid;
+	unsigned int ctx_attach_count;
 };
 
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 7110303..24d2854 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -506,27 +506,6 @@
 	mutex_unlock(&msm_iommu_lock);
 }
 
-static int msm_iommu_ctx_attached(struct device *dev)
-{
-	struct platform_device *pdev;
-	struct device_node *child;
-	struct msm_iommu_ctx_drvdata *ctx;
-
-	for_each_child_of_node(dev->of_node, child) {
-		pdev = of_find_device_by_node(child);
-
-		ctx = dev_get_drvdata(&pdev->dev);
-		if (ctx->attached_domain) {
-			of_dev_put(pdev);
-			of_node_put(child);
-			return 1;
-		}
-		of_dev_put(pdev);
-	}
-
-	return 0;
-}
-
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
 	struct msm_priv *priv;
@@ -574,8 +553,8 @@
 		goto fail;
 	}
 
-
-	if (!msm_iommu_ctx_attached(dev->parent)) {
+	/* We can only do this once */
+	if (!iommu_drvdata->ctx_attach_count) {
 		if (!is_secure) {
 			iommu_halt(iommu_drvdata);
 			__program_iommu(iommu_drvdata->base);
@@ -603,6 +582,7 @@
 
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ctx_drvdata->attached_domain = domain;
+	++iommu_drvdata->ctx_attach_count;
 
 	mutex_unlock(&msm_iommu_lock);
 
@@ -660,7 +640,8 @@
 
 	list_del_init(&ctx_drvdata->attached_elm);
 	ctx_drvdata->attached_domain = NULL;
-
+	BUG_ON(iommu_drvdata->ctx_attach_count == 0);
+	--iommu_drvdata->ctx_attach_count;
 fail:
 	mutex_unlock(&msm_iommu_lock);
 }
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 4e55bd6..29cf0c1 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -359,26 +359,30 @@
 	if (ret)
 		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret) {
-		regulator_disable(iommu_drvdata->gdsc);
-		goto fail;
-	}
+	/* We can only do this once */
+	if (!iommu_drvdata->ctx_attach_count) {
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret) {
+			regulator_disable(iommu_drvdata->gdsc);
+			goto fail;
+		}
 
-	ret = msm_iommu_sec_program_iommu(iommu_drvdata->sec_id);
+		ret = msm_iommu_sec_program_iommu(iommu_drvdata->sec_id);
 
-	/* bfb settings are always programmed by HLOS */
-	program_iommu_bfb_settings(iommu_drvdata->base,
-				   iommu_drvdata->bfb_settings);
+		/* bfb settings are always programmed by HLOS */
+		program_iommu_bfb_settings(iommu_drvdata->base,
+					   iommu_drvdata->bfb_settings);
 
-	__disable_clocks(iommu_drvdata);
-	if (ret) {
-		regulator_disable(iommu_drvdata->gdsc);
-		goto fail;
+		__disable_clocks(iommu_drvdata);
+		if (ret) {
+			regulator_disable(iommu_drvdata->gdsc);
+			goto fail;
+		}
 	}
 
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ctx_drvdata->attached_domain = domain;
+	++iommu_drvdata->ctx_attach_count;
 
 	mutex_unlock(&msm_iommu_lock);
 
@@ -410,7 +414,8 @@
 	ctx_drvdata->attached_domain = NULL;
 
 	regulator_disable(iommu_drvdata->gdsc);
-
+	BUG_ON(iommu_drvdata->ctx_attach_count == 0);
+	--iommu_drvdata->ctx_attach_count;
 fail:
 	mutex_unlock(&msm_iommu_lock);
 }