/*
 * Copyright 2008-2015 Freescale Semiconductor Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Freescale Semiconductor nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 *
 * ALTERNATIVELY, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") as published by the Free Software
 * Foundation, either version 2 of that License or (at your option) any
 * later version.
 *
 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "fman_muram.h"

#include <linux/io.h>
#include <linux/slab.h>
#include <linux/genalloc.h>

struct muram_info {
	struct gen_pool *pool;
	void __iomem *vbase;
	size_t size;
	phys_addr_t pbase;
};

static unsigned long fman_muram_vbase_to_offset(struct muram_info *muram,
						unsigned long vaddr)
{
	return vaddr - (unsigned long)muram->vbase;
}

/**
 * fman_muram_init
 * @base:	Pointer to base of memory mapped FM-MURAM.
 * @size:	Size of the FM-MURAM partition.
 *
 * Creates partition in the MURAM.
 * The routine returns a pointer to the MURAM partition.
 * This pointer must be passed as to all other FM-MURAM function calls.
 * No actual initialization or configuration of FM_MURAM hardware is done by
 * this routine.
 *
 * Return: pointer to FM-MURAM object, or NULL for Failure.
 */
struct muram_info *fman_muram_init(phys_addr_t base, size_t size)
{
	struct muram_info *muram;
	void __iomem *vaddr;
	int ret;

	muram = kzalloc(sizeof(*muram), GFP_KERNEL);
	if (!muram)
		return NULL;

	muram->pool = gen_pool_create(ilog2(64), -1);
	if (!muram->pool) {
		pr_err("%s(): MURAM pool create failed\n", __func__);
		goto  muram_free;
	}

	vaddr = ioremap(base, size);
	if (!vaddr) {
		pr_err("%s(): MURAM ioremap failed\n", __func__);
		goto pool_destroy;
	}

	ret = gen_pool_add_virt(muram->pool, (unsigned long)vaddr,
				base, size, -1);
	if (ret < 0) {
		pr_err("%s(): MURAM pool add failed\n", __func__);
		iounmap(vaddr);
		goto pool_destroy;
	}

	memset_io(vaddr, 0, (int)size);

	muram->vbase = vaddr;
	muram->pbase = base;
	return muram;

pool_destroy:
	gen_pool_destroy(muram->pool);
muram_free:
	kfree(muram);
	return NULL;
}

/**
 * fman_muram_offset_to_vbase
 * @muram:	FM-MURAM module pointer.
 * @offset:	the offset of the memory block
 *
 * Gives the address of the memory region from specific offset
 *
 * Return: The address of the memory block
 */
unsigned long fman_muram_offset_to_vbase(struct muram_info *muram,
					 unsigned long offset)
{
	return offset + (unsigned long)muram->vbase;
}

/**
 * fman_muram_alloc
 * @muram:	FM-MURAM module pointer.
 * @size:	Size of the memory to be allocated.
 *
 * Allocate some memory from FM-MURAM partition.
 *
 * Return: address of the allocated memory; NULL otherwise.
 */
unsigned long fman_muram_alloc(struct muram_info *muram, size_t size)
{
	unsigned long vaddr;

	vaddr = gen_pool_alloc(muram->pool, size);
	if (!vaddr)
		return -ENOMEM;

	memset_io((void __iomem *)vaddr, 0, size);

	return fman_muram_vbase_to_offset(muram, vaddr);
}

/**
 * fman_muram_free_mem
 * muram:	FM-MURAM module pointer.
 * offset:	offset of the memory region to be freed.
 * size:	size of the memory to be freed.
 *
 * Free an allocated memory from FM-MURAM partition.
 */
void fman_muram_free_mem(struct muram_info *muram, unsigned long offset,
			 size_t size)
{
	unsigned long addr = fman_muram_offset_to_vbase(muram, offset);

	gen_pool_free(muram->pool, addr, size);
}
