// SPDX-License-Identifier: GPL-2.0-only
/*
 * System Control and Power Interface (SCPI) Protocol based clock driver
 *
 * Copyright (C) 2015 ARM Ltd.
 */

#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/scpi_protocol.h>

struct scpi_clk {
	u32 id;
	struct clk_hw hw;
	struct scpi_dvfs_info *info;
	struct scpi_ops *scpi_ops;
};

#define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw)

static struct platform_device *cpufreq_dev;

static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
					  unsigned long parent_rate)
{
	struct scpi_clk *clk = to_scpi_clk(hw);

	return clk->scpi_ops->clk_get_val(clk->id);
}

static int scpi_clk_determine_rate(struct clk_hw *hw,
				   struct clk_rate_request *req)
{
	/*
	 * We can't figure out what rate it will be, so just return the
	 * rate back to the caller. scpi_clk_recalc_rate() will be called
	 * after the rate is set and we'll know what rate the clock is
	 * running at then.
	 */
	return 0;
}

static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
			     unsigned long parent_rate)
{
	struct scpi_clk *clk = to_scpi_clk(hw);

	return clk->scpi_ops->clk_set_val(clk->id, rate);
}

static const struct clk_ops scpi_clk_ops = {
	.recalc_rate = scpi_clk_recalc_rate,
	.determine_rate = scpi_clk_determine_rate,
	.set_rate = scpi_clk_set_rate,
};

/* find closest match to given frequency in OPP table */
static long __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
{
	int idx;
	unsigned long fmin = 0, fmax = ~0, ftmp;
	const struct scpi_opp *opp = clk->info->opps;

	for (idx = 0; idx < clk->info->count; idx++, opp++) {
		ftmp = opp->freq;
		if (ftmp >= rate) {
			if (ftmp <= fmax)
				fmax = ftmp;
			break;
		} else if (ftmp >= fmin) {
			fmin = ftmp;
		}
	}
	return fmax != ~0 ? fmax : fmin;
}

static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
					   unsigned long parent_rate)
{
	struct scpi_clk *clk = to_scpi_clk(hw);
	int idx = clk->scpi_ops->dvfs_get_idx(clk->id);
	const struct scpi_opp *opp;

	if (idx < 0)
		return 0;

	opp = clk->info->opps + idx;
	return opp->freq;
}

static int scpi_dvfs_determine_rate(struct clk_hw *hw,
				    struct clk_rate_request *req)
{
	struct scpi_clk *clk = to_scpi_clk(hw);

	req->rate = __scpi_dvfs_round_rate(clk, req->rate);

	return 0;
}

static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate)
{
	int idx, max_opp = clk->info->count;
	const struct scpi_opp *opp = clk->info->opps;

	for (idx = 0; idx < max_opp; idx++, opp++)
		if (opp->freq == rate)
			return idx;
	return -EINVAL;
}

static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate,
			      unsigned long parent_rate)
{
	struct scpi_clk *clk = to_scpi_clk(hw);
	int ret = __scpi_find_dvfs_index(clk, rate);

	if (ret < 0)
		return ret;
	return clk->scpi_ops->dvfs_set_idx(clk->id, (u8)ret);
}

static const struct clk_ops scpi_dvfs_ops = {
	.recalc_rate = scpi_dvfs_recalc_rate,
	.determine_rate = scpi_dvfs_determine_rate,
	.set_rate = scpi_dvfs_set_rate,
};

static const struct of_device_id scpi_clk_match[] __maybe_unused = {
	{ .compatible = "arm,scpi-dvfs-clocks", .data = &scpi_dvfs_ops, },
	{ .compatible = "arm,scpi-variable-clocks", .data = &scpi_clk_ops, },
	{}
};

static int
scpi_clk_ops_init(struct device *dev, const struct of_device_id *match,
		  struct scpi_clk *sclk, const char *name)
{
	struct clk_init_data init;
	unsigned long min = 0, max = 0;
	int ret;

	init.name = name;
	init.flags = 0;
	init.num_parents = 0;
	init.ops = match->data;
	sclk->hw.init = &init;
	sclk->scpi_ops = get_scpi_ops();

	if (init.ops == &scpi_dvfs_ops) {
		sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id);
		if (IS_ERR(sclk->info))
			return PTR_ERR(sclk->info);
	} else if (init.ops == &scpi_clk_ops) {
		if (sclk->scpi_ops->clk_get_range(sclk->id, &min, &max) || !max)
			return -EINVAL;
	} else {
		return -EINVAL;
	}

	ret = devm_clk_hw_register(dev, &sclk->hw);
	if (!ret && max)
		clk_hw_set_rate_range(&sclk->hw, min, max);
	return ret;
}

struct scpi_clk_data {
	struct scpi_clk **clk;
	unsigned int clk_num;
};

static struct clk_hw *
scpi_of_clk_src_get(struct of_phandle_args *clkspec, void *data)
{
	struct scpi_clk *sclk;
	struct scpi_clk_data *clk_data = data;
	unsigned int idx = clkspec->args[0], count;

	for (count = 0; count < clk_data->clk_num; count++) {
		sclk = clk_data->clk[count];
		if (idx == sclk->id)
			return &sclk->hw;
	}

	return ERR_PTR(-EINVAL);
}

static int scpi_clk_add(struct device *dev, struct device_node *np,
			const struct of_device_id *match)
{
	int idx, count, err;
	struct scpi_clk_data *clk_data;

	count = of_property_count_strings(np, "clock-output-names");
	if (count < 0) {
		dev_err(dev, "%pOFn: invalid clock output count\n", np);
		return -EINVAL;
	}

	clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL);
	if (!clk_data)
		return -ENOMEM;

	clk_data->clk_num = count;
	clk_data->clk = devm_kcalloc(dev, count, sizeof(*clk_data->clk),
				     GFP_KERNEL);
	if (!clk_data->clk)
		return -ENOMEM;

	for (idx = 0; idx < count; idx++) {
		struct scpi_clk *sclk;
		const char *name;
		u32 val;

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

		if (of_property_read_string_index(np, "clock-output-names",
						  idx, &name)) {
			dev_err(dev, "invalid clock name @ %pOFn\n", np);
			return -EINVAL;
		}

		if (of_property_read_u32_index(np, "clock-indices",
					       idx, &val)) {
			dev_err(dev, "invalid clock index @ %pOFn\n", np);
			return -EINVAL;
		}

		sclk->id = val;

		err = scpi_clk_ops_init(dev, match, sclk, name);
		if (err) {
			dev_err(dev, "failed to register clock '%s'\n", name);
			return err;
		}

		dev_dbg(dev, "Registered clock '%s'\n", name);
		clk_data->clk[idx] = sclk;
	}

	return of_clk_add_hw_provider(np, scpi_of_clk_src_get, clk_data);
}

static void scpi_clocks_remove(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *child, *np = dev->of_node;

	if (cpufreq_dev) {
		platform_device_unregister(cpufreq_dev);
		cpufreq_dev = NULL;
	}

	for_each_available_child_of_node(np, child)
		of_clk_del_provider(np);
}

static int scpi_clocks_probe(struct platform_device *pdev)
{
	int ret;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	const struct of_device_id *match;

	if (!get_scpi_ops())
		return -ENXIO;

	for_each_available_child_of_node_scoped(np, child) {
		match = of_match_node(scpi_clk_match, child);
		if (!match)
			continue;
		ret = scpi_clk_add(dev, child, match);
		if (ret) {
			scpi_clocks_remove(pdev);
			return ret;
		}

		if (match->data != &scpi_dvfs_ops)
			continue;
		/* Add the virtual cpufreq device if it's DVFS clock provider */
		cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
							      -1, NULL, 0);
		if (IS_ERR(cpufreq_dev))
			pr_warn("unable to register cpufreq device");
	}
	return 0;
}

static const struct of_device_id scpi_clocks_ids[] = {
	{ .compatible = "arm,scpi-clocks", },
	{}
};
MODULE_DEVICE_TABLE(of, scpi_clocks_ids);

static struct platform_driver scpi_clocks_driver = {
	.driver	= {
		.name = "scpi_clocks",
		.of_match_table = scpi_clocks_ids,
	},
	.probe = scpi_clocks_probe,
	.remove = scpi_clocks_remove,
};
module_platform_driver(scpi_clocks_driver);

MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
MODULE_DESCRIPTION("ARM SCPI clock driver");
MODULE_LICENSE("GPL v2");
