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