*/
struct omap_iommu_domain {
u32 *pgtable;
- struct iommu *iommu_dev;
+ struct omap_iommu *iommu_dev;
spinlock_t lock;
};
static struct kmem_cache *iopte_cachep;
/**
- * install_iommu_arch - Install archtecure specific iommu functions
+ * omap_install_iommu_arch - Install archtecure specific iommu functions
* @ops: a pointer to architecture specific iommu functions
*
* There are several kind of iommu algorithm(tlb, pagetable) among
* omap series. This interface installs such an iommu algorighm.
**/
-int install_iommu_arch(const struct iommu_functions *ops)
+int omap_install_iommu_arch(const struct iommu_functions *ops)
{
if (arch_iommu)
return -EBUSY;
arch_iommu = ops;
return 0;
}
-EXPORT_SYMBOL_GPL(install_iommu_arch);
+EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
/**
- * uninstall_iommu_arch - Uninstall archtecure specific iommu functions
+ * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
* @ops: a pointer to architecture specific iommu functions
*
* This interface uninstalls the iommu algorighm installed previously.
**/
-void uninstall_iommu_arch(const struct iommu_functions *ops)
+void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
{
if (arch_iommu != ops)
pr_err("%s: not your arch\n", __func__);
arch_iommu = NULL;
}
-EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
+EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
/**
- * iommu_save_ctx - Save registers for pm off-mode support
+ * omap_iommu_save_ctx - Save registers for pm off-mode support
* @obj: target iommu
**/
-void iommu_save_ctx(struct iommu *obj)
+void omap_iommu_save_ctx(struct omap_iommu *obj)
{
arch_iommu->save_ctx(obj);
}
-EXPORT_SYMBOL_GPL(iommu_save_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
/**
- * iommu_restore_ctx - Restore registers for pm off-mode support
+ * omap_iommu_restore_ctx - Restore registers for pm off-mode support
* @obj: target iommu
**/
-void iommu_restore_ctx(struct iommu *obj)
+void omap_iommu_restore_ctx(struct omap_iommu *obj)
{
arch_iommu->restore_ctx(obj);
}
-EXPORT_SYMBOL_GPL(iommu_restore_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
/**
- * iommu_arch_version - Return running iommu arch version
+ * omap_iommu_arch_version - Return running iommu arch version
**/
-u32 iommu_arch_version(void)
+u32 omap_iommu_arch_version(void)
{
return arch_iommu->version;
}
-EXPORT_SYMBOL_GPL(iommu_arch_version);
+EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
-static int iommu_enable(struct iommu *obj)
+static int iommu_enable(struct omap_iommu *obj)
{
int err;
return err;
}
-static void iommu_disable(struct iommu *obj)
+static void iommu_disable(struct omap_iommu *obj)
{
if (!obj)
return;
/*
* TLB operations
*/
-void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
+void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
{
BUG_ON(!cr || !e);
arch_iommu->cr_to_e(cr, e);
}
-EXPORT_SYMBOL_GPL(iotlb_cr_to_e);
+EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
static inline int iotlb_cr_valid(struct cr_regs *cr)
{
return arch_iommu->cr_valid(cr);
}
-static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
+static inline struct cr_regs *iotlb_alloc_cr(struct omap_iommu *obj,
struct iotlb_entry *e)
{
if (!e)
return arch_iommu->get_pte_attr(e);
}
-static u32 iommu_report_fault(struct iommu *obj, u32 *da)
+static u32 iommu_report_fault(struct omap_iommu *obj, u32 *da)
{
return arch_iommu->fault_isr(obj, da);
}
-static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
+static void iotlb_lock_get(struct omap_iommu *obj, struct iotlb_lock *l)
{
u32 val;
}
-static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
+static void iotlb_lock_set(struct omap_iommu *obj, struct iotlb_lock *l)
{
u32 val;
iommu_write_reg(obj, val, MMU_LOCK);
}
-static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
+static void iotlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
arch_iommu->tlb_read_cr(obj, cr);
}
-static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
+static void iotlb_load_cr(struct omap_iommu *obj, struct cr_regs *cr)
{
arch_iommu->tlb_load_cr(obj, cr);
* @cr: contents of cam and ram register
* @buf: output buffer
**/
-static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
+static inline ssize_t iotlb_dump_cr(struct omap_iommu *obj, struct cr_regs *cr,
char *buf)
{
BUG_ON(!cr || !buf);
}
/* only used in iotlb iteration for-loop */
-static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
+static struct cr_regs __iotlb_read_cr(struct omap_iommu *obj, int n)
{
struct cr_regs cr;
struct iotlb_lock l;
* @obj: target iommu
* @e: an iommu tlb entry info
**/
-static int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
+#ifdef PREFETCH_IOTLB
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
{
int err = 0;
struct iotlb_lock l;
return err;
}
+#else /* !PREFETCH_IOTLB */
+
+static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+ return 0;
+}
+
+#endif /* !PREFETCH_IOTLB */
+
+static int prefetch_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+{
+ return load_iotlb_entry(obj, e);
+}
+
/**
* flush_iotlb_page - Clear an iommu tlb entry
* @obj: target iommu
*
* Clear an iommu tlb entry which includes 'da' address.
**/
-static void flush_iotlb_page(struct iommu *obj, u32 da)
+static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
{
int i;
struct cr_regs cr;
dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
}
-/**
- * flush_iotlb_range - Clear an iommu tlb entries
- * @obj: target iommu
- * @start: iommu device virtual address(start)
- * @end: iommu device virtual address(end)
- *
- * Clear an iommu tlb entry which includes 'da' address.
- **/
-void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
-{
- u32 da = start;
-
- while (da < end) {
- flush_iotlb_page(obj, da);
- /* FIXME: Optimize for multiple page size */
- da += IOPTE_SIZE;
- }
-}
-EXPORT_SYMBOL_GPL(flush_iotlb_range);
-
/**
* flush_iotlb_all - Clear all iommu tlb entries
* @obj: target iommu
**/
-static void flush_iotlb_all(struct iommu *obj)
+static void flush_iotlb_all(struct omap_iommu *obj)
{
struct iotlb_lock l;
clk_disable(obj->clk);
}
-/**
- * iommu_set_twl - enable/disable table walking logic
- * @obj: target iommu
- * @on: enable/disable
- *
- * Function used to enable/disable TWL. If one wants to work
- * exclusively with locked TLB entries and receive notifications
- * for TLB miss then call this function to disable TWL.
- */
-void iommu_set_twl(struct iommu *obj, bool on)
-{
- clk_enable(obj->clk);
- arch_iommu->set_twl(obj, on);
- clk_disable(obj->clk);
-}
-EXPORT_SYMBOL_GPL(iommu_set_twl);
-
#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE)
-ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes)
+ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes)
{
if (!obj || !buf)
return -EINVAL;
return bytes;
}
-EXPORT_SYMBOL_GPL(iommu_dump_ctx);
+EXPORT_SYMBOL_GPL(omap_iommu_dump_ctx);
-static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
+static int
+__dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
{
int i;
struct iotlb_lock saved;
}
/**
- * dump_tlb_entries - dump cr arrays to given buffer
+ * omap_dump_tlb_entries - dump cr arrays to given buffer
* @obj: target iommu
* @buf: output buffer
**/
-size_t dump_tlb_entries(struct iommu *obj, char *buf, ssize_t bytes)
+size_t omap_dump_tlb_entries(struct omap_iommu *obj, char *buf, ssize_t bytes)
{
int i, num;
struct cr_regs *cr;
return p - buf;
}
-EXPORT_SYMBOL_GPL(dump_tlb_entries);
+EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
-int foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
+int omap_foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
{
return driver_for_each_device(&omap_iommu_driver.driver,
NULL, data, fn);
}
-EXPORT_SYMBOL_GPL(foreach_iommu_device);
+EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */
kmem_cache_free(iopte_cachep, iopte);
}
-static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
+static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd, u32 da)
{
u32 *iopte;
return iopte;
}
-static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopgd_alloc_section(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
return 0;
}
-static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopgd_alloc_super(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
int i;
return 0;
}
-static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopte_alloc_page(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
u32 *iopte = iopte_alloc(obj, iopgd, da);
return 0;
}
-static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
+static int iopte_alloc_large(struct omap_iommu *obj, u32 da, u32 pa, u32 prot)
{
u32 *iopgd = iopgd_offset(obj, da);
u32 *iopte = iopte_alloc(obj, iopgd, da);
return 0;
}
-static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
+static int
+iopgtable_store_entry_core(struct omap_iommu *obj, struct iotlb_entry *e)
{
- int (*fn)(struct iommu *, u32, u32, u32);
+ int (*fn)(struct omap_iommu *, u32, u32, u32);
u32 prot;
int err;
}
/**
- * iopgtable_store_entry - Make an iommu pte entry
+ * omap_iopgtable_store_entry - Make an iommu pte entry
* @obj: target iommu
* @e: an iommu tlb entry info
**/
-int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
+int omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
{
int err;
flush_iotlb_page(obj, e->da);
err = iopgtable_store_entry_core(obj, e);
-#ifdef PREFETCH_IOTLB
if (!err)
- load_iotlb_entry(obj, e);
-#endif
+ prefetch_iotlb_entry(obj, e);
return err;
}
-EXPORT_SYMBOL_GPL(iopgtable_store_entry);
+EXPORT_SYMBOL_GPL(omap_iopgtable_store_entry);
/**
* iopgtable_lookup_entry - Lookup an iommu pte entry
*ppte = iopte;
}
-static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
+static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
{
size_t bytes;
u32 *iopgd = iopgd_offset(obj, da);
* @obj: target iommu
* @da: iommu device virtual address
**/
-static size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
+static size_t iopgtable_clear_entry(struct omap_iommu *obj, u32 da)
{
size_t bytes;
return bytes;
}
-static void iopgtable_clear_entry_all(struct iommu *obj)
+static void iopgtable_clear_entry_all(struct omap_iommu *obj)
{
int i;
{
u32 da, errs;
u32 *iopgd, *iopte;
- struct iommu *obj = data;
+ struct omap_iommu *obj = data;
+ struct iommu_domain *domain = obj->domain;
if (!obj->refcount)
return IRQ_NONE;
return IRQ_HANDLED;
/* Fault callback or TLB/PTE Dynamic loading */
- if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
+ if (!report_iommu_fault(domain, obj->dev, da, 0))
return IRQ_HANDLED;
iommu_disable(obj);
static int device_match_by_alias(struct device *dev, void *data)
{
- struct iommu *obj = to_iommu(dev);
+ struct omap_iommu *obj = to_iommu(dev);
const char *name = data;
pr_debug("%s: %s %s\n", __func__, obj->name, name);
return strcmp(obj->name, name) == 0;
}
-/**
- * iommu_set_da_range - Set a valid device address range
- * @obj: target iommu
- * @start Start of valid range
- * @end End of valid range
- **/
-int iommu_set_da_range(struct iommu *obj, u32 start, u32 end)
-{
-
- if (!obj)
- return -EFAULT;
-
- if (end < start || !PAGE_ALIGN(start | end))
- return -EINVAL;
-
- obj->da_start = start;
- obj->da_end = end;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(iommu_set_da_range);
-
/**
* omap_find_iommu_device() - find an omap iommu device by name
* @name: name of the iommu device
* @dev: target omap iommu device
* @iopgd: page table
**/
-static struct iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
+static struct omap_iommu *omap_iommu_attach(struct device *dev, u32 *iopgd)
{
int err = -ENOMEM;
- struct iommu *obj = to_iommu(dev);
+ struct omap_iommu *obj = to_iommu(dev);
spin_lock(&obj->iommu_lock);
* omap_iommu_detach - release iommu device
* @obj: target iommu
**/
-static void omap_iommu_detach(struct iommu *obj)
+static void omap_iommu_detach(struct omap_iommu *obj)
{
if (!obj || IS_ERR(obj))
return;
dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
}
-int iommu_set_isr(const char *name,
- int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
- void *priv),
- void *isr_priv)
-{
- struct device *dev;
- struct iommu *obj;
-
- dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
- device_match_by_alias);
- if (!dev)
- return -ENODEV;
-
- obj = to_iommu(dev);
- mutex_lock(&obj->iommu_lock);
- if (obj->refcount != 0) {
- mutex_unlock(&obj->iommu_lock);
- return -EBUSY;
- }
- obj->isr = isr;
- obj->isr_priv = isr_priv;
- mutex_unlock(&obj->iommu_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(iommu_set_isr);
-
/*
* OMAP Device MMU(IOMMU) detection
*/
{
int err = -ENODEV;
int irq;
- struct iommu *obj;
+ struct omap_iommu *obj;
struct resource *res;
struct iommu_platform_data *pdata = pdev->dev.platform_data;
{
int irq;
struct resource *res;
- struct iommu *obj = platform_get_drvdata(pdev);
+ struct omap_iommu *obj = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
phys_addr_t pa, int order, int prot)
{
struct omap_iommu_domain *omap_domain = domain->priv;
- struct iommu *oiommu = omap_domain->iommu_dev;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
size_t bytes = PAGE_SIZE << order;
struct iotlb_entry e;
iotlb_init_entry(&e, da, pa, flags);
- ret = iopgtable_store_entry(oiommu, &e);
- if (ret) {
- dev_err(dev, "iopgtable_store_entry failed: %d\n", ret);
- return ret;
- }
+ ret = omap_iopgtable_store_entry(oiommu, &e);
+ if (ret)
+ dev_err(dev, "omap_iopgtable_store_entry failed: %d\n", ret);
- return 0;
+ return ret;
}
static int omap_iommu_unmap(struct iommu_domain *domain, unsigned long da,
int order)
{
struct omap_iommu_domain *omap_domain = domain->priv;
- struct iommu *oiommu = omap_domain->iommu_dev;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
- size_t bytes = PAGE_SIZE << order;
- size_t ret;
+ size_t unmap_size;
- dev_dbg(dev, "unmapping da 0x%lx size 0x%x\n", da, bytes);
+ dev_dbg(dev, "unmapping da 0x%lx order %d\n", da, order);
- ret = iopgtable_clear_entry(oiommu, da);
- if (ret != bytes) {
- dev_err(dev, "entry @ 0x%lx was %d; not %d\n", da, ret, bytes);
- return -EINVAL;
- }
+ unmap_size = iopgtable_clear_entry(oiommu, da);
- return 0;
+ return unmap_size ? get_order(unmap_size) : -EINVAL;
}
static int
omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
struct omap_iommu_domain *omap_domain = domain->priv;
- struct iommu *oiommu;
+ struct omap_iommu *oiommu;
int ret = 0;
spin_lock(&omap_domain->lock);
}
omap_domain->iommu_dev = oiommu;
+ oiommu->domain = domain;
out:
spin_unlock(&omap_domain->lock);
struct device *dev)
{
struct omap_iommu_domain *omap_domain = domain->priv;
- struct iommu *oiommu = to_iommu(dev);
+ struct omap_iommu *oiommu = to_iommu(dev);
spin_lock(&omap_domain->lock);
unsigned long da)
{
struct omap_iommu_domain *omap_domain = domain->priv;
- struct iommu *oiommu = omap_domain->iommu_dev;
+ struct omap_iommu *oiommu = omap_domain->iommu_dev;
struct device *dev = oiommu->dev;
u32 *pgd, *pte;
phys_addr_t ret = 0;