/*
 * SH QSPI (Quad SPI) driver
 *
 * Copyright (C) 2013 Renesas Electronics Corporation
 * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
 *
 * SPDX-License-Identifier:	GPL-2.0
 */

#include <common.h>
#include <malloc.h>
#include <spi.h>
#include <asm/arch/rmobile.h>
#include <asm/io.h>

/* SH QSPI register bit masks <REG>_<BIT> */
#define SPCR_MSTR	0x08
#define SPCR_SPE	0x40
#define SPSR_SPRFF	0x80
#define SPSR_SPTEF	0x20
#define SPPCR_IO3FV	0x04
#define SPPCR_IO2FV	0x02
#define SPPCR_IO1FV	0x01
#define SPBDCR_RXBC0	(1 << 0)
#define SPCMD_SCKDEN	(1 << 15)
#define SPCMD_SLNDEN	(1 << 14)
#define SPCMD_SPNDEN	(1 << 13)
#define SPCMD_SSLKP	(1 << 7)
#define SPCMD_BRDV0	(1 << 2)
#define SPCMD_INIT1	SPCMD_SCKDEN | SPCMD_SLNDEN | \
			SPCMD_SPNDEN | SPCMD_SSLKP | \
			SPCMD_BRDV0
#define SPCMD_INIT2	SPCMD_SPNDEN | SPCMD_SSLKP | \
			SPCMD_BRDV0
#define SPBFCR_TXRST	(1 << 7)
#define SPBFCR_RXRST	(1 << 6)

/* SH QSPI register set */
struct sh_qspi_regs {
	unsigned char spcr;
	unsigned char sslp;
	unsigned char sppcr;
	unsigned char spsr;
	unsigned long spdr;
	unsigned char spscr;
	unsigned char spssr;
	unsigned char spbr;
	unsigned char spdcr;
	unsigned char spckd;
	unsigned char sslnd;
	unsigned char spnd;
	unsigned char dummy0;
	unsigned short spcmd0;
	unsigned short spcmd1;
	unsigned short spcmd2;
	unsigned short spcmd3;
	unsigned char spbfcr;
	unsigned char dummy1;
	unsigned short spbdcr;
	unsigned long spbmul0;
	unsigned long spbmul1;
	unsigned long spbmul2;
	unsigned long spbmul3;
};

struct sh_qspi_slave {
	struct spi_slave	slave;
	struct sh_qspi_regs	*regs;
};

static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
{
	return container_of(slave, struct sh_qspi_slave, slave);
}

static void sh_qspi_init(struct sh_qspi_slave *ss)
{
	/* QSPI initialize */
	/* Set master mode only */
	writeb(SPCR_MSTR, &ss->regs->spcr);

	/* Set SSL signal level */
	writeb(0x00, &ss->regs->sslp);

	/* Set MOSI signal value when transfer is in idle state */
	writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);

	/* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
	writeb(0x01, &ss->regs->spbr);

	/* Disable Dummy Data Transmission */
	writeb(0x00, &ss->regs->spdcr);

	/* Set clock delay value */
	writeb(0x00, &ss->regs->spckd);

	/* Set SSL negation delay value */
	writeb(0x00, &ss->regs->sslnd);

	/* Set next-access delay value */
	writeb(0x00, &ss->regs->spnd);

	/* Set equence command */
	writew(SPCMD_INIT2, &ss->regs->spcmd0);

	/* Reset transfer and receive Buffer */
	setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);

	/* Clear transfer and receive Buffer control bit */
	clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);

	/* Set equence control method. Use equence0 only */
	writeb(0x00, &ss->regs->spscr);

	/* Enable SPI function */
	setbits_8(&ss->regs->spcr, SPCR_SPE);
}

int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
	return 1;
}

void spi_cs_activate(struct spi_slave *slave)
{
	struct sh_qspi_slave *ss = to_sh_qspi(slave);

	/* Set master mode only */
	writeb(SPCR_MSTR, &ss->regs->spcr);

	/* Set command */
	writew(SPCMD_INIT1, &ss->regs->spcmd0);

	/* Reset transfer and receive Buffer */
	setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);

	/* Clear transfer and receive Buffer control bit */
	clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);

	/* Set equence control method. Use equence0 only */
	writeb(0x00, &ss->regs->spscr);

	/* Enable SPI function */
	setbits_8(&ss->regs->spcr, SPCR_SPE);
}

void spi_cs_deactivate(struct spi_slave *slave)
{
	struct sh_qspi_slave *ss = to_sh_qspi(slave);

	/* Disable SPI Function */
	clrbits_8(&ss->regs->spcr, SPCR_SPE);
}

void spi_init(void)
{
	/* nothing to do */
}

struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode)
{
	struct sh_qspi_slave *ss;

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

	ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
	if (!ss) {
		printf("SPI_error: Fail to allocate sh_qspi_slave\n");
		return NULL;
	}

	ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;

	/* Init SH QSPI */
	sh_qspi_init(ss);

	return &ss->slave;
}

void spi_free_slave(struct spi_slave *slave)
{
	struct sh_qspi_slave *spi = to_sh_qspi(slave);

	free(spi);
}

int spi_claim_bus(struct spi_slave *slave)
{
	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 sh_qspi_slave *ss = to_sh_qspi(slave);
	unsigned long nbyte;
	int ret = 0;
	unsigned char dtdata = 0, drdata;
	unsigned char *tdata = &dtdata, *rdata = &drdata;
	unsigned long *spbmul0 = &ss->regs->spbmul0;

	if (dout == NULL && din == NULL) {
		if (flags & SPI_XFER_END)
			spi_cs_deactivate(slave);
		return 0;
	}

	if (bitlen % 8) {
		printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
		return 1;
	}

	nbyte = bitlen / 8;

	if (flags & SPI_XFER_BEGIN) {
		spi_cs_activate(slave);

		/* Set 1048576 byte */
		writel(0x100000, spbmul0);
	}

	if (flags & SPI_XFER_END)
		writel(nbyte, spbmul0);

	if (dout != NULL)
		tdata = (unsigned char *)dout;

	if (din != NULL)
		rdata = din;

	while (nbyte > 0) {
		while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) {
			if (ctrlc()) {
				puts("abort\n");
				return 1;
			}
			udelay(10);
		}

		writeb(*tdata, (unsigned char *)(&ss->regs->spdr));

		while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) {
			if (ctrlc()) {
				puts("abort\n");
				return 1;
			}
			udelay(1);
		}

		while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) {
			if (ctrlc()) {
				puts("abort\n");
				return 1;
			}
			udelay(10);
		}

		*rdata = readb((unsigned char *)(&ss->regs->spdr));

		if (dout != NULL)
			tdata++;
		if (din != NULL)
			rdata++;

		nbyte--;
	}

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(slave);

	return ret;
}
