/*
 * Copyright (C) 2015 Broadcom Corporation
 *
 * 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; version 2 of the License.
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <arch/io.h>
#include <timer.h>
#include <delay.h>
#include <stdlib.h>
#include <spi-generic.h>
#include <spi_flash.h>
#include <soc/addressmap.h>

#define IPROC_QSPI_CLK	100000000

/* SPI mode flags */
#define	SPI_CPHA	0x01		/* clock phase */
#define	SPI_CPOL	0x02		/* clock polarity */
#define	SPI_MODE_0	(0|0)		/* original MicroWire */
#define	SPI_MODE_1	(0|SPI_CPHA)
#define	SPI_MODE_2	(SPI_CPOL|0)
#define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)

#define QSPI_MAX_HZ			50000000
#define QSPI_MODE			SPI_MODE_3

#define QSPI_WAIT_TIMEOUT		200U  /* msec */

/* Controller attributes */
#define SPBR_MIN			8U
#define SPBR_MAX			255U
#define NUM_TXRAM			32
#define NUM_RXRAM			32
#define NUM_CDRAM			16

/*
 * Register fields
 */
#define MSPI_SPCR0_MSB_BITS_8		0x00000020

/* BSPI registers */
#define BSPI_MAST_N_BOOT_CTRL_REG	0x008
#define BSPI_BUSY_STATUS_REG		0x00c

/* MSPI registers */
#define MSPI_SPCR0_LSB_REG		0x200
#define MSPI_SPCR0_MSB_REG		0x204
#define MSPI_SPCR1_LSB_REG		0x208
#define MSPI_SPCR1_MSB_REG		0x20c
#define MSPI_NEWQP_REG			0x210
#define MSPI_ENDQP_REG			0x214
#define MSPI_SPCR2_REG			0x218
#define MSPI_STATUS_REG			0x220
#define MSPI_CPTQP_REG			0x224
#define MSPI_TXRAM_REG			0x240
#define MSPI_RXRAM_REG			0x2c0
#define MSPI_CDRAM_REG			0x340
#define MSPI_WRITE_LOCK_REG		0x380
#define MSPI_DISABLE_FLUSH_GEN_REG	0x384

/*
 * Register access macros
 */
#define REG_RD(x)	read32(x)
#define REG_WR(x, y)	write32((x), (y))
#define REG_CLR(x, y)	REG_WR((x), REG_RD(x) & ~(y))
#define REG_SET(x, y)	REG_WR((x), REG_RD(x) | (y))

/* QSPI private data */
struct qspi_priv {
	/* Slave entry */
	struct spi_slave slave;

	/* Specified SPI parameters */
	unsigned int max_hz;
	unsigned int spi_mode;

	int mspi_enabled;
	int mspi_16bit;

	int bus_claimed;

	/* Registers */
	void *reg;
};

static struct qspi_priv qspi_slave;

/* Macro to get the private data */
#define to_qspi_slave(s) container_of(s, struct qspi_priv, slave)

struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
{
	struct qspi_priv *priv = &qspi_slave;
	unsigned int spbr;

	priv->slave.bus = bus;
	priv->slave.cs = cs;
	priv->max_hz = QSPI_MAX_HZ;
	priv->spi_mode = QSPI_MODE;
	priv->reg = (void *)(IPROC_QSPI_BASE);
	priv->mspi_enabled = 0;
	priv->bus_claimed = 0;

	/* MSPI: Basic hardware initialization */
	REG_WR(priv->reg + MSPI_SPCR1_LSB_REG, 0);
	REG_WR(priv->reg + MSPI_SPCR1_MSB_REG, 0);
	REG_WR(priv->reg + MSPI_NEWQP_REG, 0);
	REG_WR(priv->reg + MSPI_ENDQP_REG, 0);
	REG_WR(priv->reg + MSPI_SPCR2_REG, 0);

	/* MSPI: SCK configuration */
	spbr = (IPROC_QSPI_CLK - 1) / (2 * priv->max_hz) + 1;
	REG_WR(priv->reg + MSPI_SPCR0_LSB_REG,
	       MAX(MIN(spbr, SPBR_MAX), SPBR_MIN));

	/* MSPI: Mode configuration (8 bits by default) */
	priv->mspi_16bit = 0;
	REG_WR(priv->reg + MSPI_SPCR0_MSB_REG,
	       0x80 |			/* Master */
	       (8 << 2) |		/* 8 bits per word */
	       (priv->spi_mode & 3));	/* mode: CPOL / CPHA */

	return &priv->slave;
}

static int mspi_enable(struct qspi_priv *priv)
{
	struct stopwatch sw;

	/* Switch to MSPI if not yet */
	if ((REG_RD(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG) & 1) == 0) {
		stopwatch_init_msecs_expire(&sw, QSPI_WAIT_TIMEOUT);
		while (!stopwatch_expired(&sw)) {
			if ((REG_RD(priv->reg + BSPI_BUSY_STATUS_REG) & 1)
			    == 0) {
				REG_WR(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG,
				       1);
				udelay(1);
				break;
			}
			udelay(1);
		}
		if (REG_RD(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG) != 1)
			return -1;
	}
	priv->mspi_enabled = 1;
	return 0;
}

int spi_claim_bus(struct spi_slave *slave)
{
	struct qspi_priv *priv = to_qspi_slave(slave);

	if (priv->bus_claimed)
		return -1;

	if (!priv->mspi_enabled)
		if (mspi_enable(priv))
			return -1;

	/* MSPI: Enable write lock */
	REG_WR(priv->reg + MSPI_WRITE_LOCK_REG, 1);

	priv->bus_claimed = 1;

	return 0;
}

void spi_release_bus(struct spi_slave *slave)
{
	struct qspi_priv *priv = to_qspi_slave(slave);

	/* MSPI: Disable write lock */
	REG_WR(priv->reg + MSPI_WRITE_LOCK_REG, 0);

	priv->bus_claimed = 0;
}

#define RXRAM_16B(p, i)	(REG_RD((p)->reg + MSPI_RXRAM_REG + ((i) << 2)) & 0xff)
#define RXRAM_8B(p, i)	(REG_RD((p)->reg + MSPI_RXRAM_REG + \
				((((i) << 1) + 1) << 2)) & 0xff)

int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout,
	     void *din, unsigned int bytesin)
{
	struct qspi_priv *priv = to_qspi_slave(slave);
	const u8 *tx = (const u8 *)dout;
	u8 *rx = (u8 *)din;
	unsigned int bytes = bytesout + bytesin;
	unsigned int rx_idx = 0;
	unsigned int tx_idx = 0;
	unsigned int in = 0;
	unsigned int chunk;
	unsigned int queues;
	unsigned int i;
	struct stopwatch sw;

	if (!priv->bus_claimed)
		return -1;

	if (bytes & 1) {
		/* Use 8-bit queue for odd-bytes transfer */
		if (priv->mspi_16bit) {
			REG_SET(priv->reg + MSPI_SPCR0_MSB_REG,
				MSPI_SPCR0_MSB_BITS_8);
			priv->mspi_16bit = 0;
		}
	} else {
		/* Use 16-bit queue for even-bytes transfer */
		if (!priv->mspi_16bit) {
			REG_CLR(priv->reg + MSPI_SPCR0_MSB_REG,
				MSPI_SPCR0_MSB_BITS_8);
			priv->mspi_16bit = 1;
		}
	}

	while (bytes) {
		/* Separate code for 16bit and 8bit transfers for performance */
		if (priv->mspi_16bit) {
			/* Determine how many bytes to process this time */
			chunk = min(bytes, NUM_CDRAM * 2);
			queues = (chunk - 1) / 2 + 1;
			bytes -= chunk;

			/* Fill CDRAMs */
			for (i = 0; i < queues; i++)
				REG_WR(priv->reg + MSPI_CDRAM_REG + (i << 2),
				       0xc2);

			/* Fill TXRAMs */
			for (i = 0; i < chunk; i++) {
				REG_WR(priv->reg + MSPI_TXRAM_REG + (i << 2),
				       (tx && (tx_idx < bytesout)) ?
						tx[tx_idx] : 0xff);
				tx_idx++;
			}
		} else {
			/* Determine how many bytes to process this time */
			chunk = min(bytes, NUM_CDRAM);
			queues = chunk;
			bytes -= chunk;

			/* Fill CDRAMs and TXRAMS */
			for (i = 0; i < chunk; i++) {
				REG_WR(priv->reg + MSPI_CDRAM_REG + (i << 2),
				       0x82);
				REG_WR(priv->reg + MSPI_TXRAM_REG + (i << 3),
				       (tx && (tx_idx < bytesout)) ?
						tx[tx_idx] : 0xff);
				tx_idx++;
			}
		}

		/* Setup queue pointers */
		REG_WR(priv->reg + MSPI_NEWQP_REG, 0);
		REG_WR(priv->reg + MSPI_ENDQP_REG, queues - 1);

		/* Deassert CS */
		if (bytes == 0)
			REG_CLR(priv->reg + MSPI_CDRAM_REG +
				((queues - 1) << 2), 0x0);

		/* Kick off */
		REG_WR(priv->reg + MSPI_STATUS_REG, 0);
		REG_WR(priv->reg + MSPI_SPCR2_REG, 0xc0);	/* cont | spe */

		/* Wait for completion */
		stopwatch_init_msecs_expire(&sw, QSPI_WAIT_TIMEOUT);
		while (!stopwatch_expired(&sw)) {
			if (REG_RD(priv->reg + MSPI_STATUS_REG) & 1)
				break;
		}
		if ((REG_RD(priv->reg + MSPI_STATUS_REG) & 1) == 0) {
			/* Make sure no operation is in progress */
			REG_WR(priv->reg + MSPI_SPCR2_REG, 0);
			udelay(1);
			return -1;
		}

		/* Read data */
		if (rx) {
			if (priv->mspi_16bit) {
				for (i = 0; i < chunk; i++) {
					if (rx_idx >= bytesout) {
						rx[in] = RXRAM_16B(priv, i);
						in++;
					}
					rx_idx++;
				}
			} else {
				for (i = 0; i < chunk; i++) {
					if (rx_idx >= bytesout) {
						rx[in] = RXRAM_8B(priv, i);
						in++;
					}
					rx_idx++;
				}
			}
		}
	}

	return 0;
}
