/*
 * (C) Copyright 2011
 * eInfochips Ltd. <www.einfochips.com>
 * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
 *
 * (C) Copyright 2009
 * Marvell Semiconductor <www.marvell.com>
 * Based on SSP driver
 * Written-by: Lei Wen <leiwen@marvell.com>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA
 */


#include <common.h>
#include <malloc.h>
#include <spi.h>

#include <asm/io.h>
#include <asm/arch/spi.h>
#include <asm/gpio.h>

#define to_armd_spi_slave(s)	container_of(s, struct armd_spi_slave, slave)

struct armd_spi_slave {
	struct spi_slave slave;
	struct ssp_reg *spi_reg;
	u32 cr0, cr1;
	u32 int_cr1;
	u32 clear_sr;
	const void *tx;
	void *rx;
	int gpio_cs_inverted;
};

static int spi_armd_write(struct armd_spi_slave *pss)
{
	int wait_timeout = SSP_FLUSH_NUM;
	while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_TNF))
		;
	if (!wait_timeout) {
		debug("%s: timeout error\n", __func__);
		return -1;
	}

	if (pss->tx != NULL) {
		writel(*(u8 *)pss->tx, &pss->spi_reg->ssdr);
		++pss->tx;
	} else {
		writel(0, &pss->spi_reg->ssdr);
	}
	return 0;
}

static int spi_armd_read(struct armd_spi_slave *pss)
{
	int wait_timeout = SSP_FLUSH_NUM;
	while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_RNE))
		;
	if (!wait_timeout) {
		debug("%s: timeout error\n", __func__);
		return -1;
	}

	if (pss->rx != NULL) {
		*(u8 *)pss->rx = readl(&pss->spi_reg->ssdr);
		++pss->rx;
	} else {
		readl(&pss->spi_reg->ssdr);
	}
	return 0;
}

static int spi_armd_flush(struct armd_spi_slave *pss)
{
	unsigned long limit = SSP_FLUSH_NUM;

	do {
		while (readl(&pss->spi_reg->sssr) & SSSR_RNE)
			readl(&pss->spi_reg->ssdr);
	} while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--);

	writel(SSSR_ROR, &pss->spi_reg->sssr);

	return limit;
}

void spi_cs_activate(struct spi_slave *slave)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);

	gpio_set_value(slave->cs, pss->gpio_cs_inverted);
}

void spi_cs_deactivate(struct spi_slave *slave)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);

	gpio_set_value(slave->cs, !pss->gpio_cs_inverted);
}

struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode)
{
	struct armd_spi_slave *pss;

	pss = malloc(sizeof(*pss));
	if (!pss)
		return NULL;

	pss->slave.bus = bus;
	pss->slave.cs = cs;
	pss->spi_reg = (struct ssp_reg *)SSP_REG_BASE(CONFIG_SYS_SSP_PORT);

	pss->cr0 = SSCR0_MOTO | SSCR0_DATASIZE(DEFAULT_WORD_LEN) | SSCR0_SSE;

	pss->cr1 = (SSCR1_RXTRESH(RX_THRESH_DEF) & SSCR1_RFT) |
		(SSCR1_TXTRESH(TX_THRESH_DEF) & SSCR1_TFT);
	pss->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
	pss->cr1 |= (((mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
		| (((mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);

	pss->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
	pss->clear_sr = SSSR_ROR | SSSR_TINT;

	pss->gpio_cs_inverted = mode & SPI_CS_HIGH;
	gpio_set_value(cs, !pss->gpio_cs_inverted);

	return &pss->slave;
}

void spi_free_slave(struct spi_slave *slave)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);

	free(pss);
}

int spi_claim_bus(struct spi_slave *slave)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);

	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
	if (spi_armd_flush(pss) == 0)
		return -1;

	return 0;
}

void spi_release_bus(struct spi_slave *slave)
{
}

int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	struct armd_spi_slave *pss = to_armd_spi_slave(slave);
	uint bytes = bitlen / 8;
	unsigned long limit;
	int ret = 0;

	if (bitlen == 0)
		goto done;

	/* we can only do 8 bit transfers */
	if (bitlen % 8) {
		flags |= SPI_XFER_END;
		goto done;
	}

	if (dout)
		pss->tx = dout;
	else
		pss->tx = NULL;

	if (din)
		pss->rx = din;
	else
		pss->rx = NULL;

	if (flags & SPI_XFER_BEGIN) {
		spi_cs_activate(slave);
		writel(pss->cr1 | pss->int_cr1, &pss->spi_reg->sscr1);
		writel(TIMEOUT_DEF, &pss->spi_reg->ssto);
		writel(pss->cr0, &pss->spi_reg->sscr0);
	}

	while (bytes--) {
		limit = SSP_FLUSH_NUM;
		ret = spi_armd_write(pss);
		if (ret)
			break;

		while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--)
			udelay(1);

		ret = spi_armd_read(pss);
		if (ret)
			break;
	}

 done:
	if (flags & SPI_XFER_END) {
		/* Stop SSP */
		writel(pss->clear_sr, &pss->spi_reg->sssr);
		clrbits_le32(&pss->spi_reg->sscr1, pss->int_cr1);
		writel(0, &pss->spi_reg->ssto);
		spi_cs_deactivate(slave);
	}

	return ret;
}
