// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2018 Stefan Roese <sr@denx.de>
 *
 * Derived from the Linux driver version drivers/spi/spi-mt7621.c
 *   Copyright (C) 2011 Sergiy <piratfm@gmail.com>
 *   Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org>
 *   Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name>
 */

#include <common.h>
#include <clk.h>
#include <dm.h>
#include <log.h>
#include <spi.h>
#include <wait_bit.h>
#include <linux/io.h>

#define MT7621_RX_FIFO_LEN	32
#define MT7621_TX_FIFO_LEN	36

#define MT7621_SPI_TRANS	0x00
#define MT7621_SPI_TRANS_START	BIT(8)
#define MT7621_SPI_TRANS_BUSY	BIT(16)
#define TRANS_ADDR_SZ		GENMASK(20, 19)
#define TRANS_ADDR_SZ_SHIFT	19
#define TRANS_MOSI_BCNT		GENMASK(3, 0)
#define TRANS_MOSI_BCNT_SHIFT	0

#define MT7621_SPI_OPCODE	0x04
#define MT7621_SPI_DATA0	0x08
#define MT7621_SPI_DATA4	0x18
#define MT7621_SPI_MASTER	0x28
#define MT7621_SPI_MOREBUF	0x2c
#define MT7621_SPI_POLAR	0x38

#define MT7621_LSB_FIRST	BIT(3)
#define MT7621_CPOL		BIT(4)
#define MT7621_CPHA		BIT(5)

#define MASTER_MORE_BUFMODE	BIT(2)
#define MASTER_RS_CLK_SEL	GENMASK(27, 16)
#define MASTER_RS_CLK_SEL_SHIFT	16
#define MASTER_RS_SLAVE_SEL	GENMASK(31, 29)

#define MOREBUF_CMD_CNT		GENMASK(29, 24)
#define MOREBUF_CMD_CNT_SHIFT	24
#define MOREBUF_MISO_CNT	GENMASK(20, 12)
#define MOREBUF_MISO_CNT_SHIFT	12
#define MOREBUF_MOSI_CNT	GENMASK(8, 0)
#define MOREBUF_MOSI_CNT_SHIFT	0

struct mt7621_spi {
	void __iomem *base;
	unsigned int sys_freq;
};

static void mt7621_spi_set_cs(struct mt7621_spi *rs, int cs, int enable)
{
	debug("%s: cs#%d -> %s\n", __func__, cs, enable ? "enable" : "disable");

	if (enable) {
		setbits_le32(rs->base + MT7621_SPI_MASTER,
			     MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE);
		iowrite32(BIT(cs), rs->base + MT7621_SPI_POLAR);
	} else {
		iowrite32(0, rs->base + MT7621_SPI_POLAR);
		iowrite32((2 << TRANS_ADDR_SZ_SHIFT) |
			  (1 << TRANS_MOSI_BCNT_SHIFT),
			  rs->base + MT7621_SPI_TRANS);
		clrbits_le32(rs->base + MT7621_SPI_MASTER,
			     MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE);
	}
}

static int mt7621_spi_set_mode(struct udevice *bus, uint mode)
{
	struct mt7621_spi *rs = dev_get_priv(bus);
	u32 reg;

	debug("%s: mode=0x%08x\n", __func__, mode);
	reg = ioread32(rs->base + MT7621_SPI_MASTER);

	reg &= ~MT7621_LSB_FIRST;
	if (mode & SPI_LSB_FIRST)
		reg |= MT7621_LSB_FIRST;

	reg &= ~(MT7621_CPHA | MT7621_CPOL);
	switch (mode & (SPI_CPOL | SPI_CPHA)) {
	case SPI_MODE_0:
		break;
	case SPI_MODE_1:
		reg |= MT7621_CPHA;
		break;
	case SPI_MODE_2:
		reg |= MT7621_CPOL;
		break;
	case SPI_MODE_3:
		reg |= MT7621_CPOL | MT7621_CPHA;
		break;
	}
	iowrite32(reg, rs->base + MT7621_SPI_MASTER);

	return 0;
}

static int mt7621_spi_set_speed(struct udevice *bus, uint speed)
{
	struct mt7621_spi *rs = dev_get_priv(bus);
	u32 rate;
	u32 reg;

	debug("%s: speed=%d\n", __func__, speed);
	rate = DIV_ROUND_UP(rs->sys_freq, speed);
	debug("rate:%u\n", rate);

	if (rate > 4097)
		return -EINVAL;

	if (rate < 2)
		rate = 2;

	reg = ioread32(rs->base + MT7621_SPI_MASTER);
	reg &= ~MASTER_RS_CLK_SEL;
	reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT;
	iowrite32(reg, rs->base + MT7621_SPI_MASTER);

	return 0;
}

static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
{
	int ret;

	ret =  wait_for_bit_le32(rs->base + MT7621_SPI_TRANS,
				 MT7621_SPI_TRANS_BUSY, 0, 10, 0);
	if (ret)
		pr_err("Timeout in %s!\n", __func__);

	return ret;
}

static int mt7621_spi_read(struct mt7621_spi *rs, u8 *buf, size_t len)
{
	size_t rx_len;
	int i, ret;
	u32 val = 0;

	while (len) {
		rx_len = min_t(size_t, len, MT7621_RX_FIFO_LEN);

		iowrite32((rx_len * 8) << MOREBUF_MISO_CNT_SHIFT,
			  rs->base + MT7621_SPI_MOREBUF);
		iowrite32(MT7621_SPI_TRANS_START, rs->base + MT7621_SPI_TRANS);

		ret = mt7621_spi_wait_till_ready(rs);
		if (ret)
			return ret;

		for (i = 0; i < rx_len; i++) {
			if ((i % 4) == 0)
				val = ioread32(rs->base + MT7621_SPI_DATA0 + i);
			*buf++ = val & 0xff;
			val >>= 8;
		}

		len -= rx_len;
	}

	return ret;
}

static int mt7621_spi_write(struct mt7621_spi *rs, const u8 *buf, size_t len)
{
	size_t tx_len, opcode_len, dido_len;
	int i, ret;
	u32 val;

	while (len) {
		tx_len = min_t(size_t, len, MT7621_TX_FIFO_LEN);

		opcode_len = min_t(size_t, tx_len, 4);
		dido_len = tx_len - opcode_len;

		val = 0;
		for (i = 0; i < opcode_len; i++) {
			val <<= 8;
			val |= *buf++;
		}

		iowrite32(val, rs->base + MT7621_SPI_OPCODE);

		val = 0;
		for (i = 0; i < dido_len; i++) {
			val |= (*buf++) << ((i % 4) * 8);

			if ((i % 4 == 3) || (i == dido_len - 1)) {
				iowrite32(val, rs->base + MT7621_SPI_DATA0 +
					  (i & ~3));
				val = 0;
			}
		}

		iowrite32(((opcode_len * 8) << MOREBUF_CMD_CNT_SHIFT) |
			  ((dido_len * 8) << MOREBUF_MOSI_CNT_SHIFT),
			  rs->base + MT7621_SPI_MOREBUF);
		iowrite32(MT7621_SPI_TRANS_START, rs->base + MT7621_SPI_TRANS);

		ret = mt7621_spi_wait_till_ready(rs);
		if (ret)
			return ret;

		len -= tx_len;
	}

	return 0;
}

static int mt7621_spi_xfer(struct udevice *dev, unsigned int bitlen,
			   const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;
	struct mt7621_spi *rs = dev_get_priv(bus);
	int total_size = bitlen >> 3;
	int ret = 0;

	debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din,
	      total_size, flags);

	/*
	 * This driver only supports half-duplex, so complain and bail out
	 * upon full-duplex messages
	 */
	if (dout && din) {
		printf("Only half-duplex SPI transfer supported\n");
		return -EIO;
	}

	mt7621_spi_wait_till_ready(rs);

	/*
	 * Set CS active upon start of SPI message. This message can
	 * be split upon multiple calls to this xfer function
	 */
	if (flags & SPI_XFER_BEGIN)
		mt7621_spi_set_cs(rs, spi_chip_select(dev), 1);

	if (din)
		ret = mt7621_spi_read(rs, din, total_size);
	else if (dout)
		ret = mt7621_spi_write(rs, dout, total_size);

	if (flags & SPI_XFER_END)
		mt7621_spi_set_cs(rs, spi_chip_select(dev), 0);

	return ret;
}

static int mt7621_spi_probe(struct udevice *dev)
{
	struct mt7621_spi *rs = dev_get_priv(dev);
	struct clk clk;
	int ret;

	rs->base = dev_remap_addr(dev);
	if (!rs->base)
		return -EINVAL;

	ret = clk_get_by_index(dev, 0, &clk);
	if (ret < 0) {
		printf("Please provide a clock!\n");
		return ret;
	}

	clk_enable(&clk);

	rs->sys_freq = clk_get_rate(&clk);
	if (!rs->sys_freq) {
		printf("Please provide a valid clock!\n");
		return -EINVAL;
	}

	return 0;
}

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

static const struct udevice_id mt7621_spi_ids[] = {
	{ .compatible = "ralink,mt7621-spi" },
	{ }
};

U_BOOT_DRIVER(mt7621_spi) = {
	.name = "mt7621_spi",
	.id = UCLASS_SPI,
	.of_match = mt7621_spi_ids,
	.ops = &mt7621_spi_ops,
	.priv_auto_alloc_size = sizeof(struct mt7621_spi),
	.probe = mt7621_spi_probe,
};
