aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2011-06-01 18:46:12 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2011-08-26 05:46:00 -0400
commitf626b52d4a568d4315cd152123ef2d1ea406def2 (patch)
tree3592dfe99e9fd2713609cef9fbb8d0dfc8653a52 /drivers
parentfcb8ce5cfe30ca9ca5c9a79cdfe26d1993e65e0c (diff)
omap: iommu: migrate to the generic IOMMU API
Migrate OMAP's iommu driver to the generic IOMMU API, so users can stay generic, and any generic IOMMU functionality can be developed once in the generic framework. Migrate omap's iovmm (virtual memory manager) to the generic IOMMU API, and adapt omap3isp as needed, so the latter won't break. The plan is to eventually remove iovmm completely by replacing it with the (upcoming) IOMMU-based DMA-API. Tested on OMAP3 (with omap3isp) and OMAP4 (with rpmsg/remoteproc). Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/omap3isp/isp.c41
-rw-r--r--drivers/media/video/omap3isp/isp.h3
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c16
-rw-r--r--drivers/media/video/omap3isp/ispstat.c6
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c4
5 files changed, 50 insertions, 20 deletions
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index 5cea2bbd7014..0db45ac7489b 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -80,6 +80,13 @@
80#include "isph3a.h" 80#include "isph3a.h"
81#include "isphist.h" 81#include "isphist.h"
82 82
83/*
84 * this is provided as an interim solution until omap3isp doesn't need
85 * any omap-specific iommu API
86 */
87#define to_iommu(dev) \
88 (struct iommu *)platform_get_drvdata(to_platform_device(dev))
89
83static unsigned int autoidle; 90static unsigned int autoidle;
84module_param(autoidle, int, 0444); 91module_param(autoidle, int, 0444);
85MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support"); 92MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
@@ -1975,7 +1982,8 @@ static int isp_remove(struct platform_device *pdev)
1975 isp_cleanup_modules(isp); 1982 isp_cleanup_modules(isp);
1976 1983
1977 omap3isp_get(isp); 1984 omap3isp_get(isp);
1978 iommu_put(isp->iommu); 1985 iommu_detach_device(isp->domain, isp->iommu_dev);
1986 iommu_domain_free(isp->domain);
1979 omap3isp_put(isp); 1987 omap3isp_put(isp);
1980 1988
1981 free_irq(isp->irq_num, isp); 1989 free_irq(isp->irq_num, isp);
@@ -2123,25 +2131,41 @@ static int isp_probe(struct platform_device *pdev)
2123 } 2131 }
2124 2132
2125 /* IOMMU */ 2133 /* IOMMU */
2126 isp->iommu = iommu_get("isp"); 2134 isp->iommu_dev = omap_find_iommu_device("isp");
2127 if (IS_ERR_OR_NULL(isp->iommu)) { 2135 if (!isp->iommu_dev) {
2128 isp->iommu = NULL; 2136 dev_err(isp->dev, "omap_find_iommu_device failed\n");
2129 ret = -ENODEV; 2137 ret = -ENODEV;
2130 goto error_isp; 2138 goto error_isp;
2131 } 2139 }
2132 2140
2141 /* to be removed once iommu migration is complete */
2142 isp->iommu = to_iommu(isp->iommu_dev);
2143
2144 isp->domain = iommu_domain_alloc();
2145 if (!isp->domain) {
2146 dev_err(isp->dev, "can't alloc iommu domain\n");
2147 ret = -ENOMEM;
2148 goto error_isp;
2149 }
2150
2151 ret = iommu_attach_device(isp->domain, isp->iommu_dev);
2152 if (ret) {
2153 dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
2154 goto free_domain;
2155 }
2156
2133 /* Interrupt */ 2157 /* Interrupt */
2134 isp->irq_num = platform_get_irq(pdev, 0); 2158 isp->irq_num = platform_get_irq(pdev, 0);
2135 if (isp->irq_num <= 0) { 2159 if (isp->irq_num <= 0) {
2136 dev_err(isp->dev, "No IRQ resource\n"); 2160 dev_err(isp->dev, "No IRQ resource\n");
2137 ret = -ENODEV; 2161 ret = -ENODEV;
2138 goto error_isp; 2162 goto detach_dev;
2139 } 2163 }
2140 2164
2141 if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { 2165 if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
2142 dev_err(isp->dev, "Unable to request IRQ\n"); 2166 dev_err(isp->dev, "Unable to request IRQ\n");
2143 ret = -EINVAL; 2167 ret = -EINVAL;
2144 goto error_isp; 2168 goto detach_dev;
2145 } 2169 }
2146 2170
2147 /* Entities */ 2171 /* Entities */
@@ -2162,8 +2186,11 @@ error_modules:
2162 isp_cleanup_modules(isp); 2186 isp_cleanup_modules(isp);
2163error_irq: 2187error_irq:
2164 free_irq(isp->irq_num, isp); 2188 free_irq(isp->irq_num, isp);
2189detach_dev:
2190 iommu_detach_device(isp->domain, isp->iommu_dev);
2191free_domain:
2192 iommu_domain_free(isp->domain);
2165error_isp: 2193error_isp:
2166 iommu_put(isp->iommu);
2167 omap3isp_put(isp); 2194 omap3isp_put(isp);
2168error: 2195error:
2169 isp_put_clocks(isp); 2196 isp_put_clocks(isp);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
index 529e582ef948..c9ec7a2e53ea 100644
--- a/drivers/media/video/omap3isp/isp.h
+++ b/drivers/media/video/omap3isp/isp.h
@@ -32,6 +32,7 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/platform_device.h> 33#include <linux/platform_device.h>
34#include <linux/wait.h> 34#include <linux/wait.h>
35#include <linux/iommu.h>
35#include <plat/iommu.h> 36#include <plat/iommu.h>
36#include <plat/iovmm.h> 37#include <plat/iovmm.h>
37 38
@@ -295,6 +296,8 @@ struct isp_device {
295 unsigned int subclk_resources; 296 unsigned int subclk_resources;
296 297
297 struct iommu *iommu; 298 struct iommu *iommu;
299 struct iommu_domain *domain;
300 struct device *iommu_dev;
298 301
299 struct isp_platform_callback platform_cb; 302 struct isp_platform_callback platform_cb;
300}; 303};
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 9d3459de04b2..de2547413739 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -365,7 +365,7 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
365 dma_unmap_sg(isp->dev, req->iovm->sgt->sgl, 365 dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
366 req->iovm->sgt->nents, DMA_TO_DEVICE); 366 req->iovm->sgt->nents, DMA_TO_DEVICE);
367 if (req->table) 367 if (req->table)
368 iommu_vfree(isp->iommu, req->table); 368 iommu_vfree(isp->domain, isp->iommu, req->table);
369 kfree(req); 369 kfree(req);
370} 370}
371 371
@@ -437,8 +437,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
437 437
438 req->enable = 1; 438 req->enable = 1;
439 439
440 req->table = iommu_vmalloc(isp->iommu, 0, req->config.size, 440 req->table = iommu_vmalloc(isp->domain, isp->iommu, 0,
441 IOMMU_FLAG); 441 req->config.size, IOMMU_FLAG);
442 if (IS_ERR_VALUE(req->table)) { 442 if (IS_ERR_VALUE(req->table)) {
443 req->table = 0; 443 req->table = 0;
444 ret = -ENOMEM; 444 ret = -ENOMEM;
@@ -733,15 +733,15 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
733 * already done by iommu_vmalloc(). 733 * already done by iommu_vmalloc().
734 */ 734 */
735 size = ccdc->fpc.fpnum * 4; 735 size = ccdc->fpc.fpnum * 4;
736 table_new = iommu_vmalloc(isp->iommu, 0, size, 736 table_new = iommu_vmalloc(isp->domain, isp->iommu, 0,
737 IOMMU_FLAG); 737 size, IOMMU_FLAG);
738 if (IS_ERR_VALUE(table_new)) 738 if (IS_ERR_VALUE(table_new))
739 return -ENOMEM; 739 return -ENOMEM;
740 740
741 if (copy_from_user(da_to_va(isp->iommu, table_new), 741 if (copy_from_user(da_to_va(isp->iommu, table_new),
742 (__force void __user *) 742 (__force void __user *)
743 ccdc->fpc.fpcaddr, size)) { 743 ccdc->fpc.fpcaddr, size)) {
744 iommu_vfree(isp->iommu, table_new); 744 iommu_vfree(isp->domain, isp->iommu, table_new);
745 return -EFAULT; 745 return -EFAULT;
746 } 746 }
747 747
@@ -751,7 +751,7 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
751 751
752 ccdc_configure_fpc(ccdc); 752 ccdc_configure_fpc(ccdc);
753 if (table_old != 0) 753 if (table_old != 0)
754 iommu_vfree(isp->iommu, table_old); 754 iommu_vfree(isp->domain, isp->iommu, table_old);
755 } 755 }
756 756
757 return ccdc_lsc_config(ccdc, ccdc_struct); 757 return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -2286,5 +2286,5 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
2286 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue); 2286 ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
2287 2287
2288 if (ccdc->fpc.fpcaddr != 0) 2288 if (ccdc->fpc.fpcaddr != 0)
2289 iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr); 2289 iommu_vfree(isp->domain, isp->iommu, ccdc->fpc.fpcaddr);
2290} 2290}
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
index 808065948ac1..98af736b9a90 100644
--- a/drivers/media/video/omap3isp/ispstat.c
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -366,7 +366,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
366 dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl, 366 dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
367 buf->iovm->sgt->nents, 367 buf->iovm->sgt->nents,
368 DMA_FROM_DEVICE); 368 DMA_FROM_DEVICE);
369 iommu_vfree(isp->iommu, buf->iommu_addr); 369 iommu_vfree(isp->domain, isp->iommu, buf->iommu_addr);
370 } else { 370 } else {
371 if (!buf->virt_addr) 371 if (!buf->virt_addr)
372 continue; 372 continue;
@@ -399,8 +399,8 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
399 struct iovm_struct *iovm; 399 struct iovm_struct *iovm;
400 400
401 WARN_ON(buf->dma_addr); 401 WARN_ON(buf->dma_addr);
402 buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size, 402 buf->iommu_addr = iommu_vmalloc(isp->domain, isp->iommu, 0,
403 IOMMU_FLAG); 403 size, IOMMU_FLAG);
404 if (IS_ERR((void *)buf->iommu_addr)) { 404 if (IS_ERR((void *)buf->iommu_addr)) {
405 dev_err(stat->isp->dev, 405 dev_err(stat->isp->dev,
406 "%s: Can't acquire memory for " 406 "%s: Can't acquire memory for "
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index fd965adfd597..023b5028a27b 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -446,7 +446,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
446 sgt->nents = sglen; 446 sgt->nents = sglen;
447 sgt->orig_nents = sglen; 447 sgt->orig_nents = sglen;
448 448
449 da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG); 449 da = iommu_vmap(isp->domain, isp->iommu, 0, sgt, IOMMU_FLAG);
450 if (IS_ERR_VALUE(da)) 450 if (IS_ERR_VALUE(da))
451 kfree(sgt); 451 kfree(sgt);
452 452
@@ -462,7 +462,7 @@ static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
462{ 462{
463 struct sg_table *sgt; 463 struct sg_table *sgt;
464 464
465 sgt = iommu_vunmap(isp->iommu, (u32)da); 465 sgt = iommu_vunmap(isp->domain, isp->iommu, (u32)da);
466 kfree(sgt); 466 kfree(sgt);
467} 467}
468 468