/*
 * Xilinx SPI driver
 *
 * supports 8 bit SPI transfers only, with or w/o FIFO
 *
 * based on bfin_spi.c, by way of altera_spi.c
 * Copyright (c) 2005-2008 Analog Devices Inc.
 * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
 * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
 * Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 *
 * [0]: http://www.xilinx.com/support/documentation
 *
 * [S]:	[0]/ip_documentation/xps_spi.pdf
 *	[0]/ip_documentation/axi_spi_ds742.pdf
 */
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <spi.h>

#include "xilinx_spi.h"

#ifndef CONFIG_SYS_XILINX_SPI_LIST
#define CONFIG_SYS_XILINX_SPI_LIST	{ CONFIG_SYS_SPI_BASE }
#endif

#ifndef CONFIG_XILINX_SPI_IDLE_VAL
#define CONFIG_XILINX_SPI_IDLE_VAL	0xff
#endif

#define XILSPI_SPICR_DFLT_ON		(SPICR_MANUAL_SS | \
					 SPICR_MASTER_MODE | \
					 SPICR_SPE)

#define XILSPI_SPICR_DFLT_OFF		(SPICR_MASTER_INHIBIT | \
					 SPICR_MANUAL_SS)

#define XILSPI_MAX_XFER_BITS		8

static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST;

__attribute__((weak))
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
	return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
}

__attribute__((weak))
void spi_cs_activate(struct spi_slave *slave)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);

	writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr);
}

__attribute__((weak))
void spi_cs_deactivate(struct spi_slave *slave)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);

	writel(SPISSR_OFF, &xilspi->regs->spissr);
}

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

void spi_set_speed(struct spi_slave *slave, uint hz)
{
	/* xilinx spi core does not support programmable speed */
}

struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
				  unsigned int max_hz, unsigned int mode)
{
	struct xilinx_spi_slave *xilspi;

	if (!spi_cs_is_valid(bus, cs)) {
		printf("XILSPI error: %s: unsupported bus %d / cs %d\n",
				__func__, bus, cs);
		return NULL;
	}

	xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs);
	if (!xilspi) {
		printf("XILSPI error: %s: malloc of SPI structure failed\n",
				__func__);
		return NULL;
	}
	xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus];
	xilspi->freq = max_hz;
	xilspi->mode = mode;
	debug("%s: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", __func__,
		bus, cs, xilspi->regs, xilspi->mode, xilspi->freq);

	writel(SPISSR_RESET_VALUE, &xilspi->regs->srr);

	return &xilspi->slave;
}

void spi_free_slave(struct spi_slave *slave)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);

	free(xilspi);
}

int spi_claim_bus(struct spi_slave *slave)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
	u32 spicr;

	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
	writel(SPISSR_OFF, &xilspi->regs->spissr);

	spicr = XILSPI_SPICR_DFLT_ON;
	if (xilspi->mode & SPI_LSB_FIRST)
		spicr |= SPICR_LSB_FIRST;
	if (xilspi->mode & SPI_CPHA)
		spicr |= SPICR_CPHA;
	if (xilspi->mode & SPI_CPOL)
		spicr |= SPICR_CPOL;
	if (xilspi->mode & SPI_LOOP)
		spicr |= SPICR_LOOP;

	writel(spicr, &xilspi->regs->spicr);
	return 0;
}

void spi_release_bus(struct spi_slave *slave)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);

	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
	writel(SPISSR_OFF, &xilspi->regs->spissr);
	writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr);
}

int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
	     void *din, unsigned long flags)
{
	struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
	/* assume spi core configured to do 8 bit transfers */
	unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
	const unsigned char *txp = dout;
	unsigned char *rxp = din;
	unsigned rxecount = 17;	/* max. 16 elements in FIFO, leftover 1 */
	unsigned global_timeout;

	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;

	if (bitlen % XILSPI_MAX_XFER_BITS) {
		printf("XILSPI warning: %s: Not a multiple of %d bits\n",
				__func__, XILSPI_MAX_XFER_BITS);
		flags |= SPI_XFER_END;
		goto done;
	}

	/* empty read buffer */
	while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) {
		readl(&xilspi->regs->spidrr);
		rxecount--;
	}

	if (!rxecount) {
		printf("XILSPI error: %s: Rx buffer not empty\n", __func__);
		return -1;
	}

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(slave);

	/* at least 1usec or greater, leftover 1 */
	global_timeout = xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
			(XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1;

	while (bytes--) {
		unsigned timeout = global_timeout;
		/* get Tx element from data out buffer and count up */
		unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
		debug("%s: tx:%x ", __func__, d);

		/* write out and wait for processing (receive data) */
		writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr);
		while (timeout && readl(&xilspi->regs->spisr)
						& SPISR_RX_EMPTY) {
			timeout--;
			udelay(1);
		}

		if (!timeout) {
			printf("XILSPI error: %s: Xfer timeout\n", __func__);
			return -1;
		}

		/* read Rx element and push into data in buffer */
		d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK;
		if (rxp)
			*rxp++ = d;
		debug("rx:%x\n", d);
	}

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

	return 0;
}
