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

#include <malloc.h>
#include <mapmem.h>
#include <asm/global_data.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <linux/bitops.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;
	u32 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_conf_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 = devfdt_get_addr_size_index(dev, 0, &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;
}
