// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2013 STMicroelectronics Limited
 * Author: Stephen Gallimore <stephen.gallimore@st.com>
 *
 * Inspired by mach-imx/src.c
 */
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>

#include "reset-syscfg.h"

/**
 * struct syscfg_reset_channel - Reset channel regmap configuration
 *
 * @reset: regmap field for the channel's reset bit.
 * @ack: regmap field for the channel's ack bit (optional).
 */
struct syscfg_reset_channel {
	struct regmap_field *reset;
	struct regmap_field *ack;
};

/**
 * struct syscfg_reset_controller - A reset controller which groups together
 * a set of related reset bits, which may be located in different system
 * configuration registers.
 *
 * @rst: base reset controller structure.
 * @active_low: are the resets in this controller active low, i.e. clearing
 *              the reset bit puts the hardware into reset.
 * @channels: An array of reset channels for this controller.
 */
struct syscfg_reset_controller {
	struct reset_controller_dev rst;
	bool active_low;
	struct syscfg_reset_channel channels[];
};

#define to_syscfg_reset_controller(_rst) \
	container_of(_rst, struct syscfg_reset_controller, rst)

static int syscfg_reset_program_hw(struct reset_controller_dev *rcdev,
				   unsigned long idx, int assert)
{
	struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev);
	const struct syscfg_reset_channel *ch;
	u32 ctrl_val = rst->active_low ? !assert : !!assert;
	int err;

	if (idx >= rcdev->nr_resets)
		return -EINVAL;

	ch = &rst->channels[idx];

	err = regmap_field_write(ch->reset, ctrl_val);
	if (err)
		return err;

	if (ch->ack) {
		u32 ack_val;

		err = regmap_field_read_poll_timeout(ch->ack, ack_val, (ack_val == ctrl_val),
						     100, USEC_PER_SEC);
		if (err)
			return err;
	}

	return 0;
}

static int syscfg_reset_assert(struct reset_controller_dev *rcdev,
			       unsigned long idx)
{
	return syscfg_reset_program_hw(rcdev, idx, true);
}

static int syscfg_reset_deassert(struct reset_controller_dev *rcdev,
				 unsigned long idx)
{
	return syscfg_reset_program_hw(rcdev, idx, false);
}

static int syscfg_reset_dev(struct reset_controller_dev *rcdev,
			    unsigned long idx)
{
	int err;

	err = syscfg_reset_assert(rcdev, idx);
	if (err)
		return err;

	return syscfg_reset_deassert(rcdev, idx);
}

static int syscfg_reset_status(struct reset_controller_dev *rcdev,
			       unsigned long idx)
{
	struct syscfg_reset_controller *rst = to_syscfg_reset_controller(rcdev);
	const struct syscfg_reset_channel *ch;
	u32 ret_val = 0;
	int err;

	if (idx >= rcdev->nr_resets)
		return -EINVAL;

	ch = &rst->channels[idx];
	if (ch->ack)
		err = regmap_field_read(ch->ack, &ret_val);
	else
		err = regmap_field_read(ch->reset, &ret_val);
	if (err)
		return err;

	return rst->active_low ? !ret_val : !!ret_val;
}

static const struct reset_control_ops syscfg_reset_ops = {
	.reset    = syscfg_reset_dev,
	.assert   = syscfg_reset_assert,
	.deassert = syscfg_reset_deassert,
	.status   = syscfg_reset_status,
};

static int syscfg_reset_controller_register(struct device *dev,
				const struct syscfg_reset_controller_data *data)
{
	struct syscfg_reset_controller *rc;
	int i, err;

	rc = devm_kzalloc(dev, struct_size(rc, channels, data->nr_channels), GFP_KERNEL);
	if (!rc)
		return -ENOMEM;

	rc->rst.ops = &syscfg_reset_ops;
	rc->rst.of_node = dev->of_node;
	rc->rst.nr_resets = data->nr_channels;
	rc->active_low = data->active_low;

	for (i = 0; i < data->nr_channels; i++) {
		struct regmap *map;
		struct regmap_field *f;
		const char *compatible = data->channels[i].compatible;

		map = syscon_regmap_lookup_by_compatible(compatible);
		if (IS_ERR(map))
			return PTR_ERR(map);

		f = devm_regmap_field_alloc(dev, map, data->channels[i].reset);
		if (IS_ERR(f))
			return PTR_ERR(f);

		rc->channels[i].reset = f;

		if (!data->wait_for_ack)
			continue;

		f = devm_regmap_field_alloc(dev, map, data->channels[i].ack);
		if (IS_ERR(f))
			return PTR_ERR(f);

		rc->channels[i].ack = f;
	}

	err = reset_controller_register(&rc->rst);
	if (!err)
		dev_info(dev, "registered\n");

	return err;
}

int syscfg_reset_probe(struct platform_device *pdev)
{
	struct device *dev = pdev ? &pdev->dev : NULL;
	const void *data;

	if (!dev || !dev->driver)
		return -ENODEV;

	data = device_get_match_data(&pdev->dev);
	if (!data)
		return -EINVAL;

	return syscfg_reset_controller_register(dev, data);
}
