/*
 * Copyright (C) ST-Ericsson AB 2010
 * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
 * Author:  Daniel Martensson / Daniel.Martensson@stericsson.com
 * License terms: GNU General Public License (GPL) version 2.
 */
#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/semaphore.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/debugfs.h>
#include <net/caif/caif_spi.h>

#ifndef CONFIG_CAIF_SPI_SYNC
#define SPI_DATA_POS 0
static inline int forward_to_spi_cmd(struct cfspi *cfspi)
{
	return cfspi->rx_cpck_len;
}
#else
#define SPI_DATA_POS SPI_CMD_SZ
static inline int forward_to_spi_cmd(struct cfspi *cfspi)
{
	return 0;
}
#endif

int spi_frm_align = 2;

/*
 * SPI padding options.
 * Warning: must be a base of 2 (& operation used) and can not be zero !
 */
int spi_up_head_align   = 1 << 1;
int spi_up_tail_align   = 1 << 0;
int spi_down_head_align = 1 << 2;
int spi_down_tail_align = 1 << 1;

#ifdef CONFIG_DEBUG_FS
static inline void debugfs_store_prev(struct cfspi *cfspi)
{
	/* Store previous command for debugging reasons.*/
	cfspi->pcmd = cfspi->cmd;
	/* Store previous transfer. */
	cfspi->tx_ppck_len = cfspi->tx_cpck_len;
	cfspi->rx_ppck_len = cfspi->rx_cpck_len;
}
#else
static inline void debugfs_store_prev(struct cfspi *cfspi)
{
}
#endif

void cfspi_xfer(struct work_struct *work)
{
	struct cfspi *cfspi;
	u8 *ptr = NULL;
	unsigned long flags;
	int ret;
	cfspi = container_of(work, struct cfspi, work);

	/* Initialize state. */
	cfspi->cmd = SPI_CMD_EOT;

	for (;;) {

		cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING);

		/* Wait for master talk or transmit event. */
		wait_event_interruptible(cfspi->wait,
				 test_bit(SPI_XFER, &cfspi->state) ||
				 test_bit(SPI_TERMINATE, &cfspi->state));

		if (test_bit(SPI_TERMINATE, &cfspi->state))
			return;

#if CFSPI_DBG_PREFILL
		/* Prefill buffers for easier debugging. */
		memset(cfspi->xfer.va_tx, 0xFF, SPI_DMA_BUF_LEN);
		memset(cfspi->xfer.va_rx, 0xFF, SPI_DMA_BUF_LEN);
#endif	/* CFSPI_DBG_PREFILL */

		cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE);

	/* Check whether we have a committed frame. */
		if (cfspi->tx_cpck_len) {
			int len;

			cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);

			/* Copy commited SPI frames after the SPI indication. */
			ptr = (u8 *) cfspi->xfer.va_tx;
			ptr += SPI_IND_SZ;
			len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
			WARN_ON(len != cfspi->tx_cpck_len);
	}

		cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT);

		/* Get length of next frame to commit. */
		cfspi->tx_npck_len = cfspi_xmitlen(cfspi);

		WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN);

		/*
		 * Add indication and length at the beginning of the frame,
		 * using little endian.
		 */
		ptr = (u8 *) cfspi->xfer.va_tx;
		*ptr++ = SPI_CMD_IND;
		*ptr++ = (SPI_CMD_IND  & 0xFF00) >> 8;
		*ptr++ = cfspi->tx_npck_len & 0x00FF;
		*ptr++ = (cfspi->tx_npck_len & 0xFF00) >> 8;

		/* Calculate length of DMAs. */
		cfspi->xfer.tx_dma_len = cfspi->tx_cpck_len + SPI_IND_SZ;
		cfspi->xfer.rx_dma_len = cfspi->rx_cpck_len + SPI_CMD_SZ;

		/* Add SPI TX frame alignment padding, if necessary. */
		if (cfspi->tx_cpck_len &&
			(cfspi->xfer.tx_dma_len % spi_frm_align)) {

			cfspi->xfer.tx_dma_len += spi_frm_align -
			    (cfspi->xfer.tx_dma_len % spi_frm_align);
		}

		/* Add SPI RX frame alignment padding, if necessary. */
		if (cfspi->rx_cpck_len &&
			(cfspi->xfer.rx_dma_len % spi_frm_align)) {

			cfspi->xfer.rx_dma_len += spi_frm_align -
			    (cfspi->xfer.rx_dma_len % spi_frm_align);
		}

		cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER);

		/* Start transfer. */
		ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev);
		WARN_ON(ret);

		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE);

		/*
		 * TODO: We might be able to make an assumption if this is the
		 * first loop. Make sure that minimum toggle time is respected.
		 */
		udelay(MIN_TRANSITION_TIME_USEC);

		cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);

		/* Signal that we are ready to recieve data. */
		cfspi->dev->sig_xfer(true, cfspi->dev);

		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);

		/* Wait for transfer completion. */
		wait_for_completion(&cfspi->comp);

		cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE);

		if (cfspi->cmd == SPI_CMD_EOT) {
			/*
			 * Clear the master talk bit. A xfer is always at
			 *  least two bursts.
			 */
			clear_bit(SPI_SS_ON, &cfspi->state);
		}

		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE);

		/* Make sure that the minimum toggle time is respected. */
		if (SPI_XFER_TIME_USEC(cfspi->xfer.tx_dma_len,
					cfspi->dev->clk_mhz) <
			MIN_TRANSITION_TIME_USEC) {

			udelay(MIN_TRANSITION_TIME_USEC -
				SPI_XFER_TIME_USEC
				(cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz));
		}

		cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE);

		/* De-assert transfer signal. */
		cfspi->dev->sig_xfer(false, cfspi->dev);

		/* Check whether we received a CAIF packet. */
		if (cfspi->rx_cpck_len) {
			int len;

			cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT);

			/* Parse SPI frame. */
			ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS));

			len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len);
			WARN_ON(len != cfspi->rx_cpck_len);
		}

		/* Check the next SPI command and length. */
		ptr = (u8 *) cfspi->xfer.va_rx;

		ptr += forward_to_spi_cmd(cfspi);

		cfspi->cmd = *ptr++;
		cfspi->cmd |= ((*ptr++) << 8) & 0xFF00;
		cfspi->rx_npck_len = *ptr++;
		cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00;

		WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN);
		WARN_ON(cfspi->cmd > SPI_CMD_EOT);

		debugfs_store_prev(cfspi);

		/* Check whether the master issued an EOT command. */
		if (cfspi->cmd == SPI_CMD_EOT) {
			/* Reset state. */
			cfspi->tx_cpck_len = 0;
			cfspi->rx_cpck_len = 0;
		} else {
			/* Update state. */
			cfspi->tx_cpck_len = cfspi->tx_npck_len;
			cfspi->rx_cpck_len = cfspi->rx_npck_len;
		}

		/*
		 * Check whether we need to clear the xfer bit.
		 * Spin lock needed for packet insertion.
		 * Test and clear of different bits
		 * are not supported.
		 */
		spin_lock_irqsave(&cfspi->lock, flags);
		if (cfspi->cmd == SPI_CMD_EOT && !cfspi_xmitlen(cfspi)
			&& !test_bit(SPI_SS_ON, &cfspi->state))
			clear_bit(SPI_XFER, &cfspi->state);

		spin_unlock_irqrestore(&cfspi->lock, flags);
	}
}

struct platform_driver cfspi_spi_driver = {
	.probe = cfspi_spi_probe,
	.remove = cfspi_spi_remove,
	.driver = {
		   .name = "cfspi_sspi",
		   .owner = THIS_MODULE,
		   },
};
