File Index
Files and directories
Sign in
FILE

sram.c

File preview with syntax highlighting.

linux-6.19.14/drivers/dma/bestcomm/sram.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Simple memory allocator for on-board SRAM
  4 *
  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 the
 35   _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);
~/ Read-only file preview.