/*
 *  Port on Texas Instruments TMS320C6x architecture
 *
 *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
 *  Author: Aurelien Jacquiot <aurelien.jacquiot@ti.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  DMA uncached mapping support.
 *
 *  Using code pulled from ARM
 *  Copyright (C) 2000-2004 Russell King
 *
 */
#include <linux/slab.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/memblock.h>

#include <asm/page.h>

/*
 * DMA coherent memory management, can be redefined using the memdma=
 * kernel command line
 */

/* none by default */
static phys_addr_t dma_base;
static u32 dma_size;
static u32 dma_pages;

static unsigned long *dma_bitmap;

/* bitmap lock */
static DEFINE_SPINLOCK(dma_lock);

/*
 * Return a DMA coherent and contiguous memory chunk from the DMA memory
 */
static inline u32 __alloc_dma_pages(int order)
{
	unsigned long flags;
	u32 pos;

	spin_lock_irqsave(&dma_lock, flags);
	pos = bitmap_find_free_region(dma_bitmap, dma_pages, order);
	spin_unlock_irqrestore(&dma_lock, flags);

	return dma_base + (pos << PAGE_SHIFT);
}

static void __free_dma_pages(u32 addr, int order)
{
	unsigned long flags;
	u32 pos = (addr - dma_base) >> PAGE_SHIFT;

	if (addr < dma_base || (pos + (1 << order)) >= dma_pages) {
		printk(KERN_ERR "%s: freeing outside range.\n", __func__);
		BUG();
	}

	spin_lock_irqsave(&dma_lock, flags);
	bitmap_release_region(dma_bitmap, pos, order);
	spin_unlock_irqrestore(&dma_lock, flags);
}

/*
 * Allocate DMA coherent memory space and return both the kernel
 * virtual and DMA address for that space.
 */
void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
		gfp_t gfp, unsigned long attrs)
{
	u32 paddr;
	int order;

	if (!dma_size || !size)
		return NULL;

	order = get_count_order(((size - 1) >> PAGE_SHIFT) + 1);

	paddr = __alloc_dma_pages(order);

	if (handle)
		*handle = paddr;

	if (!paddr)
		return NULL;

	return phys_to_virt(paddr);
}

/*
 * Free DMA coherent memory as defined by the above mapping.
 */
void c6x_dma_free(struct device *dev, size_t size, void *vaddr,
		dma_addr_t dma_handle, unsigned long attrs)
{
	int order;

	if (!dma_size || !size)
		return;

	order = get_count_order(((size - 1) >> PAGE_SHIFT) + 1);

	__free_dma_pages(virt_to_phys(vaddr), order);
}

/*
 * Initialise the coherent DMA memory allocator using the given uncached region.
 */
void __init coherent_mem_init(phys_addr_t start, u32 size)
{
	phys_addr_t bitmap_phys;

	if (!size)
		return;

	printk(KERN_INFO
	       "Coherent memory (DMA) region start=0x%x size=0x%x\n",
	       start, size);

	dma_base = start;
	dma_size = size;

	/* allocate bitmap */
	dma_pages = dma_size >> PAGE_SHIFT;
	if (dma_size & (PAGE_SIZE - 1))
		++dma_pages;

	bitmap_phys = memblock_alloc(BITS_TO_LONGS(dma_pages) * sizeof(long),
				     sizeof(long));

	dma_bitmap = phys_to_virt(bitmap_phys);
	memset(dma_bitmap, 0, dma_pages * PAGE_SIZE);
}
