Skip to contentSkip to conversation

arm: omap iommu: add initial support

PATCH In review Hiroshi DOYU 3 participants 22 messages Jan 16, 2009 – Jan 28, 2009

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover arm: omap iommu: add initial support

The following patches add initial support of omap iommu.

Some of TI OMAP series have the peripheral devices with their own MMU(iommu), which is composed of its own tlb and optional h/w pagetable(twl). These MMUs don't depend on mpu(arm) mmu at all, but their algorithms are somewhat similar and they share the same physical address space. This patch provides with common in-kernel iommu APIs such OMAP peripheral devices(Camera ISP, IVA1, IVA2, DSP and the equivalent ones in the latest OMAP successors) to handle peripheral device iommus in the same manner.

---

Hiroshi DOYU (6):
omap2 iommu: entries for Kconfig and Makefile omap iommu: entries for Kconfig and Makefile omap iommu: simple virtual address space management omap iommu: omap3 iommu device registration omap iommu: omap2 architecture specific functions omap iommu: tlb and pagetable primitives

 arch/arm/include/asm/io.h                |    6 
 arch/arm/mach-omap2/Makefile             |    5 
 arch/arm/mach-omap2/iommu2.c             |  325 +++++++++++
 arch/arm/mach-omap2/omap3-iommu.c        |  111 ++++
 arch/arm/mm/ioremap.c                    |   11 
 arch/arm/plat-omap/Kconfig               |    8 
 arch/arm/plat-omap/Makefile              |    1 
 arch/arm/plat-omap/include/mach/iommu.h  |  157 +++++
 arch/arm/plat-omap/include/mach/iommu2.h |   94 +++
 arch/arm/plat-omap/include/mach/iovmm.h  |   94 +++
 arch/arm/plat-omap/iommu.c               |  913 ++++++++++++++++++++++++++++++
 arch/arm/plat-omap/iopgtable.h           |   72 ++
 arch/arm/plat-omap/iovmm.c               |  892 +++++++++++++++++++++++++++++
 13 files changed, 2689 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/iommu2.c
 create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
 create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
 create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h
 create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
 create mode 100644 arch/arm/plat-omap/iommu.c
 create mode 100644 arch/arm/plat-omap/iopgtable.h
 create mode 100644 arch/arm/plat-omap/iovmm.c
Signature · 1 line
   Hiroshi DOYU
#1 lore raw

PATCH 1/6 omap iommu: tlb and pagetable primitives

This patch provides:

- iotlb_*() : iommu tlb operations
- iopgtable_*() : iommu pagetable(twl) operations
- iommu_*() : the other generic operations

and the entry points to register and acquire iommu object.

---

 arch/arm/plat-omap/include/mach/iommu.h |  157 +++++
 arch/arm/plat-omap/iommu.c              |  913 +++++++++++++++++++++++++++++++
 arch/arm/plat-omap/iopgtable.h          |   72 ++
 3 files changed, 1142 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
 create mode 100644 arch/arm/plat-omap/iommu.c
 create mode 100644 arch/arm/plat-omap/iopgtable.h
arch/arm/plat-omap/include/mach/iommu.h new file +157 -0
new file mode 100644
index 0000000..8bd5c58
@@ -0,0 +1,157 @@
+/*
+ * omap iommu: main structures
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <[email protected]>
+ *
+ * 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 iommu {
+	const char	*name;
+	struct module	*owner;
+	struct clk	*clk;
+	void __iomem	*regbase;
+	struct device	*dev;
+
+	unsigned int	refcount;
+	struct mutex	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 */
+
+	int (*isr)(struct iommu *obj);
+
+	void *ctx; /* iommu context: registres saved area */
+};
+
+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 iommu *obj);
+	void (*disable)(struct iommu *obj);
+	u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+
+	void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
+	void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+
+	struct cr_regs *(*alloc_cr)(struct 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 iommu *obj, struct cr_regs *cr, char *buf);
+
+	u32 (*get_pte_attr)(struct iotlb_entry *e);
+
+	void (*save_ctx)(struct iommu *obj);
+	void (*restore_ctx)(struct iommu *obj);
+	ssize_t (*dump_ctx)(struct iommu *obj, char *buf);
+};
+
+struct iommu_platform_data {
+	char	*name;
+	char	*clk_name;
+	int	nr_tlb_entries;
+};
+
+#include <mach/iommu2.h>
+
+/*
+ * 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 iommu_arch_version(void);
+
+extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void flush_iotlb_page(struct iommu *obj, u32 da);
+extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
+extern void flush_iotlb_all(struct iommu *obj);
+
+ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf);
+
+extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
+extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
+
+extern struct iommu *iommu_get(const char *name);
+extern void iommu_put(struct iommu *obj);
+
+extern void iommu_save_ctx(struct iommu *obj);
+extern void iommu_restore_ctx(struct iommu *obj);
+
+extern int install_iommu_arch(const struct iommu_functions *ops);
+extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+
+#endif /* __MACH_IOMMU_H */
arch/arm/plat-omap/iommu.c new file +913 -0

913 lines not on this page · raw message

arch/arm/plat-omap/iopgtable.h new file +72 -0

72 lines not on this page · raw message

#2 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

A few more simple comments...

arch/arm/plat-omap/include/mach/iommu.h line 102

Quoted 2 lines · Hiroshi DOYU
arch/arm/plat-omap/include/mach/iommu.h new file +2 -0
+struct iommu_platform_data {
+	char	*name;

const?

arch/arm/plat-omap/include/mach/iommu.h line 103

Quoted 1 line
arch/arm/plat-omap/include/mach/iommu.h new file +1 -0
+	char	*clk_name;

const?

Quoted 2 lines
(quoted diff) +2 -0
+	int	nr_tlb_entries;
+};

...

arch/arm/plat-omap/iommu.c line 45

Quoted 9 lines
arch/arm/plat-omap/iommu.c new file +9 -0
+int install_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu)
+		return -EBUSY;
+
+	arch_iommu = ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(install_iommu_arch);

Exported functions should have some documentation in the standard kernel documentation format. See Documentation/kernel-doc-nano-HOWTO.txt

arch/arm/plat-omap/iommu.c line 78

Quoted 5 lines
arch/arm/plat-omap/iommu.c new file +5 -0
+static int iommu_enable(struct iommu *obj)
+{
+	int err;
+
+	BUG_ON(!arch_iommu || !arch_iommu->enable);

Are these run-time BUG_ON checks really worth it? BUG_ON is effectively:

	if (condition_is_true)
		cause_a_null_pointer_dereference;

So, if you're checking for pointers you're about dereference being NULL, there's little point - dereferencing the when they're NULL will cause an oops, and you won't have the overhead of the runtime tests checking them for NULL. Ditto elsewhere in this file.

Quoted 15 lines
arch/arm/plat-omap/iommu.c new file +15 -0
+static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
+{
+	u32 *iopte;
+
+	/* a table has already existed */
+	if (*iopgd)
+		goto pte_ready;
+
+	/*
+	 * do the allocation outside the page table lock
+	 */
+	spin_unlock(&obj->page_table_lock);
+	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
+	spin_lock(&obj->page_table_lock);
+

arch/arm/plat-omap/iommu.c line 393

Quoted 10 lines
arch/arm/plat-omap/iommu.c new file +10 -0
+	if (!*iopgd) {
+		if (!iopte)
+			return ERR_PTR(-ENOMEM);
+
+		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
+		flush_iopgd_range(iopgd, iopgd);
+
+#ifdef DEBUG_VERBOSE
+		dev_dbg(obj->dev, "%s:\ta new pte:%p\n", __func__, iopte);
+#endif

Not sure wrapping these in DEBUG_VERBOSE is necessary. dev_dbg() is a no-op unless DEBUG is defined.

Quoted 15 lines
arch/arm/plat-omap/iommu.c new file +15 -0
+#ifdef DEBUG
+static void dump_tlb_entries(struct iommu *obj)
+{
+	int i;
+	struct iotlb_lock l;
+
+	clk_enable(obj->clk);
+
+	pr_info("%8s %8s\n", "cam:", "ram:");
+	pr_info("-----------------------------------------\n");
+
+	for (i = 0; i < obj->nr_tlb_entries; i++) {
+		struct cr_regs cr;
+		static char buf[4096];
+

arch/arm/plat-omap/iommu.c line 524

Quoted 10 lines
arch/arm/plat-omap/iommu.c new file +10 -0
+		iotlb_lock_get(obj, &l);
+		l.vict = i;
+		iotlb_lock_set(obj, &l);
+		iotlb_read_cr(obj, &cr);
+		if (!iotlb_cr_valid(&cr))
+			continue;
+
+		memset(buf, 0, 4096);
+		iotlb_dump_cr(obj, &cr, buf);
+		pr_info("%s", buf);

Hmm. You call this in relation to an error, but you print everything at 'info' level. Are you sure that's correct?

Quoted 10 lines
arch/arm/plat-omap/iommu.c new file +10 -0
+/*
+ *	OMAP Device MMU(IOMMU) detection
+ */
+static int __devinit omap_iommu_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	void *p;
+	int irq;
+	struct iommu *obj;
+	struct resource *res;

arch/arm/plat-omap/iommu.c line 781

Quoted 10 lines
arch/arm/plat-omap/iommu.c new file +10 -0
+	struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdev->num_resources != 2)
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	obj->clk = clk_get(NULL, pdata->clk_name);

Avoid passing a NULL struct device except when you have absolutely no other choice. &pdev->dev looks sensible. By doing this, it also provides us with a path to fixing the OMAP clk API implementation without having to fix lots of drivers.

#3 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

Quoted 6 lines · Russell King - ARM Linux

arch/arm/plat-omap/iommu.c line 393

Quoted 3 lines
arch/arm/plat-omap/iommu.c new file +3 -0
+#ifdef DEBUG_VERBOSE
+             dev_dbg(obj->dev, "%s:\ta new pte:%p\n", __func__, iopte);
+#endif

Not sure wrapping these in DEBUG_VERBOSE is necessary.  dev_dbg() is a no-op unless DEBUG is defined.

Use dev_vdbg() to get the "NOP unless VERBOSE is set" semantics.

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

Hi David,

From: "ext David Brownell" <[email protected]>
Subject: Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives
Date: Sat, 17 Jan 2009 12:48:45 -0800

Quoted 9 lines · Russell King - ARM Linux
Quoted 6 lines

arch/arm/plat-omap/iommu.c line 393

Quoted 3 lines
arch/arm/plat-omap/iommu.c new file +3 -0
+#ifdef DEBUG_VERBOSE
+             dev_dbg(obj->dev, "%s:\ta new pte:%p\n", __func__, iopte);
+#endif

Not sure wrapping these in DEBUG_VERBOSE is necessary.  dev_dbg() is a no-op unless DEBUG is defined.

Use dev_vdbg() to get the "NOP unless VERBOSE is set" semantics.

Thanks. This is what I wanted... I'll update with "dev_vdbg()". --
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

Quoted 14 lines · Hiroshi DOYU

Hi David,

From: "ext David Brownell" <[email protected]>
Subject: Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives
Date: Sat, 17 Jan 2009 12:48:45 -0800

Quoted 8 lines · Russell King - ARM Linux
Quoted 6 lines

arch/arm/plat-omap/iommu.c line 393

Quoted 3 lines
arch/arm/plat-omap/iommu.c new file +3 -0
+#ifdef DEBUG_VERBOSE
+             dev_dbg(obj->dev, "%s:\ta new pte:%p\n", __func__, iopte);
+#endif

Not sure wrapping these in DEBUG_VERBOSE is necessary.  dev_dbg() is a no-op unless DEBUG is defined.

Quoted 3 lines
Quoted 1 line

Use dev_vdbg() to get the "NOP unless VERBOSE is set" semantics.

Thanks. This is what I wanted... I'll update with "dev_vdbg()".

Sorry, drop the 'v' in that (typo).
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

Quoted 6 lines · Russell King - ARM Linux
Quoted 4 lines
Quoted 2 lines

Use dev_vdbg() to get the "NOP unless VERBOSE is set" semantics.

Thanks. This is what I wanted... I'll update with "dev_vdbg()".

Sorry, drop the 'v' in that (typo).

Not clear what that comment means ... dev_vdbg() is the same as dev_dbg() *IF* the VERBOSE option is set, and is otherwise a NOP.

That is: two levels of debug messaging, for use as needed. As a rule, some Kconfig option will

  ccflags-$(CONFIG_DEBUG_whatever)    += -DDEBUG

to enable DEBUG for that subsystem, and the VERBOSE option (see <linux/device.h>) is set selectively by hand.

- Dave

#7 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

In reply to Russell King - ARM Linux

Hi Russell, thank you for your reivew.

I've attached the updated one.

From: "ext Russell King - ARM Linux" <[email protected]>
Subject: Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives
Date: Sat, 17 Jan 2009 16:06:08 +0000

Quoted 122 lines

A few more simple comments...

Review

Quoted 2 lines · Hiroshi DOYU
(quoted diff) +2 -0
+struct iommu_platform_data {
+	char	*name;

const?

Review

Quoted 1 line
(quoted diff) +1 -0
+	char	*clk_name;

const?

Quoted 2 lines
(quoted diff) +2 -0
+	int	nr_tlb_entries;
+};

...

Review

Quoted 9 lines
(quoted diff) +9 -0
+int install_iommu_arch(const struct iommu_functions *ops)
+{
+	if (arch_iommu)
+		return -EBUSY;
+
+	arch_iommu = ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(install_iommu_arch);

Exported functions should have some documentation in the standard kernel documentation format. See Documentation/kernel-doc-nano-HOWTO.txt

Review

Quoted 5 lines
(quoted diff) +5 -0
+static int iommu_enable(struct iommu *obj)
+{
+	int err;
+
+	BUG_ON(!arch_iommu || !arch_iommu->enable);

Are these run-time BUG_ON checks really worth it? BUG_ON is effectively:

	if (condition_is_true)
		cause_a_null_pointer_dereference;

So, if you're checking for pointers you're about dereference being NULL, there's little point - dereferencing the when they're NULL will cause an oops, and you won't have the overhead of the runtime tests checking them for NULL. Ditto elsewhere in this file.

Quoted 15 lines
(quoted diff) +15 -0
+static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
+{
+	u32 *iopte;
+
+	/* a table has already existed */
+	if (*iopgd)
+		goto pte_ready;
+
+	/*
+	 * do the allocation outside the page table lock
+	 */
+	spin_unlock(&obj->page_table_lock);
+	iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
+	spin_lock(&obj->page_table_lock);
+

Review

Quoted 10 lines
(quoted diff) +10 -0
+	if (!*iopgd) {
+		if (!iopte)
+			return ERR_PTR(-ENOMEM);
+
+		*iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
+		flush_iopgd_range(iopgd, iopgd);
+
+#ifdef DEBUG_VERBOSE
+		dev_dbg(obj->dev, "%s:\ta new pte:%p\n", __func__, iopte);
+#endif

Not sure wrapping these in DEBUG_VERBOSE is necessary. dev_dbg() is a no-op unless DEBUG is defined.

Quoted 15 lines
(quoted diff) +15 -0
+#ifdef DEBUG
+static void dump_tlb_entries(struct iommu *obj)
+{
+	int i;
+	struct iotlb_lock l;
+
+	clk_enable(obj->clk);
+
+	pr_info("%8s %8s\n", "cam:", "ram:");
+	pr_info("-----------------------------------------\n");
+
+	for (i = 0; i < obj->nr_tlb_entries; i++) {
+		struct cr_regs cr;
+		static char buf[4096];
+

Review

Quoted 10 lines
(quoted diff) +10 -0
+		iotlb_lock_get(obj, &l);
+		l.vict = i;
+		iotlb_lock_set(obj, &l);
+		iotlb_read_cr(obj, &cr);
+		if (!iotlb_cr_valid(&cr))
+			continue;
+
+		memset(buf, 0, 4096);
+		iotlb_dump_cr(obj, &cr, buf);
+		pr_info("%s", buf);

Hmm. You call this in relation to an error, but you print everything at 'info' level. Are you sure that's correct?

Quoted 18 lines
(quoted diff) +18 -0
+/*
+ *	OMAP Device MMU(IOMMU) detection
+ */
+static int __devinit omap_iommu_probe(struct platform_device *pdev)
+{
+	int err = -ENODEV;
+	void *p;
+	int irq;
+	struct iommu *obj;
+	struct resource *res;
+	struct iommu_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdev->num_resources != 2)
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
Quoted 8 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+	obj->clk = clk_get(NULL, pdata->clk_name);

Avoid passing a NULL struct device except when you have absolutely no other choice. &pdev->dev looks sensible. By doing this, it also provides us with a path to fixing the OMAP clk API implementation without having to fix lots of drivers.
From 42aa6fc9c17e82a2252b8b726f5e90ffc192ab07 Mon Sep 17 00:00:00 2001

From: Hiroshi DOYU <[email protected]>
Date: Mon, 26 Jan 2009 15:13:40 +0200
Subject: [PATCH 1/6] omap iommu: tlb and pagetable primitives

This patch provides:

- iotlb_*() : iommu tlb operations
- iopgtable_*() : iommu pagetable(twl) operations
- iommu_*() : the other generic operations

and the entry points to register and acquire iommu object.

---
 arch/arm/plat-omap/include/mach/iommu.h |  157 +++++
 arch/arm/plat-omap/iommu.c              |  953 +++++++++++++++++++++++++++++++
 arch/arm/plat-omap/iopgtable.h          |   72 +++
 3 files changed, 1182 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
 create mode 100644 arch/arm/plat-omap/iommu.c
 create mode 100644 arch/arm/plat-omap/iopgtable.h
arch/arm/plat-omap/include/mach/iommu.h new file +157 -0
new file mode 100644
index 0000000..ef04d7a
@@ -0,0 +1,157 @@
+/*
+ * omap iommu: main structures
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <[email protected]>
+ *
+ * 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 iommu {
+	const char	*name;
+	struct module	*owner;
+	struct clk	*clk;
+	void __iomem	*regbase;
+	struct device	*dev;
+
+	unsigned int	refcount;
+	struct mutex	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 */
+
+	int (*isr)(struct iommu *obj);
+
+	void *ctx; /* iommu context: registres saved area */
+};
+
+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 iommu *obj);
+	void (*disable)(struct iommu *obj);
+	u32 (*fault_isr)(struct iommu *obj, u32 *ra);
+
+	void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
+	void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
+
+	struct cr_regs *(*alloc_cr)(struct 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 iommu *obj, struct cr_regs *cr, char *buf);
+
+	u32 (*get_pte_attr)(struct iotlb_entry *e);
+
+	void (*save_ctx)(struct iommu *obj);
+	void (*restore_ctx)(struct iommu *obj);
+	ssize_t (*dump_ctx)(struct iommu *obj, char *buf);
+};
+
+struct iommu_platform_data {
+	const char *name;
+	const char *clk_name;
+	const int nr_tlb_entries;
+};
+
+#include <mach/iommu2.h>
+
+/*
+ * 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 iommu_arch_version(void);
+
+extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void flush_iotlb_page(struct iommu *obj, u32 da);
+extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
+extern void flush_iotlb_all(struct iommu *obj);
+
+ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf);
+
+extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
+extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
+
+extern struct iommu *iommu_get(const char *name);
+extern void iommu_put(struct iommu *obj);
+
+extern void iommu_save_ctx(struct iommu *obj);
+extern void iommu_restore_ctx(struct iommu *obj);
+
+extern int install_iommu_arch(const struct iommu_functions *ops);
+extern void uninstall_iommu_arch(const struct iommu_functions *ops);
+
+#endif /* __MACH_IOMMU_H */
arch/arm/plat-omap/iommu.c new file +953 -0

953 lines not on this page · raw message

arch/arm/plat-omap/iopgtable.h new file +72 -0

72 lines not on this page · raw message

Signature · 1 line
1.6.1.rc4
#8 lore raw

Re: [PATCH 1/6] omap iommu: tlb and pagetable primitives

In reply to Russell King - ARM Linux

Hi Russell, Thank you for your reivew.

Just for your convenience, the updated patchset is available as below.

The following changes since commit 1de9e8e70f5acc441550ca75433563d91b269bbe:
Linus Torvalds (1):

        Linux 2.6.29-rc2

are available in the git repository at:

http://git.gitorious.org/lk/mainline.git iommu

Hiroshi DOYU (6):
omap iommu: tlb and pagetable primitives omap iommu: omap2 architecture specific functions omap iommu: omap3 iommu device registration omap iommu: simple virtual address space management omap iommu: entries for Kconfig and Makefile omap2 iommu: entries for Kconfig and Makefile

 arch/arm/include/asm/io.h                |    6 +
 arch/arm/mach-omap2/Makefile             |    5 +
 arch/arm/mach-omap2/iommu2.c             |  326 ++++++++++
 arch/arm/mach-omap2/omap3-iommu.c        |  103 ++++
 arch/arm/mm/ioremap.c                    |   11 +
 arch/arm/plat-omap/Kconfig               |    8 +
 arch/arm/plat-omap/Makefile              |    1 +
 arch/arm/plat-omap/include/mach/iommu.h  |  157 +++++
 arch/arm/plat-omap/include/mach/iommu2.h |   94 +++
 arch/arm/plat-omap/include/mach/iovmm.h  |   94 +++
 arch/arm/plat-omap/iommu.c               |  953 ++++++++++++++++++++++++++++++
 arch/arm/plat-omap/iopgtable.h           |   72 +++
 arch/arm/plat-omap/iovmm.c               |  891 ++++++++++++++++++++++++++++
 13 files changed, 2721 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/iommu2.c
 create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
 create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
 create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h
 create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
 create mode 100644 arch/arm/plat-omap/iommu.c
 create mode 100644 arch/arm/plat-omap/iopgtable.h
 create mode 100644 arch/arm/plat-omap/iovmm.c
#9 lore raw

PATCH 2/6 omap iommu: omap2 architecture specific functions

In reply to Hiroshi DOYU

The structure 'arch_mmu' accommodates the difference between omap1 and omap2/3.

This patch provides omap2/3 specific functions

---

 arch/arm/mach-omap2/iommu2.c             |  325 ++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/mach/iommu2.h |   94 +++++++++
 2 files changed, 419 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/iommu2.c
 create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h
arch/arm/mach-omap2/iommu2.c new file +325 -0
new file mode 100644
index 0000000..daaa6f5
@@ -0,0 +1,325 @@
+/*
+ * omap iommu: omap2/3 architecture specific functions
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <[email protected]>,
+ *		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/io.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/stringify.h>
+
+#include <mach/iommu.h>
+#include <mach/iommu2.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_MASK	\
+	(MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \
+	 MMU_IRQ_TRANSLATIONFAULT)
+
+/* 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 int omap2_iommu_enable(struct 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, MMU_IRQ_MASK, MMU_IRQENABLE);
+	iommu_write_reg(obj, pa, MMU_TTB);
+
+	l = iommu_read_reg(obj, MMU_CNTL);
+	l &= ~MMU_CNTL_MASK;
+	l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
+	iommu_write_reg(obj, l, MMU_CNTL);
+
+	return 0;
+}
+
+static void omap2_iommu_disable(struct 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 u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
+{
+	int i;
+	u32 stat, da;
+	const char *err_msg[] =	{
+		"tlb miss",
+		"translation fault",
+		"emulation miss",
+		"table walk fault",
+		"multi hit fault",
+	};
+
+	stat = iommu_read_reg(obj, MMU_IRQSTATUS);
+	stat &= MMU_IRQ_MASK;
+	if (!stat)
+		return 0;
+
+	da = iommu_read_reg(obj, MMU_FAULT_AD);
+	*ra = da;
+
+	dev_err(obj->dev, "%s:\tda:%08x ", __func__, da);
+
+	for (i = 0; i < ARRAY_SIZE(err_msg); i++) {
+		if (stat & (1 << i))
+			printk("%s ", err_msg[i]);
+	}
+	printk("\n");
+
+	iommu_write_reg(obj, stat, MMU_IRQSTATUS);
+	return stat;
+}
+
+static void omap2_tlb_read_cr(struct 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 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 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;
+	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) ? 0 : 6);
+
+	return attr;
+}
+
+static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
+{
+	char *p = buf;
+
+	/* FIXME: Need more detail analysis of cam/ram */
+	p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram);
+
+	return p - buf;
+}
+
+#define pr_reg(name)							\
+	p += sprintf(p, "%20s: %08x\n",					\
+		     __stringify(name), iommu_read_reg(obj, MMU_##name));
+
+static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf)
+{
+	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);
+
+	return p - buf;
+}
+
+static void omap2_iommu_save_ctx(struct 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 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,
+	.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 install_iommu_arch(&omap2_iommu_ops);
+}
+module_init(omap2_iommu_init);
+
+static void __exit omap2_iommu_exit(void)
+{
+	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");
arch/arm/plat-omap/include/mach/iommu2.h new file +94 -0

94 lines not on this page · raw message

#10 lore raw

PATCH 3/6 omap iommu: omap3 iommu device registration

In reply to Hiroshi DOYU

---

 arch/arm/mach-omap2/omap3-iommu.c |  111 +++++++++++++++++++++++++++++++++++++
 1 files changed, 111 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
arch/arm/mach-omap2/omap3-iommu.c new file +111 -0
new file mode 100644
index 0000000..52d0e56
@@ -0,0 +1,111 @@
+/*
+ * omap iommu: omap3 device registration
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <[email protected]>
+ *
+ * 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/io.h>
+#include <linux/platform_device.h>
+
+#include <mach/iommu.h>
+
+#define DEVNAME "omap-iommu"
+
+/* Camera ISP MMU */
+#define OMAP3_MMU1_BASE		0x480bd400
+#define OMAP3_MMU1_IRQ		24
+
+/* IVA2.2 MMU */
+#define OMAP3_MMU2_BASE		0x5d000000
+#define OMAP3_MMU2_IRQ		28
+
+static struct resource iommu1_res[] = { /* Camera ISP MMU */
+	{
+		.start		= OMAP3_MMU1_BASE,
+		.end		= OMAP3_MMU1_BASE + MMU_REG_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3_MMU1_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource iommu2_res[] = { /* IVA2.2 MMU */
+	{
+		.start		= OMAP3_MMU2_BASE,
+		.end		= OMAP3_MMU2_BASE + MMU_REG_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3_MMU2_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct iommu_platform_data omap3_iommu_pdata[] = {
+	{
+		.name = "isp",
+		.nr_tlb_entries = 8,
+		.clk_name = "cam_ick",
+	},
+	{
+		.name = "iva2",
+		.nr_tlb_entries = 32,
+		.clk_name = "iva2_ck",
+	},
+};
+
+static void omap3_iommu_release(struct device *dev)
+{
+}
+
+static struct platform_device omap3_iommu_pdev[] = {
+	{
+		.name		= DEVNAME,
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(iommu1_res),
+		.resource	= iommu1_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[0],
+		},
+	},
+	{
+		.name		= DEVNAME,
+		.id		= 2,
+		.num_resources	= ARRAY_SIZE(iommu2_res),
+		.resource	= iommu2_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[1],
+		},
+	},
+};
+
+static int __init omap3_iommu_init(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)
+		platform_device_register(&omap3_iommu_pdev[i]);
+	return 0;
+}
+module_init(omap3_iommu_init);
+
+static void __exit omap3_iommu_exit(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)
+		platform_device_unregister(&omap3_iommu_pdev[i]);
+}
+module_exit(omap3_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_DESCRIPTION("omap iommu: omap3 device registration");
+MODULE_LICENSE("GPL v2");
#11 lore raw

Re: [PATCH 3/6] omap iommu: omap3 iommu device registration

Quoted 1 line · Hiroshi DOYU

+#include <linux/io.h>

Is linux/io.h needed, or will a more specific include be better?

arch/arm/mach-omap2/omap3-iommu.c line 18

Quoted 5 lines
arch/arm/mach-omap2/omap3-iommu.c new file +5 -0
+#include <linux/platform_device.h>
+
+#include <mach/iommu.h>
+
+#define DEVNAME "omap-iommu"

I'm not sure this DEVNAME definition really helps anything.

arch/arm/mach-omap2/omap3-iommu.c line 67

Quoted 3 lines
arch/arm/mach-omap2/omap3-iommu.c new file +3 -0
+static void omap3_iommu_release(struct device *dev)
+{
+}

Err, no. Never ever ever provide a NULL release function. Providing such a function is a screaming message that what you're doing is buggy.

And if you get a warning through not providing such a function, it's telling you that what your overall approach with the driver API is buggy (and you haven't understood the implications of refcounted object management.)

Quoted 28 lines
arch/arm/mach-omap2/omap3-iommu.c new file +28 -0
+
+static struct platform_device omap3_iommu_pdev[] = {
+	{
+		.name		= DEVNAME,
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(iommu1_res),
+		.resource	= iommu1_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[0],
+		},
+	},
+	{
+		.name		= DEVNAME,
+		.id		= 2,
+		.num_resources	= ARRAY_SIZE(iommu2_res),
+		.resource	= iommu2_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[1],
+		},
+	},
+};
+
+static int __init omap3_iommu_init(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)

arch/arm/mach-omap2/omap3-iommu.c line 105

Quoted 10 lines
arch/arm/mach-omap2/omap3-iommu.c new file +10 -0
+		platform_device_register(&omap3_iommu_pdev[i]);
+	return 0;
+}
+module_init(omap3_iommu_init);
+
+static void __exit omap3_iommu_exit(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)
+		platform_device_unregister(&omap3_iommu_pdev[i]);

So... this can never be bug free - you can _never_ unregister statically allocated devices. Not even if you provide an empty release function.

If you want to register and unregister device structures, it must be done using the correct APIs, and in the case of platform devices, that's the platform_device_alloc(), platform_device_add() and platform_device_unregister() APIs.

#12 lore raw

Re: [PATCH 3/6] omap iommu: omap3 iommu device registration

Hi Russell,

I attached the update one.

From: ext Russell King - ARM Linux <[email protected]>
Subject: Re: [PATCH 3/6] omap iommu: omap3 iommu device registration
Date: Sat, 17 Jan 2009 17:21:39 +0100

Quoted 67 lines · Hiroshi DOYU
Quoted 1 line

+#include <linux/io.h>

Is linux/io.h needed, or will a more specific include be better?

Review

Quoted 5 lines
(quoted diff) +5 -0
+#include <linux/platform_device.h>
+
+#include <mach/iommu.h>
+
+#define DEVNAME "omap-iommu"

I'm not sure this DEVNAME definition really helps anything.

Review

Quoted 3 lines
(quoted diff) +3 -0
+static void omap3_iommu_release(struct device *dev)
+{
+}

Err, no. Never ever ever provide a NULL release function. Providing such a function is a screaming message that what you're doing is buggy.

And if you get a warning through not providing such a function, it's telling you that what your overall approach with the driver API is buggy (and you haven't understood the implications of refcounted object management.)

Quoted 28 lines
(quoted diff) +28 -0
+
+static struct platform_device omap3_iommu_pdev[] = {
+	{
+		.name		= DEVNAME,
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(iommu1_res),
+		.resource	= iommu1_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[0],
+		},
+	},
+	{
+		.name		= DEVNAME,
+		.id		= 2,
+		.num_resources	= ARRAY_SIZE(iommu2_res),
+		.resource	= iommu2_res,
+		.dev		= {
+			.release = omap3_iommu_release,
+			.platform_data = &omap3_iommu_pdata[1],
+		},
+	},
+};
+
+static int __init omap3_iommu_init(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)

Review

Quoted 10 lines
(quoted diff) +10 -0
+		platform_device_register(&omap3_iommu_pdev[i]);
+	return 0;
+}
+module_init(omap3_iommu_init);
+
+static void __exit omap3_iommu_exit(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(omap3_iommu_pdev); i++)
+		platform_device_unregister(&omap3_iommu_pdev[i]);

So... this can never be bug free - you can _never_ unregister statically allocated devices. Not even if you provide an empty release function.

Quoted 5 lines

If you want to register and unregister device structures, it must be done using the correct APIs, and in the case of platform devices, that's the platform_device_alloc(), platform_device_add() and platform_device_unregister() APIs.
From 5b61d40f516d7df3a597df5bd798cb06df01fb28 Mon Sep 17 00:00:00 2001

From: Hiroshi DOYU <[email protected]>
Date: Tue, 27 Jan 2009 22:46:36 +0200
Subject: [PATCH 3/6] omap iommu: omap3 iommu device registration

---
 arch/arm/mach-omap2/omap3-iommu.c |  103 +++++++++++++++++++++++++++++++++++++
 1 files changed, 103 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
arch/arm/mach-omap2/omap3-iommu.c new file +103 -0
new file mode 100644
index 0000000..4f51c18
@@ -0,0 +1,103 @@
+/*
+ * omap iommu: omap3 device registration
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Written by Hiroshi DOYU <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <asm/io.h>
+#include <mach/iommu.h>
+
+#define OMAP3_MMU1_BASE	0x480bd400
+#define OMAP3_MMU2_BASE	0x5d000000
+#define OMAP3_MMU1_IRQ	24
+#define OMAP3_MMU2_IRQ	28
+
+static struct resource omap3_iommu_res[] = {
+	{ /* Camera ISP MMU */
+		.start		= OMAP3_MMU1_BASE,
+		.end		= OMAP3_MMU1_BASE + MMU_REG_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3_MMU1_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{ /* IVA2.2 MMU */
+		.start		= OMAP3_MMU2_BASE,
+		.end		= OMAP3_MMU2_BASE + MMU_REG_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3_MMU2_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+#define NR_IOMMU_RES (ARRAY_SIZE(omap3_iommu_res) / 2)
+
+static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
+	{
+		.name = "isp",
+		.nr_tlb_entries = 8,
+		.clk_name = "cam_ick",
+	},
+	{
+		.name = "iva2",
+		.nr_tlb_entries = 32,
+		.clk_name = "iva2_ck",
+	},
+};
+#define NR_IOMMU_DEVICES ARRAY_SIZE(omap3_iommu_pdata)
+
+static struct platform_device *omap3_iommu_pdev[NR_IOMMU_DEVICES];
+
+static int __init omap3_iommu_init(void)
+{
+	int i, err;
+
+	for (i = 0; i < NR_IOMMU_DEVICES; i++) {
+		struct platform_device *pdev;
+
+		pdev = platform_device_alloc("omap-iommu", i + 1);
+		if (!pdev)
+			goto err_out;
+		err = platform_device_add_resources(pdev,
+				    &omap3_iommu_res[2 * i], NR_IOMMU_RES);
+		if (err)
+			goto err_out;
+		err = platform_device_add_data(pdev, &omap3_iommu_pdata[i],
+					       sizeof(omap3_iommu_pdata[0]));
+		if (err)
+			goto err_out;
+		err = platform_device_add(pdev);
+		if (err)
+			goto err_out;
+		omap3_iommu_pdev[i] = pdev;
+	}
+	return 0;
+
+err_out:
+	while (i--)
+		platform_device_put(omap3_iommu_pdev[i]);
+	return err;
+}
+module_init(omap3_iommu_init);
+
+static void __exit omap3_iommu_exit(void)
+{
+	int i;
+
+	for (i = 0; i < NR_IOMMU_DEVICES; i++)
+		platform_device_unregister(omap3_iommu_pdev[i]);
+}
+module_exit(omap3_iommu_exit);
+
+MODULE_AUTHOR("Hiroshi DOYU");
+MODULE_DESCRIPTION("omap iommu: omap3 device registration");
+MODULE_LICENSE("GPL v2");
Signature · 1 line
1.6.1.rc4
#13 lore raw

Re: [PATCH 3/6] omap iommu: omap3 iommu device registration

Quoted 1 line · Hiroshi DOYU

I attached the update one.

Thanks. I want to hold off on taking these just a little bit longer.

arch/arm/mach-omap2/omap3-iommu.c line 53

Quoted 10 lines
arch/arm/mach-omap2/omap3-iommu.c new file +10 -0
+static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
+	{
+		.name = "isp",
+		.nr_tlb_entries = 8,
+		.clk_name = "cam_ick",
+	},
+	{
+		.name = "iva2",
+		.nr_tlb_entries = 32,
+		.clk_name = "iva2_ck",

With the omap clk implementation in a state of flux, hopefully moving towards something which better reflects the intentions of the clk API, passing clk names around becomes entirely wasteful and unnecessary.

That's not to say that what you currently have won't work with the patches as they currently stand - it will work as is. I'd just rather avoid having to have a separate patch to convert this code as well.

#14 lore raw

Re: [PATCH 3/6] omap iommu: omap3 iommu device registration

From: ext Russell King - ARM Linux <[email protected]>
Subject: Re: [PATCH 3/6] omap iommu: omap3 iommu device registration
Date: Wed, 28 Jan 2009 11:41:57 +0100

Quoted 4 lines · Hiroshi DOYU
Quoted 1 line

I attached the update one.

Thanks. I want to hold off on taking these just a little bit longer.

OK. agreed.

Quoted 11 lines

arch/arm/mach-omap2/omap3-iommu.c line 53

Quoted 10 lines
arch/arm/mach-omap2/omap3-iommu.c new file +10 -0
+static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
+     {
+             .name = "isp",
+             .nr_tlb_entries = 8,
+             .clk_name = "cam_ick",
+     },
+     {
+             .name = "iva2",
+             .nr_tlb_entries = 32,
+             .clk_name = "iva2_ck",
Quoted 7 lines

With the omap clk implementation in a state of flux, hopefully moving towards something which better reflects the intentions of the clk API, passing clk names around becomes entirely wasteful and unnecessary.

That's not to say that what you currently have won't work with the patches as they currently stand - it will work as is. I'd just rather avoid having to have a separate patch to convert this code as well.

OK. I'll update later, then.

#15 lore raw

PATCH 4/6 omap iommu: simple virtual address space management

In reply to Hiroshi DOYU

This patch provides a device drivers, which has a omap iommu, with address mapping APIs between device virtual address(iommu), physical address and MPU virtual address.

There are 4 possible patterns for iommu virtual address(iova/da) mapping.

    |iova/			  mapping		iommu_		page
    | da	pa	va	(d)-(p)-(v)		function	type
  ---------------------------------------------------------------------------
  1 | c		c	c	 1 - 1 - 1	  _kmap() / _kunmap()	s
  2 | c		c,a	c	 1 - 1 - 1	_kmalloc()/ _kfree()	s
  3 | c		d	c	 1 - n - 1	  _vmap() / _vunmap()	s
  4 | c		d,a	c	 1 - n - 1	_vmalloc()/ _vfree()	n*

'iova': device iommu virtual address
'da': alias of 'iova'
'pa': physical address
'va': mpu virtual address

'c': contiguous memory area
'd': dicontiguous memory area
'a': anonymous memory allocation
'()': optional feature

'n': a normal page(4KB) size is used.
's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.

'*': not yet, but feasible.

---

 arch/arm/include/asm/io.h               |    6 
 arch/arm/mm/ioremap.c                   |   11 
 arch/arm/plat-omap/include/mach/iovmm.h |   94 +++
 arch/arm/plat-omap/iovmm.c              |  892 +++++++++++++++++++++++++++++++
 4 files changed, 1003 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
 create mode 100644 arch/arm/plat-omap/iovmm.c
arch/arm/include/asm/io.h +6 -0
index d2a59cf..cbdadfe 100644
@@ -75,6 +75,12 @@ extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
+ * external interface to remap single page with appropriate type
+ */
+extern int ioremap_page(unsigned long virt, unsigned long phys,
+			unsigned int mtype);
+
+/*
  * Bad read/write accesses...
  */
 extern void __readwrite_bug(const char *fn);
arch/arm/mm/ioremap.c +11 -0
index 18373f7..ad2a0c1 100644
@@ -110,6 +110,17 @@ static int remap_area_pages(unsigned long start, unsigned long pfn,
 	return err;
 }
 
+int ioremap_page(unsigned long virt, unsigned long phys, unsigned int mtype)
+{
+	const struct mem_type *type;
+
+	type = get_mem_type(mtype);
+	if (!type)
+		return -EINVAL;
+
+	return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, type);
+}
+EXPORT_SYMBOL(ioremap_page);
 
 void __check_kvm_seq(struct mm_struct *mm)
 {
arch/arm/plat-omap/include/mach/iovmm.h new file +94 -0

94 lines not on this page · raw message

arch/arm/plat-omap/iovmm.c new file +892 -0

892 lines not on this page · raw message

#16 lore raw

Re: [PATCH 4/6] omap iommu: simple virtual address space management

Quoted 4 lines · Hiroshi DOYU
arch/arm/plat-omap/iovmm.c new file +4 -0
+static struct iovm_struct *__find_iovm_area(struct iommu *obj, const void *_da)
+{
+	struct iovm_struct *tmp;
+	u32 da = (u32)_da;

...

Quoted 10 lines
arch/arm/plat-omap/iovmm.c new file +10 -0
+static struct iovm_struct *alloc_iovm_area(struct iommu *obj, void *da,
+					   size_t bytes, u32 flags)
+{
+	struct iovm_struct *new, *tmp;
+	u32 start, prev_end, alignement;
+
+	if (!obj || !bytes)
+		return ERR_PTR(-EINVAL);
+
+	start = (u32)da;

...

arch/arm/plat-omap/iovmm.c line 529

Quoted 10 lines
arch/arm/plat-omap/iovmm.c new file +10 -0
+/* template function for all unmapping */
+static struct sg_table *unmap_vm_area(struct iommu *obj, const void *da,
+				      void (*fn)(const void *), u32 flags)
+{
+	struct sg_table *sgt = NULL;
+	struct iovm_struct *area;
+
+	BUG_ON(in_interrupt());
+
+	if (!IS_ALIGNED((u32)da, PAGE_SIZE)) {

...etc

I've been wondering whether 'void *' is the right type for the device address, and I've pretty much come to the conclusion that it isn't. 'void *' is a pointer, so one might expect it to point at memory. It may point at memory, just not on the host CPU. So using a pointer seems wrong to me.

I know that screws up error handling in the code somewhat since you're using IS_ERR and friends - but have you also considered whether a valid device address falls within the space used for error values (iow, small negative numbers)?

Lastly, I'm not entirely sold on the four different interfaces and whether they're the right approach. I've not yet seen users of each of these interfaces so I don't think I can really comment yet - but I think it's important to have some examples before acking this patch.

#17 lore raw

Re: [PATCH 4/6] omap iommu: simple virtual address space management

Hi Russell, Thank you for your reivew.

I attached the update one.

From: ext Russell King - ARM Linux <[email protected]>
Subject: Re: [PATCH 4/6] omap iommu: simple virtual address space management
Date: Sat, 17 Jan 2009 17:57:26 +0100

[...]

Quoted 4 lines

Lastly, I'm not entirely sold on the four different interfaces and whether they're the right approach. I've not yet seen users of each of these interfaces so I don't think I can really comment yet - but I think it's important to have some examples before acking this patch.

There are 2 clients/users of this module, one of them is "camera isp" and the other is "dspbridge". The former one has already used this APIs for a while but it may take some time to publish it..I'll let you know if it's published.

Hiroshi DOYU

Quoted 1 line

From 332cf874b37caa8fa4de2c833c1849398116551e Mon Sep 17 00:00:00 2001

From: Hiroshi DOYU <[email protected]>
Date: Tue, 27 Jan 2009 22:46:40 +0200
Subject: [PATCH 4/6] omap iommu: simple virtual address space management

This patch provides a device drivers, which has a omap iommu, with address mapping APIs between device virtual address(iommu), physical address and MPU virtual address.

There are 4 possible patterns for iommu virtual address(iova/da) mapping.

    |iova/			  mapping		iommu_		page
    | da	pa	va	(d)-(p)-(v)		function	type
  ---------------------------------------------------------------------------
  1 | c		c	c	 1 - 1 - 1	  _kmap() / _kunmap()	s
  2 | c		c,a	c	 1 - 1 - 1	_kmalloc()/ _kfree()	s
  3 | c		d	c	 1 - n - 1	  _vmap() / _vunmap()	s
  4 | c		d,a	c	 1 - n - 1	_vmalloc()/ _vfree()	n*

'iova': device iommu virtual address
'da': alias of 'iova'
'pa': physical address
'va': mpu virtual address

'c': contiguous memory area
'd': dicontiguous memory area
'a': anonymous memory allocation
'()': optional feature

'n': a normal page(4KB) size is used.
's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.

'*': not yet, but feasible.

---
 arch/arm/include/asm/io.h               |    6 +
 arch/arm/mm/ioremap.c                   |   11 +
 arch/arm/plat-omap/include/mach/iovmm.h |   94 ++++
 arch/arm/plat-omap/iovmm.c              |  891 +++++++++++++++++++++++++++++++
 4 files changed, 1002 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
 create mode 100644 arch/arm/plat-omap/iovmm.c
arch/arm/include/asm/io.h +6 -0
index d2a59cf..cbdadfe 100644
@@ -75,6 +75,12 @@ extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iounmap(volatile void __iomem *addr);
 
 /*
+ * external interface to remap single page with appropriate type
+ */
+extern int ioremap_page(unsigned long virt, unsigned long phys,
+			unsigned int mtype);
+
+/*
  * Bad read/write accesses...
  */
 extern void __readwrite_bug(const char *fn);
arch/arm/mm/ioremap.c +11 -0
index 18373f7..ad2a0c1 100644
@@ -110,6 +110,17 @@ static int remap_area_pages(unsigned long start, unsigned long pfn,
 	return err;
 }
 
+int ioremap_page(unsigned long virt, unsigned long phys, unsigned int mtype)
+{
+	const struct mem_type *type;
+
+	type = get_mem_type(mtype);
+	if (!type)
+		return -EINVAL;
+
+	return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, type);
+}
+EXPORT_SYMBOL(ioremap_page);
 
 void __check_kvm_seq(struct mm_struct *mm)
 {
arch/arm/plat-omap/include/mach/iovmm.h new file +94 -0

94 lines not on this page · raw message

arch/arm/plat-omap/iovmm.c new file +891 -0

891 lines not on this page · raw message

Signature · 1 line
1.6.1.rc4
#18 lore raw

PATCH 5/6 omap iommu: entries for Kconfig and Makefile

In reply to Hiroshi DOYU

---

 arch/arm/plat-omap/Kconfig  |    8 ++++++++
 arch/arm/plat-omap/Makefile |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)
arch/arm/plat-omap/Kconfig +8 -0
index 46d3b0b..bacdc32 100644
@@ -104,6 +104,14 @@ config OMAP_MCBSP
 	  Say Y here if you want support for the OMAP Multichannel
 	  Buffered Serial Port.
 
+config OMAP_IOMMU
+	tristate "IOMMU support"
+	depends on ARCH_OMAP
+	default n
+	help
+	  Say Y here if you want to use OMAP IOMMU support for IVA2 and
+	  Camera in OMAP3.
+
 choice
         prompt "System timer"
 	default OMAP_MPU_TIMER
arch/arm/plat-omap/Makefile +1 -0
index deaff58..e2453e2 100644
@@ -13,6 +13,7 @@ obj-  :=
 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
 
 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
#19 lore raw

PATCH 6/6 omap2 iommu: entries for Kconfig and Makefile

In reply to Hiroshi DOYU

---

 arch/arm/mach-omap2/Makefile |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/Makefile +5 -0
index bbd12bc..443e71f 100644
@@ -24,6 +24,11 @@ endif
 obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 
+obj-$(CONFIG_OMAP_IOMMU)		+= iommu2.o
+ifeq ($(CONFIG_ARCH_OMAP3),y)
+obj-$(CONFIG_OMAP_IOMMU)		+= omap3-iommu.o
+endif
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
#20 lore raw

Re: [PATCH 6/6] omap2 iommu: entries for Kconfig and Makefile

Quoted 11 lines · Hiroshi DOYU

---

 arch/arm/mach-omap2/Makefile |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/Makefile +0 -0
index bbd12bc..443e71f 100644

arch/arm/mach-omap2/Makefile endif · line 31

Quoted 8 lines
arch/arm/mach-omap2/Makefile +5 -0
@@ -24,6 +24,11 @@ endif
 obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 
+obj-$(CONFIG_OMAP_IOMMU)		+= iommu2.o
+ifeq ($(CONFIG_ARCH_OMAP3),y)
+obj-$(CONFIG_OMAP_IOMMU)		+= omap3-iommu.o
+endif
+

I can see this expanding still further... so what about nipping it now before it gets out of hand:

iommu-y += iommu2.o
iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o

obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)

Quoted 9 lines
arch/arm/mach-omap2/Makefile +0 -1
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
 
 
-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php
#21 lore raw

Re: [PATCH 6/6] omap2 iommu: entries for Kconfig and Makefile

Hi Russell,

From: "ext Russell King - ARM Linux" <[email protected]>
Subject: Re: [PATCH 6/6] omap2 iommu: entries for Kconfig and Makefile
Date: Sat, 17 Jan 2009 16:59:20 +0000

Quoted 24 lines · Hiroshi DOYU
Quoted 11 lines

---

 arch/arm/mach-omap2/Makefile |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/Makefile +0 -0
index bbd12bc..443e71f 100644

arch/arm/mach-omap2/Makefile endif · line 31

Quoted 8 lines
arch/arm/mach-omap2/Makefile +5 -0
@@ -24,6 +24,11 @@ endif
 obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 
+obj-$(CONFIG_OMAP_IOMMU)		+= iommu2.o
+ifeq ($(CONFIG_ARCH_OMAP3),y)
+obj-$(CONFIG_OMAP_IOMMU)		+= omap3-iommu.o
+endif
+

I can see this expanding still further... so what about nipping it now before it gets out of hand:

Quoted 4 lines

iommu-y += iommu2.o
iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o

obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)

Much simpler. Thanks. The updated one is attached.

Quoted 1 line

From 80c17b5d26e89a3c5a65b2dfac02eeaf6426404b Mon Sep 17 00:00:00 2001

From: Hiroshi DOYU <[email protected]>
Date: Mon, 19 Jan 2009 13:01:01 +0200
Subject: [PATCH 6/6] omap2 iommu: entries for Kconfig and Makefile

---
 arch/arm/mach-omap2/Makefile |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/Makefile +5 -0
index bbd12bc..4f6123d 100644
@@ -24,6 +24,11 @@ endif
 obj-$(CONFIG_ARCH_OMAP2)		+= clock24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o
 
+iommu-y					+= iommu2.o
+iommu-$(CONFIG_ARCH_OMAP3)		+= omap3-iommu.o
+
+obj-$(CONFIG_OMAP_IOMMU)		+= $(iommu-y)
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
Signature · 1 line
1.6.1.rc4