// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (c) 2021 Nuvoton Technology.
 */

#include <common.h>
#include <dm.h>
#include <spi.h>
#include <clk.h>
#include <asm/gpio.h>
#include <linux/iopoll.h>

#define MAX_DIV	127

/* Register offsets */
#define PSPI_DATA		0
#define PSPI_CTL1		2
#define PSPI_STAT		4

/* PSPI_CTL1 fields */
#define PSPI_CTL1_SPIEN		BIT(0)
#define PSPI_CTL1_SCM		BIT(7)
#define PSPI_CTL1_SCIDL		BIT(8)
#define PSPI_CTL1_SCDV_MASK	GENMASK(15, 9)
#define PSPI_CTL1_SCDV_SHIFT	9

/* PSPI_STAT fields */
#define PSPI_STAT_BSY		BIT(0)
#define PSPI_STAT_RBF		BIT(1)

struct npcm_pspi_priv {
	void __iomem *base;
	struct clk clk;
	struct gpio_desc cs_gpio;
	u32 max_hz;
};

static inline void spi_cs_activate(struct udevice *dev)
{
	struct udevice *bus = dev->parent;
	struct npcm_pspi_priv *priv = dev_get_priv(bus);

	dm_gpio_set_value(&priv->cs_gpio, 0);
}

static inline void spi_cs_deactivate(struct udevice *dev)
{
	struct udevice *bus = dev->parent;
	struct npcm_pspi_priv *priv = dev_get_priv(bus);

	dm_gpio_set_value(&priv->cs_gpio, 1);
}

static inline void npcm_pspi_enable(struct npcm_pspi_priv *priv)
{
	u16 val;

	val = readw(priv->base + PSPI_CTL1);
	val |= PSPI_CTL1_SPIEN;
	writew(val, priv->base + PSPI_CTL1);
}

static inline void npcm_pspi_disable(struct npcm_pspi_priv *priv)
{
	u16 val;

	val = readw(priv->base + PSPI_CTL1);
	val &= ~PSPI_CTL1_SPIEN;
	writew(val, priv->base + PSPI_CTL1);
}

static int npcm_pspi_xfer(struct udevice *dev, unsigned int bitlen,
			  const void *dout, void *din, unsigned long flags)
{
	struct udevice *bus = dev->parent;
	struct npcm_pspi_priv *priv = dev_get_priv(bus);
	void __iomem *base = priv->base;
	const u8 *tx = dout;
	u8 *rx = din;
	u32 bytes = bitlen / 8;
	u8 tmp;
	u32 val;
	int i, ret = 0;

	npcm_pspi_enable(priv);

	if (flags & SPI_XFER_BEGIN)
		spi_cs_activate(dev);

	for (i = 0; i < bytes; i++) {
		/* Making sure we can write */
		ret = readb_poll_timeout(base + PSPI_STAT, val,
					 !(val & PSPI_STAT_BSY),
					 1000000);
		if (ret < 0)
			break;

		if (tx)
			writeb(*tx++, base + PSPI_DATA);
		else
			writeb(0, base + PSPI_DATA);

		/* Wait till write completed */
		ret = readb_poll_timeout(base + PSPI_STAT, val,
					 !(val & PSPI_STAT_BSY),
					 1000000);
		if (ret < 0)
			break;

		/* Wait till read buffer full */
		ret = readb_poll_timeout(base + PSPI_STAT, val,
					 (val & PSPI_STAT_RBF),
					 1000000);
		if (ret < 0)
			break;

		tmp = readb(base + PSPI_DATA);
		if (rx)
			*rx++ = tmp;
	}

	if (flags & SPI_XFER_END)
		spi_cs_deactivate(dev);

	npcm_pspi_disable(priv);

	return ret;
}

static int npcm_pspi_set_speed(struct udevice *bus, uint speed)
{
	struct npcm_pspi_priv *priv = dev_get_priv(bus);
	ulong apb_clock;
	u32 divisor;
	u16 val;

	apb_clock = clk_get_rate(&priv->clk);
	if (!apb_clock)
		return -EINVAL;

	if (speed > priv->max_hz)
		speed = priv->max_hz;

	divisor = DIV_ROUND_CLOSEST(apb_clock, (2 * speed) - 1);
	if (divisor > MAX_DIV)
		divisor = MAX_DIV;

	val = readw(priv->base + PSPI_CTL1);
	val &= ~PSPI_CTL1_SCDV_MASK;
	val |= divisor << PSPI_CTL1_SCDV_SHIFT;
	writew(val, priv->base + PSPI_CTL1);

	debug("%s: apb_clock=%lu speed=%d divisor=%u\n",
	      __func__, apb_clock, speed, divisor);

	return 0;
}

static int npcm_pspi_set_mode(struct udevice *bus, uint mode)
{
	struct npcm_pspi_priv *priv = dev_get_priv(bus);
	u16 pspi_mode, val;

	switch (mode & (SPI_CPOL | SPI_CPHA)) {
	case SPI_MODE_0:
		pspi_mode = 0;
		break;
	case SPI_MODE_1:
		pspi_mode = PSPI_CTL1_SCM;
		break;
	case SPI_MODE_2:
		pspi_mode = PSPI_CTL1_SCIDL;
		break;
	case SPI_MODE_3:
		pspi_mode = PSPI_CTL1_SCIDL | PSPI_CTL1_SCM;
		break;
	default:
		break;
	}

	val = readw(priv->base + PSPI_CTL1);
	val &= ~(PSPI_CTL1_SCIDL | PSPI_CTL1_SCM);
	val |= pspi_mode;
	writew(val, priv->base + PSPI_CTL1);

	return 0;
}

static int npcm_pspi_probe(struct udevice *bus)
{
	struct npcm_pspi_priv *priv = dev_get_priv(bus);
	int node = dev_of_offset(bus);
	int ret;

	ret = clk_get_by_index(bus, 0, &priv->clk);
	if (ret < 0)
		return ret;

	priv->base = dev_read_addr_ptr(bus);
	priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0);
	gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0,
				   &priv->cs_gpio, GPIOD_IS_OUT);

	return 0;
}

static const struct dm_spi_ops npcm_pspi_ops = {
	.xfer           = npcm_pspi_xfer,
	.set_speed      = npcm_pspi_set_speed,
	.set_mode       = npcm_pspi_set_mode,
};

static const struct udevice_id npcm_pspi_ids[] = {
	{ .compatible = "nuvoton,npcm845-pspi"},
	{ .compatible = "nuvoton,npcm750-pspi"},
	{ }
};

U_BOOT_DRIVER(npcm_pspi) = {
	.name   = "npcm_pspi",
	.id     = UCLASS_SPI,
	.of_match = npcm_pspi_ids,
	.ops    = &npcm_pspi_ops,
	.priv_auto = sizeof(struct npcm_pspi_priv),
	.probe  = npcm_pspi_probe,
};
