// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2018 NXP
 */

#include <linux/clk-provider.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/slab.h>

#include "clk.h"

#define PCG_PREDIV_SHIFT	16
#define PCG_PREDIV_WIDTH	3
#define PCG_PREDIV_MAX		8

#define PCG_DIV_SHIFT		0
#define PCG_CORE_DIV_WIDTH	3
#define PCG_DIV_WIDTH		6
#define PCG_DIV_MAX		64

#define PCG_PCS_SHIFT		24
#define PCG_PCS_MASK		0x7

#define PCG_CGC_SHIFT		28

static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
						unsigned long parent_rate)
{
	struct clk_divider *divider = to_clk_divider(hw);
	unsigned long prediv_rate;
	unsigned int prediv_value;
	unsigned int div_value;

	prediv_value = readl(divider->reg) >> divider->shift;
	prediv_value &= clk_div_mask(divider->width);

	prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
						NULL, divider->flags,
						divider->width);

	div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
	div_value &= clk_div_mask(PCG_DIV_WIDTH);

	return divider_recalc_rate(hw, prediv_rate, div_value, NULL,
				   divider->flags, PCG_DIV_WIDTH);
}

static int imx8m_clk_composite_compute_dividers(unsigned long rate,
						unsigned long parent_rate,
						int *prediv, int *postdiv)
{
	int div1, div2;
	int error = INT_MAX;
	int ret = -EINVAL;

	*prediv = 1;
	*postdiv = 1;

	for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
		for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
			int new_error = ((parent_rate / div1) / div2) - rate;

			if (abs(new_error) < abs(error)) {
				*prediv = div1;
				*postdiv = div2;
				error = new_error;
				ret = 0;
			}
		}
	}
	return ret;
}

static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
					unsigned long rate,
					unsigned long parent_rate)
{
	struct clk_divider *divider = to_clk_divider(hw);
	unsigned long flags;
	int prediv_value;
	int div_value;
	int ret;
	u32 orig, val;

	ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
						&prediv_value, &div_value);
	if (ret)
		return -EINVAL;

	spin_lock_irqsave(divider->lock, flags);

	orig = readl(divider->reg);
	val = orig & ~((clk_div_mask(divider->width) << divider->shift) |
		       (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));

	val |= (u32)(prediv_value  - 1) << divider->shift;
	val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;

	if (val != orig)
		writel(val, divider->reg);

	spin_unlock_irqrestore(divider->lock, flags);

	return ret;
}

static int imx8m_divider_determine_rate(struct clk_hw *hw,
				      struct clk_rate_request *req)
{
	struct clk_divider *divider = to_clk_divider(hw);
	int prediv_value;
	int div_value;

	/* if read only, just return current value */
	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
		u32 val;

		val = readl(divider->reg);
		prediv_value = val >> divider->shift;
		prediv_value &= clk_div_mask(divider->width);
		prediv_value++;

		div_value = val >> PCG_DIV_SHIFT;
		div_value &= clk_div_mask(PCG_DIV_WIDTH);
		div_value++;

		return divider_ro_determine_rate(hw, req, divider->table,
						 PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
						 divider->flags, prediv_value * div_value);
	}

	return divider_determine_rate(hw, req, divider->table,
				      PCG_PREDIV_WIDTH + PCG_DIV_WIDTH,
				      divider->flags);
}

static const struct clk_ops imx8m_clk_composite_divider_ops = {
	.recalc_rate = imx8m_clk_composite_divider_recalc_rate,
	.set_rate = imx8m_clk_composite_divider_set_rate,
	.determine_rate = imx8m_divider_determine_rate,
};

static u8 imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
{
	return clk_mux_ops.get_parent(hw);
}

static int imx8m_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_mux *mux = to_clk_mux(hw);
	u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
	unsigned long flags = 0;
	u32 reg;

	if (mux->lock)
		spin_lock_irqsave(mux->lock, flags);

	reg = readl(mux->reg);
	reg &= ~(mux->mask << mux->shift);
	val = val << mux->shift;
	reg |= val;
	/*
	 * write twice to make sure non-target interface
	 * SEL_A/B point the same clk input.
	 */
	writel(reg, mux->reg);
	writel(reg, mux->reg);

	if (mux->lock)
		spin_unlock_irqrestore(mux->lock, flags);

	return 0;
}

static int
imx8m_clk_composite_mux_determine_rate(struct clk_hw *hw,
				       struct clk_rate_request *req)
{
	return clk_mux_ops.determine_rate(hw, req);
}


static const struct clk_ops imx8m_clk_composite_mux_ops = {
	.get_parent = imx8m_clk_composite_mux_get_parent,
	.set_parent = imx8m_clk_composite_mux_set_parent,
	.determine_rate = imx8m_clk_composite_mux_determine_rate,
};

static int imx8m_clk_composite_gate_enable(struct clk_hw *hw)
{
	struct clk_gate *gate = to_clk_gate(hw);
	unsigned long flags;
	u32 val;

	spin_lock_irqsave(gate->lock, flags);

	val = readl(gate->reg);
	val |= BIT(gate->bit_idx);
	writel(val, gate->reg);

	spin_unlock_irqrestore(gate->lock, flags);

	return 0;
}

static void imx8m_clk_composite_gate_disable(struct clk_hw *hw)
{
	/* composite clk requires the disable hook */
}

static const struct clk_ops imx8m_clk_composite_gate_ops = {
	.enable = imx8m_clk_composite_gate_enable,
	.disable = imx8m_clk_composite_gate_disable,
	.is_enabled = clk_gate_is_enabled,
};

struct clk_hw *__imx8m_clk_hw_composite(const char *name,
					const char * const *parent_names,
					int num_parents, void __iomem *reg,
					u32 composite_flags,
					unsigned long flags)
{
	struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw;
	struct clk_hw *div_hw, *gate_hw = NULL;
	struct clk_divider *div;
	struct clk_gate *gate = NULL;
	struct clk_mux *mux;
	const struct clk_ops *divider_ops;
	const struct clk_ops *mux_ops;
	const struct clk_ops *gate_ops;

	mux = kzalloc_obj(*mux);
	if (!mux)
		return ERR_CAST(hw);

	mux_hw = &mux->hw;
	mux->reg = reg;
	mux->shift = PCG_PCS_SHIFT;
	mux->mask = PCG_PCS_MASK;
	mux->lock = &imx_ccm_lock;

	div = kzalloc_obj(*div);
	if (!div)
		goto free_mux;

	div_hw = &div->hw;
	div->reg = reg;
	if (composite_flags & IMX_COMPOSITE_CORE) {
		div->shift = PCG_DIV_SHIFT;
		div->width = PCG_CORE_DIV_WIDTH;
		divider_ops = &clk_divider_ops;
		mux_ops = &imx8m_clk_composite_mux_ops;
	} else if (composite_flags & IMX_COMPOSITE_BUS) {
		div->shift = PCG_PREDIV_SHIFT;
		div->width = PCG_PREDIV_WIDTH;
		divider_ops = &imx8m_clk_composite_divider_ops;
		mux_ops = &imx8m_clk_composite_mux_ops;
	} else {
		div->shift = PCG_PREDIV_SHIFT;
		div->width = PCG_PREDIV_WIDTH;
		divider_ops = &imx8m_clk_composite_divider_ops;
		mux_ops = &clk_mux_ops;
		if (!(composite_flags & IMX_COMPOSITE_FW_MANAGED))
			flags |= CLK_SET_PARENT_GATE;
	}

	div->lock = &imx_ccm_lock;
	div->flags = CLK_DIVIDER_ROUND_CLOSEST;

	/* skip registering the gate ops if M4 is enabled */
	gate = kzalloc_obj(*gate);
	if (!gate)
		goto free_div;

	gate_hw = &gate->hw;
	gate->reg = reg;
	gate->bit_idx = PCG_CGC_SHIFT;
	gate->lock = &imx_ccm_lock;
	if (!mcore_booted)
		gate_ops = &clk_gate_ops;
	else
		gate_ops = &imx8m_clk_composite_gate_ops;

	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
			mux_hw, mux_ops, div_hw,
			divider_ops, gate_hw, gate_ops, flags);
	if (IS_ERR(hw))
		goto free_gate;

	return hw;

free_gate:
	kfree(gate);
free_div:
	kfree(div);
free_mux:
	kfree(mux);
	return ERR_CAST(hw);
}
EXPORT_SYMBOL_GPL(__imx8m_clk_hw_composite);
