msm: iommu: Configure iommu devices for 8064

Add support for new SMMUs found on the APQ8064
target and enable the iommu driver for 8064.

Change-Id: I0b4d42f5b47dd5299c44e381dd4320b7570c3ce5
Signed-off-by: Joel King <joelking@codeaurora.org>
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index a945349..73c96fb 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -15,6 +15,9 @@
 #include <linux/bootmem.h>
 #include <mach/irqs.h>
 #include <mach/iommu.h>
+#include <mach/socinfo.h>
+#include <mach/irqs-8960.h>
+#include <mach/irqs-8064.h>
 
 static struct resource msm_iommu_jpegd_resources[] = {
 	{
@@ -226,6 +229,27 @@
 	},
 };
 
+static struct resource msm_iommu_gfx3d1_resources[] = {
+	{
+		.start = 0x07D00000,
+		.end   = 0x07D00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX3D1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX3D1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX3D1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX3D1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
 static struct resource msm_iommu_gfx2d0_resources[] = {
 	{
 		.start = 0x07D00000,
@@ -268,6 +292,27 @@
 	},
 };
 
+static struct resource msm_iommu_vcap_resources[] = {
+	{
+		.start = 0x07200000,
+		.end   = 0x07200000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VCAP_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VCAP_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VCAP_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VCAP_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device msm_root_iommu_dev = {
 	.name = "msm_iommu",
 	.id = -1,
@@ -323,6 +368,11 @@
 	.ncb = 3,
 };
 
+static struct msm_iommu_dev gfx3d1_iommu = {
+	.name = "gfx3d1",
+	.ncb = 3,
+};
+
 static struct msm_iommu_dev gfx2d0_iommu = {
 	.name = "gfx2d0",
 	.ncb = 2,
@@ -333,6 +383,11 @@
 	.ncb = 2,
 };
 
+static struct msm_iommu_dev vcap_iommu = {
+	.name = "vcap",
+	.ncb = 2,
+};
+
 static struct platform_device msm_device_iommu_jpegd = {
 	.name = "msm_iommu",
 	.id = 0,
@@ -433,6 +488,16 @@
 	.resource = msm_iommu_gfx3d_resources,
 };
 
+static struct platform_device msm_device_iommu_gfx3d1 = {
+	.name = "msm_iommu",
+	.id = 10,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d1_resources),
+	.resource = msm_iommu_gfx3d1_resources,
+};
+
 static struct platform_device msm_device_iommu_gfx2d0 = {
 	.name = "msm_iommu",
 	.id = 10,
@@ -443,7 +508,7 @@
 	.resource = msm_iommu_gfx2d0_resources,
 };
 
-struct platform_device msm_device_iommu_gfx2d1 = {
+static struct platform_device msm_device_iommu_gfx2d1 = {
 	.name = "msm_iommu",
 	.id = 11,
 	.dev = {
@@ -453,6 +518,16 @@
 	.resource = msm_iommu_gfx2d1_resources,
 };
 
+static struct platform_device msm_device_iommu_vcap = {
+	.name = "msm_iommu",
+	.id = 11,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vcap_resources),
+	.resource = msm_iommu_vcap_resources,
+};
+
 static struct msm_iommu_ctx_dev jpegd_src_ctx = {
 	.name = "jpegd_src",
 	.num = 0,
@@ -568,6 +643,19 @@
 		 31, -1}
 };
 
+static struct msm_iommu_ctx_dev gfx3d1_user_ctx = {
+	.name = "gfx3d1_user",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d1_priv_ctx = {
+	.name = "gfx3d1_priv",
+	.num = 1,
+	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		 31, -1}
+};
+
 static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
 	.name = "gfx2d0_2d0",
 	.num = 0,
@@ -580,6 +668,18 @@
 	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
 };
 
+static struct msm_iommu_ctx_dev vcap_vc_ctx = {
+	.name = "vcap_vc",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev vcap_vp_ctx = {
+	.name = "vcap_vp",
+	.num = 1,
+	.mids = {1, -1}
+};
+
 static struct platform_device msm_device_jpegd_src_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 0,
@@ -732,6 +832,22 @@
 	},
 };
 
+static struct platform_device msm_device_gfx3d1_user_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 19,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d1.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d1_priv_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 20,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d1.dev,
+	},
+};
+
 static struct platform_device msm_device_gfx2d0_2d0_ctx = {
 	.name = "msm_iommu_ctx",
 	.id = 19,
@@ -748,7 +864,23 @@
 	},
 };
 
-static struct platform_device *msm_iommu_devs[] = {
+static struct platform_device msm_device_vcap_vc_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 21,
+	.dev = {
+		.parent = &msm_device_iommu_vcap.dev,
+	},
+};
+
+static struct platform_device msm_device_vcap_vp_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 22,
+	.dev = {
+		.parent = &msm_device_iommu_vcap.dev,
+	},
+};
+
+static struct platform_device *msm_iommu_common_devs[] = {
 	&msm_device_iommu_jpegd,
 	&msm_device_iommu_vpe,
 	&msm_device_iommu_mdp0,
@@ -759,11 +891,19 @@
 	&msm_device_iommu_vcodec_a,
 	&msm_device_iommu_vcodec_b,
 	&msm_device_iommu_gfx3d,
+};
+
+static struct platform_device *msm_iommu_gfx2d_devs[] = {
 	&msm_device_iommu_gfx2d0,
 	&msm_device_iommu_gfx2d1,
 };
 
-static struct msm_iommu_dev *msm_iommu_data[] = {
+static struct platform_device *msm_iommu_8064_devs[] = {
+	&msm_device_iommu_gfx3d1,
+	&msm_device_iommu_vcap,
+};
+
+static struct msm_iommu_dev *msm_iommu_common_data[] = {
 	&jpegd_iommu,
 	&vpe_iommu,
 	&mdp0_iommu,
@@ -774,11 +914,19 @@
 	&vcodec_a_iommu,
 	&vcodec_b_iommu,
 	&gfx3d_iommu,
+};
+
+static struct msm_iommu_dev *msm_iommu_gfx2d_data[] = {
 	&gfx2d0_iommu,
 	&gfx2d1_iommu,
 };
 
-static struct platform_device *msm_iommu_ctx_devs[] = {
+static struct msm_iommu_dev *msm_iommu_8064_data[] = {
+	&gfx3d1_iommu,
+	&vcap_iommu,
+};
+
+static struct platform_device *msm_iommu_common_ctx_devs[] = {
 	&msm_device_jpegd_src_ctx,
 	&msm_device_jpegd_dst_ctx,
 	&msm_device_vpe_src_ctx,
@@ -798,11 +946,21 @@
 	&msm_device_vcodec_b_mm2_ctx,
 	&msm_device_gfx3d_user_ctx,
 	&msm_device_gfx3d_priv_ctx,
+};
+
+static struct platform_device *msm_iommu_gfx2d_ctx_devs[] = {
 	&msm_device_gfx2d0_2d0_ctx,
 	&msm_device_gfx2d1_2d1_ctx,
 };
 
-static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
+static struct platform_device *msm_iommu_8064_ctx_devs[] = {
+	&msm_device_gfx3d1_user_ctx,
+	&msm_device_gfx3d1_priv_ctx,
+	&msm_device_vcap_vc_ctx,
+	&msm_device_vcap_vp_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_common_ctx_data[] = {
 	&jpegd_src_ctx,
 	&jpegd_dst_ctx,
 	&vpe_src_ctx,
@@ -822,31 +980,35 @@
 	&vcodec_b_mm2_ctx,
 	&gfx3d_user_ctx,
 	&gfx3d_priv_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_gfx2d_ctx_data[] = {
 	&gfx2d0_2d0_ctx,
 	&gfx2d1_2d1_ctx,
 };
 
-static int __init msm8x60_iommu_init(void)
+static struct msm_iommu_ctx_dev *msm_iommu_8064_ctx_data[] = {
+	&gfx3d1_user_ctx,
+	&gfx3d1_priv_ctx,
+	&vcap_vc_ctx,
+	&vcap_vp_ctx,
+};
+
+static int iommu_init_devs(struct platform_device *devs[],
+	struct msm_iommu_dev *data[], int size)
 {
 	int ret, i;
 
-	ret = platform_device_register(&msm_root_iommu_dev);
-	if (ret != 0) {
-		pr_err("Failed to register root IOMMU device!\n");
-		goto failure;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_devs[i],
-					       msm_iommu_data[i],
-					       sizeof(struct msm_iommu_dev));
+	for (i = 0; i < size; i++) {
+		ret = platform_device_add_data(devs[i],
+			  data[i], sizeof(struct msm_iommu_dev));
 		if (ret != 0) {
 			pr_err("platform_device_add_data failed, "
 			       "i = %d\n", i);
 			goto failure_unwind;
 		}
 
-		ret = platform_device_register(msm_iommu_devs[i]);
+		ret = platform_device_register(devs[i]);
 
 		if (ret != 0) {
 			pr_err("platform_device_register iommu failed, "
@@ -854,53 +1016,139 @@
 			goto failure_unwind;
 		}
 	}
+	return 0;
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
-					       msm_iommu_ctx_data[i],
-					       sizeof(*msm_iommu_ctx_devs[i]));
+failure_unwind:
+	while (--i >= 0)
+		platform_device_unregister(devs[i]);
+
+	return ret;
+}
+
+
+static int iommu_init_ctx_devs(struct platform_device *ctx_devs[],
+	struct msm_iommu_ctx_dev *ctx_data[], int size)
+{
+	int ret, i;
+
+	for (i = 0; i < size; i++) {
+		ret = platform_device_add_data(ctx_devs[i],
+				ctx_data[i], sizeof(struct msm_iommu_ctx_dev));
 		if (ret != 0) {
 			pr_err("platform_device_add_data iommu failed, "
 			       "i = %d\n", i);
-			goto failure_unwind2;
+			goto failure_unwind;
 		}
 
-		ret = platform_device_register(msm_iommu_ctx_devs[i]);
+		ret = platform_device_register(ctx_devs[i]);
 		if (ret != 0) {
 			pr_err("platform_device_register ctx failed, "
 			       "i = %d\n", i);
-			goto failure_unwind2;
+			goto failure_unwind;
 		}
 	}
 	return 0;
 
-failure_unwind2:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
 failure_unwind:
 	while (--i >= 0)
-		platform_device_unregister(msm_iommu_devs[i]);
+		platform_device_unregister(ctx_devs[i]);
 
+	return ret;
+}
+
+static int __init iommu_init(void)
+{
+	int ret;
+
+	ret = platform_device_register(&msm_root_iommu_dev);
+	if (ret != 0) {
+		pr_err("Failed to register root IOMMU device!\n");
+		goto failure;
+	}
+
+	/* Initialize common devs */
+	ret = iommu_init_devs(msm_iommu_common_devs,
+			 msm_iommu_common_data,
+			 ARRAY_SIZE(msm_iommu_common_devs));
+	if (ret != 0)
+		goto failure2;
+
+	/* Initialize soc-specific devs */
+	if (cpu_is_apq8064()) {
+		ret = iommu_init_devs(msm_iommu_8064_devs,
+				 msm_iommu_8064_data,
+				 ARRAY_SIZE(msm_iommu_8064_devs));
+	} else {
+		ret = iommu_init_devs(msm_iommu_gfx2d_devs,
+					 msm_iommu_gfx2d_data,
+					ARRAY_SIZE(msm_iommu_gfx2d_devs));
+	}
+	if (ret != 0)
+		goto failure2;
+
+	/* Initialize common ctx_devs */
+	ret = iommu_init_ctx_devs(msm_iommu_common_ctx_devs,
+				 msm_iommu_common_ctx_data,
+				 ARRAY_SIZE(msm_iommu_common_ctx_devs));
+	if (ret != 0)
+		goto failure2;
+
+	/* Initialize soc-specific ctx_devs */
+	if (cpu_is_apq8064()) {
+		ret = iommu_init_ctx_devs(msm_iommu_8064_ctx_devs,
+				msm_iommu_8064_ctx_data,
+				ARRAY_SIZE(msm_iommu_8064_ctx_devs));
+	} else {
+		ret = iommu_init_ctx_devs(msm_iommu_gfx2d_ctx_devs,
+					msm_iommu_gfx2d_ctx_data,
+					ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
+	}
+	if (ret != 0)
+		goto failure2;
+
+	return 0;
+
+failure2:
 	platform_device_unregister(&msm_root_iommu_dev);
 failure:
 	return ret;
 }
 
-static void __exit msm8x60_iommu_exit(void)
+static void __exit iommu_exit(void)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
+	/* Common ctx_devs */
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_common_ctx_devs); i++)
+		platform_device_unregister(msm_iommu_common_ctx_devs[i]);
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
-		platform_device_unregister(msm_iommu_devs[i]);
+	/* soc-specific ctx_devs. */
+	if (cpu_is_apq8064()) {
+		for (i = 0; i < ARRAY_SIZE(msm_iommu_8064_ctx_devs); i++)
+			platform_device_unregister(msm_iommu_8064_ctx_devs[i]);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs); i++)
+			platform_device_unregister(msm_iommu_gfx2d_ctx_devs[i]);
+	}
+
+	/* Common devs. */
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_common_devs); ++i)
+		platform_device_unregister(msm_iommu_common_devs[i]);
+
+	/* soc-specific devs. */
+	if (cpu_is_apq8064()) {
+		for (i = 0; i < ARRAY_SIZE(msm_iommu_8064_devs); i++)
+			platform_device_unregister(msm_iommu_8064_devs[i]);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(msm_iommu_gfx2d_devs); i++)
+			platform_device_unregister(msm_iommu_gfx2d_devs[i]);
+	}
 
 	platform_device_unregister(&msm_root_iommu_dev);
 }
 
-subsys_initcall(msm8x60_iommu_init);
-module_exit(msm8x60_iommu_exit);
+subsys_initcall(iommu_init);
+module_exit(iommu_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");