From 9de90ac27d752bc0177baf2699ab483888de0743 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Fri, 18 Jul 2008 13:30:31 +0400
Subject: Sh: use generic per-device coherent dma allocator

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/sh/mm/consistent.c | 98 ++-----------------------------------------------
 1 file changed, 3 insertions(+), 95 deletions(-)

(limited to 'arch/sh/mm/consistent.c')

diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index d3c33fc5b1c..3095d958147 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -27,21 +27,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret, *ret_nocache;
-	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
 	int order = get_order(size);
 
-	if (mem) {
-		int page = bitmap_find_free_region(mem->bitmap, mem->size,
-						     order);
-		if (page >= 0) {
-			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
-			ret = mem->virt_base + (page << PAGE_SHIFT);
-			memset(ret, 0, size);
-			return ret;
-		}
-		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
-			return NULL;
-	}
+	if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+		return ret;
 
 	ret = (void *)__get_free_pages(gfp, order);
 	if (!ret)
@@ -71,11 +60,7 @@ void dma_free_coherent(struct device *dev, size_t size,
 	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
 	int order = get_order(size);
 
-	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
-		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
-
-		bitmap_release_region(mem->bitmap, page, order);
-	} else {
+	if (!dma_release_from_coherent(dev, order, vaddr)) {
 		WARN_ON(irqs_disabled());	/* for portability */
 		BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
 		free_pages((unsigned long)phys_to_virt(dma_handle), order);
@@ -84,83 +69,6 @@ void dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
-int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
-				dma_addr_t device_addr, size_t size, int flags)
-{
-	void __iomem *mem_base = NULL;
-	int pages = size >> PAGE_SHIFT;
-	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
-	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
-		goto out;
-	if (!size)
-		goto out;
-	if (dev->dma_mem)
-		goto out;
-
-	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
-
-	mem_base = ioremap_nocache(bus_addr, size);
-	if (!mem_base)
-		goto out;
-
-	dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-	if (!dev->dma_mem)
-		goto out;
-	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!dev->dma_mem->bitmap)
-		goto free1_out;
-
-	dev->dma_mem->virt_base = mem_base;
-	dev->dma_mem->device_base = device_addr;
-	dev->dma_mem->size = pages;
-	dev->dma_mem->flags = flags;
-
-	if (flags & DMA_MEMORY_MAP)
-		return DMA_MEMORY_MAP;
-
-	return DMA_MEMORY_IO;
-
- free1_out:
-	kfree(dev->dma_mem);
- out:
-	if (mem_base)
-		iounmap(mem_base);
-	return 0;
-}
-EXPORT_SYMBOL(dma_declare_coherent_memory);
-
-void dma_release_declared_memory(struct device *dev)
-{
-	struct dma_coherent_mem *mem = dev->dma_mem;
-
-	if (!mem)
-		return;
-	dev->dma_mem = NULL;
-	iounmap(mem->virt_base);
-	kfree(mem->bitmap);
-	kfree(mem);
-}
-EXPORT_SYMBOL(dma_release_declared_memory);
-
-void *dma_mark_declared_memory_occupied(struct device *dev,
-					dma_addr_t device_addr, size_t size)
-{
-	struct dma_coherent_mem *mem = dev->dma_mem;
-	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	int pos, err;
-
-	if (!mem)
-		return ERR_PTR(-EINVAL);
-
-	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
-	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
-	if (err != 0)
-		return ERR_PTR(err);
-	return mem->virt_base + (pos << PAGE_SHIFT);
-}
-EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
-
 void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		    enum dma_data_direction direction)
 {
-- 
cgit v1.2.3-70-g09d2


From 1eca5c92729a83f64826d15a9ecb1652dda54bcb Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@igel.co.jp>
Date: Wed, 16 Jul 2008 19:02:54 +0900
Subject: sh: Add memory chunks to SH-Mobile UIO devices

This patch adds physically contiguous memory chunks to the UIO devices.
The same strategy can be used in the future for the CEU as well.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/kernel/cpu/sh4a/setup-sh7343.c |  8 ++++++++
 arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 12 ++++++++++++
 arch/sh/kernel/cpu/sh4a/setup-sh7722.c |  8 ++++++++
 arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 12 ++++++++++++
 arch/sh/mm/consistent.c                | 30 ++++++++++++++++++++++++++++++
 include/asm-sh/device.h                |  5 +++++
 6 files changed, 75 insertions(+)

(limited to 'arch/sh/mm/consistent.c')

diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index bcc4255acd8..79ce34e19a2 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -66,6 +66,9 @@ static struct resource vpu_resources[] = {
 		.end	= 0xfe9022eb,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device vpu_device = {
@@ -91,6 +94,9 @@ static struct resource veu_resources[] = {
 		.end	= 0xfe9200b7,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu_device = {
@@ -132,6 +138,8 @@ static struct platform_device *sh7343_devices[] __initdata = {
 
 static int __init sh7343_devices_setup(void)
 {
+	platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
+	platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
 	return platform_add_devices(sh7343_devices,
 				    ARRAY_SIZE(sh7343_devices));
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 2a0fbc3ed9c..7ee01757f3f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -48,6 +48,9 @@ static struct resource vpu_resources[] = {
 		.end	= 0xfe902807,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device vpu_device = {
@@ -73,6 +76,9 @@ static struct resource veu0_resources[] = {
 		.end	= 0xfe9200b7,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu0_device = {
@@ -98,6 +104,9 @@ static struct resource veu1_resources[] = {
 		.end	= 0xfe9240b7,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu1_device = {
@@ -139,6 +148,9 @@ static struct platform_device *sh7366_devices[] __initdata = {
 
 static int __init sh7366_devices_setup(void)
 {
+	platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+	platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+	platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
 	return platform_add_devices(sh7366_devices,
 				    ARRAY_SIZE(sh7366_devices));
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 39854d9413c..6015f842eda 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -73,6 +73,9 @@ static struct resource vpu_resources[] = {
 		.end	= 0xfe9022eb,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device vpu_device = {
@@ -98,6 +101,9 @@ static struct resource veu_resources[] = {
 		.end	= 0xfe9200b7,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu_device = {
@@ -152,6 +158,8 @@ static struct platform_device *sh7722_devices[] __initdata = {
 
 static int __init sh7722_devices_setup(void)
 {
+	platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
+	platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
 	return platform_add_devices(sh7722_devices,
 				    ARRAY_SIZE(sh7722_devices));
 }
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 1f3137ad013..cb5e6f822e6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -28,6 +28,9 @@ static struct resource vpu_resources[] = {
 		.end	= 0xfe902807,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device vpu_device = {
@@ -53,6 +56,9 @@ static struct resource veu0_resources[] = {
 		.end	= 0xfe92027b,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu0_device = {
@@ -78,6 +84,9 @@ static struct resource veu1_resources[] = {
 		.end	= 0xfe92427b,
 		.flags	= IORESOURCE_MEM,
 	},
+	[1] = {
+		/* place holder for contiguous memory */
+	},
 };
 
 static struct platform_device veu1_device = {
@@ -221,6 +230,9 @@ static struct platform_device *sh7723_devices[] __initdata = {
 
 static int __init sh7723_devices_setup(void)
 {
+	platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+	platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+	platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
 	return platform_add_devices(sh7723_devices,
 				    ARRAY_SIZE(sh7723_devices));
 }
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index d3c33fc5b1c..8277982d093 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -10,6 +10,7 @@
  * for more details.
  */
 #include <linux/mm.h>
+#include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include <asm/addrspace.h>
@@ -185,3 +186,32 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	}
 }
 EXPORT_SYMBOL(dma_cache_sync);
+
+int platform_resource_setup_memory(struct platform_device *pdev,
+				   char *name, unsigned long memsize)
+{
+	struct resource *r;
+	dma_addr_t dma_handle;
+	void *buf;
+
+	r = pdev->resource + pdev->num_resources - 1;
+	if (r->flags) {
+		pr_warning("%s: unable to find empty space for resource\n",
+			name);
+		return -EINVAL;
+	}
+
+	buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
+	if (!buf) {
+		pr_warning("%s: unable to allocate memory\n", name);
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, memsize);
+
+	r->flags = IORESOURCE_MEM;
+	r->start = dma_handle;
+	r->end = r->start + memsize - 1;
+	r->name = name;
+	return 0;
+}
diff --git a/include/asm-sh/device.h b/include/asm-sh/device.h
index d8f9872b0e2..efd511d0803 100644
--- a/include/asm-sh/device.h
+++ b/include/asm-sh/device.h
@@ -5,3 +5,8 @@
  */
 #include <asm-generic/device.h>
 
+struct platform_device;
+/* allocate contiguous memory chunk and fill in struct resource */
+int platform_resource_setup_memory(struct platform_device *pdev,
+				   char *name, unsigned long memsize);
+
-- 
cgit v1.2.3-70-g09d2