// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 */

#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>
#include "clk.h"

/**
 * struct clk_ref - mxs reference clock
 * @hw: clk_hw for the reference clock
 * @reg: register address
 * @idx: the index of the reference clock within the same register
 *
 * The mxs reference clock sources from pll.  Every 4 reference clocks share
 * one register space, and @idx is used to identify them.  Each reference
 * clock has a gate control and a fractional * divider.  The rate is calculated
 * as pll rate  * (18 / FRAC), where FRAC = 18 ~ 35.
 */
struct clk_ref {
	struct clk_hw hw;
	void __iomem *reg;
	u8 idx;
};

#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw)

static int clk_ref_enable(struct clk_hw *hw)
{
	struct clk_ref *ref = to_clk_ref(hw);

	writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR);

	return 0;
}

static void clk_ref_disable(struct clk_hw *hw)
{
	struct clk_ref *ref = to_clk_ref(hw);

	writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET);
}

static unsigned long clk_ref_recalc_rate(struct clk_hw *hw,
					 unsigned long parent_rate)
{
	struct clk_ref *ref = to_clk_ref(hw);
	u64 tmp = parent_rate;
	u8 frac = (readl_relaxed(ref->reg) >> (ref->idx * 8)) & 0x3f;

	tmp *= 18;
	do_div(tmp, frac);

	return tmp;
}

static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long *prate)
{
	unsigned long parent_rate = *prate;
	u64 tmp = parent_rate;
	u8 frac;

	tmp = tmp * 18 + rate / 2;
	do_div(tmp, rate);
	frac = tmp;

	if (frac < 18)
		frac = 18;
	else if (frac > 35)
		frac = 35;

	tmp = parent_rate;
	tmp *= 18;
	do_div(tmp, frac);

	return tmp;
}

static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate,
			    unsigned long parent_rate)
{
	struct clk_ref *ref = to_clk_ref(hw);
	unsigned long flags;
	u64 tmp = parent_rate;
	u32 val;
	u8 frac, shift = ref->idx * 8;

	tmp = tmp * 18 + rate / 2;
	do_div(tmp, rate);
	frac = tmp;

	if (frac < 18)
		frac = 18;
	else if (frac > 35)
		frac = 35;

	spin_lock_irqsave(&mxs_lock, flags);

	val = readl_relaxed(ref->reg);
	val &= ~(0x3f << shift);
	val |= frac << shift;
	writel_relaxed(val, ref->reg);

	spin_unlock_irqrestore(&mxs_lock, flags);

	return 0;
}

static const struct clk_ops clk_ref_ops = {
	.enable		= clk_ref_enable,
	.disable	= clk_ref_disable,
	.recalc_rate	= clk_ref_recalc_rate,
	.round_rate	= clk_ref_round_rate,
	.set_rate	= clk_ref_set_rate,
};

struct clk *mxs_clk_ref(const char *name, const char *parent_name,
			void __iomem *reg, u8 idx)
{
	struct clk_ref *ref;
	struct clk *clk;
	struct clk_init_data init;

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

	init.name = name;
	init.ops = &clk_ref_ops;
	init.flags = 0;
	init.parent_names = (parent_name ? &parent_name: NULL);
	init.num_parents = (parent_name ? 1 : 0);

	ref->reg = reg;
	ref->idx = idx;
	ref->hw.init = &init;

	clk = clk_register(NULL, &ref->hw);
	if (IS_ERR(clk))
		kfree(ref);

	return clk;
}
