/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 Imagination Technologies
 *
 * 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 <soc/cpu.h>
#include <soc/spi.h>
#include <spi_flash.h>
#include <spi-generic.h>
#include <stdlib.h>
#include <string.h>
#include <timer.h>

#if !CONFIG_SPI_ATOMIC_SEQUENCING
#error "Unsupported SPI driver API"
#endif

/* Imgtec controller uses 16 bit packet length. */
#define IMGTEC_SPI_MAX_TRANSFER_SIZE   ((1 << 16) - 1)

struct img_spi_slave {
	struct spi_slave slave;
	/* SPIM instance device parameters */
	struct spim_device_parameters device_parameters;
	/* SPIM instance base address */
	u32 base;
	/* Boolean property that is TRUE if API has been initialised */
	int initialised;
};

/* Allocate memory for the maximum number of devices */
static struct
img_spi_slave img_spi_slaves[SPIM_NUM_BLOCKS*SPIM_NUM_PORTS_PER_BLOCK];

/*
 * Wait for the bit at the shift position to be set in reg
 * If the bit is not set in SPI_TIMEOUT_VALUE_US return with error
 */
static int wait_status(u32 reg, u32 shift)
{
	struct stopwatch sw;

	stopwatch_init_usecs_expire(&sw, SPI_TIMEOUT_VALUE_US);
	while (!(read32(reg) & (1 << shift))) {
		if (stopwatch_expired(&sw))
			return -SPIM_TIMEOUT;
	}
	return SPIM_OK;
}

/* Transmitter function. Fills TX FIFO with data before enabling SPIM */
static int transmitdata(struct spi_slave *slave, u8 *buffer, u32 size)
{
	u32 blocksize, base, write_data;
	int ret;

	base = container_of(slave, struct img_spi_slave, slave)->base;
	while (size) {
		/* Wait until FIFO empty */
		write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_SDE_MASK);
		ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
					SPFI_SDE_SHIFT);
		if (ret)
			return ret;

		/*
		 * Write to FIFO in blocks of 16 words (64 bytes)
		 * Do 32bit writes first.
		 */
		blocksize = SPIM_MAX_BLOCK_BYTES;
		while ((size >= sizeof(u32)) && blocksize) {
			memcpy(&write_data, buffer, sizeof(u32));
			write32(base + SPFI_SEND_LONG_REG_OFFSET, write_data);
			buffer += sizeof(u32);
			size -= sizeof(u32);
			blocksize -= sizeof(u32);
		}
		while (size && blocksize) {
			write32(base + SPFI_SEND_BYTE_REG_OFFSET, *buffer);
			buffer++;
			size--;
			blocksize--;
		}
	}
	return SPIM_OK;
}

/* Receiver function */
static int receivedata(struct spi_slave *slave, u8 *buffer, u32 size)
{
	u32 read_data, base;
	int ret;

	base = container_of(slave, struct img_spi_slave, slave)->base;
	/*
	 * Do 32bit reads first. Clear status GDEX32BIT here so that the first
	 * status reg. read gets the actual bit state
	 */
	write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK);
	while (size >= sizeof(u32)) {
		ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
					SPFI_GDEX32BIT_SHIFT);
		if (ret)
			return ret;
		read_data = read32(base + SPFI_GET_LONG_REG_OFFSET);
		memcpy(buffer, &read_data, sizeof(u32));
		buffer += sizeof(u32);
		size -= sizeof(u32);
		/* Clear interrupt status on GDEX32BITL */
		write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX32BIT_MASK);
	}

	/*
	 * Do the remaining 8bit reads. Clear status GDEX8BIT here so that
	 * the first status reg. read gets the actual bit state
	 */
	write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK);
	while (size) {
		ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
					SPFI_GDEX8BIT_SHIFT);
		if (ret)
			return ret;
		*buffer = read32(base + SPFI_GET_BYTE_REG_OFFSET);
		buffer++;
		size--;
		/* Clear interrupt status on SPFI_GDEX8BIT */
		write32(base + SPFI_INT_CLEAR_REG_OFFSET, SPFI_GDEX8BIT_MASK);
	}
	return SPIM_OK;
}

/* Sets port parameters in port state register. */
static void  setparams(struct spi_slave *slave, u32 port,
			struct spim_device_parameters *params)
{
	u32 spim_parameters, port_state, base;

	spim_parameters = 0;

	base = container_of(slave, struct img_spi_slave, slave)->base;
	port_state = read32(base + SPFI_PORT_STATE_REG_OFFSET);
	port_state &= ~((SPIM_PORT0_MASK>>port)|SPFI_PORT_SELECT_MASK);
	port_state |= params->cs_idle_level<<(SPIM_CS0_IDLE_SHIFT-port);
	port_state |=
		params->data_idle_level<<(SPIM_DATA0_IDLE_SHIFT-port);

	/* Clock idle level and phase */
	switch (params->spi_mode) {
	case SPIM_MODE_0:
		break;
	case SPIM_MODE_1:
		port_state |= (1 << (SPIM_CLOCK0_PHASE_SHIFT - port));
		break;
	case SPIM_MODE_2:
		port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port));
		break;
	case SPIM_MODE_3:
		port_state |= (1 << (SPIM_CLOCK0_IDLE_SHIFT - port)) |
				 (1 << (SPIM_CLOCK0_PHASE_SHIFT - port));
		break;
	}
	/* Set port state register */
	write32(base + SPFI_PORT_STATE_REG_OFFSET, port_state);

	/* Set up values to be written to device parameter register */
	spim_parameters |= params->bitrate << SPIM_CLK_DIVIDE_SHIFT;
	spim_parameters |= params->cs_setup << SPIM_CS_SETUP_SHIFT;
	spim_parameters |= params->cs_hold << SPIM_CS_HOLD_SHIFT;
	spim_parameters |= params->cs_delay << SPIM_CS_DELAY_SHIFT;

	write32(base + SPFI_PORT_0_PARAM_REG_OFFSET + 4 * port,
			spim_parameters);
}

/* Sets up transaction register */
static u32 transaction_reg_setup(struct spim_buffer *first,
					struct spim_buffer *second)
{
	u32 reg = 0;

	/* 2nd transfer exists? */
	if (second) {
		/*
		 * If second transfer exists, it's a "command followed by data"
		 * type of transfer and first transfer is defined by
		 * CMD_LENGTH, ADDR_LENGTH, DUMMY_LENGTH... fields of
		 * transaction register
		 */
		reg = spi_write_reg_field(reg, SPFI_CMD_LENGTH, 1);
		reg = spi_write_reg_field(reg, SPFI_ADDR_LENGTH,
						first->size - 1);
		reg = spi_write_reg_field(reg, SPFI_DUMMY_LENGTH, 0);
		/* Set data size (size of the second transfer) */
		reg = spi_write_reg_field(reg, SPFI_TSIZE, second->size);
	} else {
		/* Set data size, in this case size of the 1st transfer */
		reg = spi_write_reg_field(reg, SPFI_TSIZE, first->size);
	}
	return reg;
}

/* Sets up control register */
static u32 control_reg_setup(struct spim_buffer *first,
				struct spim_buffer *second)
{
	u32 reg;

	/* Enable SPFI */
	reg = SPFI_EN_MASK;
	reg |= first->inter_byte_delay ? SPIM_BYTE_DELAY_MASK : 0;

	/* Set up the transfer mode */
	reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE_DQ, SPIM_CMD_MODE_0);
	reg = spi_write_reg_field(reg, SPFI_TRNSFR_MODE, SPIM_DMODE_SINGLE);
	reg = spi_write_reg_field(reg, SPIM_EDGE_TX_RX, 1);

	if (second) {
		/* Set TX bit if the 2nd transaction is 'send' */
		reg = spi_write_reg_field(reg, SPFI_TX_RX,
						second->isread ? 0 : 1);
		/*
		 * Set send/get DMA for both transactions
		 * (first is always 'send')
		 */
		reg = spi_write_reg_field(reg, SPIM_SEND_DMA, 1);
		if (second->isread)
			reg = spi_write_reg_field(reg, SPIM_GET_DMA, 1);

	} else {
		/* Set TX bit if the 1st transaction is 'send' */
		reg |= first->isread ? 0 : SPFI_TX_RX_MASK;
		/* Set send/get DMA */
		reg |= first->isread ? SPIM_GET_DMA_MASK : SPIM_SEND_DMA_MASK;
	}
	return reg;
}

/* Checks the given buffer information */
static int check_buffers(struct spi_slave *slave, struct spim_buffer *first,
				struct spim_buffer *second){

	if (!(container_of(slave, struct img_spi_slave, slave)->initialised))
		return -SPIM_API_NOT_INITIALISED;
	/*
	 * First operation must always be defined
	 * It can be either a read or a write and its size cannot be bigge
	 * than SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF)
	 */
	if (!first)
		return -SPIM_INVALID_READ_WRITE;
	if (first->size > SPIM_MAX_TRANSFER_BYTES)
		return -SPIM_INVALID_SIZE;
	if (first->isread > 1)
		return -SPIM_INVALID_READ_WRITE;
	/* Check operation parameters for 'second' */
	if (second) {
		/*
		 * If the second operation is defined it must be a read
		 * operation and its size must not be bigger than
		 * SPIM_MAX_TANSFER_BYTES = 64KB - 1 (0xFFFF)
		 */
		if (second->size > SPIM_MAX_TRANSFER_BYTES)
			return -SPIM_INVALID_SIZE;
		if (!second->isread)
			return -SPIM_INVALID_READ_WRITE;
		/*
		 * If the second operations is defined, the first operation
		 * must be a write and its size cannot be bigger than
		 * SPIM_MAX_FLASH_COMMAND_BYTES(8): command size (1) +
		 * address size (7).
		 */
		if (first->isread)
			return -SPIM_INVALID_READ_WRITE;
		if (first->size > SPIM_MAX_FLASH_COMMAND_BYTES)
			return -SPIM_INVALID_SIZE;

	}
	return SPIM_OK;
}

/* Checks the set bitrate */
static int check_bitrate(u32 rate)
{
	/* Bitrate must be 1, 2, 4, 8, 16, 32, 64, or 128 */
	switch (rate) {
	case 1:
	case 2:
	case 4:
	case 8:
	case 16:
	case 32:
	case 64:
	case 128:
		return SPIM_OK;
	default:
		return -SPIM_INVALID_BIT_RATE;
	}
	return -SPIM_INVALID_BIT_RATE;
}

/* Checks device parameters for errors */
static int check_device_params(struct spim_device_parameters *pdev_param)
{
	if (pdev_param->spi_mode < SPIM_MODE_0 ||
		pdev_param->spi_mode > SPIM_MODE_3)
		return -SPIM_INVALID_SPI_MODE;
	if (check_bitrate(pdev_param->bitrate) != SPIM_OK)
		return -SPIM_INVALID_BIT_RATE;
	if (pdev_param->cs_idle_level > 1)
		return -SPIM_INVALID_CS_IDLE_LEVEL;
	if (pdev_param->data_idle_level > 1)
		return -SPIM_INVALID_DATA_IDLE_LEVEL;
	return SPIM_OK;
}

/* Function that carries out read/write operations */
static int spim_io(struct spi_slave *slave, struct spim_buffer *first,
			struct spim_buffer *second)
{
	u32 reg, base;
	int i, trans_count, ret;
	struct spim_buffer *transaction[2];

	base = container_of(slave, struct img_spi_slave, slave)->base;

	ret = check_buffers(slave, first, second);
	if (ret)
		return ret;

	/*
	 * Soft reset peripheral internals, this will terminate any
	 * pending transactions
	 */
	write32(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
	write32(base + SPFI_CONTROL_REG_OFFSET, 0);
	/* Port state register */
	reg = read32(base +  SPFI_PORT_STATE_REG_OFFSET);
	reg = spi_write_reg_field(reg, SPFI_PORT_SELECT, slave->cs);
	write32(base + SPFI_PORT_STATE_REG_OFFSET, reg);
	/* Set transaction register */
	reg = transaction_reg_setup(first, second);
	write32(base + SPFI_TRANSACTION_REG_OFFSET, reg);
	/* Clear status */
	write32(base + SPFI_INT_CLEAR_REG_OFFSET, 0xffffffff);
	/* Set control register */
	reg = control_reg_setup(first, second);
	write32(base + SPFI_CONTROL_REG_OFFSET, reg);
	/* First transaction always exists */
	transaction[0] = first;
	trans_count = 1;
	/* Is there a second transaction? */
	if (second) {
		transaction[1] = second;
		trans_count++;
	}
	/* Now write/read FIFO's */
	for (i = 0; i < trans_count; i++)
		/* Which transaction to execute, "Send" or "Get"? */
		if (transaction[i]->isread) {
			/* Get */
			ret = receivedata(slave, transaction[i]->buffer,
					transaction[i]->size);
			if (ret) {
				printk(BIOS_ERR,
					"%s: Error: receive data failed.\n",
					__func__);
				return ret;
			}
		} else {
			/* Send */
			ret = transmitdata(slave, transaction[i]->buffer,
					transaction[i]->size);
			if (ret) {
				printk(BIOS_ERR,
					"%s: Error: transmit data failed.\n",
					__func__);
				return ret;
			}
		}

	/* Wait for end of the transaction */
	ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
				SPFI_ALLDONE_SHIFT);
	if (ret)
		return ret;
	/*
	 * Soft reset peripheral internals, this will terminate any
	 * pending transactions
	 */
	write32(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
	write32(base + SPFI_CONTROL_REG_OFFSET, 0);

	return SPIM_OK;
}

/* Initialization, must be called once on start up */
void spi_init(void)
{
	/* Clear everything just in case */
	memset(img_spi_slaves, 0, sizeof(img_spi_slaves));
}

/* Set up communications parameters for a SPI slave. */
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
{

	struct img_spi_slave *img_slave = NULL;
	struct spi_slave *slave;
	struct spim_device_parameters *device_parameters;
	u32 base;

	switch (bus) {
	case 0:
		base = IMG_SPIM0_BASE_ADDRESS;
		break;
	case 1:
		base = IMG_SPIM1_BASE_ADDRESS;
		break;
	default:
		printk(BIOS_ERR, "%s: Error: unsupported bus.\n",
				__func__);
		return NULL;
	}
	if (cs > SPIM_DEVICE4) {
		printk(BIOS_ERR, "%s: Error: unsupported chipselect.\n",
				__func__);
		return NULL;
	}

	img_slave = img_spi_slaves + bus * SPIM_NUM_PORTS_PER_BLOCK + cs;
	slave = &(img_slave->slave);
	device_parameters = &(img_slave->device_parameters);

	img_slave->base = base;
	slave->bus = bus;
	slave->cs = cs;
	slave->rw = SPI_READ_FLAG | SPI_WRITE_FLAG;
	slave->max_transfer_size = IMGTEC_SPI_MAX_TRANSFER_SIZE;

	device_parameters->bitrate = 64;
	device_parameters->cs_setup = 0;
	device_parameters->cs_hold = 0;
	device_parameters->cs_delay = 0;
	device_parameters->spi_mode = SPIM_MODE_0;
	device_parameters->cs_idle_level = 1;
	device_parameters->data_idle_level = 0;
	img_slave->initialised = IMG_FALSE;

	return slave;
}

/* Claim the bus and prepare it for communication */
int spi_claim_bus(struct spi_slave *slave)
{
	int ret;
	struct img_spi_slave *img_slave;

	if (!slave) {
		printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
				__func__);
		return -SPIM_API_NOT_INITIALISED;
	}
	img_slave = container_of(slave, struct img_spi_slave, slave);
	if (img_slave->initialised)
		return SPIM_OK;
	/* Check device parameters */
	ret = check_device_params(&(img_slave->device_parameters));
	if (ret) {
		printk(BIOS_ERR, "%s: Error: incorrect device parameters.\n",
				__func__);
		return ret;
	}
	/* Set device parameters */
	setparams(slave, slave->cs, &(img_slave->device_parameters));
	/* Soft reset peripheral internals */
	write32(img_slave->base + SPFI_CONTROL_REG_OFFSET,
		SPIM_SOFT_RESET_MASK);
	write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0);
	img_slave->initialised = IMG_TRUE;
	return SPIM_OK;
}

/* Release the SPI bus */
void spi_release_bus(struct spi_slave *slave)
{
	struct img_spi_slave *img_slave;

	if (!slave) {
		printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
				__func__);
		return;
	}
	img_slave = container_of(slave, struct img_spi_slave, slave);
	img_slave->initialised = IMG_FALSE;
	/* Soft reset peripheral internals */
	write32(img_slave->base + SPFI_CONTROL_REG_OFFSET,
		SPIM_SOFT_RESET_MASK);
	write32(img_slave->base + SPFI_CONTROL_REG_OFFSET, 0);
}

/* SPI transfer */
int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bytesout,
		void *din, unsigned int bytesin)
{
	struct spim_buffer	buff_0;
	struct spim_buffer	buff_1;

	if (!slave) {
		printk(BIOS_ERR, "%s: Error: slave was not set up.\n",
				__func__);
		return -SPIM_API_NOT_INITIALISED;
	}
	if (!dout && !din) {
		printk(BIOS_ERR, "%s: Error: both buffers are NULL.\n",
				__func__);
			return -SPIM_INVALID_TRANSFER_DESC;
	}
	/* If we only have a read or a write operation
	 * the parameters for it will be put in the first buffer
	 */
	buff_0.buffer = (dout) ? (void *)dout : (void *)din;
	buff_0.size = (dout) ? bytesout : bytesin;
	buff_0.isread = (dout) ? IMG_FALSE : IMG_TRUE;
	buff_0.inter_byte_delay = 0;

	if (dout && din) {
		/* Set up the read buffer to receive our data */
		buff_1.buffer = din;
		buff_1.size = bytesin;
		buff_1.isread = IMG_TRUE;
		buff_1.inter_byte_delay = 0;
	}
	return spim_io(slave, &buff_0, (dout && din) ? &buff_1 : NULL);
}

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