0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/err.h>
0011 #include <linux/kernel.h>
0012 #include <linux/export.h>
0013 #include <linux/slab.h>
0014 #include <linux/spinlock.h>
0015 #include <linux/string.h>
0016 #include <linux/ioport.h>
0017 #include <linux/of.h>
0018 #include <linux/of_address.h>
0019
0020 #include <asm/io.h>
0021 #include <asm/mmu.h>
0022
0023 #include <linux/fsl/bestcomm/sram.h>
0024
0025
0026
0027 struct bcom_sram *bcom_sram = NULL;
0028 EXPORT_SYMBOL_GPL(bcom_sram);
0029
0030
0031
0032
0033
0034
0035
0036
0037 int bcom_sram_init(struct device_node *sram_node, char *owner)
0038 {
0039 int rv;
0040 const u32 *regaddr_p;
0041 u64 regaddr64, size64;
0042 unsigned int psize;
0043
0044
0045 if (bcom_sram) {
0046 printk(KERN_ERR "%s: bcom_sram_init: "
0047 "Already initialized !\n", owner);
0048 return -EBUSY;
0049 }
0050
0051 bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL);
0052 if (!bcom_sram) {
0053 printk(KERN_ERR "%s: bcom_sram_init: "
0054 "Couldn't allocate internal state !\n", owner);
0055 return -ENOMEM;
0056 }
0057
0058
0059 regaddr_p = of_get_address(sram_node, 0, &size64, NULL);
0060 if (!regaddr_p) {
0061 printk(KERN_ERR "%s: bcom_sram_init: "
0062 "Invalid device node !\n", owner);
0063 rv = -EINVAL;
0064 goto error_free;
0065 }
0066
0067 regaddr64 = of_translate_address(sram_node, regaddr_p);
0068
0069 bcom_sram->base_phys = (phys_addr_t) regaddr64;
0070 bcom_sram->size = (unsigned int) size64;
0071
0072
0073 if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) {
0074 printk(KERN_ERR "%s: bcom_sram_init: "
0075 "Couldn't request region !\n", owner);
0076 rv = -EBUSY;
0077 goto error_free;
0078 }
0079
0080
0081
0082 bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size);
0083
0084 if (!bcom_sram->base_virt) {
0085 printk(KERN_ERR "%s: bcom_sram_init: "
0086 "Map error SRAM zone 0x%08lx (0x%0x)!\n",
0087 owner, (long)bcom_sram->base_phys, bcom_sram->size );
0088 rv = -ENOMEM;
0089 goto error_release;
0090 }
0091
0092
0093 bcom_sram->rh = rh_create(4);
0094
0095
0096 #if 0
0097
0098 reg_addr_p = of_get_property(sram_node, "available", &psize);
0099 #else
0100 regaddr_p = NULL;
0101 psize = 0;
0102 #endif
0103
0104 if (!regaddr_p || !psize) {
0105
0106 rh_attach_region(bcom_sram->rh, 0, bcom_sram->size);
0107 } else {
0108
0109 while (psize >= 2 * sizeof(u32)) {
0110 phys_addr_t zbase = of_translate_address(sram_node, regaddr_p);
0111 rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]);
0112 regaddr_p += 2;
0113 psize -= 2 * sizeof(u32);
0114 }
0115 }
0116
0117
0118 spin_lock_init(&bcom_sram->lock);
0119
0120 return 0;
0121
0122 error_release:
0123 release_mem_region(bcom_sram->base_phys, bcom_sram->size);
0124 error_free:
0125 kfree(bcom_sram);
0126 bcom_sram = NULL;
0127
0128 return rv;
0129 }
0130 EXPORT_SYMBOL_GPL(bcom_sram_init);
0131
0132 void bcom_sram_cleanup(void)
0133 {
0134
0135 if (bcom_sram) {
0136 rh_destroy(bcom_sram->rh);
0137 iounmap((void __iomem *)bcom_sram->base_virt);
0138 release_mem_region(bcom_sram->base_phys, bcom_sram->size);
0139 kfree(bcom_sram);
0140 bcom_sram = NULL;
0141 }
0142 }
0143 EXPORT_SYMBOL_GPL(bcom_sram_cleanup);
0144
0145 void* bcom_sram_alloc(int size, int align, phys_addr_t *phys)
0146 {
0147 unsigned long offset;
0148
0149 spin_lock(&bcom_sram->lock);
0150 offset = rh_alloc_align(bcom_sram->rh, size, align, NULL);
0151 spin_unlock(&bcom_sram->lock);
0152
0153 if (IS_ERR_VALUE(offset))
0154 return NULL;
0155
0156 *phys = bcom_sram->base_phys + offset;
0157 return bcom_sram->base_virt + offset;
0158 }
0159 EXPORT_SYMBOL_GPL(bcom_sram_alloc);
0160
0161 void bcom_sram_free(void *ptr)
0162 {
0163 unsigned long offset;
0164
0165 if (!ptr)
0166 return;
0167
0168 offset = ptr - bcom_sram->base_virt;
0169
0170 spin_lock(&bcom_sram->lock);
0171 rh_free(bcom_sram->rh, offset);
0172 spin_unlock(&bcom_sram->lock);
0173 }
0174 EXPORT_SYMBOL_GPL(bcom_sram_free);