/*
 * Copyright (c) 2018 SiFive Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

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

#include "spi_sifive.h"

#include <stdbool.h>

/* Helper Functions */

static inline void sys_set_mask(mem_addr_t addr, u32_t mask, u32_t value)
{
	u32_t temp = sys_read32(addr);

	temp &= ~(mask);
	temp |= value;

	sys_write32(temp, addr);
}

int spi_config(struct device *dev, u32_t frequency, u16_t operation)
{
	u32_t div;
	u32_t fmt_len;

	if (SPI_OP_MODE_GET(operation) != SPI_OP_MODE_MASTER) {
		return -ENOTSUP;
	}

	if (operation & SPI_MODE_LOOP) {
		return -ENOTSUP;
	}

	/* Set the SPI frequency */
	div = (SPI_CFG(dev)->f_sys / (frequency * 2U)) - 1;
	sys_write32((SF_SCKDIV_DIV_MASK & div), SPI_REG(dev, REG_SCKDIV));

	/* Set the polarity */
	if (operation & SPI_MODE_CPOL) {
		/* If CPOL is set, then SCK idles at logical 1 */
		sys_set_bit(SPI_REG(dev, REG_SCKMODE), SF_SCKMODE_POL);
	} else {
		/* SCK idles at logical 0 */
		sys_clear_bit(SPI_REG(dev, REG_SCKMODE), SF_SCKMODE_POL);
	}

	/* Set the phase */
	if (operation & SPI_MODE_CPHA) {
		/*
		 * If CPHA is set, then data is sampled
		 * on the trailing SCK edge
		 */
		sys_set_bit(SPI_REG(dev, REG_SCKMODE), SF_SCKMODE_PHA);
	} else {
		/* Data is sampled on the leading SCK edge */
		sys_clear_bit(SPI_REG(dev, REG_SCKMODE), SF_SCKMODE_PHA);
	}

	/* Get the frame length */
	fmt_len = SPI_WORD_SIZE_GET(operation);
	if (fmt_len > SF_FMT_LEN_MASK) {
		return -ENOTSUP;
	}

	/* Set the frame length */
	fmt_len = fmt_len << SF_FMT_LEN;
	fmt_len &= SF_FMT_LEN_MASK;
	sys_set_mask(SPI_REG(dev, REG_FMT), SF_FMT_LEN_MASK, fmt_len);

	if ((operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
		return -ENOTSUP;
	}
	/* Set single line operation */
	sys_set_mask(SPI_REG(dev, REG_FMT),
		SF_FMT_PROTO_MASK,
		SF_FMT_PROTO_SINGLE);

	/* Set the endianness */
	if (operation & SPI_TRANSFER_LSB) {
		sys_set_bit(SPI_REG(dev, REG_FMT), SF_FMT_ENDIAN);
	} else {
		sys_clear_bit(SPI_REG(dev, REG_FMT), SF_FMT_ENDIAN);
	}

	return 0;
}

void spi_sifive_send(struct device *dev, u16_t frame)
{
	while (SPI_REG(dev, REG_TXDATA) & SF_TXDATA_FULL) {
	}

	sys_write32((u32_t) frame, SPI_REG(dev, REG_TXDATA));
}

u16_t spi_sifive_recv(struct device *dev)
{
	u32_t val;

	while ((val = sys_read32(SPI_REG(dev, REG_RXDATA))) & SF_RXDATA_EMPTY) {
	}

	return (u16_t) val;
}

void spi_sifive_xfer(struct device *dev, const bool hw_cs_control)
{
	struct spi_context *ctx = &SPI_DATA(dev)->ctx;

	u32_t send_len = spi_context_longest_current_buf(ctx);

	for (u32_t i = 0; i < send_len; i++) {

		/* Send a frame */
		if (i < ctx->tx_len) {
			spi_sifive_send(dev, (u16_t) (ctx->tx_buf)[i]);
		} else {
			/* Send dummy bytes */
			spi_sifive_send(dev, 0);
		}

		/* Receive a frame */
		if (i < ctx->rx_len) {
			ctx->rx_buf[i] = (u8_t) spi_sifive_recv(dev);
		} else {
			/* Discard returned value */
			spi_sifive_recv(dev);
		}
	}

	/* Deassert the CS line */
	if (!hw_cs_control) {
		spi_context_cs_control(&SPI_DATA(dev)->ctx, false);
	} else {
		sys_write32(SF_CSMODE_OFF, SPI_REG(dev, REG_CSMODE));
	}

	spi_context_complete(ctx, 0);
}

/* API Functions */

int spi_sifive_init(struct device *dev)
{
	/* Disable SPI Flash mode */
	sys_clear_bit(SPI_REG(dev, REG_FCTRL), SF_FCTRL_EN);

	/* Make sure the context is unlocked */
	spi_context_unlock_unconditionally(&SPI_DATA(dev)->ctx);
	return 0;
}

int spi_sifive_transceive(struct device *dev,
			  const struct spi_config *config,
			  const struct spi_buf_set *tx_bufs,
			  const struct spi_buf_set *rx_bufs)
{
	int rc = 0;
	bool hw_cs_control = false;

	/* Lock the SPI Context */
	spi_context_lock(&SPI_DATA(dev)->ctx, false, NULL);

	/* Configure the SPI bus */
	SPI_DATA(dev)->ctx.config = config;

	/*
	 * If the chip select configuration is not present, we'll ask the
	 * SPI peripheral itself to control the CS line
	 */
	if (config->cs == NULL) {
		hw_cs_control = true;
	}

	if (!hw_cs_control) {
		/*
		 * If the user has requested manual GPIO control, ask the
		 * context for control and disable HW control
		 */
		spi_context_cs_configure(&SPI_DATA(dev)->ctx);
		sys_write32(SF_CSMODE_OFF, SPI_REG(dev, REG_CSMODE));
	} else {
		/*
		 * Tell the hardware to control the requested CS pin.
		 * NOTE:
		 *	For the SPI peripheral, the pin number is not the
		 *	GPIO pin, but the index into the list of available
		 *	CS lines for the SPI peripheral.
		 */
		sys_write32(config->slave, SPI_REG(dev, REG_CSID));
		sys_write32(SF_CSMODE_OFF, SPI_REG(dev, REG_CSMODE));
	}

	rc = spi_config(dev, config->frequency, config->operation);
	if (rc < 0) {
		spi_context_release(&SPI_DATA(dev)->ctx, rc);
		return rc;
	}

	spi_context_buffers_setup(&SPI_DATA(dev)->ctx, tx_bufs, rx_bufs, 1);

	/* Assert the CS line */
	if (!hw_cs_control) {
		spi_context_cs_control(&SPI_DATA(dev)->ctx, true);
	} else {
		sys_write32(SF_CSMODE_HOLD, SPI_REG(dev, REG_CSMODE));
	}

	/* Perform transfer */
	spi_sifive_xfer(dev, hw_cs_control);

	rc = spi_context_wait_for_completion(&SPI_DATA(dev)->ctx);

	spi_context_release(&SPI_DATA(dev)->ctx, rc);

	return rc;
}

int spi_sifive_release(struct device *dev, const struct spi_config *config)
{
	spi_context_unlock_unconditionally(&SPI_DATA(dev)->ctx);
	return 0;
}

/* Device Instantiation */

static struct spi_driver_api spi_sifive_api = {
	.transceive = spi_sifive_transceive,
	.release = spi_sifive_release,
};

#define SPI_INIT(n)	\
	static struct spi_sifive_data spi_sifive_data_##n = { \
		SPI_CONTEXT_INIT_LOCK(spi_sifive_data_##n, ctx), \
		SPI_CONTEXT_INIT_SYNC(spi_sifive_data_##n, ctx), \
	}; \
	static struct spi_sifive_cfg spi_sifive_cfg_##n = { \
		.base = DT_INST_##n##_SIFIVE_SPI0_CONTROL_BASE_ADDRESS, \
		.f_sys = DT_INST_##n##_SIFIVE_SPI0_CLOCK_FREQUENCY, \
	}; \
	DEVICE_AND_API_INIT(spi_##n, \
			DT_INST_##n##_SIFIVE_SPI0_LABEL, \
			spi_sifive_init, \
			&spi_sifive_data_##n, \
			&spi_sifive_cfg_##n, \
			POST_KERNEL, \
			CONFIG_SPI_INIT_PRIORITY, \
			&spi_sifive_api)

#ifndef CONFIG_SIFIVE_SPI_0_ROM
#ifdef DT_INST_0_SIFIVE_SPI0_LABEL

SPI_INIT(0);

#endif /* DT_INST_0_SIFIVE_SPI0_LABEL */
#endif /* !DT_SIFIVE_SPI0_0_ROM */

#ifdef DT_INST_1_SIFIVE_SPI0_LABEL

SPI_INIT(1);

#endif /* DT_INST_1_SIFIVE_SPI0_LABEL */

#ifdef DT_INST_2_SIFIVE_SPI0_LABEL

SPI_INIT(2);

#endif /* DT_INST_2_SIFIVE_SPI0_LABEL */

