// SPDX-License-Identifier: GPL-2.0
/*
 * Multiplexer subsystem
 *
 * Based on the linux multiplexer framework
 *
 * Copyright (C) 2017 Axentia Technologies AB
 * Author: Peter Rosin <peda@axentia.se>
 *
 * Copyright (C) 2017-2018 Texas Instruments Incorporated - https://www.ti.com/
 * Jean-Jacques Hiblot <jjhiblot@ti.com>
 */

#define LOG_CATEGORY UCLASS_MUX

#include <common.h>
#include <dm.h>
#include <mux-internal.h>
#include <dm/device-internal.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <dt-bindings/mux/mux.h>
#include <linux/bug.h>

/*
 * The idle-as-is "state" is not an actual state that may be selected, it
 * only implies that the state should not be changed. So, use that state
 * as indication that the cached state of the multiplexer is unknown.
 */
#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS

/**
 * mux_control_ops() - Get the mux_control ops.
 * @dev: The client device.
 *
 * Return: A pointer to the 'mux_control_ops' of the device.
 */
static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
{
	return (const struct mux_control_ops *)dev->driver->ops;
}

/**
 * mux_control_set() - Set the state of the given mux controller.
 * @mux: A multiplexer control
 * @state: The new requested state.
 *
 * Return: 0 if OK, or a negative error code.
 */
static int mux_control_set(struct mux_control *mux, int state)
{
	int ret = mux_dev_ops(mux->dev)->set(mux, state);

	mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;

	return ret;
}

unsigned int mux_control_states(struct mux_control *mux)
{
	return mux->states;
}

/**
 * __mux_control_select() - Select the given multiplexer state.
 * @mux: The mux-control to request a change of state from.
 * @state: The new requested state.
 *
 * Try to set the mux to the requested state. If not, try to revert if
 * appropriate.
 */
static int __mux_control_select(struct mux_control *mux, int state)
{
	int ret;

	if (WARN_ON(state < 0 || state >= mux->states))
		return -EINVAL;

	if (mux->cached_state == state)
		return 0;

	ret = mux_control_set(mux, state);
	if (ret >= 0)
		return 0;

	/* The mux update failed, try to revert if appropriate... */
	if (mux->idle_state != MUX_IDLE_AS_IS)
		mux_control_set(mux, mux->idle_state);

	return ret;
}

int mux_control_select(struct mux_control *mux, unsigned int state)
{
	int ret;

	if (mux->in_use)
		return -EBUSY;

	ret = __mux_control_select(mux, state);

	if (ret < 0)
		return ret;

	mux->in_use = true;

	return 0;
}

int mux_control_deselect(struct mux_control *mux)
{
	int ret = 0;

	if (mux->idle_state != MUX_IDLE_AS_IS &&
	    mux->idle_state != mux->cached_state)
		ret = mux_control_set(mux, mux->idle_state);

	mux->in_use = false;

	return ret;
}

static int mux_of_xlate_default(struct mux_chip *mux_chip,
				struct ofnode_phandle_args *args,
				struct mux_control **muxp)
{
	struct mux_control *mux;
	int id;

	log_debug("%s(muxp=%p)\n", __func__, muxp);

	if (args->args_count > 1) {
		debug("Invalid args_count: %d\n", args->args_count);
		return -EINVAL;
	}

	if (args->args_count)
		id = args->args[0];
	else
		id = 0;

	if (id >= mux_chip->controllers) {
		pr_err("bad mux controller %u specified in %s\n",
			id, ofnode_get_name(args->node));
		return -ERANGE;
	}

	mux = &mux_chip->mux[id];
	mux->id = id;
	*muxp = mux;
	return 0;
}

/**
 * mux_get_by_indexed_prop() - Get a mux control by integer index
 * @dev: The client device.
 * @prop_name: Name of the device tree property.
 * @index: The index of the mux to get
 * @mux: A pointer to the 'mux_control' struct to initialize.
 *
 * Return: 0 of OK, -errno otherwise.
 */
static int mux_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
				   int index, struct mux_control **mux)
{
	int ret;
	struct ofnode_phandle_args args;
	struct udevice *dev_mux;
	const struct mux_control_ops *ops;
	struct mux_chip *mux_chip;

	log_debug("%s(dev=%p, index=%d, mux=%p)\n", __func__, dev, index, mux);

	ret = dev_read_phandle_with_args(dev, prop_name, "#mux-control-cells",
					 0, index, &args);
	if (ret) {
		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
		      __func__, ret);
		return ret;
	}

	ret = uclass_get_device_by_ofnode(UCLASS_MUX, args.node, &dev_mux);
	if (ret) {
		debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
		      __func__, ret);
		return ret;
	}

	mux_chip = dev_get_uclass_priv(dev_mux);

	ops = mux_dev_ops(dev_mux);
	if (ops->of_xlate)
		ret = ops->of_xlate(mux_chip, &args, mux);
	else
		ret = mux_of_xlate_default(mux_chip, &args, mux);
	if (ret) {
		debug("of_xlate() failed: %d\n", ret);
		return ret;
	}
	(*mux)->dev = dev_mux;

	return 0;
}

int mux_get_by_index(struct udevice *dev, int index, struct mux_control **mux)
{
	return mux_get_by_indexed_prop(dev, "mux-controls", index, mux);
}

int mux_control_get(struct udevice *dev, const char *name,
		    struct mux_control **mux)
{
	int index;

	debug("%s(dev=%p, name=%s, mux=%p)\n", __func__, dev, name, mux);

	index = dev_read_stringlist_search(dev, "mux-control-names", name);
	if (index < 0) {
		debug("fdt_stringlist_search() failed: %d\n", index);
		return index;
	}

	return mux_get_by_index(dev, index, mux);
}

void mux_control_put(struct mux_control *mux)
{
	mux_control_deselect(mux);
}

/**
 * devm_mux_control_release() - Release the given managed mux.
 * @dev: The client device.
 * @res: Pointer to the mux to be released.
 *
 * This function is called by devres to release the mux. It reverses the
 * effects of mux_control_get().
 */
static void devm_mux_control_release(struct udevice *dev, void *res)
{
	mux_control_put(*(struct mux_control **)res);
}

struct mux_control *devm_mux_control_get(struct udevice *dev, const char *id)
{
	int rc;
	struct mux_control **mux;

	mux = devres_alloc(devm_mux_control_release,
			   sizeof(struct mux_control *), __GFP_ZERO);
	if (unlikely(!mux))
		return ERR_PTR(-ENOMEM);

	rc = mux_control_get(dev, id, mux);
	if (rc)
		return ERR_PTR(rc);

	devres_add(dev, mux);
	return *mux;
}

int mux_alloc_controllers(struct udevice *dev, unsigned int controllers)
{
	int i;
	struct mux_chip *mux_chip = dev_get_uclass_priv(dev);

	mux_chip->mux = devm_kmalloc(dev,
				     sizeof(struct mux_control) * controllers,
				     __GFP_ZERO);
	if (!mux_chip->mux)
		return -ENOMEM;

	mux_chip->controllers = controllers;

	for (i = 0; i < mux_chip->controllers; ++i) {
		struct mux_control *mux = &mux_chip->mux[i];

		mux->dev = dev;
		mux->cached_state = MUX_CACHE_UNKNOWN;
		mux->idle_state = MUX_IDLE_AS_IS;
		mux->in_use = false;
		mux->id = i;
	}

	return 0;
}

static int mux_uclass_post_probe(struct udevice *dev)
{
	int i, ret;
	struct mux_chip *mux_chip = dev_get_uclass_priv(dev);

	/* Set all mux controllers to their idle state. */
	for (i = 0; i < mux_chip->controllers; ++i) {
		struct mux_control *mux = &mux_chip->mux[i];

		if (mux->idle_state == mux->cached_state)
			continue;

		ret = mux_control_set(mux, mux->idle_state);
		if (ret < 0) {
			dev_err(dev, "unable to set idle state\n");
			return ret;
		}
	}
	return 0;
}

int dm_mux_init(void)
{
	struct uclass *uc;
	struct udevice *dev;
	int ret;

	ret = uclass_get(UCLASS_MUX, &uc);
	if (ret < 0) {
		log_debug("unable to get MUX uclass\n");
		return ret;
	}
	uclass_foreach_dev(dev, uc) {
		if (dev_read_bool(dev, "u-boot,mux-autoprobe") ||
		    dev_read_bool(dev, "idle-states")) {
			ret = device_probe(dev);
			if (ret)
				log_debug("unable to probe device %s\n",
					  dev->name);
		}
	}

	return 0;
}

UCLASS_DRIVER(mux) = {
	.id		= UCLASS_MUX,
	.name		= "mux",
	.post_probe	= mux_uclass_post_probe,
	.per_device_auto	= sizeof(struct mux_chip),
};
