summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHari Kanigeri <h-kanigeri2@ti.com>2011-10-25 10:50:45 +0800
committerAndy Green <andy.green@linaro.org>2011-10-25 10:50:45 +0800
commit7aed2894a9593ba9adf39278d3a2d068d3df2bdc (patch)
tree97ff09778a24a46e742d7b75ae14c3416d3ea10d
parentea2c163c318eb814e6a26b430d872d4152ef60de (diff)
omap:iommu-adapt to hwmod implementation
This patch adapts iommu to hwmod implementation for OMAP4. Work needs to be done for OMAP3 Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com>
-rw-r--r--arch/arm/mach-omap2/iommu2.c10
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c153
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h5
-rw-r--r--arch/arm/plat-omap/iommu.c56
4 files changed, 85 insertions, 139 deletions
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 636a788d554..bf4ca2cbbb1 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -19,6 +19,7 @@
#include <linux/stringify.h>
#include <plat/iommu.h>
+#include <plat/omap_device.h>
/*
* omap2 architecture specific register bit definitions
@@ -88,6 +89,7 @@ static int omap2_iommu_enable(struct iommu *obj)
{
u32 l, pa;
unsigned long timeout;
+ int ret = 0;
if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
return -EINVAL;
@@ -96,6 +98,10 @@ static int omap2_iommu_enable(struct iommu *obj)
if (!IS_ALIGNED(pa, SZ_16K))
return -EINVAL;
+ ret = omap_device_enable(obj->pdev);
+ if (ret)
+ return ret;
+
iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
timeout = jiffies + msecs_to_jiffies(20);
@@ -128,6 +134,8 @@ static int omap2_iommu_enable(struct iommu *obj)
static void omap2_iommu_disable(struct iommu *obj)
{
+ int ret = 0;
+
u32 l = iommu_read_reg(obj, MMU_CNTL);
l &= ~MMU_CNTL_MASK;
@@ -135,6 +143,8 @@ static void omap2_iommu_disable(struct iommu *obj)
iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
+ if (omap_device_shutdown(obj->pdev))
+ dev_err(obj->dev, "%s err 0x%x\n", __func__, ret);
}
static void omap2_iommu_set_twl(struct iommu *obj, bool on)
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index e61feadcda4..12fd0387270 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -11,9 +11,12 @@
*/
#include <linux/platform_device.h>
+#include <linux/err.h>
#include <plat/iommu.h>
-#include <plat/irqs.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+
struct iommu_device {
resource_size_t base;
@@ -21,46 +24,32 @@ struct iommu_device {
struct iommu_platform_data pdata;
struct resource res[2];
};
-static struct iommu_device *devices;
+static struct iommu_platform_data *devices_data;
static int num_iommu_devices;
#ifdef CONFIG_ARCH_OMAP3
-static struct iommu_device omap3_devices[] = {
+static struct iommu_platform_data omap3_devices_data[] = {
{
- .base = 0x480bd400,
- .irq = 24,
- .pdata = {
- .name = "isp",
- .nr_tlb_entries = 8,
- .clk_name = "cam_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
+ .name = "isp",
+ .oh_name = "isp",
+ .nr_tlb_entries = 8,
},
#if defined(CONFIG_OMAP_IOMMU_IVA2)
{
- .base = 0x5d000000,
- .irq = 28,
- .pdata = {
- .name = "iva2",
- .nr_tlb_entries = 32,
- .clk_name = "iva2_ck",
- .da_start = 0x11000000,
- .da_end = 0xFFFFF000,
- },
+ .name = "iva2",
+ .oh_name = "dsp",
+ .nr_tlb_entries = 32,
},
#endif
};
-#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
-static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
+#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices_data)
#else
-#define omap3_devices NULL
+#define omap3_devices_data NULL
#define NR_OMAP3_IOMMU_DEVICES 0
-#define omap3_iommu_pdev NULL
#endif
#ifdef CONFIG_ARCH_OMAP4
-static struct iommu_device omap4_devices[] = {
+static struct iommu_platform_data omap4_devices_data[] = {
{
.base = OMAP4_MMU1_BASE,
.irq = OMAP44XX_IRQ_DUCATI_MMU,
@@ -71,95 +60,83 @@ static struct iommu_device omap4_devices[] = {
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
+ .name = "ducati",
+ .oh_name = "ipu",
+ .nr_tlb_entries = 32,
},
-#if defined(CONFIG_MPU_TESLA_IOMMU)
{
- .base = OMAP4_MMU2_BASE,
- .irq = INT_44XX_DSP_MMU,
- .pdata = {
- .name = "tesla",
- .nr_tlb_entries = 32,
- .clk_name = "tesla_ick",
- .da_start = 0x0,
- .da_end = 0xFFFFF000,
- },
+ .name = "tesla",
+ .oh_name = "dsp",
+ .nr_tlb_entries = 32,
},
-#endif
};
-#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
-static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
+#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices_data)
#else
-#define omap4_devices NULL
+#define omap4_devices_data NULL
#define NR_OMAP4_IOMMU_DEVICES 0
-#define omap4_iommu_pdev NULL
#endif
-static struct platform_device **omap_iommu_pdev;
+static struct omap_device_pm_latency omap_iommu_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+int iommu_get_plat_data_size()
+{
+ return num_iommu_devices;
+}
+EXPORT_SYMBOL(iommu_get_plat_data_size);
+
+struct iommu_platform_data *iommu_get_device_data(void)
+{
+ return devices_data;
+}
static int __init omap_iommu_init(void)
{
- int i, err;
- struct resource res[] = {
- { .flags = IORESOURCE_MEM },
- { .flags = IORESOURCE_IRQ },
- };
+ int i, ohl_cnt;
+ struct omap_hwmod *oh;
+ struct omap_device *od;
+ struct omap_device_pm_latency *ohl;
if (cpu_is_omap34xx()) {
- devices = omap3_devices;
- omap_iommu_pdev = omap3_iommu_pdev;
+ devices_data = omap3_devices_data;
num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
} else if (cpu_is_omap44xx()) {
- devices = omap4_devices;
- omap_iommu_pdev = omap4_iommu_pdev;
+ devices_data = omap4_devices_data;
num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
} else
return -ENODEV;
+ ohl = omap_iommu_latency;
+ ohl_cnt = ARRAY_SIZE(omap_iommu_latency);
+
for (i = 0; i < num_iommu_devices; i++) {
- struct platform_device *pdev;
- const struct iommu_device *d = &devices[i];
+ struct iommu_platform_data *data = &devices_data[i];
- pdev = platform_device_alloc("omap-iommu", i);
- if (!pdev) {
- err = -ENOMEM;
- goto err_out;
- }
+ oh = omap_hwmod_lookup(data->oh_name);
+ data->io_base = oh->_mpu_rt_va;
+ data->irq = oh->mpu_irqs[0].irq;
- res[0].start = d->base;
- res[0].end = d->base + MMU_REG_SIZE - 1;
- res[1].start = res[1].end = d->irq;
-
- err = platform_device_add_resources(pdev, res,
- ARRAY_SIZE(res));
- if (err)
- goto err_out;
- err = platform_device_add_data(pdev, &d->pdata,
- sizeof(d->pdata));
- if (err)
- goto err_out;
- err = platform_device_add(pdev);
- if (err)
- goto err_out;
- omap_iommu_pdev[i] = pdev;
+ if (!oh) {
+ pr_err("%s: could not look up %s\n", __func__,
+ data->oh_name);
+ continue;
+ }
+ od = omap_device_build("omap-iommu", i, oh,
+ data, sizeof(*data),
+ ohl, ohl_cnt, false);
+ WARN(IS_ERR(od), "Could not build omap_device"
+ "for %s %s\n", "omap-iommu", data->oh_name);
}
return 0;
-
-err_out:
- while (i--)
- platform_device_put(omap_iommu_pdev[i]);
- return err;
}
module_init(omap_iommu_init);
-static void __exit omap_iommu_exit(void)
-{
- int i;
-
- for (i = 0; i < num_iommu_devices; i++)
- platform_device_unregister(omap_iommu_pdev[i]);
-}
-module_exit(omap_iommu_exit);
-
MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_AUTHOR("Hari Kanigeri");
MODULE_DESCRIPTION("omap iommu: omap device registration");
MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 174f1b9c8c0..d3bf263fd54 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -28,7 +28,6 @@ struct iotlb_entry {
struct iommu {
const char *name;
struct module *owner;
- struct clk *clk;
void __iomem *regbase;
struct device *dev;
void *isr_priv;
@@ -104,10 +103,12 @@ struct iommu_functions {
struct iommu_platform_data {
const char *name;
- const char *clk_name;
+ const char *oh_name;
const int nr_tlb_entries;
u32 da_start;
u32 da_end;
+ int irq;
+ void __iomem *io_base;
};
/* IOMMU errors */
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 5ec694f18cd..3e84b77d5ed 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -911,25 +911,17 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
{
int err = -ENODEV;
void *p;
- int irq;
struct iommu *obj;
- struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
- if (pdev->num_resources != 2)
- return -EINVAL;
-
obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
if (!obj)
return -ENOMEM;
- obj->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(obj->clk))
- goto err_clk;
-
obj->nr_tlb_entries = pdata->nr_tlb_entries;
obj->name = pdata->name;
obj->dev = &pdev->dev;
+ obj->pdev = pdev;
obj->ctx = (void *)obj + sizeof(*obj);
obj->da_start = pdata->da_start;
obj->da_end = pdata->da_end;
@@ -939,31 +931,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
spin_lock_init(&obj->page_table_lock);
INIT_LIST_HEAD(&obj->mmap);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- err = -ENODEV;
- goto err_mem;
- }
-
- res = request_mem_region(res->start, resource_size(res),
- dev_name(&pdev->dev));
- if (!res) {
- err = -EIO;
- goto err_mem;
- }
-
- obj->regbase = ioremap(res->start, resource_size(res));
- if (!obj->regbase) {
- err = -ENOMEM;
- goto err_ioremap;
- }
+ obj->regbase = pdata->io_base;
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- err = -ENODEV;
- goto err_irq;
- }
- err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
+ err = request_irq(pdata->irq, iommu_fault_handler, IRQF_SHARED,
dev_name(&pdev->dev), obj);
if (err < 0)
goto err_irq;
@@ -984,36 +954,24 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
return 0;
err_pgd:
- free_irq(irq, obj);
+ free_irq(pdata->irq, obj);
err_irq:
- iounmap(obj->regbase);
-err_ioremap:
- release_mem_region(res->start, resource_size(res));
-err_mem:
- clk_put(obj->clk);
-err_clk:
kfree(obj);
return err;
}
static int __devexit omap_iommu_remove(struct platform_device *pdev)
{
- int irq;
- struct resource *res;
struct iommu *obj = platform_get_drvdata(pdev);
+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+ free_irq(pdata->irq, obj);
platform_set_drvdata(pdev, NULL);
iopgtable_clear_entry_all(obj);
free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
- irq = platform_get_irq(pdev, 0);
- free_irq(irq, obj);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
- iounmap(obj->regbase);
-
- clk_put(obj->clk);
dev_info(&pdev->dev, "%s removed\n", obj->name);
kfree(obj);
return 0;