mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
3.6 KiB
147 lines
3.6 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* Copyright 2009-2010 Freescale Semiconductor, Inc. |
|
* |
|
* Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM |
|
* |
|
* Author: Vivek Mahajan <[email protected]> |
|
* |
|
* This file is derived from the original work done |
|
* by Sylvain Munaut for the Bestcomm SRAM allocator. |
|
*/ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/export.h> |
|
#include <linux/slab.h> |
|
#include <linux/err.h> |
|
#include <linux/of_platform.h> |
|
#include <linux/pgtable.h> |
|
#include <asm/fsl_85xx_cache_sram.h> |
|
|
|
#include "fsl_85xx_cache_ctlr.h" |
|
|
|
struct mpc85xx_cache_sram *cache_sram; |
|
|
|
void *mpc85xx_cache_sram_alloc(unsigned int size, |
|
phys_addr_t *phys, unsigned int align) |
|
{ |
|
unsigned long offset; |
|
unsigned long flags; |
|
|
|
if (unlikely(cache_sram == NULL)) |
|
return NULL; |
|
|
|
if (!size || (size > cache_sram->size) || (align > cache_sram->size)) { |
|
pr_err("%s(): size(=%x) or align(=%x) zero or too big\n", |
|
__func__, size, align); |
|
return NULL; |
|
} |
|
|
|
if ((align & (align - 1)) || align <= 1) { |
|
pr_err("%s(): align(=%x) must be power of two and >1\n", |
|
__func__, align); |
|
return NULL; |
|
} |
|
|
|
spin_lock_irqsave(&cache_sram->lock, flags); |
|
offset = rh_alloc_align(cache_sram->rh, size, align, NULL); |
|
spin_unlock_irqrestore(&cache_sram->lock, flags); |
|
|
|
if (IS_ERR_VALUE(offset)) |
|
return NULL; |
|
|
|
*phys = cache_sram->base_phys + offset; |
|
|
|
return (unsigned char *)cache_sram->base_virt + offset; |
|
} |
|
EXPORT_SYMBOL(mpc85xx_cache_sram_alloc); |
|
|
|
void mpc85xx_cache_sram_free(void *ptr) |
|
{ |
|
unsigned long flags; |
|
BUG_ON(!ptr); |
|
|
|
spin_lock_irqsave(&cache_sram->lock, flags); |
|
rh_free(cache_sram->rh, ptr - cache_sram->base_virt); |
|
spin_unlock_irqrestore(&cache_sram->lock, flags); |
|
} |
|
EXPORT_SYMBOL(mpc85xx_cache_sram_free); |
|
|
|
int __init instantiate_cache_sram(struct platform_device *dev, |
|
struct sram_parameters sram_params) |
|
{ |
|
int ret = 0; |
|
|
|
if (cache_sram) { |
|
dev_err(&dev->dev, "Already initialized cache-sram\n"); |
|
return -EBUSY; |
|
} |
|
|
|
cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL); |
|
if (!cache_sram) { |
|
dev_err(&dev->dev, "Out of memory for cache_sram structure\n"); |
|
return -ENOMEM; |
|
} |
|
|
|
cache_sram->base_phys = sram_params.sram_offset; |
|
cache_sram->size = sram_params.sram_size; |
|
|
|
if (!request_mem_region(cache_sram->base_phys, cache_sram->size, |
|
"fsl_85xx_cache_sram")) { |
|
dev_err(&dev->dev, "%pOF: request memory failed\n", |
|
dev->dev.of_node); |
|
ret = -ENXIO; |
|
goto out_free; |
|
} |
|
|
|
cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys, |
|
cache_sram->size); |
|
if (!cache_sram->base_virt) { |
|
dev_err(&dev->dev, "%pOF: ioremap_coherent failed\n", |
|
dev->dev.of_node); |
|
ret = -ENOMEM; |
|
goto out_release; |
|
} |
|
|
|
cache_sram->rh = rh_create(sizeof(unsigned int)); |
|
if (IS_ERR(cache_sram->rh)) { |
|
dev_err(&dev->dev, "%pOF: Unable to create remote heap\n", |
|
dev->dev.of_node); |
|
ret = PTR_ERR(cache_sram->rh); |
|
goto out_unmap; |
|
} |
|
|
|
rh_attach_region(cache_sram->rh, 0, cache_sram->size); |
|
spin_lock_init(&cache_sram->lock); |
|
|
|
dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n", |
|
(unsigned long long)cache_sram->base_phys, cache_sram->size); |
|
|
|
return 0; |
|
|
|
out_unmap: |
|
iounmap(cache_sram->base_virt); |
|
|
|
out_release: |
|
release_mem_region(cache_sram->base_phys, cache_sram->size); |
|
|
|
out_free: |
|
kfree(cache_sram); |
|
return ret; |
|
} |
|
|
|
void remove_cache_sram(struct platform_device *dev) |
|
{ |
|
BUG_ON(!cache_sram); |
|
|
|
rh_detach_region(cache_sram->rh, 0, cache_sram->size); |
|
rh_destroy(cache_sram->rh); |
|
|
|
iounmap(cache_sram->base_virt); |
|
release_mem_region(cache_sram->base_phys, cache_sram->size); |
|
|
|
kfree(cache_sram); |
|
cache_sram = NULL; |
|
|
|
dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n"); |
|
}
|
|
|