// SPDX-License-Identifier: GPL-2.0-only
/*
 * Generic Pin Control Driver for Board-Level Mux Chips
 * Copyright 2026 NXP
 */

#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mutex.h>
#include <linux/mux/consumer.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>

#include "core.h"
#include "pinconf.h"
#include "pinmux.h"
#include "pinctrl-utils.h"

struct mux_pin_function {
	struct mux_state *mux_state;
};

struct mux_pinctrl {
	struct device *dev;
	struct pinctrl_dev *pctl;

	/* mutex protect [pinctrl|pinmux]_generic functions */
	struct mutex lock;
};

static int
mux_pinmux_dt_node_to_map(struct pinctrl_dev *pctldev,
			  struct device_node *np_config,
			  struct pinctrl_map **maps, unsigned int *num_maps)
{
	unsigned int num_reserved_maps = 0;
	struct mux_pin_function *function;
	const char **group_names;
	int ret;

	function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
	if (!function)
		return -ENOMEM;

	group_names = devm_kcalloc(pctldev->dev, 1, sizeof(*group_names), GFP_KERNEL);
	if (!group_names)
		return -ENOMEM;

	function->mux_state = devm_mux_state_get_from_np(pctldev->dev, NULL, np_config);
	if (IS_ERR(function->mux_state))
		return PTR_ERR(function->mux_state);

	ret = pinctrl_generic_to_map(pctldev, np_config, np_config, maps,
				     num_maps, &num_reserved_maps, group_names,
				     0, &np_config->name, NULL, 0);

	if (ret)
		return ret;

	ret = pinmux_generic_add_function(pctldev, np_config->name, group_names,
					  1, function);
	if (ret < 0) {
		pinctrl_utils_free_map(pctldev, *maps, *num_maps);
		return ret;
	}

	return 0;
}

static const struct pinctrl_ops mux_pinctrl_ops = {
	.get_groups_count = pinctrl_generic_get_group_count,
	.get_group_name = pinctrl_generic_get_group_name,
	.get_group_pins = pinctrl_generic_get_group_pins,
	.dt_node_to_map = mux_pinmux_dt_node_to_map,
	.dt_free_map = pinctrl_utils_free_map,
};

static int mux_pinmux_set_mux(struct pinctrl_dev *pctldev,
			      unsigned int func_selector,
			      unsigned int group_selector)
{
	struct mux_pinctrl *mpctl = pinctrl_dev_get_drvdata(pctldev);
	const struct function_desc *function;
	struct mux_pin_function *func;
	int ret;

	guard(mutex)(&mpctl->lock);

	function = pinmux_generic_get_function(pctldev, func_selector);
	func = function->data;

	ret = mux_state_try_select(func->mux_state);
	if (ret)
		return ret;

	return 0;
}

static void mux_pinmux_release_mux(struct pinctrl_dev *pctldev,
				   unsigned int func_selector,
				   unsigned int group_selector)
{
	struct mux_pinctrl *mpctl = pinctrl_dev_get_drvdata(pctldev);
	const struct function_desc *function;
	struct mux_pin_function *func;

	guard(mutex)(&mpctl->lock);

	function = pinmux_generic_get_function(pctldev, func_selector);
	func = function->data;

	mux_state_deselect(func->mux_state);
}

static const struct pinmux_ops mux_pinmux_ops = {
	.get_functions_count = pinmux_generic_get_function_count,
	.get_function_name = pinmux_generic_get_function_name,
	.get_function_groups = pinmux_generic_get_function_groups,
	.set_mux = mux_pinmux_set_mux,
	.release_mux = mux_pinmux_release_mux,
};

static int mux_pinctrl_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct mux_pinctrl *mpctl;
	struct pinctrl_desc *pctl_desc;
	int ret;

	mpctl = devm_kzalloc(dev, sizeof(*mpctl), GFP_KERNEL);
	if (!mpctl)
		return -ENOMEM;

	mpctl->dev = dev;

	platform_set_drvdata(pdev, mpctl);

	pctl_desc = devm_kzalloc(dev, sizeof(*pctl_desc), GFP_KERNEL);
	if (!pctl_desc)
		return -ENOMEM;

	ret = devm_mutex_init(dev, &mpctl->lock);
	if (ret)
		return ret;

	pctl_desc->name = dev_name(dev);
	pctl_desc->owner = THIS_MODULE;
	pctl_desc->pctlops = &mux_pinctrl_ops;
	pctl_desc->pmxops = &mux_pinmux_ops;

	ret = devm_pinctrl_register_and_init(dev, pctl_desc, mpctl,
					     &mpctl->pctl);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to register pinctrl.\n");

	ret = pinctrl_enable(mpctl->pctl);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to enable pinctrl.\n");

	return 0;
}

static const struct of_device_id mux_pinctrl_of_match[] = {
	{ .compatible = "pinctrl-multiplexer" },
	{ }
};
MODULE_DEVICE_TABLE(of, mux_pinctrl_of_match);

static struct platform_driver mux_pinctrl_driver = {
	.driver = {
		.name = "generic-pinctrl-mux",
		.of_match_table = mux_pinctrl_of_match,
	},
	.probe = mux_pinctrl_probe,
};
module_platform_driver(mux_pinctrl_driver);

MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>");
MODULE_DESCRIPTION("Generic Pin Control Driver for Board-Level Mux Chips");
MODULE_LICENSE("GPL");
