/*
 * Copyright (C) 2015-2016 Socionext Inc.
 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/sizes.h>
#include <dm/device.h>
#include <dm/pinctrl.h>

#include "pinctrl-uniphier.h"

#define UNIPHIER_PINCTRL_PINMUX_BASE	0x1000
#define UNIPHIER_PINCTRL_LOAD_PINMUX	0x1700
#define UNIPHIER_PINCTRL_PUPDCTRL_BASE	0x1a00
#define UNIPHIER_PINCTRL_IECTRL		0x1d00

static const char *uniphier_pinctrl_dummy_name = "_dummy";

static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);

	return priv->socdata->groups_count;
}

static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
						   unsigned selector)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);

	if (!priv->socdata->groups[selector].name)
		return uniphier_pinctrl_dummy_name;

	return priv->socdata->groups[selector].name;
}

static int uniphier_pinmux_get_functions_count(struct udevice *dev)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);

	return priv->socdata->functions_count;
}

static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
						     unsigned selector)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);

	if (!priv->socdata->functions[selector])
		return uniphier_pinctrl_dummy_name;

	return priv->socdata->functions[selector];
}

static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
						unsigned int pin, int enable)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	unsigned reg;
	u32 mask, tmp;

	reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
	mask = BIT(pin % 32);

	tmp = readl(priv->base + reg);
	if (enable)
		tmp |= mask;
	else
		tmp &= ~mask;
	writel(tmp, priv->base + reg);

	return 0;
}

static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
						unsigned int pin, int enable)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	int pins_count = priv->socdata->pins_count;
	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
	int i;

	/*
	 * Multiple pins share one input enable, per-pin disabling is
	 * impossible.
	 */
	if (!enable)
		return -EINVAL;

	for (i = 0; i < pins_count; i++) {
		if (pins[i].number == pin) {
			unsigned int iectrl;
			u32 tmp;

			iectrl = uniphier_pin_get_iectrl(pins[i].data);
			tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
			tmp |= 1 << iectrl;
			writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
		}
	}

	return 0;
}

static int uniphier_pinconf_input_enable(struct udevice *dev,
					 unsigned int pin, int enable)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);

	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
		return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
	else
		return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
}

#if CONFIG_IS_ENABLED(PINCONF)

static const struct pinconf_param uniphier_pinconf_params[] = {
	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 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 },
	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
};

static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
				     unsigned int param, unsigned int arg)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	unsigned int enable = 1;
	unsigned int reg;
	u32 mask, tmp;

	if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
		return -ENOTSUPP;

	switch (param) {
	case PIN_CONFIG_BIAS_DISABLE:
		enable = 0;
		break;
	case PIN_CONFIG_BIAS_PULL_UP:
	case PIN_CONFIG_BIAS_PULL_DOWN:
		if (arg == 0)	/* total bias is not supported */
			return -EINVAL;
		break;
	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
		if (arg == 0)	/* configuration ignored */
			return 0;
	default:
		BUG();
	}

	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
	mask = BIT(pin % 32);

	tmp = readl(priv->base + reg);
	if (enable)
		tmp |= mask;
	else
		tmp &= ~mask;
	writel(tmp, priv->base + reg);

	return 0;
}

static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin,
				    unsigned int param, unsigned int arg)
{
	int ret;

	switch (param) {
	case PIN_CONFIG_BIAS_DISABLE:
	case PIN_CONFIG_BIAS_PULL_UP:
	case PIN_CONFIG_BIAS_PULL_DOWN:
	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
		ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
		break;
	case PIN_CONFIG_INPUT_ENABLE:
		ret = uniphier_pinconf_input_enable(dev, pin, arg);
		break;
	default:
		printf("unsupported configuration parameter %u\n", param);
		return -EINVAL;
	}

	return ret;
}

static int uniphier_pinconf_group_set(struct udevice *dev,
				      unsigned int group_selector,
				      unsigned int param, unsigned int arg)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	const struct uniphier_pinctrl_group *grp =
					&priv->socdata->groups[group_selector];
	int i, ret;

	for (i = 0; i < grp->num_pins; i++) {
		ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg);
		if (ret)
			return ret;
	}

	return 0;
}

#endif /* CONFIG_IS_ENABLED(PINCONF) */

static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
				    int muxval)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	unsigned reg, reg_end, shift, mask;
	unsigned mux_bits = 8;
	unsigned reg_stride = 4;
	bool load_pinctrl = false;
	u32 tmp;

	/* some pins need input-enabling */
	uniphier_pinconf_input_enable(dev, pin, 1);

	if (muxval < 0)
		return;		/* dedicated pin; nothing to do for pin-mux */

	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT)
		mux_bits = 4;

	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
		/*
		 *  Mode       offset        bit
		 *  Normal     4 * n     shift+3:shift
		 *  Debug      4 * n     shift+7:shift+4
		 */
		mux_bits /= 2;
		reg_stride = 8;
		load_pinctrl = true;
	}

	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
	reg_end = reg + reg_stride;
	shift = pin * mux_bits % 32;
	mask = (1U << mux_bits) - 1;

	/*
	 * If reg_stride is greater than 4, the MSB of each pinsel shall be
	 * stored in the offset+4.
	 */
	for (; reg < reg_end; reg += 4) {
		tmp = readl(priv->base + reg);
		tmp &= ~(mask << shift);
		tmp |= (mask & muxval) << shift;
		writel(tmp, priv->base + reg);

		muxval >>= mux_bits;
	}

	if (load_pinctrl)
		writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
}

static int uniphier_pinmux_group_set(struct udevice *dev,
				     unsigned group_selector,
				     unsigned func_selector)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	const struct uniphier_pinctrl_group *grp =
					&priv->socdata->groups[group_selector];
	int i;

	for (i = 0; i < grp->num_pins; i++)
		uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);

	return 0;
}

const struct pinctrl_ops uniphier_pinctrl_ops = {
	.get_groups_count = uniphier_pinctrl_get_groups_count,
	.get_group_name = uniphier_pinctrl_get_group_name,
	.get_functions_count = uniphier_pinmux_get_functions_count,
	.get_function_name = uniphier_pinmux_get_function_name,
	.pinmux_group_set = uniphier_pinmux_group_set,
#if CONFIG_IS_ENABLED(PINCONF)
	.pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
	.pinconf_params = uniphier_pinconf_params,
	.pinconf_group_set = uniphier_pinconf_group_set,
#endif
	.set_state = pinctrl_generic_set_state,
};

int uniphier_pinctrl_probe(struct udevice *dev,
			   struct uniphier_pinctrl_socdata *socdata)
{
	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
	fdt_addr_t addr;

	addr = dev_get_addr(dev->parent);
	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->base = devm_ioremap(dev, addr, SZ_4K);
	if (!priv->base)
		return -ENOMEM;

	priv->socdata = socdata;

	return 0;
}
