Merge tag 'omap-for-v3.8/cleanup-headers-iommu-signed' of git://git.kernel.org/pub...
authorOlof Johansson <olof@lixom.net>
Sat, 1 Dec 2012 05:38:59 +0000 (21:38 -0800)
committerOlof Johansson <olof@lixom.net>
Sat, 1 Dec 2012 05:38:59 +0000 (21:38 -0800)
From Tony Lindgren:

Move most of remaining omap iommu code to drivers/iommu.
This is needed for the multiplatform kernels as the plat
and mach headers cannot be included.

These changes were agreed to be merged via the arm-soc
tree by Joerg and Ohad as these will cause some merge
conflicts with the other related clean-up branches.

So omap-for-v3.8/cleanup-headers-iommu should be added
as one of the depends branches for arm-soc.

* tag 'omap-for-v3.8/cleanup-headers-iommu-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
  ARM: OMAP2+: Move iommu/iovmm headers to platform_data
  ARM: OMAP2+: Make some definitions local
  ARM: OMAP2+: Move iommu2 to drivers/iommu/omap-iommu2.c
  ARM: OMAP2+: Move plat/iovmm.h to include/linux/omap-iommu.h
  ARM: OMAP2+: Move iopgtable header to drivers/iommu/
  ARM: OMAP: Merge iommu2.h into iommu.h

Conflicts due to surrounding changes fixed up in:
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
drivers/media/platform/omap3isp/ispvideo.c

Signed-off-by: Olof Johansson <olof@lixom.net>
24 files changed:
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/iommu2.c [deleted file]
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/plat-omap/include/plat/iommu.h [deleted file]
arch/arm/plat-omap/include/plat/iommu2.h [deleted file]
arch/arm/plat-omap/include/plat/iopgtable.h [deleted file]
arch/arm/plat-omap/include/plat/iovmm.h [deleted file]
drivers/iommu/Makefile
drivers/iommu/omap-iommu-debug.c
drivers/iommu/omap-iommu.c
drivers/iommu/omap-iommu.h [new file with mode: 0644]
drivers/iommu/omap-iommu2.c [new file with mode: 0644]
drivers/iommu/omap-iopgtable.h [new file with mode: 0644]
drivers/iommu/omap-iovmm.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h
drivers/media/platform/omap3isp/ispccdc.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispvideo.c
include/linux/omap-iommu.h [new file with mode: 0644]
include/linux/platform_data/iommu-omap.h [new file with mode: 0644]

index dd76ff7..11c57af 100644 (file)
@@ -202,8 +202,6 @@ obj-$(CONFIG_HW_PERF_EVENTS)                += pmu.o
 obj-$(CONFIG_OMAP_MBOX_FWK)            += mailbox_mach.o
 mailbox_mach-objs                      := mailbox.o
 
-obj-$(CONFIG_OMAP_IOMMU)               += iommu2.o
-
 iommu-$(CONFIG_OMAP_IOMMU)             := omap-iommu.o
 obj-y                                  += $(iommu-m) $(iommu-y)
 
index d2215e9..3cff7dc 100644 (file)
@@ -129,7 +129,7 @@ static struct platform_device omap2cam_device = {
 
 #if defined(CONFIG_IOMMU_API)
 
-#include <plat/iommu.h>
+#include <linux/platform_data/iommu-omap.h>
 
 static struct resource omap3isp_resources[] = {
        {
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
deleted file mode 100644 (file)
index eefc379..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * omap iommu: omap2/3 architecture specific functions
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
- *             Paul Mundt and Toshihiro Kobayashi
- *
- * 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/err.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/stringify.h>
-
-#include <plat/iommu.h>
-
-/*
- * omap2 architecture specific register bit definitions
- */
-#define IOMMU_ARCH_VERSION     0x00000011
-
-/* SYSCONF */
-#define MMU_SYS_IDLE_SHIFT     3
-#define MMU_SYS_IDLE_FORCE     (0 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_NONE      (1 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_SMART     (2 << MMU_SYS_IDLE_SHIFT)
-#define MMU_SYS_IDLE_MASK      (3 << MMU_SYS_IDLE_SHIFT)
-
-#define MMU_SYS_SOFTRESET      (1 << 1)
-#define MMU_SYS_AUTOIDLE       1
-
-/* SYSSTATUS */
-#define MMU_SYS_RESETDONE      1
-
-/* IRQSTATUS & IRQENABLE */
-#define MMU_IRQ_MULTIHITFAULT  (1 << 4)
-#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
-#define MMU_IRQ_EMUMISS                (1 << 2)
-#define MMU_IRQ_TRANSLATIONFAULT       (1 << 1)
-#define MMU_IRQ_TLBMISS                (1 << 0)
-
-#define __MMU_IRQ_FAULT                \
-       (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT)
-#define MMU_IRQ_MASK           \
-       (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS)
-#define MMU_IRQ_TWL_MASK       (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT)
-#define MMU_IRQ_TLB_MISS_MASK  (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS)
-
-/* MMU_CNTL */
-#define MMU_CNTL_SHIFT         1
-#define MMU_CNTL_MASK          (7 << MMU_CNTL_SHIFT)
-#define MMU_CNTL_EML_TLB       (1 << 3)
-#define MMU_CNTL_TWL_EN                (1 << 2)
-#define MMU_CNTL_MMU_EN                (1 << 1)
-
-#define get_cam_va_mask(pgsz)                          \
-       (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 :    \
-        ((pgsz) == MMU_CAM_PGSZ_1M)  ? 0xfff00000 :    \
-        ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 :    \
-        ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xfffff000 : 0)
-
-
-static void __iommu_set_twl(struct omap_iommu *obj, bool on)
-{
-       u32 l = iommu_read_reg(obj, MMU_CNTL);
-
-       if (on)
-               iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
-       else
-               iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
-
-       l &= ~MMU_CNTL_MASK;
-       if (on)
-               l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
-       else
-               l |= (MMU_CNTL_MMU_EN);
-
-       iommu_write_reg(obj, l, MMU_CNTL);
-}
-
-
-static int omap2_iommu_enable(struct omap_iommu *obj)
-{
-       u32 l, pa;
-       unsigned long timeout;
-
-       if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd,  SZ_16K))
-               return -EINVAL;
-
-       pa = virt_to_phys(obj->iopgd);
-       if (!IS_ALIGNED(pa, SZ_16K))
-               return -EINVAL;
-
-       iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
-
-       timeout = jiffies + msecs_to_jiffies(20);
-       do {
-               l = iommu_read_reg(obj, MMU_SYSSTATUS);
-               if (l & MMU_SYS_RESETDONE)
-                       break;
-       } while (!time_after(jiffies, timeout));
-
-       if (!(l & MMU_SYS_RESETDONE)) {
-               dev_err(obj->dev, "can't take mmu out of reset\n");
-               return -ENODEV;
-       }
-
-       l = iommu_read_reg(obj, MMU_REVISION);
-       dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
-                (l >> 4) & 0xf, l & 0xf);
-
-       l = iommu_read_reg(obj, MMU_SYSCONFIG);
-       l &= ~MMU_SYS_IDLE_MASK;
-       l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
-       iommu_write_reg(obj, l, MMU_SYSCONFIG);
-
-       iommu_write_reg(obj, pa, MMU_TTB);
-
-       __iommu_set_twl(obj, true);
-
-       return 0;
-}
-
-static void omap2_iommu_disable(struct omap_iommu *obj)
-{
-       u32 l = iommu_read_reg(obj, MMU_CNTL);
-
-       l &= ~MMU_CNTL_MASK;
-       iommu_write_reg(obj, l, MMU_CNTL);
-       iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
-
-       dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
-}
-
-static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
-{
-       __iommu_set_twl(obj, false);
-}
-
-static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
-{
-       u32 stat, da;
-       u32 errs = 0;
-
-       stat = iommu_read_reg(obj, MMU_IRQSTATUS);
-       stat &= MMU_IRQ_MASK;
-       if (!stat) {
-               *ra = 0;
-               return 0;
-       }
-
-       da = iommu_read_reg(obj, MMU_FAULT_AD);
-       *ra = da;
-
-       if (stat & MMU_IRQ_TLBMISS)
-               errs |= OMAP_IOMMU_ERR_TLB_MISS;
-       if (stat & MMU_IRQ_TRANSLATIONFAULT)
-               errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
-       if (stat & MMU_IRQ_EMUMISS)
-               errs |= OMAP_IOMMU_ERR_EMU_MISS;
-       if (stat & MMU_IRQ_TABLEWALKFAULT)
-               errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
-       if (stat & MMU_IRQ_MULTIHITFAULT)
-               errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
-       iommu_write_reg(obj, stat, MMU_IRQSTATUS);
-
-       return errs;
-}
-
-static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
-{
-       cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
-       cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
-}
-
-static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
-{
-       iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
-       iommu_write_reg(obj, cr->ram, MMU_RAM);
-}
-
-static u32 omap2_cr_to_virt(struct cr_regs *cr)
-{
-       u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
-       u32 mask = get_cam_va_mask(cr->cam & page_size);
-
-       return cr->cam & mask;
-}
-
-static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
-                                               struct iotlb_entry *e)
-{
-       struct cr_regs *cr;
-
-       if (e->da & ~(get_cam_va_mask(e->pgsz))) {
-               dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
-                       e->da);
-               return ERR_PTR(-EINVAL);
-       }
-
-       cr = kmalloc(sizeof(*cr), GFP_KERNEL);
-       if (!cr)
-               return ERR_PTR(-ENOMEM);
-
-       cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz | e->valid;
-       cr->ram = e->pa | e->endian | e->elsz | e->mixed;
-
-       return cr;
-}
-
-static inline int omap2_cr_valid(struct cr_regs *cr)
-{
-       return cr->cam & MMU_CAM_V;
-}
-
-static u32 omap2_get_pte_attr(struct iotlb_entry *e)
-{
-       u32 attr;
-
-       attr = e->mixed << 5;
-       attr |= e->endian;
-       attr |= e->elsz >> 3;
-       attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
-                       (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
-       return attr;
-}
-
-static ssize_t
-omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
-{
-       char *p = buf;
-
-       /* FIXME: Need more detail analysis of cam/ram */
-       p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram,
-                                       (cr->cam & MMU_CAM_P) ? 1 : 0);
-
-       return p - buf;
-}
-
-#define pr_reg(name)                                                   \
-       do {                                                            \
-               ssize_t bytes;                                          \
-               const char *str = "%20s: %08x\n";                       \
-               const int maxcol = 32;                                  \
-               bytes = snprintf(p, maxcol, str, __stringify(name),     \
-                                iommu_read_reg(obj, MMU_##name));      \
-               p += bytes;                                             \
-               len -= bytes;                                           \
-               if (len < maxcol)                                       \
-                       goto out;                                       \
-       } while (0)
-
-static ssize_t
-omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
-{
-       char *p = buf;
-
-       pr_reg(REVISION);
-       pr_reg(SYSCONFIG);
-       pr_reg(SYSSTATUS);
-       pr_reg(IRQSTATUS);
-       pr_reg(IRQENABLE);
-       pr_reg(WALKING_ST);
-       pr_reg(CNTL);
-       pr_reg(FAULT_AD);
-       pr_reg(TTB);
-       pr_reg(LOCK);
-       pr_reg(LD_TLB);
-       pr_reg(CAM);
-       pr_reg(RAM);
-       pr_reg(GFLUSH);
-       pr_reg(FLUSH_ENTRY);
-       pr_reg(READ_CAM);
-       pr_reg(READ_RAM);
-       pr_reg(EMU_FAULT_AD);
-out:
-       return p - buf;
-}
-
-static void omap2_iommu_save_ctx(struct omap_iommu *obj)
-{
-       int i;
-       u32 *p = obj->ctx;
-
-       for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
-               p[i] = iommu_read_reg(obj, i * sizeof(u32));
-               dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
-       }
-
-       BUG_ON(p[0] != IOMMU_ARCH_VERSION);
-}
-
-static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
-{
-       int i;
-       u32 *p = obj->ctx;
-
-       for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
-               iommu_write_reg(obj, p[i], i * sizeof(u32));
-               dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
-       }
-
-       BUG_ON(p[0] != IOMMU_ARCH_VERSION);
-}
-
-static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
-{
-       e->da           = cr->cam & MMU_CAM_VATAG_MASK;
-       e->pa           = cr->ram & MMU_RAM_PADDR_MASK;
-       e->valid        = cr->cam & MMU_CAM_V;
-       e->pgsz         = cr->cam & MMU_CAM_PGSZ_MASK;
-       e->endian       = cr->ram & MMU_RAM_ENDIAN_MASK;
-       e->elsz         = cr->ram & MMU_RAM_ELSZ_MASK;
-       e->mixed        = cr->ram & MMU_RAM_MIXED;
-}
-
-static const struct iommu_functions omap2_iommu_ops = {
-       .version        = IOMMU_ARCH_VERSION,
-
-       .enable         = omap2_iommu_enable,
-       .disable        = omap2_iommu_disable,
-       .set_twl        = omap2_iommu_set_twl,
-       .fault_isr      = omap2_iommu_fault_isr,
-
-       .tlb_read_cr    = omap2_tlb_read_cr,
-       .tlb_load_cr    = omap2_tlb_load_cr,
-
-       .cr_to_e        = omap2_cr_to_e,
-       .cr_to_virt     = omap2_cr_to_virt,
-       .alloc_cr       = omap2_alloc_cr,
-       .cr_valid       = omap2_cr_valid,
-       .dump_cr        = omap2_dump_cr,
-
-       .get_pte_attr   = omap2_get_pte_attr,
-
-       .save_ctx       = omap2_iommu_save_ctx,
-       .restore_ctx    = omap2_iommu_restore_ctx,
-       .dump_ctx       = omap2_iommu_dump_ctx,
-};
-
-static int __init omap2_iommu_init(void)
-{
-       return omap_install_iommu_arch(&omap2_iommu_ops);
-}
-module_init(omap2_iommu_init);
-
-static void __exit omap2_iommu_exit(void)
-{
-       omap_uninstall_iommu_arch(&omap2_iommu_ops);
-}
-module_exit(omap2_iommu_exit);
-
-MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
-MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
-MODULE_LICENSE("GPL v2");
index df298d4..a6a4ff8 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
-#include <plat/iommu.h>
+#include <linux/platform_data/iommu-omap.h>
 
 #include "soc.h"
 #include "common.h"
index addc1c2..7f73f21 100644 (file)
@@ -24,8 +24,8 @@
 #include "l4_3xxx.h"
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/platform_data/iommu-omap.h>
 #include <plat/dmtimer.h>
-#include <plat/iommu.h>
 
 #include "am35xx.h"
 
index f5b55a7..26f8e9f 100644 (file)
@@ -28,8 +28,8 @@
 #include <linux/platform_data/omap_ocp2scp.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/iommu-omap.h>
 #include <plat/dmtimer.h>
-#include <plat/iommu.h>
 
 #include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
deleted file mode 100644 (file)
index 68b5f03..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * omap iommu: main structures
- *
- * Copyright (C) 2008-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.
- */
-
-#ifndef __MACH_IOMMU_H
-#define __MACH_IOMMU_H
-
-struct iotlb_entry {
-       u32 da;
-       u32 pa;
-       u32 pgsz, prsvd, valid;
-       union {
-               u16 ap;
-               struct {
-                       u32 endian, elsz, mixed;
-               };
-       };
-};
-
-struct omap_iommu {
-       const char      *name;
-       struct module   *owner;
-       struct clk      *clk;
-       void __iomem    *regbase;
-       struct device   *dev;
-       void            *isr_priv;
-       struct iommu_domain *domain;
-
-       unsigned int    refcount;
-       spinlock_t      iommu_lock;     /* global for this whole object */
-
-       /*
-        * We don't change iopgd for a situation like pgd for a task,
-        * but share it globally for each iommu.
-        */
-       u32             *iopgd;
-       spinlock_t      page_table_lock; /* protect iopgd */
-
-       int             nr_tlb_entries;
-
-       struct list_head        mmap;
-       struct mutex            mmap_lock; /* protect mmap */
-
-       void *ctx; /* iommu context: registres saved area */
-       u32 da_start;
-       u32 da_end;
-};
-
-struct cr_regs {
-       union {
-               struct {
-                       u16 cam_l;
-                       u16 cam_h;
-               };
-               u32 cam;
-       };
-       union {
-               struct {
-                       u16 ram_l;
-                       u16 ram_h;
-               };
-               u32 ram;
-       };
-};
-
-struct iotlb_lock {
-       short base;
-       short vict;
-};
-
-/* architecture specific functions */
-struct iommu_functions {
-       unsigned long   version;
-
-       int (*enable)(struct omap_iommu *obj);
-       void (*disable)(struct omap_iommu *obj);
-       void (*set_twl)(struct omap_iommu *obj, bool on);
-       u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
-
-       void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
-       void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
-
-       struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
-                                                       struct iotlb_entry *e);
-       int (*cr_valid)(struct cr_regs *cr);
-       u32 (*cr_to_virt)(struct cr_regs *cr);
-       void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
-       ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
-                                                       char *buf);
-
-       u32 (*get_pte_attr)(struct iotlb_entry *e);
-
-       void (*save_ctx)(struct omap_iommu *obj);
-       void (*restore_ctx)(struct omap_iommu *obj);
-       ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
-};
-
-/**
- * struct omap_mmu_dev_attr - OMAP mmu device attributes for omap_hwmod
- * @da_start:          device address where the va space starts.
- * @da_end:            device address where the va space ends.
- * @nr_tlb_entries:    number of entries supported by the translation
- *                     look-aside buffer (TLB).
- */
-struct omap_mmu_dev_attr {
-       u32 da_start;
-       u32 da_end;
-       int nr_tlb_entries;
-};
-
-struct iommu_platform_data {
-       const char *name;
-       const char *clk_name;
-       const int nr_tlb_entries;
-       u32 da_start;
-       u32 da_end;
-};
-
-/**
- * struct iommu_arch_data - omap iommu private data
- * @name: name of the iommu device
- * @iommu_dev: handle of the iommu device
- *
- * This is an omap iommu private data object, which binds an iommu user
- * to its iommu device. This object should be placed at the iommu user's
- * dev_archdata so generic IOMMU API can be used without having to
- * utilize omap-specific plumbing anymore.
- */
-struct omap_iommu_arch_data {
-       const char *name;
-       struct omap_iommu *iommu_dev;
-};
-
-#ifdef CONFIG_IOMMU_API
-/**
- * dev_to_omap_iommu() - retrieves an omap iommu object from a user device
- * @dev: iommu client device
- */
-static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
-{
-       struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
-
-       return arch_data->iommu_dev;
-}
-#endif
-
-/* IOMMU errors */
-#define OMAP_IOMMU_ERR_TLB_MISS                (1 << 0)
-#define OMAP_IOMMU_ERR_TRANS_FAULT     (1 << 1)
-#define OMAP_IOMMU_ERR_EMU_MISS                (1 << 2)
-#define OMAP_IOMMU_ERR_TBLWALK_FAULT   (1 << 3)
-#define OMAP_IOMMU_ERR_MULTIHIT_FAULT  (1 << 4)
-
-#if defined(CONFIG_ARCH_OMAP1)
-#error "iommu for this processor not implemented yet"
-#else
-#include <plat/iommu2.h>
-#endif
-
-/*
- * utilities for super page(16MB, 1MB, 64KB and 4KB)
- */
-
-#define iopgsz_max(bytes)                      \
-       (((bytes) >= SZ_16M) ? SZ_16M :         \
-        ((bytes) >= SZ_1M)  ? SZ_1M  :         \
-        ((bytes) >= SZ_64K) ? SZ_64K :         \
-        ((bytes) >= SZ_4K)  ? SZ_4K  : 0)
-
-#define bytes_to_iopgsz(bytes)                         \
-       (((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M :       \
-        ((bytes) == SZ_1M)  ? MMU_CAM_PGSZ_1M  :       \
-        ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K :       \
-        ((bytes) == SZ_4K)  ? MMU_CAM_PGSZ_4K  : -1)
-
-#define iopgsz_to_bytes(iopgsz)                                \
-       (((iopgsz) == MMU_CAM_PGSZ_16M) ? SZ_16M :      \
-        ((iopgsz) == MMU_CAM_PGSZ_1M)  ? SZ_1M  :      \
-        ((iopgsz) == MMU_CAM_PGSZ_64K) ? SZ_64K :      \
-        ((iopgsz) == MMU_CAM_PGSZ_4K)  ? SZ_4K  : 0)
-
-#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0)
-
-/*
- * global functions
- */
-extern u32 omap_iommu_arch_version(void);
-
-extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
-
-extern int
-omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
-
-extern int omap_iommu_set_isr(const char *name,
-                int (*isr)(struct omap_iommu *obj, u32 da, u32 iommu_errs,
-                                   void *priv),
-                        void *isr_priv);
-
-extern void omap_iommu_save_ctx(struct device *dev);
-extern void omap_iommu_restore_ctx(struct device *dev);
-
-extern int omap_install_iommu_arch(const struct iommu_functions *ops);
-extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
-
-extern int omap_foreach_iommu_device(void *data,
-                               int (*fn)(struct device *, void *));
-
-extern ssize_t
-omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
-extern size_t
-omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
-
-#endif /* __MACH_IOMMU_H */
diff --git a/arch/arm/plat-omap/include/plat/iommu2.h b/arch/arm/plat-omap/include/plat/iommu2.h
deleted file mode 100644 (file)
index d4116b5..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * omap iommu: omap2 architecture specific definitions
- *
- * Copyright (C) 2008-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.
- */
-
-#ifndef __MACH_IOMMU2_H
-#define __MACH_IOMMU2_H
-
-#include <linux/io.h>
-
-/*
- * MMU Register offsets
- */
-#define MMU_REVISION           0x00
-#define MMU_SYSCONFIG          0x10
-#define MMU_SYSSTATUS          0x14
-#define MMU_IRQSTATUS          0x18
-#define MMU_IRQENABLE          0x1c
-#define MMU_WALKING_ST         0x40
-#define MMU_CNTL               0x44
-#define MMU_FAULT_AD           0x48
-#define MMU_TTB                        0x4c
-#define MMU_LOCK               0x50
-#define MMU_LD_TLB             0x54
-#define MMU_CAM                        0x58
-#define MMU_RAM                        0x5c
-#define MMU_GFLUSH             0x60
-#define MMU_FLUSH_ENTRY                0x64
-#define MMU_READ_CAM           0x68
-#define MMU_READ_RAM           0x6c
-#define MMU_EMU_FAULT_AD       0x70
-
-#define MMU_REG_SIZE           256
-
-/*
- * MMU Register bit definitions
- */
-#define MMU_LOCK_BASE_SHIFT    10
-#define MMU_LOCK_BASE_MASK     (0x1f << MMU_LOCK_BASE_SHIFT)
-#define MMU_LOCK_BASE(x)       \
-       ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
-
-#define MMU_LOCK_VICT_SHIFT    4
-#define MMU_LOCK_VICT_MASK     (0x1f << MMU_LOCK_VICT_SHIFT)
-#define MMU_LOCK_VICT(x)       \
-       ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
-
-#define MMU_CAM_VATAG_SHIFT    12
-#define MMU_CAM_VATAG_MASK \
-       ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
-#define MMU_CAM_P              (1 << 3)
-#define MMU_CAM_V              (1 << 2)
-#define MMU_CAM_PGSZ_MASK      3
-#define MMU_CAM_PGSZ_1M                (0 << 0)
-#define MMU_CAM_PGSZ_64K       (1 << 0)
-#define MMU_CAM_PGSZ_4K                (2 << 0)
-#define MMU_CAM_PGSZ_16M       (3 << 0)
-
-#define MMU_RAM_PADDR_SHIFT    12
-#define MMU_RAM_PADDR_MASK \
-       ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
-#define MMU_RAM_ENDIAN_SHIFT   9
-#define MMU_RAM_ENDIAN_MASK    (1 << MMU_RAM_ENDIAN_SHIFT)
-#define MMU_RAM_ENDIAN_BIG     (1 << MMU_RAM_ENDIAN_SHIFT)
-#define MMU_RAM_ENDIAN_LITTLE  (0 << MMU_RAM_ENDIAN_SHIFT)
-#define MMU_RAM_ELSZ_SHIFT     7
-#define MMU_RAM_ELSZ_MASK      (3 << MMU_RAM_ELSZ_SHIFT)
-#define MMU_RAM_ELSZ_8         (0 << MMU_RAM_ELSZ_SHIFT)
-#define MMU_RAM_ELSZ_16                (1 << MMU_RAM_ELSZ_SHIFT)
-#define MMU_RAM_ELSZ_32                (2 << MMU_RAM_ELSZ_SHIFT)
-#define MMU_RAM_ELSZ_NONE      (3 << MMU_RAM_ELSZ_SHIFT)
-#define MMU_RAM_MIXED_SHIFT    6
-#define MMU_RAM_MIXED_MASK     (1 << MMU_RAM_MIXED_SHIFT)
-#define MMU_RAM_MIXED          MMU_RAM_MIXED_MASK
-
-/*
- * register accessors
- */
-static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
-{
-       return __raw_readl(obj->regbase + offs);
-}
-
-static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
-{
-       __raw_writel(val, obj->regbase + offs);
-}
-
-#endif /* __MACH_IOMMU2_H */
diff --git a/arch/arm/plat-omap/include/plat/iopgtable.h b/arch/arm/plat-omap/include/plat/iopgtable.h
deleted file mode 100644 (file)
index 66a8139..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * omap iommu: pagetable definitions
- *
- * Copyright (C) 2008-2010 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.
- */
-
-#ifndef __PLAT_OMAP_IOMMU_H
-#define __PLAT_OMAP_IOMMU_H
-
-/*
- * "L2 table" address mask and size definitions.
- */
-#define IOPGD_SHIFT            20
-#define IOPGD_SIZE             (1UL << IOPGD_SHIFT)
-#define IOPGD_MASK             (~(IOPGD_SIZE - 1))
-
-/*
- * "section" address mask and size definitions.
- */
-#define IOSECTION_SHIFT                20
-#define IOSECTION_SIZE         (1UL << IOSECTION_SHIFT)
-#define IOSECTION_MASK         (~(IOSECTION_SIZE - 1))
-
-/*
- * "supersection" address mask and size definitions.
- */
-#define IOSUPER_SHIFT          24
-#define IOSUPER_SIZE           (1UL << IOSUPER_SHIFT)
-#define IOSUPER_MASK           (~(IOSUPER_SIZE - 1))
-
-#define PTRS_PER_IOPGD         (1UL << (32 - IOPGD_SHIFT))
-#define IOPGD_TABLE_SIZE       (PTRS_PER_IOPGD * sizeof(u32))
-
-/*
- * "small page" address mask and size definitions.
- */
-#define IOPTE_SHIFT            12
-#define IOPTE_SIZE             (1UL << IOPTE_SHIFT)
-#define IOPTE_MASK             (~(IOPTE_SIZE - 1))
-
-/*
- * "large page" address mask and size definitions.
- */
-#define IOLARGE_SHIFT          16
-#define IOLARGE_SIZE           (1UL << IOLARGE_SHIFT)
-#define IOLARGE_MASK           (~(IOLARGE_SIZE - 1))
-
-#define PTRS_PER_IOPTE         (1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
-#define IOPTE_TABLE_SIZE       (PTRS_PER_IOPTE * sizeof(u32))
-
-#define IOPAGE_MASK            IOPTE_MASK
-
-/**
- * omap_iommu_translate() - va to pa translation
- * @d:         omap iommu descriptor
- * @va:                virtual address
- * @mask:      omap iommu descriptor mask
- *
- * va to pa translation
- */
-static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
-{
-       return (d & mask) | (va & (~mask));
-}
-
-/*
- * some descriptor attributes.
- */
-#define IOPGD_TABLE            (1 << 0)
-#define IOPGD_SECTION          (2 << 0)
-#define IOPGD_SUPER            (1 << 18 | 2 << 0)
-
-#define iopgd_is_table(x)      (((x) & 3) == IOPGD_TABLE)
-#define iopgd_is_section(x)    (((x) & (1 << 18 | 3)) == IOPGD_SECTION)
-#define iopgd_is_super(x)      (((x) & (1 << 18 | 3)) == IOPGD_SUPER)
-
-#define IOPTE_SMALL            (2 << 0)
-#define IOPTE_LARGE            (1 << 0)
-
-#define iopte_is_small(x)      (((x) & 2) == IOPTE_SMALL)
-#define iopte_is_large(x)      (((x) & 3) == IOPTE_LARGE)
-
-/* to find an entry in a page-table-directory */
-#define iopgd_index(da)                (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
-#define iopgd_offset(obj, da)  ((obj)->iopgd + iopgd_index(da))
-
-#define iopgd_page_paddr(iopgd)        (*iopgd & ~((1 << 10) - 1))
-#define iopgd_page_vaddr(iopgd)        ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
-
-/* to find an entry in the second-level page table. */
-#define iopte_index(da)                (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
-#define iopte_offset(iopgd, da)        (iopgd_page_vaddr(iopgd) + iopte_index(da))
-
-static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
-                                  u32 flags)
-{
-       memset(e, 0, sizeof(*e));
-
-       e->da           = da;
-       e->pa           = pa;
-       e->valid        = 1;
-       /* FIXME: add OMAP1 support */
-       e->pgsz         = flags & MMU_CAM_PGSZ_MASK;
-       e->endian       = flags & MMU_RAM_ENDIAN_MASK;
-       e->elsz         = flags & MMU_RAM_ELSZ_MASK;
-       e->mixed        = flags & MMU_RAM_MIXED_MASK;
-
-       return iopgsz_to_bytes(e->pgsz);
-}
-
-#define to_iommu(dev)                                                  \
-       (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
-
-#endif /* __PLAT_OMAP_IOMMU_H */
diff --git a/arch/arm/plat-omap/include/plat/iovmm.h b/arch/arm/plat-omap/include/plat/iovmm.h
deleted file mode 100644 (file)
index 498e57c..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * omap iommu: simple virtual address space management
- *
- * Copyright (C) 2008-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.
- */
-
-#ifndef __IOMMU_MMAP_H
-#define __IOMMU_MMAP_H
-
-#include <linux/iommu.h>
-
-struct iovm_struct {
-       struct omap_iommu       *iommu; /* iommu object which this belongs to */
-       u32                     da_start; /* area definition */
-       u32                     da_end;
-       u32                     flags; /* IOVMF_: see below */
-       struct list_head        list; /* linked in ascending order */
-       const struct sg_table   *sgt; /* keep 'page' <-> 'da' mapping */
-       void                    *va; /* mpu side mapped address */
-};
-
-/*
- * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
- *
- * lower 16 bit is used for h/w and upper 16 bit is for s/w.
- */
-#define IOVMF_SW_SHIFT         16
-
-/*
- * iovma: h/w flags derived from cam and ram attribute
- */
-#define IOVMF_CAM_MASK         (~((1 << 10) - 1))
-#define IOVMF_RAM_MASK         (~IOVMF_CAM_MASK)
-
-#define IOVMF_PGSZ_MASK                (3 << 0)
-#define IOVMF_PGSZ_1M          MMU_CAM_PGSZ_1M
-#define IOVMF_PGSZ_64K         MMU_CAM_PGSZ_64K
-#define IOVMF_PGSZ_4K          MMU_CAM_PGSZ_4K
-#define IOVMF_PGSZ_16M         MMU_CAM_PGSZ_16M
-
-#define IOVMF_ENDIAN_MASK      (1 << 9)
-#define IOVMF_ENDIAN_BIG       MMU_RAM_ENDIAN_BIG
-#define IOVMF_ENDIAN_LITTLE    MMU_RAM_ENDIAN_LITTLE
-
-#define IOVMF_ELSZ_MASK                (3 << 7)
-#define IOVMF_ELSZ_8           MMU_RAM_ELSZ_8
-#define IOVMF_ELSZ_16          MMU_RAM_ELSZ_16
-#define IOVMF_ELSZ_32          MMU_RAM_ELSZ_32
-#define IOVMF_ELSZ_NONE                MMU_RAM_ELSZ_NONE
-
-#define IOVMF_MIXED_MASK       (1 << 6)
-#define IOVMF_MIXED            MMU_RAM_MIXED
-
-/*
- * iovma: s/w flags, used for mapping and umapping internally.
- */
-#define IOVMF_MMIO             (1 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC            (2 << IOVMF_SW_SHIFT)
-#define IOVMF_ALLOC_MASK       (3 << IOVMF_SW_SHIFT)
-
-/* "superpages" is supported just with physically linear pages */
-#define IOVMF_DISCONT          (1 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR           (2 << (2 + IOVMF_SW_SHIFT))
-#define IOVMF_LINEAR_MASK      (3 << (2 + IOVMF_SW_SHIFT))
-
-#define IOVMF_DA_FIXED         (1 << (4 + IOVMF_SW_SHIFT))
-
-
-extern struct iovm_struct *omap_find_iovm_area(struct device *dev, u32 da);
-extern u32
-omap_iommu_vmap(struct iommu_domain *domain, struct device *dev, u32 da,
-                       const struct sg_table *sgt, u32 flags);
-extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain,
-                               struct device *dev, u32 da);
-extern u32
-omap_iommu_vmalloc(struct iommu_domain *domain, struct device *dev,
-                               u32 da, size_t bytes, u32 flags);
-extern void
-omap_iommu_vfree(struct iommu_domain *domain, struct device *dev,
-                               const u32 da);
-extern void *omap_da_to_va(struct device *dev, u32 da);
-
-#endif /* __IOMMU_MMAP_H */
index 14a4d5f..f66b816 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
 obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
index f55fc5d..d97fbe4 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/platform_device.h>
 #include <linux/debugfs.h>
+#include <linux/omap-iommu.h>
+#include <linux/platform_data/iommu-omap.h>
 
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-
-#include <plat/iopgtable.h>
+#include "omap-iopgtable.h"
+#include "omap-iommu.h"
 
 #define MAXCOLUMN 100 /* for short messages */
 
index d0b1234..badc17c 100644 (file)
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/iommu.h>
+#include <linux/omap-iommu.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
 
-#include <plat/iommu.h>
+#include <linux/platform_data/iommu-omap.h>
 
-#include <plat/iopgtable.h>
+#include "omap-iopgtable.h"
+#include "omap-iommu.h"
 
 #define for_each_iotlb_cr(obj, n, __i, cr)                             \
        for (__i = 0;                                                   \
@@ -51,6 +54,21 @@ struct omap_iommu_domain {
        spinlock_t lock;
 };
 
+#define MMU_LOCK_BASE_SHIFT    10
+#define MMU_LOCK_BASE_MASK     (0x1f << MMU_LOCK_BASE_SHIFT)
+#define MMU_LOCK_BASE(x)       \
+       ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
+
+#define MMU_LOCK_VICT_SHIFT    4
+#define MMU_LOCK_VICT_MASK     (0x1f << MMU_LOCK_VICT_SHIFT)
+#define MMU_LOCK_VICT(x)       \
+       ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
+
+struct iotlb_lock {
+       short base;
+       short vict;
+};
+
 /* accommodate the difference between omap1 and omap2/3 */
 static const struct iommu_functions *arch_iommu;
 
@@ -1015,6 +1033,23 @@ static void iopte_cachep_ctor(void *iopte)
        clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
 }
 
+static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
+                                  u32 flags)
+{
+       memset(e, 0, sizeof(*e));
+
+       e->da           = da;
+       e->pa           = pa;
+       e->valid        = 1;
+       /* FIXME: add OMAP1 support */
+       e->pgsz         = flags & MMU_CAM_PGSZ_MASK;
+       e->endian       = flags & MMU_RAM_ENDIAN_MASK;
+       e->elsz         = flags & MMU_RAM_ELSZ_MASK;
+       e->mixed        = flags & MMU_RAM_MIXED_MASK;
+
+       return iopgsz_to_bytes(e->pgsz);
+}
+
 static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
                         phys_addr_t pa, size_t bytes, int prot)
 {
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
new file mode 100644 (file)
index 0000000..2b5f3c0
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * omap iommu: main structures
+ *
+ * Copyright (C) 2008-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.
+ */
+
+#if defined(CONFIG_ARCH_OMAP1)
+#error "iommu for this processor not implemented yet"
+#endif
+
+struct iotlb_entry {
+       u32 da;
+       u32 pa;
+       u32 pgsz, prsvd, valid;
+       union {
+               u16 ap;
+               struct {
+                       u32 endian, elsz, mixed;
+               };
+       };
+};
+
+struct omap_iommu {
+       const char      *name;
+       struct module   *owner;
+       struct clk      *clk;
+       void __iomem    *regbase;
+       struct device   *dev;
+       void            *isr_priv;
+       struct iommu_domain *domain;
+
+       unsigned int    refcount;
+       spinlock_t      iommu_lock;     /* global for this whole object */
+
+       /*
+        * We don't change iopgd for a situation like pgd for a task,
+        * but share it globally for each iommu.
+        */
+       u32             *iopgd;
+       spinlock_t      page_table_lock; /* protect iopgd */
+
+       int             nr_tlb_entries;
+
+       struct list_head        mmap;
+       struct mutex            mmap_lock; /* protect mmap */
+
+       void *ctx; /* iommu context: registres saved area */
+       u32 da_start;
+       u32 da_end;
+};
+
+struct cr_regs {
+       union {
+               struct {
+                       u16 cam_l;
+                       u16 cam_h;
+               };
+               u32 cam;
+       };
+       union {
+               struct {
+                       u16 ram_l;
+                       u16 ram_h;
+               };
+               u32 ram;
+       };
+};
+
+/* architecture specific functions */
+struct iommu_functions {
+       unsigned long   version;
+
+       int (*enable)(struct omap_iommu *obj);
+       void (*disable)(struct omap_iommu *obj);
+       void (*set_twl)(struct omap_iommu *obj, bool on);
+       u32 (*fault_isr)(struct omap_iommu *obj, u32 *ra);
+
+       void (*tlb_read_cr)(struct omap_iommu *obj, struct cr_regs *cr);
+       void (*tlb_load_cr)(struct omap_iommu *obj, struct cr_regs *cr);
+
+       struct cr_regs *(*alloc_cr)(struct omap_iommu *obj,
+                                                       struct iotlb_entry *e);
+       int (*cr_valid)(struct cr_regs *cr);
+       u32 (*cr_to_virt)(struct cr_regs *cr);
+       void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
+       ssize_t (*dump_cr)(struct omap_iommu *obj, struct cr_regs *cr,
+                                                       char *buf);
+
+       u32 (*get_pte_attr)(struct iotlb_entry *e);
+
+       void (*save_ctx)(struct omap_iommu *obj);
+       void (*restore_ctx)(struct omap_iommu *obj);
+       ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
+};
+
+#ifdef CONFIG_IOMMU_API
+/**
+ * dev_to_omap_iommu() - retrieves an omap iommu object from a user device
+ * @dev: iommu client device
+ */
+static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev)
+{
+       struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
+
+       return arch_data->iommu_dev;
+}
+#endif
+
+/*
+ * MMU Register offsets
+ */
+#define MMU_REVISION           0x00
+#define MMU_SYSCONFIG          0x10
+#define MMU_SYSSTATUS          0x14
+#define MMU_IRQSTATUS          0x18
+#define MMU_IRQENABLE          0x1c
+#define MMU_WALKING_ST         0x40
+#define MMU_CNTL               0x44
+#define MMU_FAULT_AD           0x48
+#define MMU_TTB                        0x4c
+#define MMU_LOCK               0x50
+#define MMU_LD_TLB             0x54
+#define MMU_CAM                        0x58
+#define MMU_RAM                        0x5c
+#define MMU_GFLUSH             0x60
+#define MMU_FLUSH_ENTRY                0x64
+#define MMU_READ_CAM           0x68
+#define MMU_READ_RAM           0x6c
+#define MMU_EMU_FAULT_AD       0x70
+
+#define MMU_REG_SIZE           256
+
+/*
+ * MMU Register bit definitions
+ */
+#define MMU_CAM_VATAG_SHIFT    12
+#define MMU_CAM_VATAG_MASK \
+       ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
+#define MMU_CAM_P              (1 << 3)
+#define MMU_CAM_V              (1 << 2)
+#define MMU_CAM_PGSZ_MASK      3
+#define MMU_CAM_PGSZ_1M                (0 << 0)
+#define MMU_CAM_PGSZ_64K       (1 << 0)
+#define MMU_CAM_PGSZ_4K                (2 << 0)
+#define MMU_CAM_PGSZ_16M       (3 << 0)
+
+#define MMU_RAM_PADDR_SHIFT    12
+#define MMU_RAM_PADDR_MASK \
+       ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
+
+#define MMU_RAM_ENDIAN_MASK    (1 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ENDIAN_BIG     (1 << MMU_RAM_ENDIAN_SHIFT)
+
+#define MMU_RAM_ELSZ_MASK      (3 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_8         (0 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_16                (1 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_32                (2 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_ELSZ_NONE      (3 << MMU_RAM_ELSZ_SHIFT)
+#define MMU_RAM_MIXED_SHIFT    6
+#define MMU_RAM_MIXED_MASK     (1 << MMU_RAM_MIXED_SHIFT)
+#define MMU_RAM_MIXED          MMU_RAM_MIXED_MASK
+
+/*
+ * utilities for super page(16MB, 1MB, 64KB and 4KB)
+ */
+
+#define iopgsz_max(bytes)                      \
+       (((bytes) >= SZ_16M) ? SZ_16M :         \
+        ((bytes) >= SZ_1M)  ? SZ_1M  :         \
+        ((bytes) >= SZ_64K) ? SZ_64K :         \
+        ((bytes) >= SZ_4K)  ? SZ_4K  : 0)
+
+#define bytes_to_iopgsz(bytes)                         \
+       (((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M :       \
+        ((bytes) == SZ_1M)  ? MMU_CAM_PGSZ_1M  :       \
+        ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K :       \
+        ((bytes) == SZ_4K)  ? MMU_CAM_PGSZ_4K  : -1)
+
+#define iopgsz_to_bytes(iopgsz)                                \
+       (((iopgsz) == MMU_CAM_PGSZ_16M) ? SZ_16M :      \
+        ((iopgsz) == MMU_CAM_PGSZ_1M)  ? SZ_1M  :      \
+        ((iopgsz) == MMU_CAM_PGSZ_64K) ? SZ_64K :      \
+        ((iopgsz) == MMU_CAM_PGSZ_4K)  ? SZ_4K  : 0)
+
+#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0)
+
+/*
+ * global functions
+ */
+extern u32 omap_iommu_arch_version(void);
+
+extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
+
+extern int
+omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
+
+extern void omap_iommu_save_ctx(struct device *dev);
+extern void omap_iommu_restore_ctx(struct device *dev);
+
+extern int omap_foreach_iommu_device(void *data,
+                               int (*fn)(struct device *, void *));
+
+extern int omap_install_iommu_arch(const struct iommu_functions *ops);
+extern void omap_uninstall_iommu_arch(const struct iommu_functions *ops);
+
+extern ssize_t
+omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
+extern size_t
+omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t len);
+
+/*
+ * register accessors
+ */
+static inline u32 iommu_read_reg(struct omap_iommu *obj, size_t offs)
+{
+       return __raw_readl(obj->regbase + offs);
+}
+
+static inline void iommu_write_reg(struct omap_iommu *obj, u32 val, size_t offs)
+{
+       __raw_writel(val, obj->regbase + offs);
+}
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
new file mode 100644 (file)
index 0000000..c020202
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * omap iommu: omap2/3 architecture specific functions
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
+ *             Paul Mundt and Toshihiro Kobayashi
+ *
+ * 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/err.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/omap-iommu.h>
+#include <linux/slab.h>
+#include <linux/stringify.h>
+#include <linux/platform_data/iommu-omap.h>
+
+#include "omap-iommu.h"
+
+/*
+ * omap2 architecture specific register bit definitions
+ */
+#define IOMMU_ARCH_VERSION     0x00000011
+
+/* SYSCONF */
+#define MMU_SYS_IDLE_SHIFT     3
+#define MMU_SYS_IDLE_FORCE     (0 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_NONE      (1 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_SMART     (2 << MMU_SYS_IDLE_SHIFT)
+#define MMU_SYS_IDLE_MASK      (3 << MMU_SYS_IDLE_SHIFT)
+
+#define MMU_SYS_SOFTRESET      (1 << 1)
+#define MMU_SYS_AUTOIDLE       1
+
+/* SYSSTATUS */
+#define MMU_SYS_RESETDONE      1
+
+/* IRQSTATUS & IRQENABLE */
+#define MMU_IRQ_MULTIHITFAULT  (1 << 4)
+#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
+#define MMU_IRQ_EMUMISS                (1 << 2)
+#define MMU_IRQ_TRANSLATIONFAULT       (1 << 1)
+#define MMU_IRQ_TLBMISS                (1 << 0)
+
+#define __MMU_IRQ_FAULT                \
+       (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_EMUMISS | MMU_IRQ_TRANSLATIONFAULT)
+#define MMU_IRQ_MASK           \
+       (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_TLBMISS)
+#define MMU_IRQ_TWL_MASK       (__MMU_IRQ_FAULT | MMU_IRQ_TABLEWALKFAULT)
+#define MMU_IRQ_TLB_MISS_MASK  (__MMU_IRQ_FAULT | MMU_IRQ_TLBMISS)
+
+/* MMU_CNTL */
+#define MMU_CNTL_SHIFT         1
+#define MMU_CNTL_MASK          (7 << MMU_CNTL_SHIFT)
+#define MMU_CNTL_EML_TLB       (1 << 3)
+#define MMU_CNTL_TWL_EN                (1 << 2)
+#define MMU_CNTL_MMU_EN                (1 << 1)
+
+#define get_cam_va_mask(pgsz)                          \
+       (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 :    \
+        ((pgsz) == MMU_CAM_PGSZ_1M)  ? 0xfff00000 :    \
+        ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 :    \
+        ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xfffff000 : 0)
+
+/* IOMMU errors */
+#define OMAP_IOMMU_ERR_TLB_MISS                (1 << 0)
+#define OMAP_IOMMU_ERR_TRANS_FAULT     (1 << 1)
+#define OMAP_IOMMU_ERR_EMU_MISS                (1 << 2)
+#define OMAP_IOMMU_ERR_TBLWALK_FAULT   (1 << 3)
+#define OMAP_IOMMU_ERR_MULTIHIT_FAULT  (1 << 4)
+
+static void __iommu_set_twl(struct omap_iommu *obj, bool on)
+{
+       u32 l = iommu_read_reg(obj, MMU_CNTL);
+
+       if (on)
+               iommu_write_reg(obj, MMU_IRQ_TWL_MASK, MMU_IRQENABLE);
+       else
+               iommu_write_reg(obj, MMU_IRQ_TLB_MISS_MASK, MMU_IRQENABLE);
+
+       l &= ~MMU_CNTL_MASK;
+       if (on)
+               l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
+       else
+               l |= (MMU_CNTL_MMU_EN);
+
+       iommu_write_reg(obj, l, MMU_CNTL);
+}
+
+
+static int omap2_iommu_enable(struct omap_iommu *obj)
+{
+       u32 l, pa;
+       unsigned long timeout;
+
+       if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd,  SZ_16K))
+               return -EINVAL;
+
+       pa = virt_to_phys(obj->iopgd);
+       if (!IS_ALIGNED(pa, SZ_16K))
+               return -EINVAL;
+
+       iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
+
+       timeout = jiffies + msecs_to_jiffies(20);
+       do {
+               l = iommu_read_reg(obj, MMU_SYSSTATUS);
+               if (l & MMU_SYS_RESETDONE)
+                       break;
+       } while (!time_after(jiffies, timeout));
+
+       if (!(l & MMU_SYS_RESETDONE)) {
+               dev_err(obj->dev, "can't take mmu out of reset\n");
+               return -ENODEV;
+       }
+
+       l = iommu_read_reg(obj, MMU_REVISION);
+       dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
+                (l >> 4) & 0xf, l & 0xf);
+
+       l = iommu_read_reg(obj, MMU_SYSCONFIG);
+       l &= ~MMU_SYS_IDLE_MASK;
+       l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
+       iommu_write_reg(obj, l, MMU_SYSCONFIG);
+
+       iommu_write_reg(obj, pa, MMU_TTB);
+
+       __iommu_set_twl(obj, true);
+
+       return 0;
+}
+
+static void omap2_iommu_disable(struct omap_iommu *obj)
+{
+       u32 l = iommu_read_reg(obj, MMU_CNTL);
+
+       l &= ~MMU_CNTL_MASK;
+       iommu_write_reg(obj, l, MMU_CNTL);
+       iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
+
+       dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
+}
+
+static void omap2_iommu_set_twl(struct omap_iommu *obj, bool on)
+{
+       __iommu_set_twl(obj, false);
+}
+
+static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
+{
+       u32 stat, da;
+       u32 errs = 0;
+
+       stat = iommu_read_reg(obj, MMU_IRQSTATUS);
+       stat &= MMU_IRQ_MASK;
+       if (!stat) {
+               *ra = 0;
+               return 0;
+       }
+
+       da = iommu_read_reg(obj, MMU_FAULT_AD);
+       *ra = da;
+
+       if (stat & MMU_IRQ_TLBMISS)
+               errs |= OMAP_IOMMU_ERR_TLB_MISS;
+       if (stat & MMU_IRQ_TRANSLATIONFAULT)
+               errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
+       if (stat & MMU_IRQ_EMUMISS)
+               errs |= OMAP_IOMMU_ERR_EMU_MISS;
+       if (stat & MMU_IRQ_TABLEWALKFAULT)
+               errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
+       if (stat & MMU_IRQ_MULTIHITFAULT)
+               errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
+       iommu_write_reg(obj, stat, MMU_IRQSTATUS);
+
+       return errs;
+}
+
+static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+       cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
+       cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
+}
+
+static void omap2_tlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
+{
+       iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
+       iommu_write_reg(obj, cr->ram, MMU_RAM);
+}
+
+static u32 omap2_cr_to_virt(struct cr_regs *cr)
+{
+       u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
+       u32 mask = get_cam_va_mask(cr->cam & page_size);
+
+       return cr->cam & mask;
+}
+
+static struct cr_regs *omap2_alloc_cr(struct omap_iommu *obj,
+                                               struct iotlb_entry *e)
+{
+       struct cr_regs *cr;
+
+       if (e->da & ~(get_cam_va_mask(e->pgsz))) {
+               dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
+                       e->da);
+               return ERR_PTR(-EINVAL);
+       }
+
+       cr = kmalloc(sizeof(*cr), GFP_KERNEL);
+       if (!cr)
+               return ERR_PTR(-ENOMEM);
+
+       cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz | e->valid;
+       cr->ram = e->pa | e->endian | e->elsz | e->mixed;
+
+       return cr;
+}
+
+static inline int omap2_cr_valid(struct cr_regs *cr)
+{
+       return cr->cam & MMU_CAM_V;
+}
+
+static u32 omap2_get_pte_attr(struct iotlb_entry *e)
+{
+       u32 attr;
+
+       attr = e->mixed << 5;
+       attr |= e->endian;
+       attr |= e->elsz >> 3;
+       attr <<= (((e->pgsz == MMU_CAM_PGSZ_4K) ||
+                       (e->pgsz == MMU_CAM_PGSZ_64K)) ? 0 : 6);
+       return attr;
+}
+
+static ssize_t
+omap2_dump_cr(struct omap_iommu *obj, struct cr_regs *cr, char *buf)
+{
+       char *p = buf;
+
+       /* FIXME: Need more detail analysis of cam/ram */
+       p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram,
+                                       (cr->cam & MMU_CAM_P) ? 1 : 0);
+
+       return p - buf;
+}
+
+#define pr_reg(name)                                                   \
+       do {                                                            \
+               ssize_t bytes;                                          \
+               const char *str = "%20s: %08x\n";                       \
+               const int maxcol = 32;                                  \
+               bytes = snprintf(p, maxcol, str, __stringify(name),     \
+                                iommu_read_reg(obj, MMU_##name));      \
+               p += bytes;                                             \
+               len -= bytes;                                           \
+               if (len < maxcol)                                       \
+                       goto out;                                       \
+       } while (0)
+
+static ssize_t
+omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len)
+{
+       char *p = buf;
+
+       pr_reg(REVISION);
+       pr_reg(SYSCONFIG);
+       pr_reg(SYSSTATUS);
+       pr_reg(IRQSTATUS);
+       pr_reg(IRQENABLE);
+       pr_reg(WALKING_ST);
+       pr_reg(CNTL);
+       pr_reg(FAULT_AD);
+       pr_reg(TTB);
+       pr_reg(LOCK);
+       pr_reg(LD_TLB);
+       pr_reg(CAM);
+       pr_reg(RAM);
+       pr_reg(GFLUSH);
+       pr_reg(FLUSH_ENTRY);
+       pr_reg(READ_CAM);
+       pr_reg(READ_RAM);
+       pr_reg(EMU_FAULT_AD);
+out:
+       return p - buf;
+}
+
+static void omap2_iommu_save_ctx(struct omap_iommu *obj)
+{
+       int i;
+       u32 *p = obj->ctx;
+
+       for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+               p[i] = iommu_read_reg(obj, i * sizeof(u32));
+               dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+       }
+
+       BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+}
+
+static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
+{
+       int i;
+       u32 *p = obj->ctx;
+
+       for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+               iommu_write_reg(obj, p[i], i * sizeof(u32));
+               dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+       }
+
+       BUG_ON(p[0] != IOMMU_ARCH_VERSION);
+}
+
+static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+{
+       e->da           = cr->cam & MMU_CAM_VATAG_MASK;
+       e->pa           = cr->ram & MMU_RAM_PADDR_MASK;
+       e->valid        = cr->cam & MMU_CAM_V;
+       e->pgsz         = cr->cam & MMU_CAM_PGSZ_MASK;
+       e->endian       = cr->ram & MMU_RAM_ENDIAN_MASK;
+       e->elsz         = cr->ram & MMU_RAM_ELSZ_MASK;
+       e->mixed        = cr->ram & MMU_RAM_MIXED;
+}
+
+static const struct iommu_functions omap2_iommu_ops = {
+       .version        = IOMMU_ARCH_VERSION,
+
+       .enable         = omap2_iommu_enable,
+       .disable        = omap2_iommu_disable,
+       .set_twl        = omap2_iommu_set_twl,
+       .fault_isr      = omap2_iommu_fault_isr,
+
+       .tlb_read_cr    = omap2_tlb_read_cr,
+       .tlb_load_cr    = omap2_tlb_load_cr,
+
+       .cr_to_e        = omap2_cr_to_e,
+       .cr_to_virt     = omap2_cr_to_virt,
+       .alloc_cr       = omap2_alloc_cr,
+       .cr_valid       = omap2_cr_valid,
+       .dump_cr        = omap2_dump_cr,
+
+       .get_pte_attr   = omap2_get_pte_attr,
+
+       .save_ctx       = omap2_iommu_save_ctx,
+       .restore_ctx    = omap2_iommu_restore_ctx,
+       .dump_ctx       = omap2_iommu_dump_ctx,
+};
+
+static int __init omap2_iommu_init(void)
+{
+       return omap_install_iommu_arch(&omap2_iommu_ops);
+}
+module_init(omap2_iommu_init);
+
+static void __exit omap2_iommu_exit(void)
+{
+       omap_uninstall_iommu_arch(&omap2_iommu_ops);
+}
+module_exit(omap2_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
+MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h
new file mode 100644 (file)
index 0000000..cd4ae9e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * omap iommu: pagetable definitions
+ *
+ * Copyright (C) 2008-2010 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.
+ */
+
+/*
+ * "L2 table" address mask and size definitions.
+ */
+#define IOPGD_SHIFT            20
+#define IOPGD_SIZE             (1UL << IOPGD_SHIFT)
+#define IOPGD_MASK             (~(IOPGD_SIZE - 1))
+
+/*
+ * "section" address mask and size definitions.
+ */
+#define IOSECTION_SHIFT                20
+#define IOSECTION_SIZE         (1UL << IOSECTION_SHIFT)
+#define IOSECTION_MASK         (~(IOSECTION_SIZE - 1))
+
+/*
+ * "supersection" address mask and size definitions.
+ */
+#define IOSUPER_SHIFT          24
+#define IOSUPER_SIZE           (1UL << IOSUPER_SHIFT)
+#define IOSUPER_MASK           (~(IOSUPER_SIZE - 1))
+
+#define PTRS_PER_IOPGD         (1UL << (32 - IOPGD_SHIFT))
+#define IOPGD_TABLE_SIZE       (PTRS_PER_IOPGD * sizeof(u32))
+
+/*
+ * "small page" address mask and size definitions.
+ */
+#define IOPTE_SHIFT            12
+#define IOPTE_SIZE             (1UL << IOPTE_SHIFT)
+#define IOPTE_MASK             (~(IOPTE_SIZE - 1))
+
+/*
+ * "large page" address mask and size definitions.
+ */
+#define IOLARGE_SHIFT          16
+#define IOLARGE_SIZE           (1UL << IOLARGE_SHIFT)
+#define IOLARGE_MASK           (~(IOLARGE_SIZE - 1))
+
+#define PTRS_PER_IOPTE         (1UL << (IOPGD_SHIFT - IOPTE_SHIFT))
+#define IOPTE_TABLE_SIZE       (PTRS_PER_IOPTE * sizeof(u32))
+
+#define IOPAGE_MASK            IOPTE_MASK
+
+/**
+ * omap_iommu_translate() - va to pa translation
+ * @d:         omap iommu descriptor
+ * @va:                virtual address
+ * @mask:      omap iommu descriptor mask
+ *
+ * va to pa translation
+ */
+static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
+{
+       return (d & mask) | (va & (~mask));
+}
+
+/*
+ * some descriptor attributes.
+ */
+#define IOPGD_TABLE            (1 << 0)
+#define IOPGD_SECTION          (2 << 0)
+#define IOPGD_SUPER            (1 << 18 | 2 << 0)
+
+#define iopgd_is_table(x)      (((x) & 3) == IOPGD_TABLE)
+#define iopgd_is_section(x)    (((x) & (1 << 18 | 3)) == IOPGD_SECTION)
+#define iopgd_is_super(x)      (((x) & (1 << 18 | 3)) == IOPGD_SUPER)
+
+#define IOPTE_SMALL            (2 << 0)
+#define IOPTE_LARGE            (1 << 0)
+
+#define iopte_is_small(x)      (((x) & 2) == IOPTE_SMALL)
+#define iopte_is_large(x)      (((x) & 3) == IOPTE_LARGE)
+
+/* to find an entry in a page-table-directory */
+#define iopgd_index(da)                (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
+#define iopgd_offset(obj, da)  ((obj)->iopgd + iopgd_index(da))
+
+#define iopgd_page_paddr(iopgd)        (*iopgd & ~((1 << 10) - 1))
+#define iopgd_page_vaddr(iopgd)        ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd)))
+
+/* to find an entry in the second-level page table. */
+#define iopte_index(da)                (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
+#define iopte_offset(iopgd, da)        (iopgd_page_vaddr(iopgd) + iopte_index(da))
+
+#define to_iommu(dev)                                                  \
+       (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))
index 2e10c3e..46d8756 100644 (file)
 #include <linux/device.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu.h>
+#include <linux/omap-iommu.h>
+#include <linux/platform_data/iommu-omap.h>
 
 #include <asm/cacheflush.h>
 #include <asm/mach/map.h>
 
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
+#include "omap-iopgtable.h"
+#include "omap-iommu.h"
 
-#include <plat/iopgtable.h>
+/*
+ * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
+ *
+ * lower 16 bit is used for h/w and upper 16 bit is for s/w.
+ */
+#define IOVMF_SW_SHIFT         16
+
+/*
+ * iovma: h/w flags derived from cam and ram attribute
+ */
+#define IOVMF_CAM_MASK         (~((1 << 10) - 1))
+#define IOVMF_RAM_MASK         (~IOVMF_CAM_MASK)
+
+#define IOVMF_PGSZ_MASK                (3 << 0)
+#define IOVMF_PGSZ_1M          MMU_CAM_PGSZ_1M
+#define IOVMF_PGSZ_64K         MMU_CAM_PGSZ_64K
+#define IOVMF_PGSZ_4K          MMU_CAM_PGSZ_4K
+#define IOVMF_PGSZ_16M         MMU_CAM_PGSZ_16M
+
+#define IOVMF_ENDIAN_MASK      (1 << 9)
+#define IOVMF_ENDIAN_BIG       MMU_RAM_ENDIAN_BIG
+
+#define IOVMF_ELSZ_MASK                (3 << 7)
+#define IOVMF_ELSZ_16          MMU_RAM_ELSZ_16
+#define IOVMF_ELSZ_32          MMU_RAM_ELSZ_32
+#define IOVMF_ELSZ_NONE                MMU_RAM_ELSZ_NONE
+
+#define IOVMF_MIXED_MASK       (1 << 6)
+#define IOVMF_MIXED            MMU_RAM_MIXED
+
+/*
+ * iovma: s/w flags, used for mapping and umapping internally.
+ */
+#define IOVMF_MMIO             (1 << IOVMF_SW_SHIFT)
+#define IOVMF_ALLOC            (2 << IOVMF_SW_SHIFT)
+#define IOVMF_ALLOC_MASK       (3 << IOVMF_SW_SHIFT)
+
+/* "superpages" is supported just with physically linear pages */
+#define IOVMF_DISCONT          (1 << (2 + IOVMF_SW_SHIFT))
+#define IOVMF_LINEAR           (2 << (2 + IOVMF_SW_SHIFT))
+#define IOVMF_LINEAR_MASK      (3 << (2 + IOVMF_SW_SHIFT))
+
+#define IOVMF_DA_FIXED         (1 << (4 + IOVMF_SW_SHIFT))
 
 static struct kmem_cache *iovm_area_cachep;
 
index 99640d8..7f182f0 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/omap-iommu.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
index 8be7487..8d68669 100644 (file)
 #include <media/v4l2-device.h>
 #include <linux/device.h>
 #include <linux/io.h>
+#include <linux/iommu.h>
 #include <linux/platform_device.h>
 #include <linux/wait.h>
-#include <linux/iommu.h>
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
 
 #include "ispstat.h"
 #include "ispccdc.h"
index 60181ab..6ae1ffb 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
+#include <linux/omap-iommu.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <media/v4l2-event.h>
index d7ac76b..35c3823 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/omap-iommu.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
index 5bd40e6..c4be4fa 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/omap-iommu.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
@@ -36,6 +37,7 @@
 #include <media/v4l2-ioctl.h>
 #include <plat/iommu.h>
 #include <plat/iovmm.h>
+#include <plat/omap-pm.h>
 
 #include "ispvideo.h"
 #include "isp.h"
diff --git a/include/linux/omap-iommu.h b/include/linux/omap-iommu.h
new file mode 100644 (file)
index 0000000..cac78de
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * omap iommu: simple virtual address space management
+ *
+ * Copyright (C) 2008-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.
+ */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+struct iovm_struct {
+       struct omap_iommu       *iommu; /* iommu object which this belongs to */
+       u32                     da_start; /* area definition */
+       u32                     da_end;
+       u32                     flags; /* IOVMF_: see below */
+       struct list_head        list; /* linked in ascending order */
+       const struct sg_table   *sgt; /* keep 'page' <-> 'da' mapping */
+       void                    *va; /* mpu side mapped address */
+};
+
+#define MMU_RAM_ENDIAN_SHIFT   9
+#define MMU_RAM_ENDIAN_LITTLE  (0 << MMU_RAM_ENDIAN_SHIFT)
+#define MMU_RAM_ELSZ_8         (0 << MMU_RAM_ELSZ_SHIFT)
+#define IOVMF_ENDIAN_LITTLE    MMU_RAM_ENDIAN_LITTLE
+#define MMU_RAM_ELSZ_SHIFT     7
+#define IOVMF_ELSZ_8           MMU_RAM_ELSZ_8
+
+struct iommu_domain;
+
+extern struct iovm_struct *omap_find_iovm_area(struct device *dev, u32 da);
+extern u32
+omap_iommu_vmap(struct iommu_domain *domain, struct device *dev, u32 da,
+                       const struct sg_table *sgt, u32 flags);
+extern struct sg_table *omap_iommu_vunmap(struct iommu_domain *domain,
+                               struct device *dev, u32 da);
+extern u32
+omap_iommu_vmalloc(struct iommu_domain *domain, struct device *dev,
+                               u32 da, size_t bytes, u32 flags);
+extern void
+omap_iommu_vfree(struct iommu_domain *domain, struct device *dev,
+                               const u32 da);
+extern void *omap_da_to_va(struct device *dev, u32 da);
+
+extern void omap_iommu_save_ctx(struct device *dev);
+extern void omap_iommu_restore_ctx(struct device *dev);
+
+#endif
diff --git a/include/linux/platform_data/iommu-omap.h b/include/linux/platform_data/iommu-omap.h
new file mode 100644 (file)
index 0000000..c677b9f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * omap iommu: main structures
+ *
+ * Copyright (C) 2008-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.
+ */
+
+#define MMU_REG_SIZE           256
+
+/**
+ * struct iommu_arch_data - omap iommu private data
+ * @name: name of the iommu device
+ * @iommu_dev: handle of the iommu device
+ *
+ * This is an omap iommu private data object, which binds an iommu user
+ * to its iommu device. This object should be placed at the iommu user's
+ * dev_archdata so generic IOMMU API can be used without having to
+ * utilize omap-specific plumbing anymore.
+ */
+struct omap_iommu_arch_data {
+       const char *name;
+       struct omap_iommu *iommu_dev;
+};
+
+/**
+ * struct omap_mmu_dev_attr - OMAP mmu device attributes for omap_hwmod
+ * @da_start:          device address where the va space starts.
+ * @da_end:            device address where the va space ends.
+ * @nr_tlb_entries:    number of entries supported by the translation
+ *                     look-aside buffer (TLB).
+ */
+struct omap_mmu_dev_attr {
+       u32 da_start;
+       u32 da_end;
+       int nr_tlb_entries;
+};
+
+struct iommu_platform_data {
+       const char *name;
+       const char *clk_name;
+       const int nr_tlb_entries;
+       u32 da_start;
+       u32 da_end;
+};