// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2015 Chen-Yu Tsai
 *
 * Chen-Yu Tsai <wens@csie.org>
 *
 * Allwinner A80 CPUS clock driver
 *
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
#include <linux/of_address.h>

static DEFINE_SPINLOCK(sun9i_a80_cpus_lock);

/**
 * sun9i_a80_cpus_clk_setup() - Setup function for a80 cpus composite clk
 */

#define SUN9I_CPUS_MAX_PARENTS		4
#define SUN9I_CPUS_MUX_PARENT_PLL4	3
#define SUN9I_CPUS_MUX_SHIFT		16
#define SUN9I_CPUS_MUX_MASK		GENMASK(17, 16)
#define SUN9I_CPUS_MUX_GET_PARENT(reg)	((reg & SUN9I_CPUS_MUX_MASK) >> \
						SUN9I_CPUS_MUX_SHIFT)

#define SUN9I_CPUS_DIV_SHIFT		4
#define SUN9I_CPUS_DIV_MASK		GENMASK(5, 4)
#define SUN9I_CPUS_DIV_GET(reg)		((reg & SUN9I_CPUS_DIV_MASK) >> \
						SUN9I_CPUS_DIV_SHIFT)
#define SUN9I_CPUS_DIV_SET(reg, div)	((reg & ~SUN9I_CPUS_DIV_MASK) | \
						(div << SUN9I_CPUS_DIV_SHIFT))
#define SUN9I_CPUS_PLL4_DIV_SHIFT	8
#define SUN9I_CPUS_PLL4_DIV_MASK	GENMASK(12, 8)
#define SUN9I_CPUS_PLL4_DIV_GET(reg)	((reg & SUN9I_CPUS_PLL4_DIV_MASK) >> \
						SUN9I_CPUS_PLL4_DIV_SHIFT)
#define SUN9I_CPUS_PLL4_DIV_SET(reg, div) ((reg & ~SUN9I_CPUS_PLL4_DIV_MASK) | \
						(div << SUN9I_CPUS_PLL4_DIV_SHIFT))

struct sun9i_a80_cpus_clk {
	struct clk_hw hw;
	void __iomem *reg;
};

#define to_sun9i_a80_cpus_clk(_hw) container_of(_hw, struct sun9i_a80_cpus_clk, hw)

static unsigned long sun9i_a80_cpus_clk_recalc_rate(struct clk_hw *hw,
						    unsigned long parent_rate)
{
	struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
	unsigned long rate;
	u32 reg;

	/* Fetch the register value */
	reg = readl(cpus->reg);

	/* apply pre-divider first if parent is pll4 */
	if (SUN9I_CPUS_MUX_GET_PARENT(reg) == SUN9I_CPUS_MUX_PARENT_PLL4)
		parent_rate /= SUN9I_CPUS_PLL4_DIV_GET(reg) + 1;

	/* clk divider */
	rate = parent_rate / (SUN9I_CPUS_DIV_GET(reg) + 1);

	return rate;
}

static long sun9i_a80_cpus_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
				     u8 parent, unsigned long parent_rate)
{
	u8 div, pre_div = 1;

	/*
	 * clock can only divide, so we will never be able to achieve
	 * frequencies higher than the parent frequency
	 */
	if (parent_rate && rate > parent_rate)
		rate = parent_rate;

	div = DIV_ROUND_UP(parent_rate, rate);

	/* calculate pre-divider if parent is pll4 */
	if (parent == SUN9I_CPUS_MUX_PARENT_PLL4 && div > 4) {
		/* pre-divider is 1 ~ 32 */
		if (div < 32) {
			pre_div = div;
			div = 1;
		} else if (div < 64) {
			pre_div = DIV_ROUND_UP(div, 2);
			div = 2;
		} else if (div < 96) {
			pre_div = DIV_ROUND_UP(div, 3);
			div = 3;
		} else {
			pre_div = DIV_ROUND_UP(div, 4);
			div = 4;
		}
	}

	/* we were asked to pass back divider values */
	if (divp) {
		*divp = div - 1;
		*pre_divp = pre_div - 1;
	}

	return parent_rate / pre_div / div;
}

static int sun9i_a80_cpus_clk_determine_rate(struct clk_hw *clk,
					     struct clk_rate_request *req)
{
	struct clk_hw *parent, *best_parent = NULL;
	int i, num_parents;
	unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
	unsigned long rate = req->rate;

	/* find the parent that can help provide the fastest rate <= rate */
	num_parents = clk_hw_get_num_parents(clk);
	for (i = 0; i < num_parents; i++) {
		parent = clk_hw_get_parent_by_index(clk, i);
		if (!parent)
			continue;
		if (clk_hw_get_flags(clk) & CLK_SET_RATE_PARENT)
			parent_rate = clk_hw_round_rate(parent, rate);
		else
			parent_rate = clk_hw_get_rate(parent);

		child_rate = sun9i_a80_cpus_clk_round(rate, NULL, NULL, i,
						      parent_rate);

		if (child_rate <= rate && child_rate > best_child_rate) {
			best_parent = parent;
			best = parent_rate;
			best_child_rate = child_rate;
		}
	}

	if (!best_parent)
		return -EINVAL;

	req->best_parent_hw = best_parent;
	req->best_parent_rate = best;
	req->rate = best_child_rate;

	return 0;
}

static int sun9i_a80_cpus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
				       unsigned long parent_rate)
{
	struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
	unsigned long flags;
	u8 div, pre_div, parent;
	u32 reg;

	spin_lock_irqsave(&sun9i_a80_cpus_lock, flags);

	reg = readl(cpus->reg);

	/* need to know which parent is used to apply pre-divider */
	parent = SUN9I_CPUS_MUX_GET_PARENT(reg);
	sun9i_a80_cpus_clk_round(rate, &div, &pre_div, parent, parent_rate);

	reg = SUN9I_CPUS_DIV_SET(reg, div);
	reg = SUN9I_CPUS_PLL4_DIV_SET(reg, pre_div);
	writel(reg, cpus->reg);

	spin_unlock_irqrestore(&sun9i_a80_cpus_lock, flags);

	return 0;
}

static const struct clk_ops sun9i_a80_cpus_clk_ops = {
	.determine_rate	= sun9i_a80_cpus_clk_determine_rate,
	.recalc_rate	= sun9i_a80_cpus_clk_recalc_rate,
	.set_rate	= sun9i_a80_cpus_clk_set_rate,
};

static void sun9i_a80_cpus_setup(struct device_node *node)
{
	const char *clk_name = node->name;
	const char *parents[SUN9I_CPUS_MAX_PARENTS];
	struct resource res;
	struct sun9i_a80_cpus_clk *cpus;
	struct clk_mux *mux;
	struct clk *clk;
	int ret;

	cpus = kzalloc(sizeof(*cpus), GFP_KERNEL);
	if (!cpus)
		return;

	cpus->reg = of_io_request_and_map(node, 0, of_node_full_name(node));
	if (IS_ERR(cpus->reg))
		goto err_free_cpus;

	of_property_read_string(node, "clock-output-names", &clk_name);

	/* we have a mux, we will have >1 parents */
	ret = of_clk_parent_fill(node, parents, SUN9I_CPUS_MAX_PARENTS);

	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
	if (!mux)
		goto err_unmap;

	/* set up clock properties */
	mux->reg = cpus->reg;
	mux->shift = SUN9I_CPUS_MUX_SHIFT;
	/* un-shifted mask is what mux_clk expects */
	mux->mask = SUN9I_CPUS_MUX_MASK >> SUN9I_CPUS_MUX_SHIFT;
	mux->lock = &sun9i_a80_cpus_lock;

	clk = clk_register_composite(NULL, clk_name, parents, ret,
				     &mux->hw, &clk_mux_ops,
				     &cpus->hw, &sun9i_a80_cpus_clk_ops,
				     NULL, NULL, 0);
	if (IS_ERR(clk))
		goto err_free_mux;

	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
	if (ret)
		goto err_unregister;

	return;

err_unregister:
	clk_unregister(clk);
err_free_mux:
	kfree(mux);
err_unmap:
	iounmap(cpus->reg);
	of_address_to_resource(node, 0, &res);
	release_mem_region(res.start, resource_size(&res));
err_free_cpus:
	kfree(cpus);
}
CLK_OF_DECLARE(sun9i_a80_cpus, "allwinner,sun9i-a80-cpus-clk",
	       sun9i_a80_cpus_setup);
