msm: Make iommu domains platform devices

Information about the layout of iommu domains is a device
specific option. Convert the iommu domain information
into a platform driver with a corresponding platform device.
This allows different devices to have different layouts as
needed.

Change-Id: I6bf4162476143daabe16a2f5de3b655ae4377902
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index dbc1389..8f4af3b 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -13,6 +13,7 @@
 #include <mach/msm_subsystem_map.h>
 #include <linux/memory_alloc.h>
 #include <linux/iommu.h>
+#include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 #include <asm/sizes.h>
 #include <asm/page.h>
@@ -24,166 +25,12 @@
 /* dummy 4k for overmapping */
 char iommu_dummy[2*PAGE_SIZE-4];
 
-struct msm_iommu_domain {
-	/* iommu domain to map in */
-	struct iommu_domain *domain;
-	/* total number of allocations from this domain */
-	atomic_t allocation_cnt;
-	/* number of iova pools */
-	int npools;
-	/*
-	 * array of gen_pools for allocating iovas.
-	 * behavior is undefined if these overlap
-	 */
-	struct mem_pool *iova_pools;
-
+struct msm_iommu_domain_state {
+	struct msm_iommu_domain *domains;
+	int ndomains;
 };
 
-
-struct {
-	char *name;
-	int  domain;
-} msm_iommu_ctx_names[] = {
-	/* Camera */
-	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "ijpeg_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "ijpeg_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "jpegd_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_src",
-		.domain = ROTATOR_DOMAIN,
-	},
-	/* Rotator */
-	{
-		.name = "rot_dst",
-		.domain = ROTATOR_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_mm1",
-		.domain = VIDEO_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_b_mm2",
-		.domain = VIDEO_DOMAIN,
-	},
-	/* Video */
-	{
-		.name = "vcodec_a_stream",
-		.domain = VIDEO_DOMAIN,
-	},
-};
-
-static struct mem_pool video_pools[] =  {
-	/*
-	 * Video hardware has the following requirements:
-	 * 1. All video addresses used by the video hardware must be at a higher
-	 *    address than video firmware address.
-	 * 2. Video hardware can only access a range of 256MB from the base of
-	 *    the video firmware.
-	*/
-	[VIDEO_FIRMWARE_POOL] =
-	/* Low addresses, intended for video firmware */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_16M - SZ_128K,
-		},
-	[VIDEO_MAIN_POOL] =
-	/* Main video pool */
-		{
-			.paddr	= SZ_16M,
-			.size	= SZ_256M - SZ_16M,
-		},
-	[GEN_POOL] =
-	/* Remaining address space up to 2G */
-		{
-			.paddr	= SZ_256M,
-			.size	= SZ_2G - SZ_256M,
-		},
-};
-
-static struct mem_pool camera_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for camera */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct mem_pool display_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for display */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct mem_pool rotator_pools[] =  {
-	[GEN_POOL] =
-	/* One address space for rotator */
-		{
-			.paddr	= SZ_128K,
-			.size	= SZ_2G - SZ_128K,
-		},
-};
-
-static struct msm_iommu_domain msm_iommu_domains[] = {
-		[VIDEO_DOMAIN] = {
-			.iova_pools = video_pools,
-			.npools = ARRAY_SIZE(video_pools),
-		},
-		[CAMERA_DOMAIN] = {
-			.iova_pools = camera_pools,
-			.npools = ARRAY_SIZE(camera_pools),
-		},
-		[DISPLAY_DOMAIN] = {
-			.iova_pools = display_pools,
-			.npools = ARRAY_SIZE(display_pools),
-		},
-		[ROTATOR_DOMAIN] = {
-			.iova_pools = rotator_pools,
-			.npools = ARRAY_SIZE(rotator_pools),
-		},
-};
+static struct msm_iommu_domain_state domain_state;
 
 int msm_iommu_map_extra(struct iommu_domain *domain,
 				unsigned long start_iova,
@@ -221,8 +68,8 @@
 
 struct iommu_domain *msm_get_iommu_domain(int domain_num)
 {
-	if (domain_num >= 0 && domain_num < MAX_DOMAINS)
-		return msm_iommu_domains[domain_num].domain;
+	if (domain_num >= 0 && domain_num < domain_state.ndomains)
+		return domain_state.domains[domain_num].domain;
 	else
 		return NULL;
 }
@@ -235,13 +82,13 @@
 	struct mem_pool *pool;
 	unsigned long iova;
 
-	if (iommu_domain >= MAX_DOMAINS)
+	if (iommu_domain >= domain_state.ndomains)
 		return 0;
 
-	if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+	if (partition_no >= domain_state.domains[iommu_domain].npools)
 		return 0;
 
-	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+	pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
 
 	if (!pool->gpool)
 		return 0;
@@ -260,18 +107,18 @@
 {
 	struct mem_pool *pool;
 
-	if (iommu_domain >= MAX_DOMAINS) {
+	if (iommu_domain >= domain_state.ndomains) {
 		WARN(1, "Invalid domain %d\n", iommu_domain);
 		return;
 	}
 
-	if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+	if (partition_no >= domain_state.domains[iommu_domain].npools) {
 		WARN(1, "Invalid partition %d for domain %d\n",
 			partition_no, iommu_domain);
 		return;
 	}
 
-	pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+	pool = &domain_state.domains[iommu_domain].iova_pools[partition_no];
 
 	if (!pool)
 		return;
@@ -282,20 +129,31 @@
 
 int msm_use_iommu()
 {
-	return iommu_found();
+	/*
+	 * If there are no domains, don't bother trying to use the iommu
+	 */
+	return domain_state.ndomains && iommu_found();
 }
 
-static int __init msm_subsystem_iommu_init(void)
+static int __init iommu_domain_probe(struct platform_device *pdev)
 {
+	struct iommu_domains_pdata *p  = pdev->dev.platform_data;
 	int i, j;
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
-		msm_iommu_domains[i].domain = iommu_domain_alloc(0);
-		if (!msm_iommu_domains[i].domain)
+	if (!p)
+		return -ENODEV;
+
+	domain_state.domains = p->domains;
+	domain_state.ndomains = p->ndomains;
+
+	for (i = 0; i < domain_state.ndomains; i++) {
+		domain_state.domains[i].domain = iommu_domain_alloc(
+							p->domain_alloc_flags);
+		if (!domain_state.domains[i].domain)
 			continue;
 
-		for (j = 0; j < msm_iommu_domains[i].npools; j++) {
-			struct mem_pool *pool = &msm_iommu_domains[i].
+		for (j = 0; j < domain_state.domains[i].npools; j++) {
+			struct mem_pool *pool = &domain_state.domains[i].
 							iova_pools[j];
 			mutex_init(&pool->pool_mutex);
 			if (pool->size) {
@@ -325,29 +183,41 @@
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_names); i++) {
+	for (i = 0; i < p->nnames; i++) {
 		int domain_idx;
 		struct device *ctx = msm_iommu_get_ctx(
-						msm_iommu_ctx_names[i].name);
+						p->domain_names[i].name);
 
 		if (!ctx)
 			continue;
 
-		domain_idx = msm_iommu_ctx_names[i].domain;
+		domain_idx = p->domain_names[i].domain;
 
-		if (!msm_iommu_domains[domain_idx].domain)
+		if (!domain_state.domains[domain_idx].domain)
 			continue;
 
-		if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+		if (iommu_attach_device(domain_state.domains[domain_idx].domain,
 					ctx)) {
 			WARN(1, "%s: could not attach domain %d to context %s."
 				" iommu programming will not occur.\n",
 				__func__, domain_idx,
-				msm_iommu_ctx_names[i].name);
+				p->domain_names[i].name);
 			continue;
 		}
 	}
 
 	return 0;
 }
+
+static struct platform_driver iommu_domain_driver = {
+	.driver         = {
+		.name = "iommu_domains",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init msm_subsystem_iommu_init(void)
+{
+	return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+}
 device_initcall(msm_subsystem_iommu_init);