// SPDX-License-Identifier: GPL-2.0-only
/*
 * Based on clk-super.c
 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
 *
 * Based on older tegra20-cpufreq driver by Colin Cross <ccross@google.com>
 * Copyright (C) 2010 Google, Inc.
 *
 * Author: Dmitry Osipenko <digetx@gmail.com>
 * Copyright (C) 2019 GRATE-DRIVER project
 */

#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/types.h>

#include "clk.h"

#define PLLP_INDEX		4
#define PLLX_INDEX		8

#define SUPER_CDIV_ENB		BIT(31)

#define TSENSOR_SLOWDOWN	BIT(23)

static struct tegra_clk_super_mux *cclk_super;
static bool cclk_on_pllx;

static u8 cclk_super_get_parent(struct clk_hw *hw)
{
	return tegra_clk_super_ops.get_parent(hw);
}

static int cclk_super_set_parent(struct clk_hw *hw, u8 index)
{
	return tegra_clk_super_ops.set_parent(hw, index);
}

static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long parent_rate)
{
	return tegra_clk_super_ops.set_rate(hw, rate, parent_rate);
}

static unsigned long cclk_super_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
	u32 val = readl_relaxed(super->reg);
	unsigned int div2;

	/* check whether thermal throttling is active */
	if (val & TSENSOR_SLOWDOWN)
		div2 = 1;
	else
		div2 = 0;

	if (cclk_super_get_parent(hw) == PLLX_INDEX)
		return parent_rate >> div2;

	return tegra_clk_super_ops.recalc_rate(hw, parent_rate) >> div2;
}

static int cclk_super_determine_rate(struct clk_hw *hw,
				     struct clk_rate_request *req)
{
	struct clk_hw *pllp_hw = clk_hw_get_parent_by_index(hw, PLLP_INDEX);
	struct clk_hw *pllx_hw = clk_hw_get_parent_by_index(hw, PLLX_INDEX);
	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
	unsigned long pllp_rate;
	long rate = req->rate;

	if (WARN_ON_ONCE(!pllp_hw || !pllx_hw))
		return -EINVAL;

	/*
	 * Switch parent to PLLP for all CCLK rates that are suitable for PLLP.
	 * PLLX will be disabled in this case, saving some power.
	 */
	pllp_rate = clk_hw_get_rate(pllp_hw);

	if (rate <= pllp_rate) {
		if (super->flags & TEGRA20_SUPER_CLK)
			rate = pllp_rate;
		else {
			struct clk_rate_request parent = {
				.rate = req->rate,
				.best_parent_rate = pllp_rate,
			};

			clk_hw_get_rate_range(hw, &parent.min_rate,
					      &parent.max_rate);
			tegra_clk_super_ops.determine_rate(hw, &parent);
			pllp_rate = parent.best_parent_rate;
			rate = parent.rate;
		}

		req->best_parent_rate = pllp_rate;
		req->best_parent_hw = pllp_hw;
		req->rate = rate;
	} else {
		rate = clk_hw_round_rate(pllx_hw, rate);
		req->best_parent_rate = rate;
		req->best_parent_hw = pllx_hw;
		req->rate = rate;
	}

	if (WARN_ON_ONCE(rate <= 0))
		return -EINVAL;

	return 0;
}

static const struct clk_ops tegra_cclk_super_ops = {
	.get_parent = cclk_super_get_parent,
	.set_parent = cclk_super_set_parent,
	.set_rate = cclk_super_set_rate,
	.recalc_rate = cclk_super_recalc_rate,
	.determine_rate = cclk_super_determine_rate,
};

static const struct clk_ops tegra_cclk_super_mux_ops = {
	.get_parent = cclk_super_get_parent,
	.set_parent = cclk_super_set_parent,
	.determine_rate = cclk_super_determine_rate,
};

struct clk *tegra_clk_register_super_cclk(const char *name,
		const char * const *parent_names, u8 num_parents,
		unsigned long flags, void __iomem *reg, u8 clk_super_flags,
		spinlock_t *lock)
{
	struct tegra_clk_super_mux *super;
	struct clk *clk;
	struct clk_init_data init;
	u32 val;

	if (WARN_ON(cclk_super))
		return ERR_PTR(-EBUSY);

	super = kzalloc(sizeof(*super), GFP_KERNEL);
	if (!super)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.flags = flags;
	init.parent_names = parent_names;
	init.num_parents = num_parents;

	super->reg = reg;
	super->lock = lock;
	super->width = 4;
	super->flags = clk_super_flags;
	super->hw.init = &init;

	if (super->flags & TEGRA20_SUPER_CLK) {
		init.ops = &tegra_cclk_super_mux_ops;
	} else {
		init.ops = &tegra_cclk_super_ops;

		super->frac_div.reg = reg + 4;
		super->frac_div.shift = 16;
		super->frac_div.width = 8;
		super->frac_div.frac_width = 1;
		super->frac_div.lock = lock;
		super->div_ops = &tegra_clk_frac_div_ops;
	}

	/*
	 * Tegra30+ has the following CPUG clock topology:
	 *
	 *        +---+  +-------+  +-+            +-+                +-+
	 * PLLP+->+   +->+DIVIDER+->+0|  +-------->+0|  ------------->+0|
	 *        |   |  +-------+  | |  |  +---+  | |  |             | |
	 * PLLC+->+MUX|             | +->+  | S |  | +->+             | +->+CPU
	 *  ...   |   |             | |  |  | K |  | |  |  +-------+  | |
	 * PLLX+->+-->+------------>+1|  +->+ I +->+1|  +->+ DIV2  +->+1|
	 *        +---+             +++     | P |  +++     |SKIPPER|  +++
	 *                           ^      | P |   ^      +-------+   ^
	 *                           |      | E |   |                  |
	 *                PLLX_SEL+--+      | R |   |       OVERHEAT+--+
	 *                                  +---+   |
	 *                                          |
	 *                         SUPER_CDIV_ENB+--+
	 *
	 * Tegra20 is similar, but simpler. It doesn't have the divider and
	 * thermal DIV2 skipper.
	 *
	 * At least for now we're not going to use clock-skipper, hence let's
	 * ensure that it is disabled.
	 */
	val = readl_relaxed(reg + 4);
	val &= ~SUPER_CDIV_ENB;
	writel_relaxed(val, reg + 4);

	clk = clk_register(NULL, &super->hw);
	if (IS_ERR(clk))
		kfree(super);
	else
		cclk_super = super;

	return clk;
}

int tegra_cclk_pre_pllx_rate_change(void)
{
	if (IS_ERR_OR_NULL(cclk_super))
		return -EINVAL;

	if (cclk_super_get_parent(&cclk_super->hw) == PLLX_INDEX)
		cclk_on_pllx = true;
	else
		cclk_on_pllx = false;

	/*
	 * CPU needs to be temporarily re-parented away from PLLX if PLLX
	 * changes its rate. PLLP is a safe parent for CPU on all Tegra SoCs.
	 */
	if (cclk_on_pllx)
		cclk_super_set_parent(&cclk_super->hw, PLLP_INDEX);

	return 0;
}

void tegra_cclk_post_pllx_rate_change(void)
{
	if (cclk_on_pllx)
		cclk_super_set_parent(&cclk_super->hw, PLLX_INDEX);
}
