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

#define DT_DRV_COMPAT litex_spi

#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
#include <zephyr/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, uint16_t *control)
{
	uint8_t cs = 0x00;

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

	if (config->operation & SPI_HALF_DUPLEX) {
		LOG_ERR("Half-duplex not supported");
		return -ENOTSUP;
	}

	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 (IS_ENABLED(CONFIG_SPI_EXTENDED_MODES) &&
	    (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_ADDR);
	}
	/* Set word size */
	*control = (uint16_t) (SPI_WORD_SIZE_GET(config->operation)
			<< POSITION_WORD_SIZE);
	/* Write configurations */
	litex_write8(cs, SPI_CS_ADDR);
	litex_write16(*control, SPI_CONTROL_ADDR);

	return 0;
}

static void spi_litespi_send(const struct device *dev, uint8_t frame,
		             uint16_t control)
{
	/* Write frame to register */
	litex_write8(frame, SPI_MOSI_DATA_ADDR);
	/* Start the transfer */
	litex_write16(control | SPI_ENABLE, SPI_CONTROL_ADDR);
	/* Wait until the transfer ends */
	while (!(litex_read8(SPI_STATUS_ADDR)))
		;
}

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

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

	for (uint32_t i = 0; i < send_len; i++) {
		/* Send a frame */
		if (i < ctx->tx_len) {
			spi_litespi_send(dev, (uint8_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, dev, 0);
}

/* API Functions */

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

static int spi_litespi_transceive(const struct device *dev,
				  const struct spi_config *config,
				  const struct spi_buf_set *tx_bufs,
				  const struct spi_buf_set *rx_bufs)
{
	uint16_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(const 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(const struct device *dev,
			       const struct spi_config *config)
{
	if (!(litex_read8(SPI_STATUS_ADDR))) {
		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_REG_ADDR_BY_NAME(n, control), \
	}; \
	DEVICE_DT_INST_DEFINE(n, \
			spi_litespi_init, \
			NULL, \
			&spi_litespi_data_##n, \
			&spi_litespi_cfg_##n, \
			POST_KERNEL, \
			CONFIG_SPI_INIT_PRIORITY, \
			&spi_litespi_api);

DT_INST_FOREACH_STATUS_OKAY(SPI_INIT)
