/*
 * 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/device.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 = config->of_offset;
	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;
	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");
		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");
			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, 0x7 << 20,
					mux_mode << 20);
		} 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, 0xffff,
						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);
		}
	}

	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, 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, "reg", &size);

	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

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

	/*
	 * 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;
}
