/*
 * driver/dma/coh901318_lli.c
 *
 * Copyright (C) 2007-2009 ST-Ericsson
 * License terms: GNU General Public License (GPL) version 2
 * Support functions for handling lli for dma
 * Author: Per Friden <per.friden@stericsson.com>
 */

#include <linux/spinlock.h>
#include <linux/memory.h>
#include <linux/gfp.h>
#include <linux/dmapool.h>
#include <linux/dmaengine.h>

#include "coh901318.h"

#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
#define DEBUGFS_POOL_COUNTER_RESET(pool) (pool->debugfs_pool_counter = 0)
#define DEBUGFS_POOL_COUNTER_ADD(pool, add) (pool->debugfs_pool_counter += add)
#else
#define DEBUGFS_POOL_COUNTER_RESET(pool)
#define DEBUGFS_POOL_COUNTER_ADD(pool, add)
#endif

static struct coh901318_lli *
coh901318_lli_next(struct coh901318_lli *data)
{
	if (data == NULL || data->link_addr == 0)
		return NULL;

	return (struct coh901318_lli *) data->virt_link_addr;
}

int coh901318_pool_create(struct coh901318_pool *pool,
			  struct device *dev,
			  size_t size, size_t align)
{
	spin_lock_init(&pool->lock);
	pool->dev = dev;
	pool->dmapool = dma_pool_create("lli_pool", dev, size, align, 0);

	DEBUGFS_POOL_COUNTER_RESET(pool);
	return 0;
}

int coh901318_pool_destroy(struct coh901318_pool *pool)
{

	dma_pool_destroy(pool->dmapool);
	return 0;
}

struct coh901318_lli *
coh901318_lli_alloc(struct coh901318_pool *pool, unsigned int len)
{
	int i;
	struct coh901318_lli *head;
	struct coh901318_lli *lli;
	struct coh901318_lli *lli_prev;
	dma_addr_t phy;

	if (len == 0)
		return NULL;

	spin_lock(&pool->lock);

	head = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy);

	if (head == NULL)
		goto err;

	DEBUGFS_POOL_COUNTER_ADD(pool, 1);

	lli = head;
	lli->phy_this = phy;
	lli->link_addr = 0x00000000;
	lli->virt_link_addr = 0x00000000U;

	for (i = 1; i < len; i++) {
		lli_prev = lli;

		lli = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy);

		if (lli == NULL)
			goto err_clean_up;

		DEBUGFS_POOL_COUNTER_ADD(pool, 1);
		lli->phy_this = phy;
		lli->link_addr = 0x00000000;
		lli->virt_link_addr = 0x00000000U;

		lli_prev->link_addr = phy;
		lli_prev->virt_link_addr = lli;
	}

	spin_unlock(&pool->lock);

	return head;

 err:
	spin_unlock(&pool->lock);
	return NULL;

 err_clean_up:
	lli_prev->link_addr = 0x00000000U;
	spin_unlock(&pool->lock);
	coh901318_lli_free(pool, &head);
	return NULL;
}

void coh901318_lli_free(struct coh901318_pool *pool,
			struct coh901318_lli **lli)
{
	struct coh901318_lli *l;
	struct coh901318_lli *next;

	if (lli == NULL)
		return;

	l = *lli;

	if (l == NULL)
		return;

	spin_lock(&pool->lock);

	while (l->link_addr) {
		next = l->virt_link_addr;
		dma_pool_free(pool->dmapool, l, l->phy_this);
		DEBUGFS_POOL_COUNTER_ADD(pool, -1);
		l = next;
	}
	dma_pool_free(pool->dmapool, l, l->phy_this);
	DEBUGFS_POOL_COUNTER_ADD(pool, -1);

	spin_unlock(&pool->lock);
	*lli = NULL;
}

int
coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
			  struct coh901318_lli *lli,
			  dma_addr_t source, unsigned int size,
			  dma_addr_t destination, u32 ctrl_chained,
			  u32 ctrl_eom)
{
	int s = size;
	dma_addr_t src = source;
	dma_addr_t dst = destination;

	lli->src_addr = src;
	lli->dst_addr = dst;

	while (lli->link_addr) {
		lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE;
		lli->src_addr = src;
		lli->dst_addr = dst;

		s -= MAX_DMA_PACKET_SIZE;
		lli = coh901318_lli_next(lli);

		src += MAX_DMA_PACKET_SIZE;
		dst += MAX_DMA_PACKET_SIZE;
	}

	lli->control = ctrl_eom | s;
	lli->src_addr = src;
	lli->dst_addr = dst;

	return 0;
}

int
coh901318_lli_fill_single(struct coh901318_pool *pool,
			  struct coh901318_lli *lli,
			  dma_addr_t buf, unsigned int size,
			  dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom,
			  enum dma_transfer_direction dir)
{
	int s = size;
	dma_addr_t src;
	dma_addr_t dst;


	if (dir == DMA_MEM_TO_DEV) {
		src = buf;
		dst = dev_addr;

	} else if (dir == DMA_DEV_TO_MEM) {

		src = dev_addr;
		dst = buf;
	} else {
		return -EINVAL;
	}

	while (lli->link_addr) {
		size_t block_size = MAX_DMA_PACKET_SIZE;
		lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE;

		/* If we are on the next-to-final block and there will
		 * be less than half a DMA packet left for the last
		 * block, then we want to make this block a little
		 * smaller to balance the sizes. This is meant to
		 * avoid too small transfers if the buffer size is
		 * (MAX_DMA_PACKET_SIZE*N + 1) */
		if (s < (MAX_DMA_PACKET_SIZE + MAX_DMA_PACKET_SIZE/2))
			block_size = MAX_DMA_PACKET_SIZE/2;

		s -= block_size;
		lli->src_addr = src;
		lli->dst_addr = dst;

		lli = coh901318_lli_next(lli);

		if (dir == DMA_MEM_TO_DEV)
			src += block_size;
		else if (dir == DMA_DEV_TO_MEM)
			dst += block_size;
	}

	lli->control = ctrl_eom | s;
	lli->src_addr = src;
	lli->dst_addr = dst;

	return 0;
}

int
coh901318_lli_fill_sg(struct coh901318_pool *pool,
		      struct coh901318_lli *lli,
		      struct scatterlist *sgl, unsigned int nents,
		      dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl,
		      u32 ctrl_last,
		      enum dma_transfer_direction dir, u32 ctrl_irq_mask)
{
	int i;
	struct scatterlist *sg;
	u32 ctrl_sg;
	dma_addr_t src = 0;
	dma_addr_t dst = 0;
	u32 bytes_to_transfer;
	u32 elem_size;

	if (lli == NULL)
		goto err;

	spin_lock(&pool->lock);

	if (dir == DMA_MEM_TO_DEV)
		dst = dev_addr;
	else if (dir == DMA_DEV_TO_MEM)
		src = dev_addr;
	else
		goto err;

	for_each_sg(sgl, sg, nents, i) {
		if (sg_is_chain(sg)) {
			/* sg continues to the next sg-element don't
			 * send ctrl_finish until the last
			 * sg-element in the chain
			 */
			ctrl_sg = ctrl_chained;
		} else if (i == nents - 1)
			ctrl_sg = ctrl_last;
		else
			ctrl_sg = ctrl ? ctrl : ctrl_last;


		if (dir == DMA_MEM_TO_DEV)
			/* increment source address */
			src = sg_dma_address(sg);
		else
			/* increment destination address */
			dst = sg_dma_address(sg);

		bytes_to_transfer = sg_dma_len(sg);

		while (bytes_to_transfer) {
			u32 val;

			if (bytes_to_transfer > MAX_DMA_PACKET_SIZE) {
				elem_size = MAX_DMA_PACKET_SIZE;
				val = ctrl_chained;
			} else {
				elem_size = bytes_to_transfer;
				val = ctrl_sg;
			}

			lli->control = val | elem_size;
			lli->src_addr = src;
			lli->dst_addr = dst;

			if (dir == DMA_DEV_TO_MEM)
				dst += elem_size;
			else
				src += elem_size;

			BUG_ON(lli->link_addr & 3);

			bytes_to_transfer -= elem_size;
			lli = coh901318_lli_next(lli);
		}

	}
	spin_unlock(&pool->lock);

	return 0;
 err:
	spin_unlock(&pool->lock);
	return -EINVAL;
}
