// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2019 DENX Software Engineering
 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
 */

#include <common.h>
#include <log.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <linux/io.h>
#include <linux/err.h>
#include <dm.h>
#include <dm/pinctrl.h>
#include <dm/read.h>
#include "pinctrl-mxs.h"

DECLARE_GLOBAL_DATA_PTR;

struct mxs_pinctrl_priv {
	void __iomem *base;
	const struct mxs_regs *regs;
};

static unsigned long mxs_dt_node_to_map(struct udevice *conf)
{
	unsigned long config = 0;
	int ret;
	u32 val;

	ret = dev_read_u32(conf, "fsl,drive-strength", &val);
	if (!ret)
		config = val | MA_PRESENT;

	ret = dev_read_u32(conf, "fsl,voltage", &val);
	if (!ret)
		config |= val << VOL_SHIFT | VOL_PRESENT;

	ret = dev_read_u32(conf, "fsl,pull-up", &val);
	if (!ret)
		config |= val << PULL_SHIFT | PULL_PRESENT;

	return config;
}

static int mxs_pinctrl_set_mux(struct udevice *dev, u32 val, int bank, int pin)
{
	struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);
	int muxsel = MUXID_TO_MUXSEL(val), shift;
	void __iomem *reg;

	reg = iomux->base + iomux->regs->muxsel;
	reg += bank * 0x20 + pin / 16 * 0x10;
	shift = pin % 16 * 2;

	mxs_pinctrl_rmwl(muxsel, 0x3, shift, reg);
	debug(" mux %d,", muxsel);

	return 0;
}

static int mxs_pinctrl_set_state(struct udevice *dev, struct udevice *conf)
{
	struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);
	u32 *pin_data, val, ma, vol, pull;
	int npins, size, i, ret;
	unsigned long config;

	debug("\n%s: set state: %s\n", __func__, conf->name);

	size = dev_read_size(conf, "fsl,pinmux-ids");
	if (size < 0)
		return size;

	if (!size || size % sizeof(int)) {
		dev_err(dev, "Invalid fsl,pinmux-ids property in %s\n",
			conf->name);
		return -EINVAL;
	}

	npins = size / sizeof(int);

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

	ret = dev_read_u32_array(conf, "fsl,pinmux-ids", pin_data, npins);
	if (ret) {
		dev_err(dev, "Error reading pin data.\n");
		devm_kfree(dev, pin_data);
		return -EINVAL;
	}

	config = mxs_dt_node_to_map(conf);

	ma = CONFIG_TO_MA(config);
	vol = CONFIG_TO_VOL(config);
	pull = CONFIG_TO_PULL(config);

	for (i = 0; i < npins; i++) {
		int pinid, bank, pin, shift;
		void __iomem *reg;

		val = pin_data[i];

		pinid = MUXID_TO_PINID(val);
		bank = PINID_TO_BANK(pinid);
		pin = PINID_TO_PIN(pinid);

		debug("(val: 0x%x) pin %d,", val, pinid);
		/* Setup pinmux */
		mxs_pinctrl_set_mux(dev, val, bank, pin);

		debug(" ma: %d, vol: %d, pull: %d\n", ma, vol, pull);

		/* drive */
		reg = iomux->base + iomux->regs->drive;
		reg += bank * 0x40 + pin / 8 * 0x10;

		/* mA */
		if (config & MA_PRESENT) {
			shift = pin % 8 * 4;
			mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
		}

		/* vol */
		if (config & VOL_PRESENT) {
			shift = pin % 8 * 4 + 2;
			if (vol)
				writel(1 << shift, reg + SET);
			else
				writel(1 << shift, reg + CLR);
		}

		/* pull */
		if (config & PULL_PRESENT) {
			reg = iomux->base + iomux->regs->pull;
			reg += bank * 0x10;
			shift = pin;
			if (pull)
				writel(1 << shift, reg + SET);
			else
				writel(1 << shift, reg + CLR);
		}
	}

	devm_kfree(dev, pin_data);
	return 0;
}

static struct pinctrl_ops mxs_pinctrl_ops = {
	.set_state = mxs_pinctrl_set_state,
};

static int mxs_pinctrl_probe(struct udevice *dev)
{
	struct mxs_pinctrl_priv *iomux = dev_get_priv(dev);

	iomux->base = dev_read_addr_ptr(dev);
	iomux->regs = (struct mxs_regs *)dev_get_driver_data(dev);

	return 0;
}

static const struct mxs_regs imx23_regs = {
	.muxsel = 0x100,
	.drive = 0x200,
	.pull = 0x400,
};

static const struct mxs_regs imx28_regs = {
	.muxsel = 0x100,
	.drive = 0x300,
	.pull = 0x600,
};

static const struct udevice_id mxs_pinctrl_match[] = {
	{ .compatible = "fsl,imx23-pinctrl", .data = (ulong)&imx23_regs },
	{ .compatible = "fsl,imx28-pinctrl", .data = (ulong)&imx28_regs },
	{ /* sentinel */ }
};

U_BOOT_DRIVER(fsl_imx23_pinctrl) = {
	.name = "fsl_imx23_pinctrl",
	.id = UCLASS_PINCTRL,
	.of_match = of_match_ptr(mxs_pinctrl_match),
	.probe = mxs_pinctrl_probe,
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
	.bind		= dm_scan_fdt_dev,
#endif
	.priv_auto	= sizeof(struct mxs_pinctrl_priv),
	.ops = &mxs_pinctrl_ops,
};

U_BOOT_DRIVER_ALIAS(fsl_imx23_pinctrl, fsl_imx28_pinctrl)
