Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.35-rc6 177 lines 4.4 kB view raw
1/* 2 * Simple memory allocator for on-board SRAM 3 * 4 * 5 * Maintainer : Sylvain Munaut <tnt@246tNt.com> 6 * 7 * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com> 8 * 9 * This file is licensed under the terms of the GNU General Public License 10 * version 2. This program is licensed "as is" without any warranty of any 11 * kind, whether express or implied. 12 */ 13 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> 21 22#include <asm/io.h> 23#include <asm/mmu.h> 24 25#include "sram.h" 26 27 28/* Struct keeping our 'state' */ 29struct bcom_sram *bcom_sram = NULL; 30EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */ 31 32 33/* ======================================================================== */ 34/* Public API */ 35/* ======================================================================== */ 36/* DO NOT USE in interrupts, if needed in irq handler, we should use the 37 _irqsave version of the spin_locks */ 38 39int bcom_sram_init(struct device_node *sram_node, char *owner) 40{ 41 int rv; 42 const u32 *regaddr_p; 43 u64 regaddr64, size64; 44 unsigned int psize; 45 46 /* Create our state struct */ 47 if (bcom_sram) { 48 printk(KERN_ERR "%s: bcom_sram_init: " 49 "Already initialized !\n", owner); 50 return -EBUSY; 51 } 52 53 bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL); 54 if (!bcom_sram) { 55 printk(KERN_ERR "%s: bcom_sram_init: " 56 "Couldn't allocate internal state !\n", owner); 57 return -ENOMEM; 58 } 59 60 /* Get address and size of the sram */ 61 regaddr_p = of_get_address(sram_node, 0, &size64, NULL); 62 if (!regaddr_p) { 63 printk(KERN_ERR "%s: bcom_sram_init: " 64 "Invalid device node !\n", owner); 65 rv = -EINVAL; 66 goto error_free; 67 } 68 69 regaddr64 = of_translate_address(sram_node, regaddr_p); 70 71 bcom_sram->base_phys = (phys_addr_t) regaddr64; 72 bcom_sram->size = (unsigned int) size64; 73 74 /* Request region */ 75 if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) { 76 printk(KERN_ERR "%s: bcom_sram_init: " 77 "Couldn't request region !\n", owner); 78 rv = -EBUSY; 79 goto error_free; 80 } 81 82 /* Map SRAM */ 83 /* sram is not really __iomem */ 84 bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size); 85 86 if (!bcom_sram->base_virt) { 87 printk(KERN_ERR "%s: bcom_sram_init: " 88 "Map error SRAM zone 0x%08lx (0x%0x)!\n", 89 owner, (long)bcom_sram->base_phys, bcom_sram->size ); 90 rv = -ENOMEM; 91 goto error_release; 92 } 93 94 /* Create an rheap (defaults to 32 bits word alignment) */ 95 bcom_sram->rh = rh_create(4); 96 97 /* Attach the free zones */ 98#if 0 99 /* Currently disabled ... for future use only */ 100 reg_addr_p = of_get_property(sram_node, "available", &psize); 101#else 102 regaddr_p = NULL; 103 psize = 0; 104#endif 105 106 if (!regaddr_p || !psize) { 107 /* Attach the whole zone */ 108 rh_attach_region(bcom_sram->rh, 0, bcom_sram->size); 109 } else { 110 /* Attach each zone independently */ 111 while (psize >= 2 * sizeof(u32)) { 112 phys_addr_t zbase = of_translate_address(sram_node, regaddr_p); 113 rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]); 114 regaddr_p += 2; 115 psize -= 2 * sizeof(u32); 116 } 117 } 118 119 /* Init our spinlock */ 120 spin_lock_init(&bcom_sram->lock); 121 122 return 0; 123 124error_release: 125 release_mem_region(bcom_sram->base_phys, bcom_sram->size); 126error_free: 127 kfree(bcom_sram); 128 bcom_sram = NULL; 129 130 return rv; 131} 132EXPORT_SYMBOL_GPL(bcom_sram_init); 133 134void bcom_sram_cleanup(void) 135{ 136 /* Free resources */ 137 if (bcom_sram) { 138 rh_destroy(bcom_sram->rh); 139 iounmap((void __iomem *)bcom_sram->base_virt); 140 release_mem_region(bcom_sram->base_phys, bcom_sram->size); 141 kfree(bcom_sram); 142 bcom_sram = NULL; 143 } 144} 145EXPORT_SYMBOL_GPL(bcom_sram_cleanup); 146 147void* bcom_sram_alloc(int size, int align, phys_addr_t *phys) 148{ 149 unsigned long offset; 150 151 spin_lock(&bcom_sram->lock); 152 offset = rh_alloc_align(bcom_sram->rh, size, align, NULL); 153 spin_unlock(&bcom_sram->lock); 154 155 if (IS_ERR_VALUE(offset)) 156 return NULL; 157 158 *phys = bcom_sram->base_phys + offset; 159 return bcom_sram->base_virt + offset; 160} 161EXPORT_SYMBOL_GPL(bcom_sram_alloc); 162 163void bcom_sram_free(void *ptr) 164{ 165 unsigned long offset; 166 167 if (!ptr) 168 return; 169 170 offset = ptr - bcom_sram->base_virt; 171 172 spin_lock(&bcom_sram->lock); 173 rh_free(bcom_sram->rh, offset); 174 spin_unlock(&bcom_sram->lock); 175} 176EXPORT_SYMBOL_GPL(bcom_sram_free); 177