// 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 <vivek.mahajan@freescale.com>
 *
 * 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 <asm/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");
}
