// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
 * Microsemi SoCs serial gpio driver
 *
 * Author: <lars.povlsen@microchip.com>
 *
 * Copyright (c) 2018 Microsemi Corporation
 */

#include <common.h>
#include <dm.h>
#include <log.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <errno.h>
#include <clk.h>
#include <dm/device_compat.h>
#include <linux/bitops.h>
#include <linux/err.h>

#define MSCC_SGPIOS_PER_BANK	32
#define MSCC_SGPIO_BANK_DEPTH	4

enum {
	REG_INPUT_DATA,
	REG_PORT_CONFIG,
	REG_PORT_ENABLE,
	REG_SIO_CONFIG,
	REG_SIO_CLOCK,
	MAXREG
};

struct mscc_sgpio_bf {
	u8 beg;
	u8 end;
};

struct mscc_sgpio_props {
	u8 regoff[MAXREG];
	struct mscc_sgpio_bf auto_repeat;
	struct mscc_sgpio_bf port_width;
	struct mscc_sgpio_bf clk_freq;
	struct mscc_sgpio_bf bit_source;
};

#define __M(bf)		GENMASK((bf).end, (bf).beg)
#define __F(bf, x)	(__M(bf) & ((x) << (bf).beg))
#define __X(bf, x)	(((x) >> (bf).beg) & GENMASK(((bf).end - (bf).beg), 0))

#define MSCC_M_CFG_SIO_AUTO_REPEAT(p)		BIT(p->props->auto_repeat.beg)
#define MSCC_F_CFG_SIO_PORT_WIDTH(p, x)		__F(p->props->port_width, x)
#define MSCC_M_CFG_SIO_PORT_WIDTH(p)		__M(p->props->port_width)
#define MSCC_F_CLOCK_SIO_CLK_FREQ(p, x)		__F(p->props->clk_freq, x)
#define MSCC_M_CLOCK_SIO_CLK_FREQ(p)		__M(p->props->clk_freq)
#define MSCC_F_PORT_CFG_BIT_SOURCE(p, x)	__F(p->props->bit_source, x)
#define MSCC_X_PORT_CFG_BIT_SOURCE(p, x)	__X(p->props->bit_source, x)

const struct mscc_sgpio_props props_luton = {
	.regoff = { 0x00, 0x09, 0x29, 0x2a, 0x2b },
	.auto_repeat = { 5, 5 },
	.port_width  = { 2, 3 },
	.clk_freq    = { 0, 11 },
	.bit_source  = { 0, 11 },
};

const struct mscc_sgpio_props props_ocelot = {
	.regoff = { 0x00, 0x06, 0x26, 0x04, 0x05 },
	.auto_repeat = { 10, 10 },
	.port_width  = {  7, 8  },
	.clk_freq    = {  8, 19 },
	.bit_source  = { 12, 23 },
};

struct mscc_sgpio_priv {
	u32 bitcount;
	u32 ports;
	u32 clock;
	u32 mode[MSCC_SGPIOS_PER_BANK];
	u32 __iomem *regs;
	const struct mscc_sgpio_props *props;
};

static inline u32 sgpio_readl(struct mscc_sgpio_priv *priv, u32 rno, u32 off)
{
	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];

	return readl(reg);
}

static inline void sgpio_writel(struct mscc_sgpio_priv *priv,
				u32 val, u32 rno, u32 off)
{
	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];

	writel(val, reg);
}

static void sgpio_clrsetbits(struct mscc_sgpio_priv *priv,
			     u32 rno, u32 off, u32 clear, u32 set)
{
	u32 __iomem *reg = &priv->regs[priv->props->regoff[rno] + off];

	clrsetbits_le32(reg, clear, set);
}

static int mscc_sgpio_direction_input(struct udevice *dev, unsigned int gpio)
{
	struct mscc_sgpio_priv *priv = dev_get_priv(dev);

	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;

	priv->mode[port] |= BIT(bit);

	return 0;
}

static int mscc_sgpio_direction_output(struct udevice *dev,
				       unsigned int gpio, int value)
{
	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
	u32 mask = 3 << (3 * bit);

	debug("set: port %d, bit %d, mask 0x%08x, value %d\n",
	      port, bit, mask, value);

	value = (value & 3) << (3 * bit);
	sgpio_clrsetbits(priv, REG_PORT_CONFIG, port,
			 MSCC_F_PORT_CFG_BIT_SOURCE(priv, mask),
			 MSCC_F_PORT_CFG_BIT_SOURCE(priv, value));
	clrbits_le32(&priv->mode[port], BIT(bit));

	return 0;
}

static int mscc_sgpio_get_function(struct udevice *dev, unsigned int gpio)
{
	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
	u32 val = priv->mode[port] & BIT(bit);

	if (val)
		return GPIOF_INPUT;
	else
		return GPIOF_OUTPUT;
}

static int mscc_sgpio_set_value(struct udevice *dev,
				unsigned int gpio, int value)
{
	return mscc_sgpio_direction_output(dev, gpio, value);
}

static int mscc_sgpio_get_value(struct udevice *dev, unsigned int gpio)
{
	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
	u32 port = gpio % MSCC_SGPIOS_PER_BANK;
	u32 bit = gpio / MSCC_SGPIOS_PER_BANK;
	int ret;

	if (mscc_sgpio_get_function(dev, gpio) == GPIOF_INPUT) {
		ret = !!(sgpio_readl(priv, REG_INPUT_DATA, bit) & BIT(port));
	} else {
		u32 portval = sgpio_readl(priv, REG_PORT_CONFIG, port);

		ret = MSCC_X_PORT_CFG_BIT_SOURCE(priv, portval);
		ret = !!(ret & (3 << (3 * bit)));
	}

	debug("get: gpio %d, port %d, bit %d, value %d\n",
	      gpio, port, bit, ret);
	return ret;
}

static int mscc_sgpio_get_count(struct udevice *dev)
{
	struct ofnode_phandle_args args;
	int count = 0, i = 0, ret;

	ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3, i, &args);
	while (ret != -ENOENT) {
		count += args.args[2];
		ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
						 ++i, &args);
	}
	return count;
}

static int mscc_sgpio_probe(struct udevice *dev)
{
	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
	struct mscc_sgpio_priv *priv = dev_get_priv(dev);
	int err, div_clock = 0, port;
	u32 val;
	struct clk clk;

	err = clk_get_by_index(dev, 0, &clk);
	if (!err) {
		err = clk_get_rate(&clk);
		if (IS_ERR_VALUE(err)) {
			dev_err(dev, "Invalid clk rate\n");
			return -EINVAL;
		}
		div_clock = err;
	} else {
		dev_err(dev, "Failed to get clock\n");
		return err;
	}

	priv->props = (const struct mscc_sgpio_props *)dev_get_driver_data(dev);
	priv->ports = dev_read_u32_default(dev, "mscc,sgpio-ports", 0xFFFFFFFF);
	priv->clock = dev_read_u32_default(dev, "mscc,sgpio-frequency",
					   12500000);
	if (priv->clock <= 0 || priv->clock > div_clock) {
		dev_err(dev, "Invalid frequency %d\n", priv->clock);
		return -EINVAL;
	}

	uc_priv->gpio_count = mscc_sgpio_get_count(dev);
	uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios",
						   uc_priv->gpio_count);
	if (uc_priv->gpio_count < 1 || uc_priv->gpio_count >
	    (4 * MSCC_SGPIOS_PER_BANK)) {
		dev_err(dev, "Invalid gpio count %d\n", uc_priv->gpio_count);
		return -EINVAL;
	}
	priv->bitcount = DIV_ROUND_UP(uc_priv->gpio_count,
				      MSCC_SGPIOS_PER_BANK);
	debug("probe: gpios = %d, bit-count = %d\n",
	      uc_priv->gpio_count, priv->bitcount);

	priv->regs = dev_read_addr_ptr(dev);
	uc_priv->bank_name = "sgpio";

	sgpio_clrsetbits(priv, REG_SIO_CONFIG, 0,
			 MSCC_M_CFG_SIO_PORT_WIDTH(priv),
			 MSCC_F_CFG_SIO_PORT_WIDTH(priv, priv->bitcount - 1) |
			 MSCC_M_CFG_SIO_AUTO_REPEAT(priv));
	val = div_clock / priv->clock;
	debug("probe: div-clock = %d KHz, freq = %d KHz, div = %d\n",
	      div_clock / 1000, priv->clock / 1000, val);
	sgpio_clrsetbits(priv, REG_SIO_CLOCK, 0,
			 MSCC_M_CLOCK_SIO_CLK_FREQ(priv),
			 MSCC_F_CLOCK_SIO_CLK_FREQ(priv, val));

	for (port = 0; port < 32; port++)
		sgpio_writel(priv, 0, REG_PORT_CONFIG, port);
	sgpio_writel(priv, priv->ports, REG_PORT_ENABLE, 0);

	debug("probe: sgpio regs = %p\n", priv->regs);

	return 0;
}

static const struct dm_gpio_ops mscc_sgpio_ops = {
	.direction_input	= mscc_sgpio_direction_input,
	.direction_output	= mscc_sgpio_direction_output,
	.get_function		= mscc_sgpio_get_function,
	.get_value		= mscc_sgpio_get_value,
	.set_value		= mscc_sgpio_set_value,
};

static const struct udevice_id mscc_sgpio_ids[] = {
	{ .compatible = "mscc,luton-sgpio", .data = (ulong)&props_luton },
	{ .compatible = "mscc,ocelot-sgpio", .data = (ulong)&props_ocelot },
	{ }
};

U_BOOT_DRIVER(gpio_mscc_sgpio) = {
	.name			= "mscc-sgpio",
	.id			= UCLASS_GPIO,
	.of_match		= mscc_sgpio_ids,
	.ops			= &mscc_sgpio_ops,
	.probe			= mscc_sgpio_probe,
	.priv_auto	= sizeof(struct mscc_sgpio_priv),
};
