// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
 */

#include <dm.h>
#include <dm/pinctrl.h>
#include <dt-bindings/pinctrl/sandbox-pinmux.h>
#include <log.h>
#include <linux/bitops.h>

/*
 * This driver emulates a pin controller with the following rules:
 * - The pinctrl config for each pin must be set individually
 * - The first three pins (P0-P2) must be muxed as a group
 * - The next two pins (P3-P4) must be muxed as a group
 * - The last four pins (P5-P8) must be muxed individually
 */

static const char * const sandbox_pins[] = {
#define PIN(x) \
	[x] = "P" #x
	PIN(0),
	PIN(1),
	PIN(2),
	PIN(3),
	PIN(4),
	PIN(5),
	PIN(6),
	PIN(7),
	PIN(8),
#undef PIN
};

static const char * const sandbox_pins_muxing[][2] = {
	{ "UART TX", "I2C SCL" },
	{ "UART RX", "I2C SDA" },
	{ "SPI SCLK", "I2S SCK" },
	{ "SPI MOSI", "I2S SD" },
	{ "SPI MISO", "I2S WS" },
	{ "GPIO0", "SPI CS0" },
	{ "GPIO1", "SPI CS1" },
	{ "GPIO2", "PWM0" },
	{ "GPIO3", "ONEWIRE" },
};

#define SANDBOX_GROUP_I2C_UART 0
#define SANDBOX_GROUP_SPI_I2S 1

static const char * const sandbox_groups[] = {
	[SANDBOX_GROUP_I2C_UART] = "I2C_UART",
	[SANDBOX_GROUP_SPI_I2S] = "SPI_I2S",
};

static const char * const sandbox_functions[] = {
#define FUNC(id) \
	[SANDBOX_PINMUX_##id] = #id
	FUNC(UART),
	FUNC(I2C),
	FUNC(SPI),
	FUNC(I2S),
	FUNC(GPIO),
	FUNC(CS),
	FUNC(PWM),
	FUNC(ONEWIRE),
#undef FUNC
};

static const struct pinconf_param sandbox_conf_params[] = {
	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
	{ "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
	{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
	{ "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
};

/* Bitfield used to save param and value of each pin/selector */
struct sandbox_pinctrl_priv {
	unsigned int mux;
	unsigned int pins_param[ARRAY_SIZE(sandbox_pins)];
	unsigned int pins_value[ARRAY_SIZE(sandbox_pins)];
};

static int sandbox_get_pins_count(struct udevice *dev)
{
	return ARRAY_SIZE(sandbox_pins);
}

static const char *sandbox_get_pin_name(struct udevice *dev, unsigned selector)
{
	return sandbox_pins[selector];
}

static int sandbox_get_pin_muxing(struct udevice *dev,
				  unsigned int selector,
				  char *buf, int size)
{
	const struct pinconf_param *p;
	struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
	int i;

	snprintf(buf, size, "%s",
		 sandbox_pins_muxing[selector][!!(priv->mux & BIT(selector))]);

	if (priv->pins_param[selector]) {
		for (i = 0, p = sandbox_conf_params;
		     i < ARRAY_SIZE(sandbox_conf_params);
		     i++, p++) {
			if ((priv->pins_param[selector] & BIT(p->param)) &&
			    (!!(priv->pins_value[selector] & BIT(p->param)) ==
			     p->default_value)) {
				strncat(buf, " ", size);
				strncat(buf, p->property, size);
			}
		}
	}
	strncat(buf, ".", size);

	return 0;
}

static int sandbox_get_groups_count(struct udevice *dev)
{
	return ARRAY_SIZE(sandbox_groups);
}

static const char *sandbox_get_group_name(struct udevice *dev,
					  unsigned selector)
{
	return sandbox_groups[selector];
}

static int sandbox_get_functions_count(struct udevice *dev)
{
	return ARRAY_SIZE(sandbox_functions);
}

static const char *sandbox_get_function_name(struct udevice *dev,
					     unsigned selector)
{
	return sandbox_functions[selector];
}

static int sandbox_pinmux_set(struct udevice *dev, unsigned pin_selector,
			      unsigned func_selector)
{
	int mux;
	struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);

	debug("sandbox pinmux: pin = %d (%s), function = %d (%s)\n",
	      pin_selector, sandbox_get_pin_name(dev, pin_selector),
	      func_selector, sandbox_get_function_name(dev, func_selector));

	if (pin_selector < 5)
		return -EINVAL;

	switch (func_selector) {
	case SANDBOX_PINMUX_GPIO:
		mux = 0;
		break;
	case SANDBOX_PINMUX_CS:
	case SANDBOX_PINMUX_PWM:
	case SANDBOX_PINMUX_ONEWIRE:
		mux = BIT(pin_selector);
		break;
	default:
		return -EINVAL;
	}

	priv->mux &= ~BIT(pin_selector);
	priv->mux |= mux;
	priv->pins_param[pin_selector] = 0;
	priv->pins_value[pin_selector] = 0;

	return 0;
}

static int sandbox_pinmux_group_set(struct udevice *dev,
				    unsigned group_selector,
				    unsigned func_selector)
{
	bool mux;
	int i, group_start, group_end;
	struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
	unsigned int mask;

	debug("sandbox pinmux: group = %d (%s), function = %d (%s)\n",
	      group_selector, sandbox_get_group_name(dev, group_selector),
	      func_selector, sandbox_get_function_name(dev, func_selector));

	if (group_selector == SANDBOX_GROUP_I2C_UART) {
		group_start = 0;
		group_end = 1;

		if (func_selector == SANDBOX_PINMUX_UART)
			mux = false;
		else if (func_selector == SANDBOX_PINMUX_I2C)
			mux = true;
		else
			return -EINVAL;
	} else if (group_selector == SANDBOX_GROUP_SPI_I2S) {
		group_start = 2;
		group_end = 4;

		if (func_selector == SANDBOX_PINMUX_SPI)
			mux = false;
		else if (func_selector == SANDBOX_PINMUX_I2S)
			mux = true;
		else
			return -EINVAL;
	} else {
		return -EINVAL;
	}

	mask = GENMASK(group_end, group_start);
	priv->mux &= ~mask;
	priv->mux |= mux ? mask : 0;

	for (i = group_start; i < group_end; i++) {
		priv->pins_param[i] = 0;
		priv->pins_value[i] = 0;
	}

	return 0;
}

static int sandbox_pinmux_property_set(struct udevice *dev, u32 pinmux_group)
{
	int ret;
	unsigned pin_selector = pinmux_group & 0xFFFF;
	unsigned func_selector = pinmux_group >> 16;

	ret = sandbox_pinmux_set(dev, pin_selector, func_selector);
	return ret ? ret : pin_selector;
}

static int sandbox_pinconf_set(struct udevice *dev, unsigned pin_selector,
			       unsigned param, unsigned argument)
{
	struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);

	debug("sandbox pinconf: pin = %d (%s), param = %d, arg = %d\n",
	      pin_selector, sandbox_get_pin_name(dev, pin_selector),
	      param, argument);

	priv->pins_param[pin_selector] |= BIT(param);
	if (argument)
		priv->pins_value[pin_selector] |= BIT(param);
	else
		priv->pins_value[pin_selector] &= ~BIT(param);

	return 0;
}

static int sandbox_pinconf_group_set(struct udevice *dev,
				     unsigned group_selector,
				     unsigned param, unsigned argument)
{
	debug("sandbox pinconf: group = %d (%s), param = %d, arg = %d\n",
	      group_selector, sandbox_get_group_name(dev, group_selector),
	      param, argument);

	return 0;
}

const struct pinctrl_ops sandbox_pinctrl_ops = {
	.get_pins_count = sandbox_get_pins_count,
	.get_pin_name = sandbox_get_pin_name,
	.get_pin_muxing = sandbox_get_pin_muxing,
	.get_groups_count = sandbox_get_groups_count,
	.get_group_name = sandbox_get_group_name,
	.get_functions_count = sandbox_get_functions_count,
	.get_function_name = sandbox_get_function_name,
	.pinmux_set = sandbox_pinmux_set,
	.pinmux_group_set = sandbox_pinmux_group_set,
	.pinmux_property_set = sandbox_pinmux_property_set,
	.pinconf_num_params = ARRAY_SIZE(sandbox_conf_params),
	.pinconf_params = sandbox_conf_params,
	.pinconf_set = sandbox_pinconf_set,
	.pinconf_group_set = sandbox_pinconf_group_set,
	.set_state = pinctrl_generic_set_state,
};

static const struct udevice_id sandbox_pinctrl_match[] = {
	{ .compatible = "sandbox,pinctrl" },
	{ /* sentinel */ }
};

U_BOOT_DRIVER(sandbox_pinctrl) = {
	.name = "sandbox_pinctrl",
	.id = UCLASS_PINCTRL,
	.of_match = sandbox_pinctrl_match,
	.priv_auto	= sizeof(struct sandbox_pinctrl_priv),
	.ops = &sandbox_pinctrl_ops,
};
