/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc.
 * Copyright 2017 NXP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>

#include "../core.h"
#include "pinctrl-imx.h"

#define IMX_PAD_SION 0x40000000		/* set SION */

int imx_pmx_set_one_pin_mem(struct imx_pinctrl *ipctl, struct imx_pin *pin)
{
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	unsigned int pin_id = pin->pin;
	struct imx_pin_reg *pin_reg;
	struct imx_pin_memmap *pin_memmap;
	pin_reg = &info->pin_regs[pin_id];
	pin_memmap = &pin->pin_conf.pin_memmap;

	if (pin_reg->mux_reg == -1) {
		dev_err(ipctl->dev, "Pin(%s) does not support mux function\n",
			info->pins[pin_id].name);
		return 0;
	}

	if (info->flags & SHARE_MUX_CONF_REG) {
		u32 reg;
		reg = readl(ipctl->base + pin_reg->mux_reg);
		reg &= ~info->mux_mask;
		reg |= (pin_memmap->mux_mode << info->mux_shift);
		writel(reg, ipctl->base + pin_reg->mux_reg);
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
			pin_reg->mux_reg, reg);
	} else {
		writel(pin_memmap->mux_mode, ipctl->base + pin_reg->mux_reg);
		dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
			pin_reg->mux_reg, pin_memmap->mux_mode);
	}

	/*
	 * 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 (pin_memmap->input_val >> 24 == 0xff) {
		u32 val = pin_memmap->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(ipctl->base + pin_memmap->input_reg);
		val &= ~mask;
		val |= select << shift;
		writel(val, ipctl->base + pin_memmap->input_reg);
	} else if (pin_memmap->input_reg) {
		/*
		 * Regular select input register can never be at offset
		 * 0, and we only print register value for regular case.
		 */
		if (ipctl->input_sel_base)
			writel(pin_memmap->input_val, ipctl->input_sel_base +
					pin_memmap->input_reg);
		else
			writel(pin_memmap->input_val, ipctl->base +
					pin_memmap->input_reg);
		dev_dbg(ipctl->dev,
			"==>select_input: offset 0x%x val 0x%x\n",
			pin_memmap->input_reg, pin_memmap->input_val);
	}

	return 0;
}

int imx_pmx_backend_gpio_set_direction_mem(struct pinctrl_dev *pctldev,
	   struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg;
	u32 reg;

	/*
	 * Only Vybrid and iMX ULP has the input/output buffer enable flags
	 * (IBE/OBE) They are part of the shared mux/conf register.
	 */
	if (!(info->flags & SHARE_MUX_CONF_REG))
		return 0;

	pin_reg = &info->pin_regs[offset];
	if (pin_reg->mux_reg == -1)
		return -EINVAL;

	reg = readl(ipctl->base + pin_reg->mux_reg);
	if (input)
		reg = (reg & ~info->obe_bit) | info->ibe_bit;
	else
		reg = (reg & ~info->ibe_bit) | info->obe_bit;
	writel(reg, ipctl->base + pin_reg->mux_reg);

	return 0;
}

int imx_pinconf_backend_get_mem(struct pinctrl_dev *pctldev,
			    unsigned pin_id, unsigned long *config)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];

	if (pin_reg->conf_reg == -1) {
		dev_err(info->dev, "Pin(%s) does not support config function\n",
			info->pins[pin_id].name);
		return -EINVAL;
	}

	*config = readl(ipctl->base + pin_reg->conf_reg);

	if (info->flags & SHARE_MUX_CONF_REG)
		*config &= ~info->mux_mask;

	return 0;
}

int imx_pinconf_backend_set_mem(struct pinctrl_dev *pctldev,
			    unsigned pin_id, unsigned long *configs,
			    unsigned num_configs)
{
	struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
	const struct imx_pinctrl_soc_info *info = ipctl->info;
	const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
	int i;

	if (pin_reg->conf_reg == -1) {
		dev_err(info->dev, "Pin(%s) does not support config function\n",
			info->pins[pin_id].name);
		return -EINVAL;
	}

	dev_dbg(ipctl->dev, "pinconf set pin %s\n",
		info->pins[pin_id].name);

	for (i = 0; i < num_configs; i++) {
		if (info->flags & SHARE_MUX_CONF_REG) {
			u32 reg;
			reg = readl(ipctl->base + pin_reg->conf_reg);
			reg &= info->mux_mask;
			reg |= configs[i];
			writel(reg, ipctl->base + pin_reg->conf_reg);
			dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%x\n",
				pin_reg->conf_reg, reg);
		} else {
			writel(configs[i], ipctl->base + pin_reg->conf_reg);
			dev_dbg(ipctl->dev, "write: offset 0x%x val 0x%lx\n",
				pin_reg->conf_reg, configs[i]);
		}
	} /* for each config */

	return 0;
}

int imx_pinctrl_parse_pin_mem(struct imx_pinctrl_soc_info *info,
			  unsigned int *grp_pin_id, struct imx_pin *pin,
			  const __be32 **list_p)
{
	struct imx_pin_memmap *pin_memmap = &pin->pin_conf.pin_memmap;
	u32 mux_reg = be32_to_cpu(*((*list_p)++));
	u32 conf_reg;
	u32 config;
	unsigned int pin_id;
	struct imx_pin_reg *pin_reg;

	if (info->flags & SHARE_MUX_CONF_REG) {
		conf_reg = mux_reg;
	} else {
		conf_reg = be32_to_cpu(*((*list_p)++));
		if (!conf_reg)
			conf_reg = -1;
	}

	pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
	pin_reg = &info->pin_regs[pin_id];
	pin->pin = pin_id;
	*grp_pin_id = pin_id;
	pin_reg->mux_reg = mux_reg;
	pin_reg->conf_reg = conf_reg;
	pin_memmap->input_reg = be32_to_cpu(*((*list_p)++));
	pin_memmap->mux_mode = be32_to_cpu(*((*list_p)++));
	pin_memmap->input_val = be32_to_cpu((*(*list_p)++));

	/* SION bit is in mux register */
	config = be32_to_cpu(*((*list_p)++));
	if (config & IMX_PAD_SION)
		pin_memmap->mux_mode |= IOMUXC_CONFIG_SION;
	pin_memmap->config = config & ~IMX_PAD_SION;

	dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
			pin_memmap->mux_mode, pin_memmap->config);

	return 0;
}
