// SPDX-License-Identifier: GPL-2.0
/*
 * SPI bus driver for the Ingenic SoCs
 * Copyright (c) 2017-2021 Artur Rojek <contact@artur-rojek.eu>
 * Copyright (c) 2017-2021 Paul Cercueil <paul@crapouillou.net>
 * Copyright (c) 2022 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>

#define REG_SSIDR	0x0
#define REG_SSICR0	0x4
#define REG_SSICR1	0x8
#define REG_SSISR	0xc
#define REG_SSIGR	0x18

#define REG_SSICR0_TENDIAN_LSB		BIT(19)
#define REG_SSICR0_RENDIAN_LSB		BIT(17)
#define REG_SSICR0_SSIE			BIT(15)
#define REG_SSICR0_LOOP			BIT(10)
#define REG_SSICR0_EACLRUN		BIT(7)
#define REG_SSICR0_FSEL			BIT(6)
#define REG_SSICR0_TFLUSH		BIT(2)
#define REG_SSICR0_RFLUSH		BIT(1)

#define REG_SSICR1_FRMHL_MASK		(BIT(31) | BIT(30))
#define REG_SSICR1_FRMHL		BIT(30)
#define REG_SSICR1_LFST			BIT(25)
#define REG_SSICR1_UNFIN		BIT(23)
#define REG_SSICR1_PHA			BIT(1)
#define REG_SSICR1_POL			BIT(0)

#define REG_SSISR_END			BIT(7)
#define REG_SSISR_BUSY			BIT(6)
#define REG_SSISR_TFF			BIT(5)
#define REG_SSISR_RFE			BIT(4)
#define REG_SSISR_RFHF			BIT(2)
#define REG_SSISR_UNDR			BIT(1)
#define REG_SSISR_OVER			BIT(0)

#define SPI_INGENIC_FIFO_SIZE		128u

struct jz_soc_info {
	u32 bits_per_word_mask;
	struct reg_field flen_field;
	bool has_trendian;

	unsigned int max_speed_hz;
	unsigned int max_native_cs;
};

struct ingenic_spi {
	const struct jz_soc_info *soc_info;
	struct clk *clk;
	struct resource *mem_res;

	struct regmap *map;
	struct regmap_field *flen_field;
};

static int spi_ingenic_wait(struct ingenic_spi *priv,
			    unsigned long mask,
			    bool condition)
{
	unsigned int val;

	return regmap_read_poll_timeout(priv->map, REG_SSISR, val,
					!!(val & mask) == condition,
					100, 10000);
}

static void spi_ingenic_set_cs(struct spi_device *spi, bool disable)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(spi->controller);

	if (disable) {
		regmap_clear_bits(priv->map, REG_SSICR1, REG_SSICR1_UNFIN);
		regmap_clear_bits(priv->map, REG_SSISR,
				  REG_SSISR_UNDR | REG_SSISR_OVER);

		spi_ingenic_wait(priv, REG_SSISR_END, true);
	} else {
		regmap_set_bits(priv->map, REG_SSICR1, REG_SSICR1_UNFIN);
	}

	regmap_set_bits(priv->map, REG_SSICR0,
			REG_SSICR0_RFLUSH | REG_SSICR0_TFLUSH);
}

static void spi_ingenic_prepare_transfer(struct ingenic_spi *priv,
					 struct spi_device *spi,
					 struct spi_transfer *xfer)
{
	unsigned long clk_hz = clk_get_rate(priv->clk);
	u32 cdiv, speed_hz = xfer->speed_hz ?: spi->max_speed_hz,
	    bits_per_word = xfer->bits_per_word ?: spi->bits_per_word;

	cdiv = clk_hz / (speed_hz * 2);
	cdiv = clamp(cdiv, 1u, 0x100u) - 1;

	regmap_write(priv->map, REG_SSIGR, cdiv);

	regmap_field_write(priv->flen_field, bits_per_word - 2);
}

static void spi_ingenic_finalize_transfer(void *controller)
{
	spi_finalize_current_transfer(controller);
}

static struct dma_async_tx_descriptor *
spi_ingenic_prepare_dma(struct spi_controller *ctlr, struct dma_chan *chan,
			struct sg_table *sg, enum dma_transfer_direction dir,
			unsigned int bits)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);
	struct dma_slave_config cfg = {
		.direction = dir,
		.src_addr = priv->mem_res->start + REG_SSIDR,
		.dst_addr = priv->mem_res->start + REG_SSIDR,
	};
	struct dma_async_tx_descriptor *desc;
	dma_cookie_t cookie;
	int ret;

	if (bits > 16) {
		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		cfg.src_maxburst = cfg.dst_maxburst = 4;
	} else if (bits > 8) {
		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
		cfg.src_maxburst = cfg.dst_maxburst = 2;
	} else {
		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
		cfg.src_maxburst = cfg.dst_maxburst = 1;
	}

	ret = dmaengine_slave_config(chan, &cfg);
	if (ret)
		return ERR_PTR(ret);

	desc = dmaengine_prep_slave_sg(chan, sg->sgl, sg->nents, dir,
				       DMA_PREP_INTERRUPT);
	if (!desc)
		return ERR_PTR(-ENOMEM);

	if (dir == DMA_DEV_TO_MEM) {
		desc->callback = spi_ingenic_finalize_transfer;
		desc->callback_param = ctlr;
	}

	cookie = dmaengine_submit(desc);

	ret = dma_submit_error(cookie);
	if (ret) {
		dmaengine_desc_free(desc);
		return ERR_PTR(ret);
	}

	return desc;
}

static int spi_ingenic_dma_tx(struct spi_controller *ctlr,
			      struct spi_transfer *xfer, unsigned int bits)
{
	struct dma_async_tx_descriptor *rx_desc, *tx_desc;

	rx_desc = spi_ingenic_prepare_dma(ctlr, ctlr->dma_rx,
					  &xfer->rx_sg, DMA_DEV_TO_MEM, bits);
	if (IS_ERR(rx_desc))
		return PTR_ERR(rx_desc);

	tx_desc = spi_ingenic_prepare_dma(ctlr, ctlr->dma_tx,
					  &xfer->tx_sg, DMA_MEM_TO_DEV, bits);
	if (IS_ERR(tx_desc)) {
		dmaengine_terminate_async(ctlr->dma_rx);
		dmaengine_desc_free(rx_desc);
		return PTR_ERR(tx_desc);
	}

	dma_async_issue_pending(ctlr->dma_rx);
	dma_async_issue_pending(ctlr->dma_tx);

	return 1;
}

#define SPI_INGENIC_TX(x)							\
static int spi_ingenic_tx##x(struct ingenic_spi *priv,				\
			     struct spi_transfer *xfer)				\
{										\
	unsigned int count = xfer->len / (x / 8);				\
	unsigned int prefill = min(count, SPI_INGENIC_FIFO_SIZE);		\
	const u##x *tx_buf = xfer->tx_buf;					\
	u##x *rx_buf = xfer->rx_buf;						\
	unsigned int i, val;							\
	int err;								\
										\
	/* Fill up the TX fifo */						\
	for (i = 0; i < prefill; i++) {						\
		val = tx_buf ? tx_buf[i] : 0;					\
										\
		regmap_write(priv->map, REG_SSIDR, val);			\
	}									\
										\
	for (i = 0; i < count; i++) {						\
		err = spi_ingenic_wait(priv, REG_SSISR_RFE, false);		\
		if (err)							\
			return err;						\
										\
		regmap_read(priv->map, REG_SSIDR, &val);			\
		if (rx_buf)							\
			rx_buf[i] = val;					\
										\
		if (i < count - prefill) {					\
			val = tx_buf ? tx_buf[i + prefill] : 0;			\
										\
			regmap_write(priv->map, REG_SSIDR, val);		\
		}								\
	}									\
										\
	return 0;								\
}
SPI_INGENIC_TX(8)
SPI_INGENIC_TX(16)
SPI_INGENIC_TX(32)
#undef SPI_INGENIC_TX

static int spi_ingenic_transfer_one(struct spi_controller *ctlr,
				    struct spi_device *spi,
				    struct spi_transfer *xfer)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);
	unsigned int bits = xfer->bits_per_word ?: spi->bits_per_word;
	bool can_dma = ctlr->can_dma && ctlr->can_dma(ctlr, spi, xfer);

	spi_ingenic_prepare_transfer(priv, spi, xfer);

	if (ctlr->cur_msg_mapped && can_dma)
		return spi_ingenic_dma_tx(ctlr, xfer, bits);

	if (bits > 16)
		return spi_ingenic_tx32(priv, xfer);

	if (bits > 8)
		return spi_ingenic_tx16(priv, xfer);

	return spi_ingenic_tx8(priv, xfer);
}

static int spi_ingenic_prepare_message(struct spi_controller *ctlr,
				       struct spi_message *message)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);
	struct spi_device *spi = message->spi;
	unsigned int cs = REG_SSICR1_FRMHL << spi->chip_select;
	unsigned int ssicr0_mask = REG_SSICR0_LOOP | REG_SSICR0_FSEL;
	unsigned int ssicr1_mask = REG_SSICR1_PHA | REG_SSICR1_POL | cs;
	unsigned int ssicr0 = 0, ssicr1 = 0;

	if (priv->soc_info->has_trendian) {
		ssicr0_mask |= REG_SSICR0_RENDIAN_LSB | REG_SSICR0_TENDIAN_LSB;

		if (spi->mode & SPI_LSB_FIRST)
			ssicr0 |= REG_SSICR0_RENDIAN_LSB | REG_SSICR0_TENDIAN_LSB;
	} else {
		ssicr1_mask |= REG_SSICR1_LFST;

		if (spi->mode & SPI_LSB_FIRST)
			ssicr1 |= REG_SSICR1_LFST;
	}

	if (spi->mode & SPI_LOOP)
		ssicr0 |= REG_SSICR0_LOOP;
	if (spi->chip_select)
		ssicr0 |= REG_SSICR0_FSEL;

	if (spi->mode & SPI_CPHA)
		ssicr1 |= REG_SSICR1_PHA;
	if (spi->mode & SPI_CPOL)
		ssicr1 |= REG_SSICR1_POL;
	if (spi->mode & SPI_CS_HIGH)
		ssicr1 |= cs;

	regmap_update_bits(priv->map, REG_SSICR0, ssicr0_mask, ssicr0);
	regmap_update_bits(priv->map, REG_SSICR1, ssicr1_mask, ssicr1);

	return 0;
}

static int spi_ingenic_prepare_hardware(struct spi_controller *ctlr)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);
	int ret;

	ret = clk_prepare_enable(priv->clk);
	if (ret)
		return ret;

	regmap_write(priv->map, REG_SSICR0, REG_SSICR0_EACLRUN);
	regmap_write(priv->map, REG_SSICR1, 0);
	regmap_write(priv->map, REG_SSISR, 0);
	regmap_set_bits(priv->map, REG_SSICR0, REG_SSICR0_SSIE);

	return 0;
}

static int spi_ingenic_unprepare_hardware(struct spi_controller *ctlr)
{
	struct ingenic_spi *priv = spi_controller_get_devdata(ctlr);

	regmap_clear_bits(priv->map, REG_SSICR0, REG_SSICR0_SSIE);

	clk_disable_unprepare(priv->clk);

	return 0;
}

static bool spi_ingenic_can_dma(struct spi_controller *ctlr,
				struct spi_device *spi,
				struct spi_transfer *xfer)
{
	struct dma_slave_caps caps;
	int ret;

	ret = dma_get_slave_caps(ctlr->dma_tx, &caps);
	if (ret) {
		dev_err(&spi->dev, "Unable to get slave caps: %d\n", ret);
		return false;
	}

	return !caps.max_sg_burst ||
		xfer->len <= caps.max_sg_burst * SPI_INGENIC_FIFO_SIZE;
}

static int spi_ingenic_request_dma(struct spi_controller *ctlr,
				   struct device *dev)
{
	ctlr->dma_tx = dma_request_slave_channel(dev, "tx");
	if (!ctlr->dma_tx)
		return -ENODEV;

	ctlr->dma_rx = dma_request_slave_channel(dev, "rx");

	if (!ctlr->dma_rx)
		return -ENODEV;

	ctlr->can_dma = spi_ingenic_can_dma;

	return 0;
}

static void spi_ingenic_release_dma(void *data)
{
	struct spi_controller *ctlr = data;

	if (ctlr->dma_tx)
		dma_release_channel(ctlr->dma_tx);
	if (ctlr->dma_rx)
		dma_release_channel(ctlr->dma_rx);
}

static const struct regmap_config spi_ingenic_regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
	.max_register = REG_SSIGR,
};

static int spi_ingenic_probe(struct platform_device *pdev)
{
	const struct jz_soc_info *pdata;
	struct device *dev = &pdev->dev;
	struct spi_controller *ctlr;
	struct ingenic_spi *priv;
	void __iomem *base;
	int num_cs, ret;

	pdata = of_device_get_match_data(dev);
	if (!pdata) {
		dev_err(dev, "Missing platform data.\n");
		return -EINVAL;
	}

	ctlr = devm_spi_alloc_master(dev, sizeof(*priv));
	if (!ctlr) {
		dev_err(dev, "Unable to allocate SPI controller.\n");
		return -ENOMEM;
	}

	priv = spi_controller_get_devdata(ctlr);
	priv->soc_info = pdata;

	priv->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->clk)) {
		return dev_err_probe(dev, PTR_ERR(priv->clk),
				     "Unable to get clock.\n");
	}

	base = devm_platform_get_and_ioremap_resource(pdev, 0, &priv->mem_res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	priv->map = devm_regmap_init_mmio(dev, base, &spi_ingenic_regmap_config);
	if (IS_ERR(priv->map))
		return PTR_ERR(priv->map);

	priv->flen_field = devm_regmap_field_alloc(dev, priv->map,
						   pdata->flen_field);
	if (IS_ERR(priv->flen_field))
		return PTR_ERR(priv->flen_field);

	if (device_property_read_u32(dev, "num-cs", &num_cs))
		num_cs = pdata->max_native_cs;

	platform_set_drvdata(pdev, ctlr);

	ctlr->prepare_transfer_hardware = spi_ingenic_prepare_hardware;
	ctlr->unprepare_transfer_hardware = spi_ingenic_unprepare_hardware;
	ctlr->prepare_message = spi_ingenic_prepare_message;
	ctlr->set_cs = spi_ingenic_set_cs;
	ctlr->transfer_one = spi_ingenic_transfer_one;
	ctlr->mode_bits = SPI_MODE_3 | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH;
	ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX;
	ctlr->max_dma_len = SPI_INGENIC_FIFO_SIZE;
	ctlr->bits_per_word_mask = pdata->bits_per_word_mask;
	ctlr->min_speed_hz = 7200;
	ctlr->max_speed_hz = pdata->max_speed_hz;
	ctlr->use_gpio_descriptors = true;
	ctlr->max_native_cs = pdata->max_native_cs;
	ctlr->num_chipselect = num_cs;
	ctlr->dev.of_node = pdev->dev.of_node;

	if (spi_ingenic_request_dma(ctlr, dev))
		dev_warn(dev, "DMA not available.\n");

	ret = devm_add_action_or_reset(dev, spi_ingenic_release_dma, ctlr);
	if (ret) {
		dev_err(dev, "Unable to add action.\n");
		return ret;
	}

	ret = devm_spi_register_controller(dev, ctlr);
	if (ret)
		dev_err(dev, "Unable to register SPI controller.\n");

	return ret;
}

static const struct jz_soc_info jz4750_soc_info = {
	.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 17),
	.flen_field = REG_FIELD(REG_SSICR1, 4, 7),
	.has_trendian = false,

	.max_speed_hz = 54000000,
	.max_native_cs = 2,
};

static const struct jz_soc_info jz4780_soc_info = {
	.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
	.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
	.has_trendian = true,

	.max_speed_hz = 54000000,
	.max_native_cs = 2,
};

static const struct jz_soc_info x1000_soc_info = {
	.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
	.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
	.has_trendian = true,

	.max_speed_hz = 50000000,
	.max_native_cs = 2,
};

static const struct jz_soc_info x2000_soc_info = {
	.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
	.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
	.has_trendian = true,

	.max_speed_hz = 50000000,
	.max_native_cs = 1,
};

static const struct of_device_id spi_ingenic_of_match[] = {
	{ .compatible = "ingenic,jz4750-spi", .data = &jz4750_soc_info },
	{ .compatible = "ingenic,jz4775-spi", .data = &jz4780_soc_info },
	{ .compatible = "ingenic,jz4780-spi", .data = &jz4780_soc_info },
	{ .compatible = "ingenic,x1000-spi", .data = &x1000_soc_info },
	{ .compatible = "ingenic,x2000-spi", .data = &x2000_soc_info },
	{}
};
MODULE_DEVICE_TABLE(of, spi_ingenic_of_match);

static struct platform_driver spi_ingenic_driver = {
	.driver = {
		.name = "spi-ingenic",
		.of_match_table = spi_ingenic_of_match,
	},
	.probe = spi_ingenic_probe,
};

module_platform_driver(spi_ingenic_driver);
MODULE_DESCRIPTION("SPI bus driver for the Ingenic SoCs");
MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
MODULE_LICENSE("GPL");
