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);