/*
 * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

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

#include "pinctrl-imx.h"

DECLARE_GLOBAL_DATA_PTR;

static int imx_pinctrl_set_state(struct udevice *dev, struct udevice *config)
{
	struct imx_pinctrl_priv *priv = dev_get_priv(dev);
	struct imx_pinctrl_soc_info *info = priv->info;
	int node = dev_of_offset(config);
	const struct fdt_property *prop;
	u32 *pin_data;
	int npins, size, pin_size;
	int mux_reg, conf_reg, input_reg, input_val, mux_mode, config_val;
	u32 mux_shift = info->mux_mask ? ffs(info->mux_mask) - 1 : 0;
	int i, j = 0;

	dev_dbg(dev, "%s: %s\n", __func__, config->name);

	if (info->flags & SHARE_MUX_CONF_REG)
		pin_size = SHARE_FSL_PIN_SIZE;
	else
		pin_size = FSL_PIN_SIZE;

	prop = fdt_getprop(gd->fdt_blob, node, "fsl,pins", &size);
	if (!prop) {
		dev_err(dev, "No fsl,pins property in node %s\n", config->name);
		return -EINVAL;
	}

	if (!size || size % pin_size) {
		dev_err(dev, "Invalid fsl,pins property in node %s\n",
			config->name);
		return -EINVAL;
	}

	pin_data = devm_kzalloc(dev, size, 0);
	if (!pin_data)
		return -ENOMEM;

	if (fdtdec_get_int_array(gd->fdt_blob, node, "fsl,pins",
				 pin_data, size >> 2)) {
		dev_err(dev, "Error reading pin data.\n");
		devm_kfree(dev, pin_data);
		return -EINVAL;
	}

	npins = size / pin_size;

	/*
	 * Refer to linux documentation for details:
	 * Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
	 */
	for (i = 0; i < npins; i++) {
		mux_reg = pin_data[j++];

		if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
			mux_reg = -1;

		if (info->flags & SHARE_MUX_CONF_REG) {
			conf_reg = mux_reg;
		} else {
			conf_reg = pin_data[j++];
			if (!(info->flags & ZERO_OFFSET_VALID) && !conf_reg)
				conf_reg = -1;
		}

		if ((mux_reg == -1) || (conf_reg == -1)) {
			dev_err(dev, "Error mux_reg or conf_reg\n");
			devm_kfree(dev, pin_data);
			return -EINVAL;
		}

		input_reg = pin_data[j++];
		mux_mode = pin_data[j++];
		input_val = pin_data[j++];
		config_val = pin_data[j++];

		dev_dbg(dev, "mux_reg 0x%x, conf_reg 0x%x, input_reg 0x%x, "
			"mux_mode 0x%x, input_val 0x%x, config_val 0x%x\n",
			mux_reg, conf_reg, input_reg, mux_mode, input_val,
			config_val);

		if (config_val & IMX_PAD_SION)
			mux_mode |= IOMUXC_CONFIG_SION;

		config_val &= ~IMX_PAD_SION;

		/* Set Mux */
		if (info->flags & SHARE_MUX_CONF_REG) {
			clrsetbits_le32(info->base + mux_reg, info->mux_mask,
					mux_mode << mux_shift);
		} else {
			writel(mux_mode, info->base + mux_reg);
		}

		dev_dbg(dev, "write mux: offset 0x%x val 0x%x\n", mux_reg,
			mux_mode);

		/*
		 * Set select input
		 *
		 * If the select input value begins with 0xff, it's a quirky
		 * select input and the value should be interpreted as below.
		 *     31     23      15      7        0
		 *     | 0xff | shift | width | select |
		 * It's used to work around the problem that the select
		 * input for some pin is not implemented in the select
		 * input register but in some general purpose register.
		 * We encode the select input value, width and shift of
		 * the bit field into input_val cell of pin function ID
		 * in device tree, and then decode them here for setting
		 * up the select input bits in general purpose register.
		 */

		if (input_val >> 24 == 0xff) {
			u32 val = input_val;
			u8 select = val & 0xff;
			u8 width = (val >> 8) & 0xff;
			u8 shift = (val >> 16) & 0xff;
			u32 mask = ((1 << width) - 1) << shift;
			/*
			 * The input_reg[i] here is actually some IOMUXC general
			 * purpose register, not regular select input register.
			 */
			val = readl(info->base + input_reg);
			val &= ~mask;
			val |= select << shift;
			writel(val, info->base + input_reg);
		} else if (input_reg) {
			/*
			 * Regular select input register can never be at offset
			 * 0, and we only print register value for regular case.
			 */
			if (info->input_sel_base)
				writel(input_val, info->input_sel_base +
				       input_reg);
			else
				writel(input_val, info->base + input_reg);

			dev_dbg(dev, "select_input: offset 0x%x val 0x%x\n",
				input_reg, input_val);
		}

		/* Set config */
		if (!(config_val & IMX_NO_PAD_CTL)) {
			if (info->flags & SHARE_MUX_CONF_REG) {
				clrsetbits_le32(info->base + conf_reg,
						~info->mux_mask, config_val);
			} else {
				writel(config_val, info->base + conf_reg);
			}

			dev_dbg(dev, "write config: offset 0x%x val 0x%x\n",
				conf_reg, config_val);
		}
	}

	devm_kfree(dev, pin_data);

	return 0;
}

const struct pinctrl_ops imx_pinctrl_ops  = {
	.set_state = imx_pinctrl_set_state,
};

int imx_pinctrl_probe(struct udevice *dev,
		      struct imx_pinctrl_soc_info *info)
{
	struct imx_pinctrl_priv *priv = dev_get_priv(dev);
	int node = dev_of_offset(dev), ret;
	struct fdtdec_phandle_args arg;
	fdt_addr_t addr;
	fdt_size_t size;

	if (!info) {
		dev_err(dev, "wrong pinctrl info\n");
		return -EINVAL;
	}

	priv->dev = dev;
	priv->info = info;

	addr = fdtdec_get_addr_size(gd->fdt_blob, dev_of_offset(dev), "reg",
				    &size);

	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

	info->base = map_sysmem(addr, size);
	if (!info->base)
		return -ENOMEM;
	priv->info = info;

	info->mux_mask = fdtdec_get_int(gd->fdt_blob, node, "fsl,mux_mask", 0);
	/*
	 * Refer to linux documentation for details:
	 * Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt
	 */
	if (fdtdec_get_bool(gd->fdt_blob, node, "fsl,input-sel")) {
		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
						     node, "fsl,input-sel",
						     NULL, 0, 0, &arg);
		if (ret) {
			dev_err(dev, "iomuxc fsl,input-sel property not found\n");
			return -EINVAL;
		}

		addr = fdtdec_get_addr_size(gd->fdt_blob, arg.node, "reg",
					    &size);
		if (addr == FDT_ADDR_T_NONE)
			return -EINVAL;

		info->input_sel_base = map_sysmem(addr, size);
		if (!info->input_sel_base)
			return -ENOMEM;
	}

	dev_dbg(dev, "initialized IMX pinctrl driver\n");

	return 0;
}

int imx_pinctrl_remove(struct udevice *dev)
{
	struct imx_pinctrl_priv *priv = dev_get_priv(dev);
	struct imx_pinctrl_soc_info *info = priv->info;

	if (info->input_sel_base)
		unmap_sysmem(info->input_sel_base);
	if (info->base)
		unmap_sysmem(info->base);

	return 0;
}
