/*
 * Authors:	Oskar Schirmer <os@emlix.com>
 *		Daniel Gloeckner <dg@emlix.com>
 * (c) 2008 emlix GmbH http://www.emlix.com
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <asm/cacheflush.h>
#include <variant/dmac.h>

/* DMA engine lookup */

struct s6dmac_ctrl s6dmac_ctrl[S6_DMAC_NB];


/* DMA control, per engine */

void s6dmac_put_fifo_cache(u32 dmac, int chan, u32 src, u32 dst, u32 size)
{
	if (xtensa_need_flush_dma_source(src)) {
		u32 base = src;
		u32 span = size;
		u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
		if (chunk && (size > chunk)) {
			s32 skip =
				readl(DMA_CHNL(dmac, chan) + S6_DMA_SRCSKIP);
			u32 gaps = (size+chunk-1)/chunk - 1;
			if (skip >= 0) {
				span += gaps * skip;
			} else if (-skip > chunk) {
				s32 decr = gaps * (chunk + skip);
				base += decr;
				span = chunk - decr;
			} else {
				span = max(span + gaps * skip,
					(chunk + skip) * gaps - skip);
			}
		}
		flush_dcache_unaligned(base, span);
	}
	if (xtensa_need_invalidate_dma_destination(dst)) {
		u32 base = dst;
		u32 span = size;
		u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
		if (chunk && (size > chunk)) {
			s32 skip =
				readl(DMA_CHNL(dmac, chan) + S6_DMA_DSTSKIP);
			u32 gaps = (size+chunk-1)/chunk - 1;
			if (skip >= 0) {
				span += gaps * skip;
			} else if (-skip > chunk) {
				s32 decr = gaps * (chunk + skip);
				base += decr;
				span = chunk - decr;
			} else {
				span = max(span + gaps * skip,
					(chunk + skip) * gaps - skip);
			}
		}
		invalidate_dcache_unaligned(base, span);
	}
	s6dmac_put_fifo(dmac, chan, src, dst, size);
}

void s6dmac_disable_error_irqs(u32 dmac, u32 mask)
{
	unsigned long flags;
	spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
	spin_lock_irqsave(spinl, flags);
	_s6dmac_disable_error_irqs(dmac, mask);
	spin_unlock_irqrestore(spinl, flags);
}

u32 s6dmac_int_sources(u32 dmac, u32 channel)
{
	u32 mask, ret, tmp;
	mask = 1 << channel;

	tmp = readl(dmac + S6_DMA_TERMCNTIRQSTAT);
	tmp &= mask;
	writel(tmp, dmac + S6_DMA_TERMCNTIRQCLR);
	ret = tmp >> channel;

	tmp = readl(dmac + S6_DMA_PENDCNTIRQSTAT);
	tmp &= mask;
	writel(tmp, dmac + S6_DMA_PENDCNTIRQCLR);
	ret |= (tmp >> channel) << 1;

	tmp = readl(dmac + S6_DMA_LOWWMRKIRQSTAT);
	tmp &= mask;
	writel(tmp, dmac + S6_DMA_LOWWMRKIRQCLR);
	ret |= (tmp >> channel) << 2;

	tmp = readl(dmac + S6_DMA_INTRAW0);
	tmp &= (mask << S6_DMA_INT0_OVER) | (mask << S6_DMA_INT0_UNDER);
	writel(tmp, dmac + S6_DMA_INTCLEAR0);

	if (tmp & (mask << S6_DMA_INT0_UNDER))
		ret |= 1 << 3;
	if (tmp & (mask << S6_DMA_INT0_OVER))
		ret |= 1 << 4;

	tmp = readl(dmac + S6_DMA_MASTERERRINFO);
	mask <<= S6_DMA_INT1_CHANNEL;
	if (((tmp >> S6_DMA_MASTERERR_CHAN(0)) & S6_DMA_MASTERERR_CHAN_MASK)
			== channel)
		mask |= 1 << S6_DMA_INT1_MASTER;
	if (((tmp >> S6_DMA_MASTERERR_CHAN(1)) & S6_DMA_MASTERERR_CHAN_MASK)
			== channel)
		mask |= 1 << (S6_DMA_INT1_MASTER + 1);
	if (((tmp >> S6_DMA_MASTERERR_CHAN(2)) & S6_DMA_MASTERERR_CHAN_MASK)
			== channel)
		mask |= 1 << (S6_DMA_INT1_MASTER + 2);

	tmp = readl(dmac + S6_DMA_INTRAW1) & mask;
	writel(tmp, dmac + S6_DMA_INTCLEAR1);
	ret |= ((tmp >> channel) & 1) << 5;
	ret |= ((tmp >> S6_DMA_INT1_MASTER) & S6_DMA_INT1_MASTER_MASK) << 6;

	return ret;
}

void s6dmac_release_chan(u32 dmac, int chan)
{
	if (chan >= 0)
		s6dmac_disable_chan(dmac, chan);
}


/* global init */

static inline void __init dmac_init(u32 dmac, u8 chan_nb)
{
	s6dmac_ctrl[S6_DMAC_INDEX(dmac)].dmac = dmac;
	spin_lock_init(&s6dmac_ctrl[S6_DMAC_INDEX(dmac)].lock);
	s6dmac_ctrl[S6_DMAC_INDEX(dmac)].chan_nb = chan_nb;
	writel(S6_DMA_INT1_MASTER_MASK << S6_DMA_INT1_MASTER,
		dmac + S6_DMA_INTCLEAR1);
}

static inline void __init dmac_master(u32 dmac,
	u32 m0start, u32 m0end, u32 m1start, u32 m1end)
{
	writel(m0start, dmac + S6_DMA_MASTER0START);
	writel(m0end - 1, dmac + S6_DMA_MASTER0END);
	writel(m1start, dmac + S6_DMA_MASTER1START);
	writel(m1end - 1, dmac + S6_DMA_MASTER1END);
}

static void __init s6_dmac_init(void)
{
	dmac_init(S6_REG_LMSDMA, S6_LMSDMA_NB);
	dmac_master(S6_REG_LMSDMA,
		S6_MEM_DDR, S6_MEM_PCIE_APER, S6_MEM_EFI, S6_MEM_GMAC);
	dmac_init(S6_REG_NIDMA, S6_NIDMA_NB);
	dmac_init(S6_REG_DPDMA, S6_DPDMA_NB);
	dmac_master(S6_REG_DPDMA,
		S6_MEM_DDR, S6_MEM_PCIE_APER, S6_REG_DP, S6_REG_DPDMA);
	dmac_init(S6_REG_HIFDMA, S6_HIFDMA_NB);
	dmac_master(S6_REG_HIFDMA,
		S6_MEM_GMAC, S6_MEM_PCIE_CFG, S6_MEM_PCIE_APER, S6_MEM_AUX);
}

arch_initcall(s6_dmac_init);
