/*
 * Copyright (c) 2021 BrainCo Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT gd_gd32_spi

#include <errno.h>
#include <kernel.h>
#include <drivers/pinctrl.h>
#include <drivers/spi.h>
#include <soc.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(spi_gd32);

#include "spi_context.h"

/* SPI error status mask. */
#define SPI_GD32_ERR_MASK	(SPI_STAT_RXORERR | SPI_STAT_CONFERR | SPI_STAT_CRCERR)

#define GD32_SPI_PSC_MAX	0x7U

#if defined(CONFIG_SOC_SERIES_GD32F4XX) || \
	defined(CONFIG_SOC_SERIES_GD32F403) || \
	defined(CONFIG_SOC_SERIES_GD32VF103) || \
	defined(CONFIG_SOC_SERIES_GD32E10X)
#define RCU_APB1EN_OFFSET	APB1EN_REG_OFFSET
#elif defined(CONFIG_SOC_SERIES_GD32F3X0)
#define RCU_APB1EN_OFFSET	IDX_APB1EN
#else
#error Unknown GD32 soc series
#endif

/* Obtain RCU register offset from RCU clock value */
#define RCU_CLOCK_OFFSET(rcu_clock) ((rcu_clock) >> 6U)

struct spi_gd32_config {
	uint32_t reg;
	uint32_t rcu_periph_clock;
	const struct pinctrl_dev_config *pcfg;
};

struct spi_gd32_data {
	struct spi_context ctx;
};

static int spi_gd32_get_err(const struct spi_gd32_config *cfg)
{
	uint32_t stat = SPI_STAT(cfg->reg);

	if (stat & SPI_GD32_ERR_MASK) {
		LOG_ERR("spi%u error status detected, err = %u",
			cfg->reg, stat & (uint32_t)SPI_GD32_ERR_MASK);

		return -EIO;
	}

	return 0;
}

static bool spi_gd32_transfer_ongoing(struct spi_gd32_data *data)
{
	return spi_context_tx_on(&data->ctx) ||
	       spi_context_rx_on(&data->ctx);
}

static uint32_t spi_gd32_bus_freq_get(uint32_t rcu_periph_clock)
{
	uint32_t rcu_bus;

	if (RCU_CLOCK_OFFSET(rcu_periph_clock) == RCU_APB1EN_OFFSET) {
		rcu_bus = CK_APB1;
	} else {
		rcu_bus = CK_APB2;
	}

	return rcu_clock_freq_get(rcu_bus);
}

static int spi_gd32_configure(const struct device *dev,
			      const struct spi_config *config)
{
	struct spi_gd32_data *data = dev->data;
	const struct spi_gd32_config *cfg = dev->config;
	uint32_t bus_freq;

	if (spi_context_configured(&data->ctx, config)) {
		return 0;
	}

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

	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_SPIEN;

	SPI_CTL0(cfg->reg) |= SPI_MASTER;
	SPI_CTL0(cfg->reg) &= ~SPI_TRANSMODE_BDTRANSMIT;

	if (SPI_WORD_SIZE_GET(config->operation) == 8) {
		SPI_CTL0(cfg->reg) |= SPI_FRAMESIZE_8BIT;
	} else {
		SPI_CTL0(cfg->reg) |= SPI_FRAMESIZE_16BIT;
	}

	/* Reset to hardware NSS mode. */
	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_SWNSSEN;
	if (config->cs != NULL) {
		SPI_CTL0(cfg->reg) |= SPI_CTL0_SWNSSEN;
	} else {
		/*
		 * For single master env,
		 * hardware NSS mode also need to set the NSSDRV bit.
		 */
		SPI_CTL1(cfg->reg) |= SPI_CTL1_NSSDRV;
	}

	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_LF;
	if (config->operation & SPI_TRANSFER_LSB) {
		SPI_CTL0(cfg->reg) |= SPI_CTL0_LF;
	}

	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_CKPL;
	if (config->operation & SPI_MODE_CPOL) {
		SPI_CTL0(cfg->reg) |= SPI_CTL0_CKPL;
	}

	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_CKPH;
	if (config->operation & SPI_MODE_CPHA) {
		SPI_CTL0(cfg->reg) |= SPI_CTL0_CKPH;
	}

	bus_freq = spi_gd32_bus_freq_get(cfg->rcu_periph_clock);

	for (uint8_t i = 0U; i <= GD32_SPI_PSC_MAX; i++) {
		bus_freq = bus_freq >> 1U;
		if (bus_freq <= config->frequency) {
			SPI_CTL0(cfg->reg) &= ~SPI_CTL0_PSC;
			SPI_CTL0(cfg->reg) |= CTL0_PSC(i);
			break;
		}
	}

	data->ctx.config = config;

	return 0;
}

static int spi_gd32_frame_exchange(const struct device *dev)
{
	struct spi_gd32_data *data = dev->data;
	const struct spi_gd32_config *cfg = dev->config;
	struct spi_context *ctx = &data->ctx;
	uint16_t tx_frame = 0U, rx_frame = 0U;

	if (SPI_WORD_SIZE_GET(ctx->config->operation) == 8) {
		if (spi_context_tx_buf_on(ctx)) {
			tx_frame = UNALIGNED_GET((uint8_t *)(data->ctx.tx_buf));
		}
		/* For 8 bits mode, spi will forced SPI_DATA[15:8] to 0. */
		SPI_DATA(cfg->reg) = tx_frame;

		spi_context_update_tx(ctx, 1, 1);
	} else {
		if (spi_context_tx_buf_on(ctx)) {
			tx_frame = UNALIGNED_GET((uint8_t *)(data->ctx.tx_buf));
		}
		SPI_DATA(cfg->reg) = tx_frame;

		spi_context_update_tx(ctx, 2, 1);
	}

	while ((SPI_STAT(cfg->reg) & SPI_STAT_RBNE) == 0) {
		/* NOP */
	}

	if (SPI_WORD_SIZE_GET(data->ctx.config->operation) == 8) {
		/* For 8 bits mode, spi will forced SPI_DATA[15:8] to 0. */
		rx_frame = SPI_DATA(cfg->reg);
		if (spi_context_rx_buf_on(ctx)) {
			UNALIGNED_PUT(rx_frame, (uint8_t *)data->ctx.rx_buf);
		}

		spi_context_update_rx(ctx, 1, 1);
	} else {
		rx_frame = SPI_DATA(cfg->reg);
		if (spi_context_rx_buf_on(ctx)) {
			UNALIGNED_PUT(rx_frame, (uint16_t *)data->ctx.rx_buf);
		}

		spi_context_update_rx(ctx, 2, 1);
	}

	return spi_gd32_get_err(cfg);
}

static int spi_gd32_transceive(const struct device *dev,
			       const struct spi_config *config,
			       const struct spi_buf_set *tx_bufs,
			       const struct spi_buf_set *rx_bufs)
{
	struct spi_gd32_data *data = dev->data;
	const struct spi_gd32_config *cfg = dev->config;
	int ret;

	spi_context_lock(&data->ctx, false, NULL, config);

	ret = spi_gd32_configure(dev, config);
	if (ret < 0) {
		goto error;
	}

	SPI_CTL0(cfg->reg) |= SPI_CTL0_SPIEN;

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

	spi_context_cs_control(&data->ctx, true);

	do {
		ret = spi_gd32_frame_exchange(dev);
		if (ret < 0) {
			break;
		}
	} while (spi_gd32_transfer_ongoing(data));

	spi_context_cs_control(&data->ctx, false);

	SPI_CTL0(cfg->reg) &= ~SPI_CTL0_SPIEN;

error:
	spi_context_release(&data->ctx, ret);

	return ret;
}

static int spi_gd32_release(const struct device *dev,
			    const struct spi_config *config)
{
	struct spi_gd32_data *data = dev->data;

	spi_context_unlock_unconditionally(&data->ctx);

	return 0;
}

static struct spi_driver_api spi_gd32_driver_api = {
	.transceive = spi_gd32_transceive,
	.release = spi_gd32_release
};

int spi_gd32_init(const struct device *dev)
{
	struct spi_gd32_data *data = dev->data;
	const struct spi_gd32_config *cfg = dev->config;
	int ret;

	rcu_periph_clock_enable(cfg->rcu_periph_clock);

	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
	if (ret) {
		LOG_ERR("Failed to apply pinctrl state");
		return ret;
	}

	ret = spi_context_cs_configure_all(&data->ctx);
	if (ret < 0) {
		return ret;
	}

	spi_context_unlock_unconditionally(&data->ctx);

	return 0;
}

#define GD32_SPI_INIT(idx)							\
	PINCTRL_DT_INST_DEFINE(idx);						\
	static struct spi_gd32_data spi_gd32_data_##idx = {			\
		SPI_CONTEXT_INIT_LOCK(spi_gd32_data_##idx, ctx),		\
		SPI_CONTEXT_INIT_SYNC(spi_gd32_data_##idx, ctx),		\
		SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(idx), ctx)		\
	};									\
	static struct spi_gd32_config spi_gd32_config_##idx = {			\
		.reg = DT_INST_REG_ADDR(idx),					\
		.rcu_periph_clock = DT_INST_PROP(idx, rcu_periph_clock),	\
		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),			\
	};									\
	DEVICE_DT_INST_DEFINE(idx, &spi_gd32_init, NULL, &spi_gd32_data_##idx,	\
			      &spi_gd32_config_##idx, POST_KERNEL,		\
			      CONFIG_SPI_INIT_PRIORITY, &spi_gd32_driver_api);

DT_INST_FOREACH_STATUS_OKAY(GD32_SPI_INIT)
