// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2015 Maxime Ripard
 *
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 */

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

#define TCON_CH1_SCLK2_PARENTS		4

#define TCON_CH1_SCLK2_GATE_BIT		BIT(31)
#define TCON_CH1_SCLK2_MUX_MASK		3
#define TCON_CH1_SCLK2_MUX_SHIFT	24
#define TCON_CH1_SCLK2_DIV_MASK		0xf
#define TCON_CH1_SCLK2_DIV_SHIFT	0

#define TCON_CH1_SCLK1_GATE_BIT		BIT(15)
#define TCON_CH1_SCLK1_HALF_BIT		BIT(11)

struct tcon_ch1_clk {
	struct clk_hw	hw;
	spinlock_t	lock;
	void __iomem	*reg;
};

#define hw_to_tclk(hw)	container_of(hw, struct tcon_ch1_clk, hw)

static void tcon_ch1_disable(struct clk_hw *hw)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	unsigned long flags;
	u32 reg;

	spin_lock_irqsave(&tclk->lock, flags);
	reg = readl(tclk->reg);
	reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
	writel(reg, tclk->reg);
	spin_unlock_irqrestore(&tclk->lock, flags);
}

static int tcon_ch1_enable(struct clk_hw *hw)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	unsigned long flags;
	u32 reg;

	spin_lock_irqsave(&tclk->lock, flags);
	reg = readl(tclk->reg);
	reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT;
	writel(reg, tclk->reg);
	spin_unlock_irqrestore(&tclk->lock, flags);

	return 0;
}

static int tcon_ch1_is_enabled(struct clk_hw *hw)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	u32 reg;

	reg = readl(tclk->reg);
	return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
}

static u8 tcon_ch1_get_parent(struct clk_hw *hw)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	u32 reg;

	reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT;
	reg &= reg >> TCON_CH1_SCLK2_MUX_MASK;

	return reg;
}

static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	unsigned long flags;
	u32 reg;

	spin_lock_irqsave(&tclk->lock, flags);
	reg = readl(tclk->reg);
	reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT);
	reg |= index << TCON_CH1_SCLK2_MUX_SHIFT;
	writel(reg, tclk->reg);
	spin_unlock_irqrestore(&tclk->lock, flags);

	return 0;
};

static unsigned long tcon_ch1_calc_divider(unsigned long rate,
					   unsigned long parent_rate,
					   u8 *div,
					   bool *half)
{
	unsigned long best_rate = 0;
	u8 best_m = 0, m;
	bool is_double;

	for (m = 1; m < 16; m++) {
		u8 d;

		for (d = 1; d < 3; d++) {
			unsigned long tmp_rate;

			tmp_rate = parent_rate / m / d;

			if (tmp_rate > rate)
				continue;

			if (!best_rate ||
			    (rate - tmp_rate) < (rate - best_rate)) {
				best_rate = tmp_rate;
				best_m = m;
				is_double = d;
			}
		}
	}

	if (div && half) {
		*div = best_m;
		*half = is_double;
	}

	return best_rate;
}

static int tcon_ch1_determine_rate(struct clk_hw *hw,
				   struct clk_rate_request *req)
{
	long best_rate = -EINVAL;
	int i;

	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
		unsigned long parent_rate;
		unsigned long tmp_rate;
		struct clk_hw *parent;

		parent = clk_hw_get_parent_by_index(hw, i);
		if (!parent)
			continue;

		parent_rate = clk_hw_get_rate(parent);

		tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate,
						 NULL, NULL);

		if (best_rate < 0 ||
		    (req->rate - tmp_rate) < (req->rate - best_rate)) {
			best_rate = tmp_rate;
			req->best_parent_rate = parent_rate;
			req->best_parent_hw = parent;
		}
	}

	if (best_rate < 0)
		return best_rate;

	req->rate = best_rate;
	return 0;
}

static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw,
					  unsigned long parent_rate)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	u32 reg;

	reg = readl(tclk->reg);

	parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1;

	if (reg & TCON_CH1_SCLK1_HALF_BIT)
		parent_rate /= 2;

	return parent_rate;
}

static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate,
			     unsigned long parent_rate)
{
	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
	unsigned long flags;
	bool half;
	u8 div_m;
	u32 reg;

	tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half);

	spin_lock_irqsave(&tclk->lock, flags);
	reg = readl(tclk->reg);
	reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT);
	reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK;

	if (half)
		reg |= TCON_CH1_SCLK1_HALF_BIT;

	writel(reg, tclk->reg);
	spin_unlock_irqrestore(&tclk->lock, flags);

	return 0;
}

static const struct clk_ops tcon_ch1_ops = {
	.disable	= tcon_ch1_disable,
	.enable		= tcon_ch1_enable,
	.is_enabled	= tcon_ch1_is_enabled,

	.get_parent	= tcon_ch1_get_parent,
	.set_parent	= tcon_ch1_set_parent,

	.determine_rate	= tcon_ch1_determine_rate,
	.recalc_rate	= tcon_ch1_recalc_rate,
	.set_rate	= tcon_ch1_set_rate,
};

static void __init tcon_ch1_setup(struct device_node *node)
{
	const char *parents[TCON_CH1_SCLK2_PARENTS];
	const char *clk_name = node->name;
	struct clk_init_data init;
	struct tcon_ch1_clk *tclk;
	struct resource res;
	struct clk *clk;
	void __iomem *reg;
	int ret;

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

	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
	if (IS_ERR(reg)) {
		pr_err("%s: Could not map the clock registers\n", clk_name);
		return;
	}

	ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS);
	if (ret != TCON_CH1_SCLK2_PARENTS) {
		pr_err("%s Could not retrieve the parents\n", clk_name);
		goto err_unmap;
	}

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

	init.name = clk_name;
	init.ops = &tcon_ch1_ops;
	init.parent_names = parents;
	init.num_parents = TCON_CH1_SCLK2_PARENTS;
	init.flags = CLK_SET_RATE_PARENT;

	tclk->reg = reg;
	tclk->hw.init = &init;
	spin_lock_init(&tclk->lock);

	clk = clk_register(NULL, &tclk->hw);
	if (IS_ERR(clk)) {
		pr_err("%s: Couldn't register the clock\n", clk_name);
		goto err_free_data;
	}

	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
	if (ret) {
		pr_err("%s: Couldn't register our clock provider\n", clk_name);
		goto err_unregister_clk;
	}

	return;

err_unregister_clk:
	clk_unregister(clk);
err_free_data:
	kfree(tclk);
err_unmap:
	iounmap(reg);
	of_address_to_resource(node, 0, &res);
	release_mem_region(res.start, resource_size(&res));
}

CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk",
	       tcon_ch1_setup);
