ARM: OMAP2+: Move iommu2 to drivers/iommu/omap-iommu2.c
authorTony Lindgren <tony@atomide.com>
Fri, 2 Nov 2012 19:24:06 +0000 (12:24 -0700)
committerTony Lindgren <tony@atomide.com>
Tue, 20 Nov 2012 18:04:41 +0000 (10:04 -0800)
This file should not be in arch/arm. Move it to drivers/iommu
to allow making most of the header local to drivers/iommu.

This is needed as we are removing plat and mach includes
from drivers for ARM common zImage support.

Cc: Ido Yariv <ido@wizery.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
Cc: Omar Ramirez Luna <omar.luna@linaro.org>
Cc: linux-media@vger.kernel.org
Acked-by: Ohad Ben-Cohen <ohad@wizery.com>
Acked-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/iommu2.c [deleted file]
arch/arm/plat-omap/include/plat/iommu.h
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
drivers/iommu/omap-iovmm.c

index fe40d9e488c96cdf1c68ba1d6dd7acc9631b360b..d6721a7f4c3bd88fc1e9d124fcfc78aa92ab0ea5 100644 (file)
@@ -184,8 +184,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)
 
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
deleted file mode 100644 (file)
index e8116cf..0000000
+++ /dev/null
@@ -1,362 +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/omap-iommu.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 a4b71b14975a06ffcc29a0a05c43d766d0c82a2e..c677b9f2fefa33cbf7c9c49b1d50721a1e7e00b0 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#ifndef __MACH_IOMMU_H
-#define __MACH_IOMMU_H
-
-#include <linux/io.h>
-
-#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;
-       };
-};
-
-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);
+#define MMU_REG_SIZE           256
 
-       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 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;
 };
 
 /**
@@ -129,165 +47,3 @@ struct iommu_platform_data {
        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)
-
-/*
- * 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_MASK    (1 << MMU_RAM_ENDIAN_SHIFT)
-#define MMU_RAM_ELSZ_MASK      (3 << 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 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 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);
-
-/*
- * 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_IOMMU_H */
index 14a4d5fc94fa3122efc44eb87bdc6770f9693c37..f66b816d455ced7e9cc58d370e7935fcc6291888 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 cf4a0b5c1d828656fd29b4c28f8a10c912a2baca..d0427bd21361956080706b81dc7fb77fe76b9b0e 100644 (file)
@@ -23,6 +23,7 @@
 #include <plat/iommu.h>
 
 #include "omap-iopgtable.h"
+#include "omap-iommu.h"
 
 #define MAXCOLUMN 100 /* for short messages */
 
index eadcfde757ee78b9f7672786ca54edda47e9270d..4db86e12c20031407955c4bd973b43ad8b9b44b1 100644 (file)
 #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 "omap-iopgtable.h"
+#include "omap-iommu.h"
 
 #define for_each_iotlb_cr(obj, n, __i, cr)                             \
        for (__i = 0;                                                   \
@@ -1016,6 +1018,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..8c3378d
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * 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;
+       };
+};
+
+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);
+};
+
+#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)
+
+/*
+ * 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_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 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);
+
+/*
+ * 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..f97c386
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * 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 <plat/iommu.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)
+
+
+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 66a813977d52f453c155b45710028f087e1dec35..cd4ae9e5b0c6bf20bc485c448ca00ed059478ebe 100644 (file)
@@ -10,9 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __PLAT_OMAP_IOMMU_H
-#define __PLAT_OMAP_IOMMU_H
-
 /*
  * "L2 table" address mask and size definitions.
  */
@@ -97,24 +94,5 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
 #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 */
index 9852101cf0427f4e1e296fdf0c66c79f215e1de1..3e3b2421b9247281751ceb71b08749b23ab4b790 100644 (file)
@@ -25,6 +25,7 @@
 #include <plat/iommu.h>
 
 #include "omap-iopgtable.h"
+#include "omap-iommu.h"
 
 /*
  * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
This page took 0.041922 seconds and 5 git commands to generate.