diff mbox

[RFC,v3] Consolidate SRAM support

Message ID 20110512174546.GB8633@n2100.arm.linux.org.uk (mailing list archive)
State Not Applicable
Headers show

Commit Message

Russell King - ARM Linux May 12, 2011, 5:45 p.m. UTC
On Fri, Apr 15, 2011 at 02:06:07PM +0100, Russell King - ARM Linux wrote:
This is work in progress.

We have two SoCs using SRAM, both with their own allocation systems,
and both with their own ways of copying functions into the SRAM.

Let's unify this before we have additional SoCs re-implementing this
obviously common functionality themselves.

Unfortunately, we end up with code growth through doing this, but that
will become a win when we have another SoC using this (which I know
there's at least one in the pipeline).

One of the considerations here is that we can easily convert sram-pool.c
to hook into device tree stuff, which can tell the sram allocator:
	- physical address of sram
	- size of sram
	- allocation granularity
and then we just need to ensure that it is appropriately mapped.

This uses the physical address, and unlike Davinci's dma address usage,
it always wants to have the physical address, and will always return
the corresponding physical address when passed that pointer.

OMAP could probably do with some more work to make the omapfb and other
allocations use the sram allocator, rather than hooking in before the
sram allocator is initialized - and then further cleanups so that we
have an initialization function which just does

sram_create(phys, size)
	virt = map sram(phys, size)
	create sram pool(virt, phys, size, min_alloc_order)

Another question is whether we should allow multiple SRAM pools or not -
this code does allow multiple pools, but so far we only have one pool
per SoC.  Overdesign?  Maybe, but it prevents SoCs wanting to duplicate
it if they want to partition the SRAM, or have peripheral-local SRAMs.

Lastly, uio_pruss should probably take the SRAM pool pointer via
platform data so that it doesn't have to include Davinci specific
includes.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---

This version fixes the davinci pm free, and adds updates for the
davinci pcm driver.  As I don't know what's happening with Jean's
patch tweaking the genpool allocator, I've kept my version.

This still suffers from the "only one region per pvpool" problem
which I believe Jean's patch doesn't suffer.

 arch/arm/Kconfig                            |    2 +
 arch/arm/common/Kconfig                     |    4 ++
 arch/arm/common/Makefile                    |    1 +
 arch/arm/common/pv-pool.c                   |   69 +++++++++++++++++++++++++++
 arch/arm/include/asm/pv-pool.h              |   20 ++++++++
 arch/arm/mach-davinci/da850.c               |    2 +-
 arch/arm/mach-davinci/dm355.c               |    2 +-
 arch/arm/mach-davinci/dm365.c               |    2 +-
 arch/arm/mach-davinci/dm644x.c              |    2 +-
 arch/arm/mach-davinci/dm646x.c              |    2 +-
 arch/arm/mach-davinci/include/mach/common.h |    2 +-
 arch/arm/mach-davinci/include/mach/sram.h   |   13 +----
 arch/arm/mach-davinci/pm.c                  |   20 +++-----
 arch/arm/mach-davinci/sram.c                |   42 +++--------------
 arch/arm/plat-mxc/Kconfig                   |    2 +-
 arch/arm/plat-mxc/include/mach/iram.h       |   24 +++++++--
 arch/arm/plat-mxc/iram_alloc.c              |   50 +++++---------------
 arch/arm/plat-omap/include/plat/sram.h      |   17 ++++---
 arch/arm/plat-omap/sram.c                   |   34 +++++---------
 drivers/uio/uio_pruss.c                     |    7 ++-
 sound/soc/davinci/davinci-pcm.c             |    9 ++--
 21 files changed, 182 insertions(+), 144 deletions(-)

Comments

Russell King - ARM Linux May 13, 2011, 9:11 a.m. UTC | #1
On Fri, May 13, 2011 at 09:30:14AM +0200, Jean Pihet wrote:
> On Thu, May 12, 2011 at 7:45 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> >    This version fixes the davinci pm free, and adds updates for the
> >    davinci pcm driver.  As I don't know what's happening with Jean's
> >    patch tweaking the genpool allocator, I've kept my version.
> 
> Sorry I do not get the question. The latest changes I submitted have
> been merged in mainline as 'ARM: 6649/1: omap: use fncpy to copy the
> PM code functions to SRAM' [1] . Thanks for that!
> This change is only about the simple linear SRAM allocator, not the
> genpool allocator.

The wrong Jean!  I meant Jean-Christophe PLAGNIOL-VILLARD.
Sekhar Nori June 29, 2011, 1:12 p.m. UTC | #2
Hi Jean-Christophe,

On Thu, May 26, 2011 at 06:32:57, Jean-Christophe PLAGNIOL-VILLARD wrote:
> From: Russell King - ARM Linux <linux@arm.linux.org.uk>
> 
> We have two SoCs using SRAM, both with their own allocation systems,
> and both with their own ways of copying functions into the SRAM.
> 
> Let's unify this before we have additional SoCs re-implementing this
> obviously common functionality themselves.
> 
> For this use the generic allocator and the newly introduce
> gen_pool_add_virt and gen_pool_virt_to_phys
> 
> Uio_pruss should probably take the SRAM pool pointer via
> platform data so that it doesn't have to include Davinci specific
> includes.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: Sekhar Nori <nsekhar@ti.com>
> Cc: Kevin Hilman <khilman@ti.com>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Sascha Hauer <kernel@pengutronix.de>

Is this patch slated to be merged for v3.1?
I did not find it in linux-next.

There is some further cleanup done by Ben
Gardiner for DaVinci which depends on this patch.

> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index f4b7dfa..5ec5e5f 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -848,6 +848,7 @@ config ARCH_DAVINCI
>  	bool "TI DaVinci"
>  	select GENERIC_CLOCKEVENTS
>  	select ARCH_REQUIRE_GPIOLIB
> +	select GENERIC_ALLOCATOR
>  	select ZONE_DMA
>  	select HAVE_IDE
>  	select CLKDEV_LOOKUP

Just noticed that GENERIC_ALLOCATOR is already selected
For DaVinci (it is right below the CLKDEV_LOOKUP selection)
so this part of the patch can be dropped.

Thanks,
Sekhar
Sekhar Nori July 8, 2011, 4:58 p.m. UTC | #3
On Fri, Jul 08, 2011 at 22:21:52, Nori, Sekhar wrote:
> Hi Jean-Christophe,
> 
> On Thu, May 26, 2011 at 06:32:57, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > From: Russell King - ARM Linux <linux@arm.linux.org.uk>

> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index f4b7dfa..5ec5e5f 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -848,6 +848,7 @@ config ARCH_DAVINCI
> >  	bool "TI DaVinci"
> >  	select GENERIC_CLOCKEVENTS
> >  	select ARCH_REQUIRE_GPIOLIB
> > +	select GENERIC_ALLOCATOR
> >  	select ZONE_DMA
> >  	select HAVE_IDE
> >  	select CLKDEV_LOOKUP
> 
> GENERIC_ALLOCATOR is already selected for
> DaVinci (below the "select CLKDEV_LOOKUP"
> line).
> 
> Please drop this hunk.

This mail popped up at the top of my inbox
as an unread message and I replied to it
without looking at the sent date assuming
it is a patch resend.

Sorry about the noise.

Thanks,
Sekhar
diff mbox

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 903c9c4..7a4a625 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -862,6 +862,7 @@  config ARCH_DAVINCI
 	bool "TI DaVinci"
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
+	select PV_POOL
 	select ZONE_DMA
 	select HAVE_IDE
 	select CLKDEV_LOOKUP
@@ -875,6 +876,7 @@  config ARCH_OMAP
 	select HAVE_CLK
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAS_CPUFREQ
+	select PV_POOL
 	select GENERIC_CLOCKEVENTS
 	select HAVE_SCHED_CLOCK
 	select ARCH_HAS_HOLES_MEMORYMODEL
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index ea5ee4d..abee3ca 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -39,3 +39,7 @@  config SHARP_PARAM
 
 config SHARP_SCOOP
 	bool
+
+config PV_POOL
+	bool
+	select GENERIC_ALLOCATOR
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 6ea9b6f..4ae455e 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -17,3 +17,4 @@  obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
+obj-$(CONFIG_PV_POOL)		+= pv-pool.o
diff --git a/arch/arm/common/pv-pool.c b/arch/arm/common/pv-pool.c
index e69de29..748367a 100644
--- a/arch/arm/common/pv-pool.c
+++ b/arch/arm/common/pv-pool.c
@@ -0,0 +1,69 @@ 
+/*
+ * Unified Phys/Virt allocator, based on mach-davinci/sram.c, which was
+ * Copyright (C) 2009 David Brownell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/genalloc.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <asm/pv-pool.h>
+
+struct pv_pool {
+	struct gen_pool *genpool;
+	void *cpu_base;
+	phys_addr_t phys_base;
+};
+
+void *pv_pool_alloc(struct pv_pool *pool, size_t len, phys_addr_t *phys)
+{
+	void *addr = (void *)gen_pool_alloc(pool->genpool, len);
+
+	if (phys)
+		*phys = addr ? (pool->phys_base + (addr - pool->cpu_base)) :
+			 (phys_addr_t)-1ULL;
+
+	return addr;
+}
+EXPORT_SYMBOL_GPL(pv_pool_alloc);
+
+void pv_pool_free(struct pv_pool *pool, void *addr, size_t len)
+{
+	gen_pool_free(pool->genpool, (unsigned long)addr, len);
+}
+EXPORT_SYMBOL_GPL(pv_pool_free);
+
+struct pv_pool *pv_pool_create(void *addr, phys_addr_t phys, size_t len,
+	int min_alloc_order)
+{
+	struct pv_pool *pool = kzalloc(sizeof(struct pv_pool), GFP_KERNEL);
+
+	if (pool) {
+		pool->cpu_base = addr;
+		pool->phys_base = phys;
+		pool->genpool = gen_pool_create(min_alloc_order, -1);
+		if (!pool->genpool) {
+			kfree(pool);
+			pool = NULL;
+		} else {
+			WARN_ON(gen_pool_add(pool->genpool, (unsigned long)addr,
+						len, -1) < 0);
+		}
+	}
+
+	return pool;
+}
+EXPORT_SYMBOL_GPL(pv_pool_create);
+
+void pv_pool_destroy(struct pv_pool *pool)
+{
+	gen_pool_destroy(pool->genpool);
+	kfree(pool);
+}
+EXPORT_SYMBOL_GPL(pv_pool_destroy);
diff --git a/arch/arm/include/asm/pv-pool.h b/arch/arm/include/asm/pv-pool.h
index e69de29..0834216 100644
--- a/arch/arm/include/asm/pv-pool.h
+++ b/arch/arm/include/asm/pv-pool.h
@@ -0,0 +1,20 @@ 
+#ifndef __ASMARM_PV_POOL_H
+#define __ASMARM_PV_POOL_H
+
+#include <asm/fncpy.h>
+
+struct pv_pool;
+
+void *pv_pool_alloc(struct pv_pool *, size_t, phys_addr_t *);
+void pv_pool_free(struct pv_pool *, void *, size_t);
+struct pv_pool *pv_pool_create(void *, phys_addr_t, size_t, int);
+void pv_pool_destroy(struct pv_pool *);
+
+/* Macro to copy a function into SRAM, using the fncpy API */
+#define pv_pool_fncpy(pool, funcp, size) ({			\
+	size_t _sz = size;					\
+	void *_sram = pv_pool_alloc(pool, _sz, NULL);		\
+	(_sram ? fncpy(_sram, &(funcp), _sz) : NULL);		\
+})
+
+#endif
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index b95b919..09f6c12 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -1099,7 +1099,7 @@  static struct davinci_soc_info davinci_soc_info_da850 = {
 	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.serial_dev		= &da8xx_serial_device,
 	.emac_pdata		= &da8xx_emac_pdata,
-	.sram_dma		= DA8XX_ARM_RAM_BASE,
+	.sram_phys		= DA8XX_ARM_RAM_BASE,
 	.sram_len		= SZ_8K,
 	.reset_device		= &da8xx_wdt_device,
 };
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index a3a94e9..9bda687 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -850,7 +850,7 @@  static struct davinci_soc_info davinci_soc_info_dm355 = {
 	.gpio_num		= 104,
 	.gpio_irq		= IRQ_DM355_GPIOBNK0,
 	.serial_dev		= &dm355_serial_device,
-	.sram_dma		= 0x00010000,
+	.sram_phys		= 0x00010000,
 	.sram_len		= SZ_32K,
 	.reset_device		= &davinci_wdt_device,
 };
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 4604e72..d306034 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -1082,7 +1082,7 @@  static struct davinci_soc_info davinci_soc_info_dm365 = {
 	.gpio_unbanked		= 8,	/* really 16 ... skip muxed GPIOs */
 	.serial_dev		= &dm365_serial_device,
 	.emac_pdata		= &dm365_emac_pdata,
-	.sram_dma		= 0x00010000,
+	.sram_phys		= 0x00010000,
 	.sram_len		= SZ_32K,
 	.reset_device		= &davinci_wdt_device,
 };
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 4c82c27..3949ed7 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -764,7 +764,7 @@  static struct davinci_soc_info davinci_soc_info_dm644x = {
 	.gpio_irq		= IRQ_GPIOBNK0,
 	.serial_dev		= &dm644x_serial_device,
 	.emac_pdata		= &dm644x_emac_pdata,
-	.sram_dma		= 0x00008000,
+	.sram_phys		= 0x00008000,
 	.sram_len		= SZ_16K,
 	.reset_device		= &davinci_wdt_device,
 };
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 1e0f809..a4365f7 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -848,7 +848,7 @@  static struct davinci_soc_info davinci_soc_info_dm646x = {
 	.gpio_irq		= IRQ_DM646X_GPIOBNK0,
 	.serial_dev		= &dm646x_serial_device,
 	.emac_pdata		= &dm646x_emac_pdata,
-	.sram_dma		= 0x10010000,
+	.sram_phys		= 0x10010000,
 	.sram_len		= SZ_32K,
 	.reset_device		= &davinci_wdt_device,
 };
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index a57cba2..665d049 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -75,7 +75,7 @@  struct davinci_soc_info {
 	int				gpio_ctlrs_num;
 	struct platform_device		*serial_dev;
 	struct emac_platform_data	*emac_pdata;
-	dma_addr_t			sram_dma;
+	phys_addr_t			sram_phys;
 	unsigned			sram_len;
 	struct platform_device		*reset_device;
 	void				(*reset)(struct platform_device *);
diff --git a/arch/arm/mach-davinci/include/mach/sram.h b/arch/arm/mach-davinci/include/mach/sram.h
index 111f7cc..14676de 100644
--- a/arch/arm/mach-davinci/include/mach/sram.h
+++ b/arch/arm/mach-davinci/include/mach/sram.h
@@ -10,18 +10,11 @@ 
 #ifndef __MACH_SRAM_H
 #define __MACH_SRAM_H
 
+#include <asm/pv-pool.h>
+
 /* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
 #define SRAM_GRANULARITY	512
 
-/*
- * SRAM allocations return a CPU virtual address, or NULL on error.
- * If a DMA address is requested and the SRAM supports DMA, its
- * mapped address is also returned.
- *
- * Errors include SRAM memory not being available, and requesting
- * DMA mapped SRAM on systems which don't allow that.
- */
-extern void *sram_alloc(size_t len, dma_addr_t *dma);
-extern void sram_free(void *addr, size_t len);
+extern struct pv_pool *davinci_pv_pool;
 
 #endif /* __MACH_SRAM_H */
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
index 1bd73a0..c2f9767 100644
--- a/arch/arm/mach-davinci/pm.c
+++ b/arch/arm/mach-davinci/pm.c
@@ -27,14 +27,9 @@ 
 #define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
 
 static void (*davinci_sram_suspend) (struct davinci_pm_config *);
+static void *davinci_sram_suspend_mem;
 static struct davinci_pm_config *pdata;
 
-static void davinci_sram_push(void *dest, void *src, unsigned int size)
-{
-	memcpy(dest, src, size);
-	flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
-}
-
 static void davinci_pm_suspend(void)
 {
 	unsigned val;
@@ -123,14 +118,14 @@  static int __init davinci_pm_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
-	if (!davinci_sram_suspend) {
+	davinci_sram_suspend_mem = pv_pool_alloc(davinci_pv_pool,
+				davinci_cpu_suspend_sz, NULL);
+	if (!davinci_sram_suspend_mem) {
 		dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
 		return -ENOMEM;
 	}
-
-	davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
-						davinci_cpu_suspend_sz);
+	davinci_sram_suspend = fncpy(davinci_sram_suspend_mem,
+				davinci_cpu_suspend, davinci_cpu_suspend_sz);
 
 	suspend_set_ops(&davinci_pm_ops);
 
@@ -139,7 +134,8 @@  static int __init davinci_pm_probe(struct platform_device *pdev)
 
 static int __exit davinci_pm_remove(struct platform_device *pdev)
 {
-	sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
+	pv_pool_free(davinci_pv_pool, davinci_sram_suspend_mem,
+		davinci_cpu_suspend_sz);
 	return 0;
 }
 
diff --git a/arch/arm/mach-davinci/sram.c b/arch/arm/mach-davinci/sram.c
index db0f778..219d4c5 100644
--- a/arch/arm/mach-davinci/sram.c
+++ b/arch/arm/mach-davinci/sram.c
@@ -10,40 +10,13 @@ 
  */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/genalloc.h>
+#include <asm/pv-pool.h>
 
 #include <mach/common.h>
 #include <mach/sram.h>
 
-static struct gen_pool *sram_pool;
-
-void *sram_alloc(size_t len, dma_addr_t *dma)
-{
-	unsigned long vaddr;
-	dma_addr_t dma_base = davinci_soc_info.sram_dma;
-
-	if (dma)
-		*dma = 0;
-	if (!sram_pool || (dma && !dma_base))
-		return NULL;
-
-	vaddr = gen_pool_alloc(sram_pool, len);
-	if (!vaddr)
-		return NULL;
-
-	if (dma)
-		*dma = dma_base + (vaddr - SRAM_VIRT);
-	return (void *)vaddr;
-
-}
-EXPORT_SYMBOL(sram_alloc);
-
-void sram_free(void *addr, size_t len)
-{
-	gen_pool_free(sram_pool, (unsigned long) addr, len);
-}
-EXPORT_SYMBOL(sram_free);
-
+struct pv_pool *davinci_pv_pool;
+EXPORT_SYMBOL_GPL(davinci_pv_pool);
 
 /*
  * REVISIT This supports CPU and DMA access to/from SRAM, but it
@@ -58,13 +31,12 @@  static int __init sram_init(void)
 
 	if (len) {
 		len = min_t(unsigned, len, SRAM_SIZE);
-		sram_pool = gen_pool_create(ilog2(SRAM_GRANULARITY), -1);
-		if (!sram_pool)
+		davinci_pv_pool = pv_pool_create((void *)SRAM_VIRT,
+					davinci_soc_info.sram_phys, len,
+					ilog2(SRAM_GRANULARITY));
+		if (!davinci_pv_pool)
 			status = -ENOMEM;
 	}
-	if (sram_pool)
-		status = gen_pool_add(sram_pool, SRAM_VIRT, len, -1);
-	WARN_ON(status < 0);
 	return status;
 }
 core_initcall(sram_init);
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index b0cb425..fb23497 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -118,6 +118,6 @@  config ARCH_MXC_AUDMUX_V2
 
 config IRAM_ALLOC
 	bool
-	select GENERIC_ALLOCATOR
+	select PV_POOL
 
 endif
diff --git a/arch/arm/plat-mxc/include/mach/iram.h b/arch/arm/plat-mxc/include/mach/iram.h
index 022690c..a989bff 100644
--- a/arch/arm/plat-mxc/include/mach/iram.h
+++ b/arch/arm/plat-mxc/include/mach/iram.h
@@ -17,25 +17,37 @@ 
  * MA 02110-1301, USA.
  */
 #include <linux/errno.h>
+#include <asm/pv-pool.h>
 
 #ifdef CONFIG_IRAM_ALLOC
 
-int __init iram_init(unsigned long base, unsigned long size);
-void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr);
-void iram_free(unsigned long dma_addr, unsigned int size);
+int __init iram_init(phys_addr_t base, size_t size);
+
+extern struct pv_pool *mxc_iram_pool;
+
+static inline void *iram_alloc(size_t size, phys_addr_t *phys)
+{
+	return pv_pool_alloc(iram_pool, size, phys);
+}
+
+static inline void iram_free(void *addr, size_t size)
+{
+	pv_pool_free(iram_pool, addr, size);
+}
 
 #else
 
-static inline int __init iram_init(unsigned long base, unsigned long size)
+static inline int __init iram_init(phys_addr_t base, size_t size)
 {
 	return -ENOMEM;
 }
 
-static inline void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
+static inline void *iram_alloc(size_t size, phys_addr_t *phys)
 {
+	*phys = (phys_addr_t)-1ULL;
 	return NULL;
 }
 
-static inline void iram_free(unsigned long base, unsigned long size) {}
+static inline void iram_free(void *addr, size_t size) {}
 
 #endif
diff --git a/arch/arm/plat-mxc/iram_alloc.c b/arch/arm/plat-mxc/iram_alloc.c
index 074c386..30bccc8 100644
--- a/arch/arm/plat-mxc/iram_alloc.c
+++ b/arch/arm/plat-mxc/iram_alloc.c
@@ -24,50 +24,24 @@ 
 #include <linux/genalloc.h>
 #include <mach/iram.h>
 
-static unsigned long iram_phys_base;
-static void __iomem *iram_virt_base;
-static struct gen_pool *iram_pool;
+struct pv_pool *mxc_iram_pool;
+EXPORT_SYMBOL(mxc_iram_pool);
 
-static inline void __iomem *iram_phys_to_virt(unsigned long p)
+int __init iram_init(phys_addr_t base, size_t size)
 {
-	return iram_virt_base + (p - iram_phys_base);
-}
-
-void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr)
-{
-	if (!iram_pool)
-		return NULL;
-
-	*dma_addr = gen_pool_alloc(iram_pool, size);
-	pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr);
-	if (!*dma_addr)
-		return NULL;
-	return iram_phys_to_virt(*dma_addr);
-}
-EXPORT_SYMBOL(iram_alloc);
-
-void iram_free(unsigned long addr, unsigned int size)
-{
-	if (!iram_pool)
-		return;
-
-	gen_pool_free(iram_pool, addr, size);
-}
-EXPORT_SYMBOL(iram_free);
+	void *addr = /*FIXME*/ ioremap(base, size);
 
-int __init iram_init(unsigned long base, unsigned long size)
-{
-	iram_phys_base = base;
+	if (!addr)
+		return -EIO;
 
-	iram_pool = gen_pool_create(PAGE_SHIFT, -1);
-	if (!iram_pool)
+	mxc_iram_pool = pv_pool_create(addr, base, size, PAGE_SHIFT);
+	if (!mxc_iram_pool) {
+		iounmap(addr);
 		return -ENOMEM;
+	}
 
-	gen_pool_add(iram_pool, base, size, -1);
-	iram_virt_base = ioremap(iram_phys_base, size);
-	if (!iram_virt_base)
-		return -EIO;
+	pr_debug("i.MX IRAM pool: %lu KB@0x%08llx\n", size / 1024,
+		 (unsigned long long)base);
 
-	pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
 	return 0;
 }
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index f500fc3..711931a 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -12,16 +12,19 @@ 
 #define __ARCH_ARM_OMAP_SRAM_H
 
 #ifndef __ASSEMBLY__
-#include <asm/fncpy.h>
+#include <asm/pv-pool.h>
 
-extern void *omap_sram_push_address(unsigned long size);
+extern struct pv_pool *omap_pv_pool;
 
-/* Macro to push a function to the internal SRAM, using the fncpy API */
+/*
+ * Note that fncpy requires the SRAM address to be aligned to an 8-byte
+ * boundary, so the min_alloc_order for the pool is set appropriately.
+ */
 #define omap_sram_push(funcp, size) ({				\
-	typeof(&(funcp)) _res = NULL;				\
-	void *_sram_address = omap_sram_push_address(size);	\
-	if (_sram_address)					\
-		_res = fncpy(_sram_address, &(funcp), size);	\
+	typeof(&(funcp)) _res;					\
+	_res = pv_pool_fncpy(omap_pv_pool, funcp, size);	\
+	if (!_res)						\
+		pr_err("Not enough space in SRAM\n");		\
 	_res;							\
 })
 
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index a3f50b3..68f57ff 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -75,7 +75,6 @@ 
 static unsigned long omap_sram_start;
 static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
-static unsigned long omap_sram_ceil;
 
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
@@ -104,6 +103,8 @@  static int is_sram_locked(void)
 		return 1; /* assume locked with no PPA or security driver */
 }
 
+struct pv_pool *omap_pv_pool;
+
 /*
  * The amount of SRAM depends on the core type.
  * Note that we cannot try to test for SRAM here because writes
@@ -182,7 +183,16 @@  static void __init omap_detect_sram(void)
 			omap_sram_size - SRAM_BOOTLOADER_SZ);
 	omap_sram_size -= reserved;
 
-	omap_sram_ceil = omap_sram_base + omap_sram_size;
+	{
+		/* The first SRAM_BOOTLOADER_SZ of SRAM are reserved */
+		void *base = (void *)omap_sram_base + SRAM_BOOTLOADER_SZ;
+		phys_addr_t phys = omap_sram_start + SRAM_BOOTLOADER_SZ;
+		size_t len = omap_sram_size - SRAM_BOOTLOADER_SZ;
+
+		omap_pv_pool = pv_pool_create(base, phys, len,
+						ilog2(FNCPY_ALIGN));
+		WARN_ON(!omap_pv_pool);
+	}
 }
 
 static struct map_desc omap_sram_io_desc[] __initdata = {
@@ -242,26 +252,6 @@  static void __init omap_map_sram(void)
 	       omap_sram_size - SRAM_BOOTLOADER_SZ);
 }
 
-/*
- * Memory allocator for SRAM: calculates the new ceiling address
- * for pushing a function using the fncpy API.
- *
- * Note that fncpy requires the returned address to be aligned
- * to an 8-byte boundary.
- */
-void *omap_sram_push_address(unsigned long size)
-{
-	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
-		printk(KERN_ERR "Not enough space in SRAM\n");
-		return NULL;
-	}
-
-	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
-
-	return (void *)omap_sram_ceil;
-}
-
 #ifdef CONFIG_ARCH_OMAP1
 
 static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl);
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index e67b566..0c558e7 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -62,7 +62,7 @@  MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate");
 struct uio_pruss_dev {
 	struct uio_info *info;
 	struct clk *pruss_clk;
-	dma_addr_t sram_paddr;
+	phys_addr_t sram_paddr;
 	dma_addr_t ddr_paddr;
 	void __iomem *prussio_vaddr;
 	void *sram_vaddr;
@@ -106,7 +106,7 @@  static void pruss_cleanup(struct platform_device *dev,
 			gdev->ddr_paddr);
 	}
 	if (gdev->sram_vaddr)
-		sram_free(gdev->sram_vaddr, sram_pool_sz);
+		pv_pool_free(davinci_pv_pool, gdev->sram_vaddr, sram_pool_sz);
 	kfree(gdev->info);
 	clk_put(gdev->pruss_clk);
 	kfree(gdev);
@@ -152,7 +152,8 @@  static int __devinit pruss_probe(struct platform_device *dev)
 		goto out_free;
 	}
 
-	gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
+	gdev->sram_vaddr = pv_pool_alloc(davinci_pv_pool, sram_pool_sz,
+					   &(gdev->sram_paddr));
 	if (!gdev->sram_vaddr) {
 		dev_err(&dev->dev, "Could not allocate SRAM pool\n");
 		goto out_free;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 9d35b8c..621e2a1 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -232,14 +232,14 @@  static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
 {
 	struct snd_dma_buffer *buf = &substream->dma_buffer;
 	struct snd_dma_buffer *iram_dma = NULL;
-	dma_addr_t iram_phys = 0;
+	phys_addr_t iram_phys;
 	void *iram_virt = NULL;
 
 	if (buf->private_data || !size)
 		return 0;
 
 	ppcm->period_bytes_max = size;
-	iram_virt = sram_alloc(size, &iram_phys);
+	iram_virt = pv_pool_alloc(davinci_pv_pool, size, &iram_phys);
 	if (!iram_virt)
 		goto exit1;
 	iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
@@ -253,7 +253,7 @@  static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
 	return 0;
 exit2:
 	if (iram_virt)
-		sram_free(iram_virt, size);
+		pv_pool_free(davinci_pv_pool, iram_virt, size);
 exit1:
 	return -ENOMEM;
 }
@@ -803,7 +803,8 @@  static void davinci_pcm_free(struct snd_pcm *pcm)
 		buf->area = NULL;
 		iram_dma = buf->private_data;
 		if (iram_dma) {
-			sram_free(iram_dma->area, iram_dma->bytes);
+			pv_pool_free(davinci_pv_pool, iram_dma->area,
+				iram_dma->bytes);
 			kfree(iram_dma);
 		}
 	}