// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022 MediaTek Inc.
 * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
 */

#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clkdev.h>
#include <linux/delay.h>

#include "clk-mtk.h"
#include "clk-pllfh.h"
#include "clk-fhctl.h"

static DEFINE_SPINLOCK(pllfh_lock);

inline struct mtk_fh *to_mtk_fh(struct clk_hw *hw)
{
	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);

	return container_of(pll, struct mtk_fh, clk_pll);
}

static int mtk_fhctl_set_rate(struct clk_hw *hw, unsigned long rate,
			      unsigned long parent_rate)
{
	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
	struct mtk_fh *fh = to_mtk_fh(hw);
	u32 pcw = 0;
	u32 postdiv;

	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);

	return fh->ops->hopping(fh, pcw, postdiv);
}

static const struct clk_ops mtk_pllfh_ops = {
	.is_prepared	= mtk_pll_is_prepared,
	.prepare	= mtk_pll_prepare,
	.unprepare	= mtk_pll_unprepare,
	.recalc_rate	= mtk_pll_recalc_rate,
	.round_rate	= mtk_pll_round_rate,
	.set_rate	= mtk_fhctl_set_rate,
};

static struct mtk_pllfh_data *get_pllfh_by_id(struct mtk_pllfh_data *pllfhs,
					      int num_fhs, int pll_id)
{
	int i;

	for (i = 0; i < num_fhs; i++)
		if (pllfhs[i].data.pll_id == pll_id)
			return &pllfhs[i];

	return NULL;
}

void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs,
		    int num_fhs)
{
	void __iomem *base;
	struct device_node *node;
	u32 num_clocks, pll_id, ssc_rate;
	int offset, i;

	node = of_find_compatible_node(NULL, NULL, compatible_node);
	if (!node) {
		pr_err("cannot find \"%s\"\n", compatible_node);
		return;
	}

	base = of_iomap(node, 0);
	if (!base) {
		pr_err("%s(): ioremap failed\n", __func__);
		return;
	}

	num_clocks = of_clk_get_parent_count(node);
	if (!num_clocks) {
		pr_err("%s(): failed to get clocks property\n", __func__);
		return;
	}

	for (i = 0; i < num_clocks; i++) {
		struct mtk_pllfh_data *pllfh;

		offset = i * 2;

		of_property_read_u32_index(node, "clocks", offset + 1, &pll_id);
		of_property_read_u32_index(node,
					   "mediatek,hopping-ssc-percent",
					   i, &ssc_rate);

		pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll_id);
		if (!pllfh)
			continue;

		pllfh->state.fh_enable = 1;
		pllfh->state.ssc_rate = ssc_rate;
		pllfh->state.base = base;
	}
}

static void pllfh_init(struct mtk_fh *fh, struct mtk_pllfh_data *pllfh_data)
{
	struct fh_pll_regs *regs = &fh->regs;
	const struct fhctl_offset *offset;
	void __iomem *base = pllfh_data->state.base;
	void __iomem *fhx_base = base + pllfh_data->data.fhx_offset;

	offset = fhctl_get_offset_table();

	regs->reg_hp_en = base + offset->offset_hp_en;
	regs->reg_clk_con = base + offset->offset_clk_con;
	regs->reg_rst_con = base + offset->offset_rst_con;
	regs->reg_slope0 = base + offset->offset_slope0;
	regs->reg_slope1 = base + offset->offset_slope1;

	regs->reg_cfg = fhx_base + offset->offset_cfg;
	regs->reg_updnlmt = fhx_base + offset->offset_updnlmt;
	regs->reg_dds = fhx_base + offset->offset_dds;
	regs->reg_dvfs = fhx_base + offset->offset_dvfs;
	regs->reg_mon = fhx_base + offset->offset_mon;

	fh->pllfh_data = pllfh_data;
	fh->lock = &pllfh_lock;

	fh->ops = fhctl_get_ops();
}

static bool fhctl_is_supported_and_enabled(const struct mtk_pllfh_data *pllfh)
{
	return pllfh && (pllfh->state.fh_enable == 1);
}

static struct clk_hw *
mtk_clk_register_pllfh(const struct mtk_pll_data *pll_data,
		       struct mtk_pllfh_data *pllfh_data, void __iomem *base)
{
	struct clk_hw *hw;
	struct mtk_fh *fh;

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

	pllfh_init(fh, pllfh_data);

	hw = mtk_clk_register_pll_ops(&fh->clk_pll, pll_data, base,
				      &mtk_pllfh_ops);

	if (IS_ERR(hw))
		kfree(fh);
	else
		fhctl_hw_init(fh);

	return hw;
}

static void mtk_clk_unregister_pllfh(struct clk_hw *hw)
{
	struct mtk_fh *fh;

	if (!hw)
		return;

	fh = to_mtk_fh(hw);

	clk_hw_unregister(hw);
	kfree(fh);
}

int mtk_clk_register_pllfhs(struct device_node *node,
			    const struct mtk_pll_data *plls, int num_plls,
			    struct mtk_pllfh_data *pllfhs, int num_fhs,
			    struct clk_hw_onecell_data *clk_data)
{
	void __iomem *base;
	int i;
	struct clk_hw *hw;

	base = of_iomap(node, 0);
	if (!base) {
		pr_err("%s(): ioremap failed\n", __func__);
		return -EINVAL;
	}

	for (i = 0; i < num_plls; i++) {
		const struct mtk_pll_data *pll = &plls[i];
		struct mtk_pllfh_data *pllfh;
		bool use_fhctl;

		pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
		use_fhctl = fhctl_is_supported_and_enabled(pllfh);

		if (use_fhctl)
			hw = mtk_clk_register_pllfh(pll, pllfh, base);
		else
			hw = mtk_clk_register_pll(pll, base);

		if (IS_ERR(hw)) {
			pr_err("Failed to register %s clk %s: %ld\n",
			       use_fhctl ? "fhpll" : "pll", pll->name,
			       PTR_ERR(hw));
			goto err;
		}

		clk_data->hws[pll->id] = hw;
	}

	return 0;

err:
	while (--i >= 0) {
		const struct mtk_pll_data *pll = &plls[i];
		struct mtk_pllfh_data *pllfh;
		bool use_fhctl;

		pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
		use_fhctl = fhctl_is_supported_and_enabled(pllfh);

		if (use_fhctl)
			mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
		else
			mtk_clk_unregister_pll(clk_data->hws[pll->id]);

		clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
	}

	iounmap(base);

	return PTR_ERR(hw);
}

void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_plls,
			       struct mtk_pllfh_data *pllfhs, int num_fhs,
			       struct clk_hw_onecell_data *clk_data)
{
	void __iomem *base = NULL, *fhctl_base = NULL;
	int i;

	if (!clk_data)
		return;

	for (i = num_plls; i > 0; i--) {
		const struct mtk_pll_data *pll = &plls[i - 1];
		struct mtk_pllfh_data *pllfh;
		bool use_fhctl;

		if (IS_ERR_OR_NULL(clk_data->hws[pll->id]))
			continue;

		pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
		use_fhctl = fhctl_is_supported_and_enabled(pllfh);

		if (use_fhctl) {
			fhctl_base = pllfh->state.base;
			mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
		} else {
			base = mtk_clk_pll_get_base(clk_data->hws[pll->id],
						    pll);
			mtk_clk_unregister_pll(clk_data->hws[pll->id]);
		}

		clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
	}

	if (fhctl_base)
		iounmap(fhctl_base);

	iounmap(base);
}
