brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · ad74d57 Raw
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