/*
 * 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.
 */

#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;
}

unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
{
	return min(65535, buf_len);
}
