/*
 * Analog Devices SPI3 controller driver
 *
 * Copyright (c) 2011 Analog Devices Inc.
 *
 * 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.
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

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

#include <asm/blackfin.h>
#include <asm/gpio.h>
#include <asm/portmux.h>
#include <asm/mach-common/bits/spi6xx.h>

struct bfin_spi_slave {
	struct spi_slave slave;
	u32 control, clock;
	struct bfin_spi_regs *regs;
	int cs_pol;
};

#define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave)

#define gpio_cs(cs) ((cs) - MAX_CTRL_CS)
#ifdef CONFIG_BFIN_SPI_GPIO_CS
# define is_gpio_cs(cs) ((cs) > MAX_CTRL_CS)
#else
# define is_gpio_cs(cs) 0
#endif

int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
	if (is_gpio_cs(cs))
		return gpio_is_valid(gpio_cs(cs));
	else
		return (cs >= 1 && cs <= MAX_CTRL_CS);
}

void spi_cs_activate(struct spi_slave *slave)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);

	if (is_gpio_cs(slave->cs)) {
		unsigned int cs = gpio_cs(slave->cs);
		gpio_set_value(cs, bss->cs_pol);
	} else {
		u32 ssel;
		ssel = bfin_read32(&bss->regs->ssel);
		ssel |= 1 << slave->cs;
		if (bss->cs_pol)
			ssel |= (1 << 8) << slave->cs;
		else
			ssel &= ~((1 << 8) << slave->cs);
		bfin_write32(&bss->regs->ssel, ssel);
	}

	SSYNC();
}

void spi_cs_deactivate(struct spi_slave *slave)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);

	if (is_gpio_cs(slave->cs)) {
		unsigned int cs = gpio_cs(slave->cs);
		gpio_set_value(cs, !bss->cs_pol);
	} else {
		u32 ssel;
		ssel = bfin_read32(&bss->regs->ssel);
		if (bss->cs_pol)
			ssel &= ~((1 << 8) << slave->cs);
		else
			ssel |= (1 << 8) << slave->cs;
		/* deassert cs */
		bfin_write32(&bss->regs->ssel, ssel);
		SSYNC();
		/* disable cs */
		ssel &= ~(1 << slave->cs);
		bfin_write32(&bss->regs->ssel, ssel);
	}

	SSYNC();
}

void spi_init()
{
}

#define SPI_PINS(n) \
	{ 0, P_SPI##n##_SCK, P_SPI##n##_MISO, P_SPI##n##_MOSI, 0 }
static unsigned short pins[][5] = {
#ifdef SPI0_REGBASE
	[0] = SPI_PINS(0),
#endif
#ifdef SPI1_REGBASE
	[1] = SPI_PINS(1),
#endif
#ifdef SPI2_REGBASE
	[2] = SPI_PINS(2),
#endif
};

#define SPI_CS_PINS(n) \
	{ \
		P_SPI##n##_SSEL1, P_SPI##n##_SSEL2, P_SPI##n##_SSEL3, \
		P_SPI##n##_SSEL4, P_SPI##n##_SSEL5, P_SPI##n##_SSEL6, \
		P_SPI##n##_SSEL7, \
	}
static const unsigned short cs_pins[][7] = {
#ifdef SPI0_REGBASE
	[0] = SPI_CS_PINS(0),
#endif
#ifdef SPI1_REGBASE
	[1] = SPI_CS_PINS(1),
#endif
#ifdef SPI2_REGBASE
	[2] = SPI_CS_PINS(2),
#endif
};

void spi_set_speed(struct spi_slave *slave, uint hz)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
	ulong sclk;
	u32 clock;

	sclk = get_sclk1();
	clock = sclk / hz;
	if (clock)
		clock--;
	bss->clock = clock;
}

struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode)
{
	struct bfin_spi_slave *bss;
	u32 reg_base;

	if (!spi_cs_is_valid(bus, cs))
		return NULL;

	if (bus >= ARRAY_SIZE(pins) || pins[bus] == NULL) {
		debug("%s: invalid bus %u\n", __func__, bus);
		return NULL;
	}
	switch (bus) {
#ifdef SPI0_REGBASE
	case 0:
		reg_base = SPI0_REGBASE;
		break;
#endif
#ifdef SPI1_REGBASE
	case 1:
		reg_base = SPI1_REGBASE;
		break;
#endif
#ifdef SPI2_REGBASE
	case 2:
		reg_base = SPI2_REGBASE;
		break;
#endif
	default:
		return NULL;
	}

	bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs);
	if (!bss)
		return NULL;

	bss->regs = (struct bfin_spi_regs *)reg_base;
	bss->control = SPI_CTL_EN | SPI_CTL_MSTR;
	if (mode & SPI_CPHA)
		bss->control |= SPI_CTL_CPHA;
	if (mode & SPI_CPOL)
		bss->control |= SPI_CTL_CPOL;
	if (mode & SPI_LSB_FIRST)
		bss->control |= SPI_CTL_LSBF;
	bss->control &= ~SPI_CTL_ASSEL;
	bss->cs_pol = mode & SPI_CS_HIGH ? 1 : 0;
	spi_set_speed(&bss->slave, max_hz);

	return &bss->slave;
}

void spi_free_slave(struct spi_slave *slave)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
	free(bss);
}

int spi_claim_bus(struct spi_slave *slave)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);

	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);

	if (is_gpio_cs(slave->cs)) {
		unsigned int cs = gpio_cs(slave->cs);
		gpio_request(cs, "bfin-spi");
		gpio_direction_output(cs, !bss->cs_pol);
		pins[slave->bus][0] = P_DONTCARE;
	} else
		pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1];
	peripheral_request_list(pins[slave->bus], "bfin-spi");

	bfin_write32(&bss->regs->control, bss->control);
	bfin_write32(&bss->regs->clock, bss->clock);
	bfin_write32(&bss->regs->delay, 0x0);
	bfin_write32(&bss->regs->rx_control, SPI_RXCTL_REN);
	bfin_write32(&bss->regs->tx_control, SPI_TXCTL_TEN | SPI_TXCTL_TTI);
	SSYNC();

	return 0;
}

void spi_release_bus(struct spi_slave *slave)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);

	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);

	peripheral_free_list(pins[slave->bus]);
	if (is_gpio_cs(slave->cs))
		gpio_free(gpio_cs(slave->cs));

	bfin_write32(&bss->regs->rx_control, 0x0);
	bfin_write32(&bss->regs->tx_control, 0x0);
	bfin_write32(&bss->regs->control, 0x0);
	SSYNC();
}

#ifndef CONFIG_BFIN_SPI_IDLE_VAL
# define CONFIG_BFIN_SPI_IDLE_VAL 0xff
#endif

static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx,
			uint bytes)
{
	/* discard invalid rx data and empty rfifo */
	while (!(bfin_read32(&bss->regs->status) & SPI_STAT_RFE))
		bfin_read32(&bss->regs->rfifo);

	while (bytes--) {
		u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL);
		debug("%s: tx:%x ", __func__, value);
		bfin_write32(&bss->regs->tfifo, value);
		SSYNC();
		while (bfin_read32(&bss->regs->status) & SPI_STAT_RFE)
			if (ctrlc())
				return -1;
		value = bfin_read32(&bss->regs->rfifo);
		if (rx)
			*rx++ = value;
		debug("rx:%x\n", value);
	}

	return 0;
}

int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags)
{
	struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
	const u8 *tx = dout;
	u8 *rx = din;
	uint bytes = bitlen / 8;
	int ret = 0;

	debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
		slave->bus, slave->cs, bitlen, bytes, flags);

	if (bitlen == 0)
		goto done;

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

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	ret = spi_pio_xfer(bss, tx, rx, bytes);

 done:
	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return ret;
}
