/*
 * Copyright (C) 2016 Maxime Ripard
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>

#include "ccu_gate.h"
#include "ccu_mux.h"

void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
					     struct ccu_mux_internal *cm,
					     int parent_index,
					     unsigned long *parent_rate)
{
	u16 prediv = 1;
	u32 reg;
	int i;

	if (!((common->features & CCU_FEATURE_FIXED_PREDIV) ||
	      (common->features & CCU_FEATURE_VARIABLE_PREDIV) ||
	      (common->features & CCU_FEATURE_ALL_PREDIV)))
		return;

	if (common->features & CCU_FEATURE_ALL_PREDIV) {
		*parent_rate = *parent_rate / common->prediv;
		return;
	}

	reg = readl(common->base + common->reg);
	if (parent_index < 0) {
		parent_index = reg >> cm->shift;
		parent_index &= (1 << cm->width) - 1;
	}

	if (common->features & CCU_FEATURE_FIXED_PREDIV)
		for (i = 0; i < cm->n_predivs; i++)
			if (parent_index == cm->fixed_predivs[i].index)
				prediv = cm->fixed_predivs[i].div;

	if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
		if (parent_index == cm->variable_prediv.index) {
			u8 div;

			div = reg >> cm->variable_prediv.shift;
			div &= (1 << cm->variable_prediv.width) - 1;
			prediv = div + 1;
		}

	*parent_rate = *parent_rate / prediv;
}

int ccu_mux_helper_determine_rate(struct ccu_common *common,
				  struct ccu_mux_internal *cm,
				  struct clk_rate_request *req,
				  unsigned long (*round)(struct ccu_mux_internal *,
							 unsigned long,
							 unsigned long,
							 void *),
				  void *data)
{
	unsigned long best_parent_rate = 0, best_rate = 0;
	struct clk_hw *best_parent, *hw = &common->hw;
	unsigned int i;

	if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
		unsigned long adj_parent_rate;

		best_parent = clk_hw_get_parent(hw);
		best_parent_rate = clk_hw_get_rate(best_parent);

		adj_parent_rate = best_parent_rate;
		ccu_mux_helper_adjust_parent_for_prediv(common, cm, -1,
							&adj_parent_rate);

		best_rate = round(cm, adj_parent_rate, req->rate, data);

		goto out;
	}

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

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

		if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
			struct clk_rate_request parent_req = *req;
			int ret = __clk_determine_rate(parent, &parent_req);

			if (ret)
				continue;

			parent_rate = parent_req.rate;
		} else {
			parent_rate = clk_hw_get_rate(parent);
		}

		adj_parent_rate = parent_rate;
		ccu_mux_helper_adjust_parent_for_prediv(common, cm, i,
							&adj_parent_rate);

		tmp_rate = round(cm, adj_parent_rate, req->rate, data);
		if (tmp_rate == req->rate) {
			best_parent = parent;
			best_parent_rate = parent_rate;
			best_rate = tmp_rate;
			goto out;
		}

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

	if (best_rate == 0)
		return -EINVAL;

out:
	req->best_parent_hw = best_parent;
	req->best_parent_rate = best_parent_rate;
	req->rate = best_rate;
	return 0;
}

u8 ccu_mux_helper_get_parent(struct ccu_common *common,
			     struct ccu_mux_internal *cm)
{
	u32 reg;
	u8 parent;

	reg = readl(common->base + common->reg);
	parent = reg >> cm->shift;
	parent &= (1 << cm->width) - 1;

	if (cm->table) {
		int num_parents = clk_hw_get_num_parents(&common->hw);
		int i;

		for (i = 0; i < num_parents; i++)
			if (cm->table[i] == parent)
				return i;
	}

	return parent;
}

int ccu_mux_helper_set_parent(struct ccu_common *common,
			      struct ccu_mux_internal *cm,
			      u8 index)
{
	unsigned long flags;
	u32 reg;

	if (cm->table)
		index = cm->table[index];

	spin_lock_irqsave(common->lock, flags);

	reg = readl(common->base + common->reg);
	reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
	writel(reg | (index << cm->shift), common->base + common->reg);

	spin_unlock_irqrestore(common->lock, flags);

	return 0;
}

static void ccu_mux_disable(struct clk_hw *hw)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	return ccu_gate_helper_disable(&cm->common, cm->enable);
}

static int ccu_mux_enable(struct clk_hw *hw)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	return ccu_gate_helper_enable(&cm->common, cm->enable);
}

static int ccu_mux_is_enabled(struct clk_hw *hw)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
}

static u8 ccu_mux_get_parent(struct clk_hw *hw)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
}

static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
}

static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
					 unsigned long parent_rate)
{
	struct ccu_mux *cm = hw_to_ccu_mux(hw);

	ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
						&parent_rate);

	return parent_rate;
}

const struct clk_ops ccu_mux_ops = {
	.disable	= ccu_mux_disable,
	.enable		= ccu_mux_enable,
	.is_enabled	= ccu_mux_is_enabled,

	.get_parent	= ccu_mux_get_parent,
	.set_parent	= ccu_mux_set_parent,

	.determine_rate	= __clk_mux_determine_rate,
	.recalc_rate	= ccu_mux_recalc_rate,
};

/*
 * This clock notifier is called when the frequency of the of the parent
 * PLL clock is to be changed. The idea is to switch the parent to a
 * stable clock, such as the main oscillator, while the PLL frequency
 * stabilizes.
 */
static int ccu_mux_notifier_cb(struct notifier_block *nb,
			       unsigned long event, void *data)
{
	struct ccu_mux_nb *mux = to_ccu_mux_nb(nb);
	int ret = 0;

	if (event == PRE_RATE_CHANGE) {
		mux->original_index = ccu_mux_helper_get_parent(mux->common,
								mux->cm);
		ret = ccu_mux_helper_set_parent(mux->common, mux->cm,
						mux->bypass_index);
	} else if (event == POST_RATE_CHANGE) {
		ret = ccu_mux_helper_set_parent(mux->common, mux->cm,
						mux->original_index);
	}

	udelay(mux->delay_us);

	return notifier_from_errno(ret);
}

int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb)
{
	mux_nb->clk_nb.notifier_call = ccu_mux_notifier_cb;

	return clk_notifier_register(clk, &mux_nb->clk_nb);
}
