/*
 * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
 * Copyright 2017 NXP
 *
 * 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 = 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 & IMX8_USE_SCU)
		pin_size = SHARE_IMX8_PIN_SIZE;
	else 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;

	if (info->flags & IMX8_USE_SCU) {
		imx_pinctrl_scu_process_pins(info, pin_data, npins);
	} else {
		/*
		 * 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;

	if (info->flags & IMX8_USE_SCU)
		return 0;

	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->flags & IMX8_USE_SCU)
		return 0;

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

	return 0;
}
