// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2015 Marvell International Ltd.
 *
 * Copyright (C) 2016 Stefan Roese <sr@denx.de>
 */

#include <dm.h>
#include <log.h>
#include <malloc.h>
#include <spi.h>
#include <clk.h>
#include <wait_bit.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <asm/gpio.h>

DECLARE_GLOBAL_DATA_PTR;

#define MVEBU_SPI_A3700_XFER_RDY		BIT(1)
#define MVEBU_SPI_A3700_FIFO_FLUSH		BIT(9)
#define MVEBU_SPI_A3700_BYTE_LEN		BIT(5)
#define MVEBU_SPI_A3700_CLK_PHA			BIT(6)
#define MVEBU_SPI_A3700_CLK_POL			BIT(7)
#define MVEBU_SPI_A3700_FIFO_EN			BIT(17)
#define MVEBU_SPI_A3700_SPI_EN_0		BIT(16)
#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK	0x1f

#define MAX_CS_COUNT	4

/* SPI registers */
struct spi_reg {
	u32 ctrl;	/* 0x10600 */
	u32 cfg;	/* 0x10604 */
	u32 dout;	/* 0x10608 */
	u32 din;	/* 0x1060c */
};

struct mvebu_spi_plat {
	struct spi_reg *spireg;
	struct clk clk;
	struct gpio_desc cs_gpios[MAX_CS_COUNT];
};

static void spi_cs_activate(struct mvebu_spi_plat *plat, int cs)
{
	if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&plat->cs_gpios[cs]))
		dm_gpio_set_value(&plat->cs_gpios[cs], 1);
	else
		setbits_le32(&plat->spireg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
}

static void spi_cs_deactivate(struct mvebu_spi_plat *plat, int cs)
{
	if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&plat->cs_gpios[cs]))
		dm_gpio_set_value(&plat->cs_gpios[cs], 0);
	else
		clrbits_le32(&plat->spireg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
}

/**
 * spi_legacy_shift_byte() - triggers the real SPI transfer
 * @bytelen:	Indicate how many bytes to transfer.
 * @dout:	Buffer address of what to send.
 * @din:	Buffer address of where to receive.
 *
 * This function triggers the real SPI transfer in legacy mode. It
 * will shift out char buffer from @dout, and shift in char buffer to
 * @din, if necessary.
 *
 * This function assumes that only one byte is shifted at one time.
 * However, it is not its responisbility to set the transfer type to
 * one-byte. Also, it does not guarantee that it will work if transfer
 * type becomes two-byte. See spi_set_legacy() for details.
 *
 * In legacy mode, simply write to the SPI_DOUT register will trigger
 * the transfer.
 *
 * If @dout == NULL, which means no actual data needs to be sent out,
 * then the function will shift out 0x00 in order to shift in data.
 * The XFER_RDY flag is checked every time before accessing SPI_DOUT
 * and SPI_DIN register.
 *
 * The number of transfers to be triggered is decided by @bytelen.
 *
 * Return:	0 - cool
 *		-ETIMEDOUT - XFER_RDY flag timeout
 */
static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
				 const void *dout, void *din)
{
	const u8 *dout_8;
	u8 *din_8;
	int ret;

	/* Use 0x00 as dummy dout */
	const u8 dummy_dout = 0x0;
	u32 pending_dout = 0x0;

	/* dout_8: pointer of current dout */
	dout_8 = dout;
	/* din_8: pointer of current din */
	din_8 = din;

	while (bytelen) {
		ret = wait_for_bit_le32(&reg->ctrl,
					MVEBU_SPI_A3700_XFER_RDY,
					true,100, false);
		if (ret)
			return ret;

		if (dout)
			pending_dout = (u32)*dout_8;
		else
			pending_dout = (u32)dummy_dout;

		/* Trigger the xfer */
		writel(pending_dout, &reg->dout);

		if (din) {
			ret = wait_for_bit_le32(&reg->ctrl,
						MVEBU_SPI_A3700_XFER_RDY,
						true, 100, false);
			if (ret)
				return ret;

			/* Read what is transferred in */
			*din_8 = (u8)readl(&reg->din);
		}

		/* Don't increment the current pointer if NULL */
		if (dout)
			dout_8++;
		if (din)
			din_8++;

		bytelen--;
	}

	return 0;
}

static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
			  const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;
	struct mvebu_spi_plat *plat = dev_get_plat(bus);
	struct spi_reg *reg = plat->spireg;
	unsigned int bytelen;
	int ret;

	bytelen = bitlen / 8;

	if (dout && din)
		debug("This is a duplex transfer.\n");

	/* Activate CS */
	if (flags & SPI_XFER_BEGIN) {
		debug("SPI: activate cs.\n");
		spi_cs_activate(plat, spi_chip_select(dev));
	}

	/* Send and/or receive */
	if (dout || din) {
		ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
		if (ret)
			return ret;
	}

	/* Deactivate CS */
	if (flags & SPI_XFER_END) {
		ret = wait_for_bit_le32(&reg->ctrl,
					MVEBU_SPI_A3700_XFER_RDY,
					true, 100, false);
		if (ret)
			return ret;

		debug("SPI: deactivate cs.\n");
		spi_cs_deactivate(plat, spi_chip_select(dev));
	}

	return 0;
}

static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
{
	struct mvebu_spi_plat *plat = dev_get_plat(bus);
	struct spi_reg *reg = plat->spireg;
	u32 data, prescale;

	data = readl(&reg->cfg);

	prescale = DIV_ROUND_UP(clk_get_rate(&plat->clk), hz);
	if (prescale > 0xf)
		prescale = 0x10 + (prescale + 1) / 2;
	prescale = min(prescale, 0x1fu);

	data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
	data |= prescale & MVEBU_SPI_A3700_CLK_PRESCALE_MASK;

	writel(data, &reg->cfg);

	return 0;
}

static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
{
	struct mvebu_spi_plat *plat = dev_get_plat(bus);
	struct spi_reg *reg = plat->spireg;

	/*
	 * Set SPI polarity
	 * 0: Serial interface clock is low when inactive
	 * 1: Serial interface clock is high when inactive
	 */
	if (mode & SPI_CPOL)
		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
	else
		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
	if (mode & SPI_CPHA)
		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
	else
		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);

	return 0;
}

static int mvebu_spi_probe(struct udevice *bus)
{
	struct mvebu_spi_plat *plat = dev_get_plat(bus);
	struct spi_reg *reg = plat->spireg;
	u32 data;
	int ret;

	/*
	 * Settings SPI controller to be working in legacy mode, which
	 * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
	 * for Data In.
	 */

	/* Flush read/write FIFO */
	data = readl(&reg->cfg);
	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
	ret = wait_for_bit_le32(&reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
				false, 1000, false);
	if (ret)
		return ret;

	/* Disable FIFO mode */
	data &= ~MVEBU_SPI_A3700_FIFO_EN;

	/* Always shift 1 byte at a time */
	data &= ~MVEBU_SPI_A3700_BYTE_LEN;

	writel(data, &reg->cfg);

	/* Set up CS GPIOs in device tree, if any */
	if (CONFIG_IS_ENABLED(DM_GPIO) && gpio_get_list_count(bus, "cs-gpios") > 0) {
		int i;

		for (i = 0; i < ARRAY_SIZE(plat->cs_gpios); i++) {
			ret = gpio_request_by_name(bus, "cs-gpios", i, &plat->cs_gpios[i], 0);
			if (ret < 0 || !dm_gpio_is_valid(&plat->cs_gpios[i])) {
				/* Use the native CS function for this line */
				continue;
			}

			ret = dm_gpio_set_dir_flags(&plat->cs_gpios[i],
						    GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
			if (ret) {
				dev_err(bus, "Setting cs %d error\n", i);
				return ret;
			}
		}
	}

	return 0;
}

static int mvebu_spi_of_to_plat(struct udevice *bus)
{
	struct mvebu_spi_plat *plat = dev_get_plat(bus);
	int ret;

	plat->spireg = dev_read_addr_ptr(bus);

	ret = clk_get_by_index(bus, 0, &plat->clk);
	if (ret) {
		dev_err(bus, "cannot get clock\n");
		return ret;
	}

	return 0;
}

static const struct dm_spi_ops mvebu_spi_ops = {
	.xfer		= mvebu_spi_xfer,
	.set_speed	= mvebu_spi_set_speed,
	.set_mode	= mvebu_spi_set_mode,
	/*
	 * cs_info is not needed, since we require all chip selects to be
	 * in the device tree explicitly
	 */
};

static const struct udevice_id mvebu_spi_ids[] = {
	{ .compatible = "marvell,armada-3700-spi" },
	{ }
};

U_BOOT_DRIVER(mvebu_spi) = {
	.name = "mvebu_spi",
	.id = UCLASS_SPI,
	.of_match = mvebu_spi_ids,
	.ops = &mvebu_spi_ops,
	.of_to_plat = mvebu_spi_of_to_plat,
	.plat_auto	= sizeof(struct mvebu_spi_plat),
	.probe = mvebu_spi_probe,
};
