Path: blob/master/arch/powerpc/sysdev/bestcomm/sram.c
10818 views
/*1* Simple memory allocator for on-board SRAM2*3*4* Maintainer : Sylvain Munaut <[email protected]>5*6* Copyright (C) 2005 Sylvain Munaut <[email protected]>7*8* This file is licensed under the terms of the GNU General Public License9* version 2. This program is licensed "as is" without any warranty of any10* kind, whether express or implied.11*/1213#include <linux/err.h>14#include <linux/kernel.h>15#include <linux/module.h>16#include <linux/slab.h>17#include <linux/spinlock.h>18#include <linux/string.h>19#include <linux/ioport.h>20#include <linux/of.h>2122#include <asm/io.h>23#include <asm/mmu.h>2425#include "sram.h"262728/* Struct keeping our 'state' */29struct bcom_sram *bcom_sram = NULL;30EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */313233/* ======================================================================== */34/* Public API */35/* ======================================================================== */36/* DO NOT USE in interrupts, if needed in irq handler, we should use the37_irqsave version of the spin_locks */3839int bcom_sram_init(struct device_node *sram_node, char *owner)40{41int rv;42const u32 *regaddr_p;43u64 regaddr64, size64;44unsigned int psize;4546/* Create our state struct */47if (bcom_sram) {48printk(KERN_ERR "%s: bcom_sram_init: "49"Already initialized !\n", owner);50return -EBUSY;51}5253bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);54if (!bcom_sram) {55printk(KERN_ERR "%s: bcom_sram_init: "56"Couldn't allocate internal state !\n", owner);57return -ENOMEM;58}5960/* Get address and size of the sram */61regaddr_p = of_get_address(sram_node, 0, &size64, NULL);62if (!regaddr_p) {63printk(KERN_ERR "%s: bcom_sram_init: "64"Invalid device node !\n", owner);65rv = -EINVAL;66goto error_free;67}6869regaddr64 = of_translate_address(sram_node, regaddr_p);7071bcom_sram->base_phys = (phys_addr_t) regaddr64;72bcom_sram->size = (unsigned int) size64;7374/* Request region */75if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {76printk(KERN_ERR "%s: bcom_sram_init: "77"Couldn't request region !\n", owner);78rv = -EBUSY;79goto error_free;80}8182/* Map SRAM */83/* sram is not really __iomem */84bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);8586if (!bcom_sram->base_virt) {87printk(KERN_ERR "%s: bcom_sram_init: "88"Map error SRAM zone 0x%08lx (0x%0x)!\n",89owner, (long)bcom_sram->base_phys, bcom_sram->size );90rv = -ENOMEM;91goto error_release;92}9394/* Create an rheap (defaults to 32 bits word alignment) */95bcom_sram->rh = rh_create(4);9697/* Attach the free zones */98#if 099/* Currently disabled ... for future use only */100reg_addr_p = of_get_property(sram_node, "available", &psize);101#else102regaddr_p = NULL;103psize = 0;104#endif105106if (!regaddr_p || !psize) {107/* Attach the whole zone */108rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);109} else {110/* Attach each zone independently */111while (psize >= 2 * sizeof(u32)) {112phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);113rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);114regaddr_p += 2;115psize -= 2 * sizeof(u32);116}117}118119/* Init our spinlock */120spin_lock_init(&bcom_sram->lock);121122return 0;123124error_release:125release_mem_region(bcom_sram->base_phys, bcom_sram->size);126error_free:127kfree(bcom_sram);128bcom_sram = NULL;129130return rv;131}132EXPORT_SYMBOL_GPL(bcom_sram_init);133134void bcom_sram_cleanup(void)135{136/* Free resources */137if (bcom_sram) {138rh_destroy(bcom_sram->rh);139iounmap((void __iomem *)bcom_sram->base_virt);140release_mem_region(bcom_sram->base_phys, bcom_sram->size);141kfree(bcom_sram);142bcom_sram = NULL;143}144}145EXPORT_SYMBOL_GPL(bcom_sram_cleanup);146147void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)148{149unsigned long offset;150151spin_lock(&bcom_sram->lock);152offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);153spin_unlock(&bcom_sram->lock);154155if (IS_ERR_VALUE(offset))156return NULL;157158*phys = bcom_sram->base_phys + offset;159return bcom_sram->base_virt + offset;160}161EXPORT_SYMBOL_GPL(bcom_sram_alloc);162163void bcom_sram_free(void *ptr)164{165unsigned long offset;166167if (!ptr)168return;169170offset = ptr - bcom_sram->base_virt;171172spin_lock(&bcom_sram->lock);173rh_free(bcom_sram->rh, offset);174spin_unlock(&bcom_sram->lock);175}176EXPORT_SYMBOL_GPL(bcom_sram_free);177178179180