From patchwork Fri Apr 15 13:06:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King - ARM Linux X-Patchwork-Id: 710741 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3FD6u36006199 for ; Fri, 15 Apr 2011 13:06:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754138Ab1DONGz (ORCPT ); Fri, 15 Apr 2011 09:06:55 -0400 Received: from caramon.arm.linux.org.uk ([78.32.30.218]:43475 "EHLO caramon.arm.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753948Ab1DONGy (ORCPT ); Fri, 15 Apr 2011 09:06:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=caramon; h=Sender:Content-Type:MIME-Version:Message-ID:Subject:Cc:To:From:Date; bh=t6wkgAOCgw+XFPcQ5q27FiP0lJCQHgGXyJ3+O9VaW8A=; b=jbO9KX1VuPcziKmQCSKzNAN/MX8eTdKJEX+onFZYJ5REbSfZJ6xGNQbv3TrXgxuaZCBaa0DXzs2DhpYN1xOtY80V271X2nHS0U5OxQ0/T8yP+U983++PJFg6vWwiMkDBmAdt4Xwjo3DEqAnFDLWUATrDD/kQZLFHQUeGjLGuQhg=; Received: from n2100.arm.linux.org.uk ([2002:4e20:1eda:1:214:fdff:fe10:4f86]) by caramon.arm.linux.org.uk with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.72) (envelope-from ) id 1QAiiv-00049u-16; Fri, 15 Apr 2011 14:06:10 +0100 Received: from linux by n2100.arm.linux.org.uk with local (Exim 4.72) (envelope-from ) id 1QAiit-0005pv-Mq; Fri, 15 Apr 2011 14:06:07 +0100 Date: Fri, 15 Apr 2011 14:06:07 +0100 From: Russell King - ARM Linux To: Sekhar Nori , Kevin Hilman , Tony Lindgren Cc: davinci-linux-open-source@linux.davincidsp.com, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH] Consolidate SRAM support Message-ID: <20110415130607.GM1611@n2100.arm.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.19 (2009-01-05) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 15 Apr 2011 13:06:57 +0000 (UTC) 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 --- arch/arm/Kconfig | 2 + arch/arm/common/Kconfig | 4 ++ arch/arm/common/Makefile | 1 + arch/arm/common/sram-pool.c | 69 +++++++++++++++++++++++++++ arch/arm/include/asm/sram-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 | 12 +---- arch/arm/mach-davinci/sram.c | 42 +++-------------- arch/arm/plat-omap/include/plat/sram.h | 17 ++++--- arch/arm/plat-omap/sram.c | 34 +++++--------- drivers/uio/uio_pruss.c | 8 ++- 17 files changed, 141 insertions(+), 93 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5b9f78b..5c3401c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -850,6 +850,7 @@ config ARCH_DAVINCI bool "TI DaVinci" select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB + select ARM_SRAM_POOL select ZONE_DMA select HAVE_IDE select CLKDEV_LOOKUP @@ -863,6 +864,7 @@ config ARCH_OMAP select HAVE_CLK select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_CPUFREQ + select ARM_SRAM_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..ddbd20b 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -39,3 +39,7 @@ config SHARP_PARAM config SHARP_SCOOP bool + +config ARM_SRAM_POOL + bool + select GENERIC_ALLOCATOR diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index e7521bca..b79ad68 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_ARCH_IXP23XX) += uengine.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o +obj-$(CONFIG_ARM_SRAM_POOL) += sram-pool.o diff --git a/arch/arm/common/sram-pool.c b/arch/arm/common/sram-pool.c new file mode 100644 index 0000000..9ff1466 --- /dev/null +++ b/arch/arm/common/sram-pool.c @@ -0,0 +1,69 @@ +/* + * Unified SRAM 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 +#include +#include +#include +#include + +#include + +struct sram_pool { + struct gen_pool *genpool; + void *cpu_base; + phys_addr_t phys_base; +}; + +void *sram_pool_alloc(struct sram_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(sram_pool_alloc); + +void sram_pool_free(struct sram_pool *pool, void *addr, size_t len) +{ + gen_pool_free(pool->genpool, (unsigned long)addr, len); +} +EXPORT_SYMBOL_GPL(sram_pool_free); + +struct sram_pool *sram_pool_create(void *addr, phys_addr_t phys, size_t len, + int min_alloc_order) +{ + struct sram_pool *pool = kzalloc(sizeof(struct sram_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(sram_pool_create); + +void sram_pool_destroy(struct sram_pool *pool) +{ + gen_pool_destroy(pool->genpool); + kfree(pool); +} +EXPORT_SYMBOL_GPL(sram_pool_destroy); diff --git a/arch/arm/include/asm/sram-pool.h b/arch/arm/include/asm/sram-pool.h new file mode 100644 index 0000000..b7ae871 --- /dev/null +++ b/arch/arm/include/asm/sram-pool.h @@ -0,0 +1,20 @@ +#ifndef __ASMARM_SRAM_POOL_H +#define __ASMARM_SRAM_POOL_H + +#include + +struct sram_pool; + +void *sram_pool_alloc(struct sram_pool *, size_t, phys_addr_t *); +void sram_pool_free(struct sram_pool *, void *, size_t); +struct sram_pool *sram_pool_create(void *, phys_addr_t, size_t, int); +void sram_pool_destroy(struct sram_pool *); + +/* Macro to copy a function into SRAM, using the fncpy API */ +#define sram_pool_fncpy(pool, funcp, size) ({ \ + size_t _sz = size; \ + void *_sram = sram_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 68fe4c2..5eca128 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 76364d1..3df8730 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 9a2376b..4ca7295 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..7d77e85 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 + /* 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 sram_pool *davinci_sram_pool; #endif /* __MACH_SRAM_H */ diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c index 1bd73a0..f69cd7b 100644 --- a/arch/arm/mach-davinci/pm.c +++ b/arch/arm/mach-davinci/pm.c @@ -29,12 +29,6 @@ static void (*davinci_sram_suspend) (struct davinci_pm_config *); 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,15 +117,13 @@ static int __init davinci_pm_probe(struct platform_device *pdev) return -ENOENT; } - davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL); + davinci_sram_suspend = sram_pool_fncpy(davinci_sram_pool, + davinci_cpu_suspend, davinci_cpu_suspend_sz); if (!davinci_sram_suspend) { dev_err(&pdev->dev, "cannot allocate SRAM memory\n"); return -ENOMEM; } - davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend, - davinci_cpu_suspend_sz); - suspend_set_ops(&davinci_pm_ops); return 0; diff --git a/arch/arm/mach-davinci/sram.c b/arch/arm/mach-davinci/sram.c index db0f778..ebd4d67 100644 --- a/arch/arm/mach-davinci/sram.c +++ b/arch/arm/mach-davinci/sram.c @@ -10,40 +10,13 @@ */ #include #include -#include +#include #include #include -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 sram_pool *davinci_sram_pool; +EXPORT_SYMBOL_GPL(davinci_sram_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_sram_pool = sram_pool_create((void *)SRAM_VIRT, + davinci_soc_info.sram_phys, len, + ilog2(SRAM_GRANULARITY)); + if (!davinci_sram_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-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index f500fc3..9fc27d0 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 +#include -extern void *omap_sram_push_address(unsigned long size); +extern struct sram_pool *omap_sram_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 = sram_pool_fncpy(omap_sram_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..3588749 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 sram_pool *omap_sram_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_sram_pool = sram_pool_create(base, phys, len, + ilog2(FNCPY_ALIGN)); + WARN_ON(!omap_sram_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 daf6e77..2be3155 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,8 @@ static void pruss_cleanup(struct platform_device *dev, gdev->ddr_paddr); } if (gdev->sram_vaddr) - sram_free(gdev->sram_vaddr, sram_pool_sz); + sram_pool_free(davinci_sram_pool, gdev->sram_vaddr, + sram_pool_sz); kfree(gdev->info); clk_put(gdev->pruss_clk); kfree(gdev); @@ -152,7 +153,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 = sram_pool_alloc(davinci_sram_pool, sram_pool_sz, + &(gdev->sram_paddr)); if (!gdev->sram_vaddr) { dev_err(&dev->dev, "Could not allocate SRAM pool\n"); goto out_free;