summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2009-11-07 06:59:47 +0530
committerSantosh Shilimkar <santosh.shilimkar@ti.com>2009-11-07 06:59:47 +0530
commit9e034c986287a3338c393836f27e838b8f87539e (patch)
tree2a7cdc1384ad5f3ce230310e275cf17aa35db735 /arch/arm/mach-omap2
parent8aa5e79648ce7b16943456f2578b9b68573aac9c (diff)
parent3d8b36e8e6725484d6a5d7fc258afaf37ca2db96 (diff)
Merge branch 'tesla-dev-v2.6.31_wakeup' of git://dev.omapzoom.org/pub/scm/tisyslink/kernel-syslink into L24x-20091106
Conflicts: arch/arm/Kconfig arch/arm/plat-omap/include/mach/irqs.h drivers/Makefile
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Makefile7
-rw-r--r--arch/arm/mach-omap2/devices.c20
-rw-r--r--arch/arm/mach-omap2/dspbridge.c76
-rw-r--r--arch/arm/mach-omap2/io.c2
-rw-r--r--arch/arm/mach-omap2/iommu2.c8
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-omap2/mailbox.c164
-rw-r--r--arch/arm/mach-omap2/omap4-iommu.c112
7 files changed, 354 insertions, 35 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 71506f325d63..a6cea7e84825 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -39,9 +39,13 @@ endif
obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+# MAILBOX
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+mailbox_mach-objs := mailbox.o
+
iommu-y += iommu2.o
iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o
-
+iommu-$(CONFIG_ARCH_OMAP4) += omap4-iommu.o
obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)
# Specific board support
@@ -81,3 +85,4 @@ obj-y += $(onenand-m) $(onenand-y)
smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o
obj-y += $(smc91x-m) $(smc91x-y)
+obj-$(CONFIG_MPU_BRIDGE) += dspbridge.o
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index b6b437e6fc6b..2575394fd119 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -136,8 +136,11 @@ static inline void omap_init_camera(void)
#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+#ifdef CONFIG_ARCH_OMAP4
+#define MBOX_REG_SIZE 0x130
+#else
#define MBOX_REG_SIZE 0x120
-
+#endif
static struct resource omap2_mbox_resources[] = {
{
.start = OMAP24XX_MAILBOX_BASE,
@@ -166,6 +169,18 @@ static struct resource omap3_mbox_resources[] = {
},
};
+static struct resource omap4_mbox_resources[] = {
+ {
+ .start = OMAP44xx_MAILBOX_BASE,
+ .end = OMAP44xx_MAILBOX_BASE + MBOX_REG_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_44XX_MAIL_U0_MPU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct platform_device mbox_device = {
.name = "omap2-mailbox",
.id = -1,
@@ -179,6 +194,9 @@ static inline void omap_init_mbox(void)
} else if (cpu_is_omap3430()) {
mbox_device.num_resources = ARRAY_SIZE(omap3_mbox_resources);
mbox_device.resource = omap3_mbox_resources;
+ } else if (cpu_is_omap44xx()) {
+ mbox_device.num_resources = ARRAY_SIZE(omap4_mbox_resources);
+ mbox_device.resource = omap4_mbox_resources;
} else {
pr_err("%s: platform not supported\n", __func__);
return;
diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
new file mode 100644
index 000000000000..f00d0c963c7b
--- /dev/null
+++ b/arch/arm/mach-omap2/dspbridge.c
@@ -0,0 +1,76 @@
+/*
+ * TI's dspbridge platform device registration
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+#include <mach/omap-pm.h>
+#endif
+#include <dspbridge/host_os.h>
+
+static struct platform_device *dspbridge_pdev;
+
+static struct dspbridge_platform_data dspbridge_pdata __initdata = {
+
+#ifdef CONFIG_BRIDGE_DVFS
+ .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
+ .dsp_get_opp = omap_pm_dsp_get_opp,
+ .cpu_set_freq = omap_pm_cpu_set_freq,
+ .cpu_get_freq = omap_pm_cpu_get_freq,
+#endif
+};
+
+static int __init dspbridge_init(void)
+{
+ struct platform_device *pdev;
+ int err = -ENOMEM;
+ struct dspbridge_platform_data *pdata = &dspbridge_pdata;
+
+ pdata->phys_mempool_base = dspbridge_get_mempool_base();
+
+ if (pdata->phys_mempool_base) {
+ pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
+ pr_info("%s: %x bytes @ %x\n", __func__,
+ pdata->phys_mempool_size, pdata->phys_mempool_base);
+ }
+
+ pdev = platform_device_alloc("C6410", -1);
+ if (!pdev)
+ goto err_out;
+
+ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (err)
+ goto err_out;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_out;
+
+ dspbridge_pdev = pdev;
+ return 0;
+
+err_out:
+ platform_device_put(pdev);
+ return err;
+}
+module_init(dspbridge_init);
+
+static void __exit dspbridge_exit(void)
+{
+ platform_device_unregister(dspbridge_pdev);
+}
+module_exit(dspbridge_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_DESCRIPTION("TI's dspbridge platform device registration");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 650497aed793..e5156408eab4 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -43,6 +43,7 @@
#include <mach/clockdomain.h>
#include "clockdomains.h"
#endif
+#include <dspbridge/host_os.h>
/*
* The machine specific code may provide the extra mapping besides the
* default mapping provided here.
@@ -264,6 +265,7 @@ void __init omap2_map_common_io(void)
omap2_check_revision();
omap_sram_init();
omapfb_reserve_sdram();
+ dspbridge_reserve_sdram();
}
/*
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 015f22a53ead..01cb15d9df3c 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -80,12 +80,16 @@ static int omap2_iommu_enable(struct iommu *obj)
if (l & MMU_SYS_RESETDONE)
break;
} while (time_after(jiffies, timeout));
-
+/* FIXME: Hack till the reading the MMU status register
+ * is resolved in Simulator. Simulator doesn't update
+ * the STATUS register.
+ */
+#ifndef CONFIG_ARCH_OMAP4
if (!(l & MMU_SYS_RESETDONE)) {
dev_err(obj->dev, "can't take mmu out of reset\n");
return -ENODEV;
}
-
+#endif
l = iommu_read_reg(obj, MMU_REVISION);
dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
(l >> 4) & 0xf, l & 0xf);
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 6f71f3730c97..6fc859079410 100644..100755
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -18,21 +18,36 @@
#include <mach/mailbox.h>
#include <mach/irqs.h>
+#define DRV_NAME "omap2-mailbox"
+
#define MAILBOX_REVISION 0x000
#define MAILBOX_SYSCONFIG 0x010
#define MAILBOX_SYSSTATUS 0x014
#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
#define MAILBOX_FIFOSTATUS(m) (0x080 + 4 * (m))
#define MAILBOX_MSGSTATUS(m) (0x0c0 + 4 * (m))
+
+#ifdef CONFIG_ARCH_OMAP4
+#define MAILBOX_IRQSTATUS(u) (0x104 + 10 * (u))
+#define MAILBOX_IRQENABLE(u) (0x108 + 10 * (u))
+#define MAILBOX_IRQENABLE_CLR(u) (0x10c + 10 * (u))
+#else
#define MAILBOX_IRQSTATUS(u) (0x100 + 8 * (u))
#define MAILBOX_IRQENABLE(u) (0x104 + 8 * (u))
+#endif
-#define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u)))
-#define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1))
+#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1))
+#ifdef CONFIG_ARCH_OMAP4
+#define MBOX_REG_SIZE 0x130
+#else
#define MBOX_REG_SIZE 0x120
+#endif
+
#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
+
static void __iomem *mbox_base;
struct omap_mbox2_fifo {
@@ -49,9 +64,13 @@ struct omap_mbox2_priv {
u32 newmsg_bit;
u32 notfull_bit;
u32 ctx[MBOX_NR_REGS];
+#ifdef CONFIG_ARCH_OMAP4
+ unsigned long irqdisable;
+#endif
};
static struct clk *mbox_ick_handle;
+static int mbox_configured;
static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
omap_mbox_type_t irq);
@@ -70,31 +89,45 @@ static inline void mbox_write_reg(u32 val, size_t ofs)
static int omap2_mbox_startup(struct omap_mbox *mbox)
{
unsigned int l;
+ if (!mbox_configured) {
+ if (!cpu_is_omap44xx()) {
+ mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
+ if (IS_ERR(mbox_ick_handle)) {
+ printk(KERN_ERR "Could not get"
+ "mailboxes_ick\n");
+ return -ENODEV;
+ }
+ clk_enable(mbox_ick_handle);
+ }
- mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
- if (IS_ERR(mbox_ick_handle)) {
- printk("Could not get mailboxes_ick\n");
- return -ENODEV;
- }
- clk_enable(mbox_ick_handle);
-
- l = mbox_read_reg(MAILBOX_REVISION);
- pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
- /* set smart-idle & autoidle */
- l = mbox_read_reg(MAILBOX_SYSCONFIG);
- l |= 0x00000011;
- mbox_write_reg(l, MAILBOX_SYSCONFIG);
+ l = mbox_read_reg(MAILBOX_REVISION);
+ pr_info("omap mailbox rev %d.%d\n",
+ (l & 0xf0) >> 4, (l & 0x0f));
+ /* set smart-idle & autoidle */
+ l = mbox_read_reg(MAILBOX_SYSCONFIG);
+ l |= 0x00000011;
+ mbox_write_reg(l, MAILBOX_SYSCONFIG);
+ }
+ mbox_configured++;
omap2_mbox_enable_irq(mbox, IRQ_RX);
return 0;
}
static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
- clk_disable(mbox_ick_handle);
- clk_put(mbox_ick_handle);
+{ if (mbox_configured > 0)
+ mbox_configured--;
+ if (!cpu_is_omap44xx()) {
+ if (!mbox_configured) {
+ clk_disable(mbox_ick_handle);
+ clk_put(mbox_ick_handle);
+ mbox_ick_handle = NULL;
+ }
+ } else {
+ printk(KERN_ERR "OMAP4 clocks are not modeled");
+ }
+
}
/* Mailbox FIFO handle functions */
@@ -123,7 +156,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
{
struct omap_mbox2_fifo *fifo =
&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
- return (mbox_read_reg(fifo->fifo_stat));
+ return mbox_read_reg(fifo->fifo_stat);
}
/* Mailbox IRQ handle functions */
@@ -143,10 +176,9 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
{
struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
- l = mbox_read_reg(p->irqenable);
+ l = mbox_read_reg(p->irqdisable);
l &= ~bit;
- mbox_write_reg(l, p->irqenable);
+ mbox_write_reg(l, p->irqdisable);
}
static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
@@ -156,6 +188,8 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_write_reg(bit, p->irqstatus);
+ /* Flush post writing */
+ mbox_read_reg(p->irqstatus);
}
static int omap2_mbox_is_irq(struct omap_mbox *mbox,
@@ -166,7 +200,7 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox,
u32 enable = mbox_read_reg(p->irqenable);
u32 status = mbox_read_reg(p->irqstatus);
- return (enable & status & bit);
+ return (int)(enable & status & bit);
}
static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
@@ -219,9 +253,12 @@ static struct omap_mbox_ops omap2_mbox_ops = {
*/
/* FIXME: the following structs should be filled automatically by the user id */
-
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_mbox2_priv omap2_mbox_1_priv = {
+#else
/* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
+#endif
.tx_fifo = {
.msg = MAILBOX_MESSAGE(0),
.fifo_stat = MAILBOX_FIFOSTATUS(0),
@@ -234,7 +271,19 @@ static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
.irqstatus = MAILBOX_IRQSTATUS(0),
.notfull_bit = MAILBOX_IRQ_NOTFULL(0),
.newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
+#ifdef CONFIG_ARCH_OMAP4
+ .irqdisable = MAILBOX_IRQENABLE_CLR(0),
+#endif
+};
+
+#ifdef CONFIG_ARCH_OMAP4
+struct omap_mbox mbox_1_info = {
+ .name = "mailbox-1",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_1_priv,
};
+EXPORT_SYMBOL(mbox_1_info);
+#else
struct omap_mbox mbox_dsp_info = {
.name = "dsp",
@@ -242,6 +291,33 @@ struct omap_mbox mbox_dsp_info = {
.priv = &omap2_mbox_dsp_priv,
};
EXPORT_SYMBOL(mbox_dsp_info);
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_mbox2_priv omap2_mbox_2_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE(3),
+ .fifo_stat = MAILBOX_FIFOSTATUS(3),
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE(2),
+ .msg_stat = MAILBOX_MSGSTATUS(2),
+ },
+ .irqenable = MAILBOX_IRQENABLE(0),
+ .irqstatus = MAILBOX_IRQSTATUS(0),
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(3),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(2),
+ .irqdisable = MAILBOX_IRQENABLE_CLR(0),
+};
+
+struct omap_mbox mbox_2_info = {
+ .name = "mailbox-2",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_2_priv,
+};
+EXPORT_SYMBOL(mbox_2_info);
+#endif
+
#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
static struct omap_mbox2_priv omap2_mbox_iva_priv = {
@@ -282,17 +358,31 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
return -ENOMEM;
/* DSP or IVA2 IRQ */
- ret = platform_get_irq(pdev, 0);
- if (ret < 0) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid irq resource\n");
+ ret = -ENODEV;
goto err_dsp;
}
- mbox_dsp_info.irq = ret;
-
+#ifdef CONFIG_ARCH_OMAP4
+ mbox_1_info.irq = res->start;
+ ret = omap_mbox_register(&pdev->dev, &mbox_1_info);
+#else
+ mbox_dsp_info.irq = res->start;
ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
+#endif
if (ret)
goto err_dsp;
+#ifdef CONFIG_ARCH_OMAP4
+
+ mbox_2_info.irq = res->start;
+ ret = omap_mbox_register(&pdev->dev, &mbox_2_info);
+ if (ret)
+ goto err_mbox_2;
+#endif
+
#if defined(CONFIG_ARCH_OMAP2420) /* IVA */
if (cpu_is_omap2420()) {
/* IVA IRQ */
@@ -310,8 +400,14 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
#endif
return 0;
+#ifdef CONFIG_ARCH_OMAP4
+err_mbox_2:
+ omap_mbox_unregister(&mbox_1_info);
+#else
err_iva1:
omap_mbox_unregister(&mbox_dsp_info);
+#endif
+
err_dsp:
iounmap(mbox_base);
return ret;
@@ -322,7 +418,13 @@ static int __devexit omap2_mbox_remove(struct platform_device *pdev)
#if defined(CONFIG_ARCH_OMAP2420)
omap_mbox_unregister(&mbox_iva_info);
#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+ omap_mbox_unregister(&mbox_2_info);
+ omap_mbox_unregister(&mbox_1_info);
+#else
omap_mbox_unregister(&mbox_dsp_info);
+#endif
iounmap(mbox_base);
return 0;
}
@@ -331,7 +433,7 @@ static struct platform_driver omap2_mbox_driver = {
.probe = omap2_mbox_probe,
.remove = __devexit_p(omap2_mbox_remove),
.driver = {
- .name = "omap2-mailbox",
+ .name = DRV_NAME,
},
};
@@ -351,4 +453,4 @@ module_exit(omap2_mbox_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("omap mailbox: omap2/3 architecture specific functions");
MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>, Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");
+MODULE_ALIAS("platform:"DRV_NAME);
diff --git a/arch/arm/mach-omap2/omap4-iommu.c b/arch/arm/mach-omap2/omap4-iommu.c
new file mode 100644
index 000000000000..5a782df0dcd2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-iommu.c
@@ -0,0 +1,112 @@
+/*
+ * omap iommu: omap4 device registration
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Written by Hari Kanigeri <h-kanigeri2@ti.com>
+ *
+ * Added support for OMAP4. This is based on original file
+ * omap3-iommu.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/iommu.h>
+#include <mach/irqs.h>
+
+#define OMAP4_MMU1_BASE 0x55082000
+#define OMAP4_MMU2_BASE 0x4A066000
+
+#define OMAP4_MMU1_IRQ INT_44XX_DUCATI_MMU_IRQ
+#define OMAP4_MMU2_IRQ INT_44XX_DSP_MMU
+
+
+
+static unsigned long iommu_base[] __initdata = {
+ OMAP4_MMU1_BASE,
+ OMAP4_MMU2_BASE,
+};
+
+static int iommu_irq[] __initdata = {
+ OMAP4_MMU1_IRQ,
+ OMAP4_MMU2_IRQ,
+};
+
+static const struct iommu_platform_data omap4_iommu_pdata[] __initconst = {
+ {
+ .name = "ducati",
+ .nr_tlb_entries = 32,
+ .clk_name = "ducati_ick",
+ },
+#if defined(CONFIG_MPU_TESLA_IOMMU)
+ {
+ .name = "tesla",
+ .nr_tlb_entries = 32,
+ .clk_name = "tesla_ick",
+ },
+#endif
+};
+#define NR_IOMMU_DEVICES ARRAY_SIZE(omap4_iommu_pdata)
+
+static struct platform_device *omap4_iommu_pdev[NR_IOMMU_DEVICES];
+
+static int __init omap4_iommu_init(void)
+{
+ int i, err;
+
+ for (i = 0; i < NR_IOMMU_DEVICES; i++) {
+ struct platform_device *pdev;
+ struct resource res[2];
+
+ pdev = platform_device_alloc("omap-iommu", i);
+ if (!pdev) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(res, 0, sizeof(res));
+ res[0].start = iommu_base[i];
+ res[0].end = iommu_base[i] + MMU_REG_SIZE - 1;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = res[1].end = iommu_irq[i];
+ res[1].flags = IORESOURCE_IRQ;
+
+ err = platform_device_add_resources(pdev, res,
+ ARRAY_SIZE(res));
+ if (err)
+ goto err_out;
+ err = platform_device_add_data(pdev, &omap4_iommu_pdata[i],
+ sizeof(omap4_iommu_pdata[0]));
+ if (err)
+ goto err_out;
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_out;
+ omap4_iommu_pdev[i] = pdev;
+ }
+ return 0;
+
+err_out:
+ while (i--)
+ platform_device_put(omap4_iommu_pdev[i]);
+ return err;
+}
+module_init(omap4_iommu_init);
+
+static void __exit omap4_iommu_exit(void)
+{
+ int i;
+
+ for (i = 0; i < NR_IOMMU_DEVICES; i++)
+ platform_device_unregister(omap4_iommu_pdev[i]);
+}
+module_exit(omap4_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU, Hari Kanigeri");
+MODULE_DESCRIPTION("omap iommu: omap4 device registration");
+MODULE_LICENSE("GPL v2");
+