/*
 * Copyright (c) 2019 Antmicro <www.antmicro.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(spi_litespi);
#include "spi_litespi.h"
#include <stdbool.h>

/* Helper Functions */
static int spi_config(const struct spi_config *config, u16_t *control)
{
	u8_t cs = 0x00;

	if (config->slave != 0) {
		if (config->slave >= SPI_MAX_CS_SIZE) {
			LOG_ERR("More slaves than supported");
			return -ENOTSUP;
		}
		cs = (u8_t)(config->slave);
	}

	if (SPI_WORD_SIZE_GET(config->operation) != 8) {
		LOG_ERR("Word size must be %d", SPI_WORD_SIZE);
		return -ENOTSUP;
	}

	if (config->operation & SPI_CS_ACTIVE_HIGH) {
		LOG_ERR("CS active high not supported");
		return -ENOTSUP;
	}

	if (config->operation & SPI_LOCK_ON) {
		LOG_ERR("Lock On not supported");
		return -ENOTSUP;
	}

	if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
		LOG_ERR("Only supports single mode");
		return -ENOTSUP;
	}

	if (config->operation & SPI_TRANSFER_LSB) {
		LOG_ERR("LSB first not supported");
		return -ENOTSUP;
	}

	if (config->operation & (SPI_MODE_CPOL | SPI_MODE_CPHA)) {
		LOG_ERR("Only supports CPOL=CPHA=0");
		return -ENOTSUP;
	}

	if (config->operation & SPI_OP_MODE_SLAVE) {
		LOG_ERR("Slave mode not supported");
		return -ENOTSUP;
	}

	/* Set Loopback */
	if (config->operation & SPI_MODE_LOOP) {
		litex_write8(SPI_ENABLE, SPI_LOOPBACK_REG);
	}
	/* Set word size */
	*control = (u16_t) (SPI_WORD_SIZE_GET(config->operation)
			<< POSITION_WORD_SIZE);
	/* Write configurations */
	litex_write8(cs, SPI_CS_REG);
	litex_write16(*control, SPI_CONTROL_REG);

	return 0;
}

static void spi_litespi_send(struct device *dev, u8_t frame, u16_t control)
{
	/* Write frame to register */
	litex_write8(frame, SPI_MOSI_DATA_REG);
	/* Start the transfer */
	litex_write16(control | SPI_ENABLE, SPI_CONTROL_REG);
	/* Wait until the transfer ends */
	while (!(litex_read8(SPI_STATUS_REG)))
		;
}

static u8_t spi_litespi_recv(void)
{
    /* Return data inside MISO register */
	return litex_read8(SPI_MISO_DATA_REG);
}

static void spi_litespi_xfer(struct device *dev,
		const struct spi_config *config, u16_t control)
{
	struct spi_context *ctx = &SPI_DATA(dev)->ctx;
	u32_t send_len = spi_context_longest_current_buf(ctx);
	u8_t read_data;

	for (u32_t i = 0; i < send_len; i++) {
		/* Send a frame */
		if (i < ctx->tx_len) {
			spi_litespi_send(dev, (u8_t) (ctx->tx_buf)[i],
					control);
		} else {
			/* Send dummy bytes */
			spi_litespi_send(dev, 0, control);
		}
		/* Receive a frame */
		read_data = spi_litespi_recv();
		if (i < ctx->rx_len) {
			ctx->rx_buf[i] = read_data;
		}
	}
	spi_context_complete(ctx, 0);
}

/* API Functions */

static int spi_litespi_init(struct device *dev)
{
	return 0;
}

static int spi_litespi_transceive(struct device *dev,
			  const struct spi_config *config,
			  const struct spi_buf_set *tx_bufs,
			  const struct spi_buf_set *rx_bufs)
{
	u16_t control = 0;

	spi_config(config, &control);
	spi_context_buffers_setup(&SPI_DATA(dev)->ctx, tx_bufs, rx_bufs, 1);
	spi_litespi_xfer(dev, config, control);
	return 0;
}

#ifdef CONFIG_SPI_ASYNC
static int spi_litespi_transceive_async(struct device *dev,
			  const struct spi_config *config,
			  const struct spi_buf_set *tx_bufs,
			  const struct spi_buf_set *rx_bufs,
			  struct k_poll_signal *async)
{
	return -ENOTSUP;
}
#endif /* CONFIG_SPI_ASYNC */

static int spi_litespi_release(struct device *dev,
		const struct spi_config *config)
{
	if (!(litex_read8(SPI_STATUS_REG))) {
		return -EBUSY;
	}
	return 0;
}

/* Device Instantiation */
static struct spi_driver_api spi_litespi_api = {
	.transceive = spi_litespi_transceive,
#ifdef CONFIG_SPI_ASYNC
	.transceive_async = spi_litespi_transceive_async,
#endif /* CONFIG_SPI_ASYNC */
	.release = spi_litespi_release,
};

#define SPI_INIT(n)	\
	static struct spi_litespi_data spi_litespi_data_##n = { \
		SPI_CONTEXT_INIT_LOCK(spi_litespi_data_##n, ctx), \
		SPI_CONTEXT_INIT_SYNC(spi_litespi_data_##n, ctx), \
	}; \
	static struct spi_litespi_cfg spi_litespi_cfg_##n = { \
		.base = DT_INST_##n##_LITEX_SPI_CONTROL_BASE_ADDRESS, \
	}; \
	DEVICE_AND_API_INIT(spi_##n, \
			DT_INST_##n##_LITEX_SPI_LABEL, \
			spi_litespi_init, \
			&spi_litespi_data_##n, \
			&spi_litespi_cfg_##n, \
			POST_KERNEL, \
			CONFIG_SPI_INIT_PRIORITY, \
			&spi_litespi_api)

#ifdef DT_INST_0_LITEX_SPI_LABEL

SPI_INIT(0);

#endif /* DT_INST_0_LITEX_SPI_LABEL */
