/*
 * Marvell EBU SoC common clock handling
 *
 * Copyright (C) 2012 Marvell
 *
 * Gregory CLEMENT <gregory.clement@free-electrons.com>
 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 * Andrew Lunn <andrew@lunn.ch>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2.  This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>

#include "common.h"

/*
 * Core Clocks
 */

#define SSCG_CONF_MODE(reg)	(((reg) >> 16) & 0x3)
#define SSCG_SPREAD_DOWN	0x0
#define SSCG_SPREAD_UP		0x1
#define SSCG_SPREAD_CENTRAL	0x2
#define SSCG_CONF_LOW(reg)	(((reg) >> 8) & 0xFF)
#define SSCG_CONF_HIGH(reg)	((reg) & 0xFF)

static struct clk_onecell_data clk_data;

/*
 * This function can be used by the Kirkwood, the Armada 370, the
 * Armada XP and the Armada 375 SoC. The name of the function was
 * chosen following the dt convention: using the first known SoC
 * compatible with it.
 */
u32 kirkwood_fix_sscg_deviation(u32 system_clk)
{
	struct device_node *sscg_np = NULL;
	void __iomem *sscg_map;
	u32 sscg_reg;
	s32 low_bound, high_bound;
	u64 freq_swing_half;

	sscg_np = of_find_node_by_name(NULL, "sscg");
	if (sscg_np == NULL) {
		pr_err("cannot get SSCG register node\n");
		return system_clk;
	}

	sscg_map = of_iomap(sscg_np, 0);
	if (sscg_map == NULL) {
		pr_err("cannot map SSCG register\n");
		goto out;
	}

	sscg_reg = readl(sscg_map);
	high_bound = SSCG_CONF_HIGH(sscg_reg);
	low_bound = SSCG_CONF_LOW(sscg_reg);

	if ((high_bound - low_bound) <= 0)
		goto out;
	/*
	 * From Marvell engineer we got the following formula (when
	 * this code was written, the datasheet was erroneous)
	 * Spread percentage = 1/96 * (H - L) / H
	 * H = SSCG_High_Boundary
	 * L = SSCG_Low_Boundary
	 *
	 * As the deviation is half of spread then it lead to the
	 * following formula in the code.
	 *
	 * To avoid an overflow and not lose any significant digit in
	 * the same time we have to use a 64 bit integer.
	 */

	freq_swing_half = (((u64)high_bound - (u64)low_bound)
			* (u64)system_clk);
	do_div(freq_swing_half, (2 * 96 * high_bound));

	switch (SSCG_CONF_MODE(sscg_reg)) {
	case SSCG_SPREAD_DOWN:
		system_clk -= freq_swing_half;
		break;
	case SSCG_SPREAD_UP:
		system_clk += freq_swing_half;
		break;
	case SSCG_SPREAD_CENTRAL:
	default:
		break;
	}

	iounmap(sscg_map);

out:
	of_node_put(sscg_np);

	return system_clk;
}

void __init mvebu_coreclk_setup(struct device_node *np,
				const struct coreclk_soc_desc *desc)
{
	const char *tclk_name = "tclk";
	const char *cpuclk_name = "cpuclk";
	void __iomem *base;
	unsigned long rate;
	int n;

	base = of_iomap(np, 0);
	if (WARN_ON(!base))
		return;

	/* Allocate struct for TCLK, cpu clk, and core ratio clocks */
	clk_data.clk_num = 2 + desc->num_ratios;

	/* One more clock for the optional refclk */
	if (desc->get_refclk_freq)
		clk_data.clk_num += 1;

	clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
				GFP_KERNEL);
	if (WARN_ON(!clk_data.clks)) {
		iounmap(base);
		return;
	}

	/* Register TCLK */
	of_property_read_string_index(np, "clock-output-names", 0,
				      &tclk_name);
	rate = desc->get_tclk_freq(base);
	clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL, 0,
						   rate);
	WARN_ON(IS_ERR(clk_data.clks[0]));

	/* Register CPU clock */
	of_property_read_string_index(np, "clock-output-names", 1,
				      &cpuclk_name);
	rate = desc->get_cpu_freq(base);

	if (desc->is_sscg_enabled && desc->fix_sscg_deviation
		&& desc->is_sscg_enabled(base))
		rate = desc->fix_sscg_deviation(rate);

	clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL, 0,
						   rate);
	WARN_ON(IS_ERR(clk_data.clks[1]));

	/* Register fixed-factor clocks derived from CPU clock */
	for (n = 0; n < desc->num_ratios; n++) {
		const char *rclk_name = desc->ratios[n].name;
		int mult, div;

		of_property_read_string_index(np, "clock-output-names",
					      2+n, &rclk_name);
		desc->get_clk_ratio(base, desc->ratios[n].id, &mult, &div);
		clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
				       cpuclk_name, 0, mult, div);
		WARN_ON(IS_ERR(clk_data.clks[2+n]));
	}

	/* Register optional refclk */
	if (desc->get_refclk_freq) {
		const char *name = "refclk";
		of_property_read_string_index(np, "clock-output-names",
					      2 + desc->num_ratios, &name);
		rate = desc->get_refclk_freq(base);
		clk_data.clks[2 + desc->num_ratios] =
			clk_register_fixed_rate(NULL, name, NULL, 0, rate);
		WARN_ON(IS_ERR(clk_data.clks[2 + desc->num_ratios]));
	}

	/* SAR register isn't needed anymore */
	iounmap(base);

	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}

/*
 * Clock Gating Control
 */

DEFINE_SPINLOCK(ctrl_gating_lock);

struct clk_gating_ctrl {
	spinlock_t *lock;
	struct clk **gates;
	int num_gates;
	void __iomem *base;
	u32 saved_reg;
};

static struct clk_gating_ctrl *ctrl;

static struct clk *clk_gating_get_src(
	struct of_phandle_args *clkspec, void *data)
{
	int n;

	if (clkspec->args_count < 1)
		return ERR_PTR(-EINVAL);

	for (n = 0; n < ctrl->num_gates; n++) {
		struct clk_gate *gate =
			to_clk_gate(__clk_get_hw(ctrl->gates[n]));
		if (clkspec->args[0] == gate->bit_idx)
			return ctrl->gates[n];
	}
	return ERR_PTR(-ENODEV);
}

static int mvebu_clk_gating_suspend(void)
{
	ctrl->saved_reg = readl(ctrl->base);
	return 0;
}

static void mvebu_clk_gating_resume(void)
{
	writel(ctrl->saved_reg, ctrl->base);
}

static struct syscore_ops clk_gate_syscore_ops = {
	.suspend = mvebu_clk_gating_suspend,
	.resume = mvebu_clk_gating_resume,
};

void __init mvebu_clk_gating_setup(struct device_node *np,
				   const struct clk_gating_soc_desc *desc)
{
	struct clk *clk;
	void __iomem *base;
	const char *default_parent = NULL;
	int n;

	if (ctrl) {
		pr_err("mvebu-clk-gating: cannot instantiate more than one gatable clock device\n");
		return;
	}

	base = of_iomap(np, 0);
	if (WARN_ON(!base))
		return;

	clk = of_clk_get(np, 0);
	if (!IS_ERR(clk)) {
		default_parent = __clk_get_name(clk);
		clk_put(clk);
	}

	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
	if (WARN_ON(!ctrl))
		goto ctrl_out;

	/* lock must already be initialized */
	ctrl->lock = &ctrl_gating_lock;

	ctrl->base = base;

	/* Count, allocate, and register clock gates */
	for (n = 0; desc[n].name;)
		n++;

	ctrl->num_gates = n;
	ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
			      GFP_KERNEL);
	if (WARN_ON(!ctrl->gates))
		goto gates_out;

	for (n = 0; n < ctrl->num_gates; n++) {
		const char *parent =
			(desc[n].parent) ? desc[n].parent : default_parent;
		ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent,
					desc[n].flags, base, desc[n].bit_idx,
					0, ctrl->lock);
		WARN_ON(IS_ERR(ctrl->gates[n]));
	}

	of_clk_add_provider(np, clk_gating_get_src, ctrl);

	register_syscore_ops(&clk_gate_syscore_ops);

	return;
gates_out:
	kfree(ctrl);
ctrl_out:
	iounmap(base);
}
