/*
 * Copyright (C) 2014 Broadcom Corporation
 *
 * 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 version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/clkdev.h>
#include <linux/of_address.h>
#include <linux/delay.h>

#include "clk-iproc.h"

struct iproc_asiu;

struct iproc_asiu_clk {
	struct clk_hw hw;
	const char *name;
	struct iproc_asiu *asiu;
	unsigned long rate;
	struct iproc_asiu_div div;
	struct iproc_asiu_gate gate;
};

struct iproc_asiu {
	void __iomem *div_base;
	void __iomem *gate_base;

	struct clk_hw_onecell_data *clk_data;
	struct iproc_asiu_clk *clks;
};

#define to_asiu_clk(hw) container_of(hw, struct iproc_asiu_clk, hw)

static int iproc_asiu_clk_enable(struct clk_hw *hw)
{
	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
	struct iproc_asiu *asiu = clk->asiu;
	u32 val;

	/* some clocks at the ASIU level are always enabled */
	if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET)
		return 0;

	val = readl(asiu->gate_base + clk->gate.offset);
	val |= (1 << clk->gate.en_shift);
	writel(val, asiu->gate_base + clk->gate.offset);

	return 0;
}

static void iproc_asiu_clk_disable(struct clk_hw *hw)
{
	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
	struct iproc_asiu *asiu = clk->asiu;
	u32 val;

	/* some clocks at the ASIU level are always enabled */
	if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET)
		return;

	val = readl(asiu->gate_base + clk->gate.offset);
	val &= ~(1 << clk->gate.en_shift);
	writel(val, asiu->gate_base + clk->gate.offset);
}

static unsigned long iproc_asiu_clk_recalc_rate(struct clk_hw *hw,
						unsigned long parent_rate)
{
	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
	struct iproc_asiu *asiu = clk->asiu;
	u32 val;
	unsigned int div_h, div_l;

	if (parent_rate == 0) {
		clk->rate = 0;
		return 0;
	}

	/* if clock divisor is not enabled, simply return parent rate */
	val = readl(asiu->div_base + clk->div.offset);
	if ((val & (1 << clk->div.en_shift)) == 0) {
		clk->rate = parent_rate;
		return parent_rate;
	}

	/* clock rate = parent rate / (high_div + 1) + (low_div + 1) */
	div_h = (val >> clk->div.high_shift) & bit_mask(clk->div.high_width);
	div_h++;
	div_l = (val >> clk->div.low_shift) & bit_mask(clk->div.low_width);
	div_l++;

	clk->rate = parent_rate / (div_h + div_l);
	pr_debug("%s: rate: %lu. parent rate: %lu div_h: %u div_l: %u\n",
		 __func__, clk->rate, parent_rate, div_h, div_l);

	return clk->rate;
}

static long iproc_asiu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
				      unsigned long *parent_rate)
{
	unsigned int div;

	if (rate == 0 || *parent_rate == 0)
		return -EINVAL;

	if (rate == *parent_rate)
		return *parent_rate;

	div = DIV_ROUND_UP(*parent_rate, rate);
	if (div < 2)
		return *parent_rate;

	return *parent_rate / div;
}

static int iproc_asiu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
				   unsigned long parent_rate)
{
	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
	struct iproc_asiu *asiu = clk->asiu;
	unsigned int div, div_h, div_l;
	u32 val;

	if (rate == 0 || parent_rate == 0)
		return -EINVAL;

	/* simply disable the divisor if one wants the same rate as parent */
	if (rate == parent_rate) {
		val = readl(asiu->div_base + clk->div.offset);
		val &= ~(1 << clk->div.en_shift);
		writel(val, asiu->div_base + clk->div.offset);
		return 0;
	}

	div = DIV_ROUND_UP(parent_rate, rate);
	if (div < 2)
		return -EINVAL;

	div_h = div_l = div >> 1;
	div_h--;
	div_l--;

	val = readl(asiu->div_base + clk->div.offset);
	val |= 1 << clk->div.en_shift;
	if (div_h) {
		val &= ~(bit_mask(clk->div.high_width)
			 << clk->div.high_shift);
		val |= div_h << clk->div.high_shift;
	} else {
		val &= ~(bit_mask(clk->div.high_width)
			 << clk->div.high_shift);
	}
	if (div_l) {
		val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift);
		val |= div_l << clk->div.low_shift;
	} else {
		val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift);
	}
	writel(val, asiu->div_base + clk->div.offset);

	return 0;
}

static const struct clk_ops iproc_asiu_ops = {
	.enable = iproc_asiu_clk_enable,
	.disable = iproc_asiu_clk_disable,
	.recalc_rate = iproc_asiu_clk_recalc_rate,
	.round_rate = iproc_asiu_clk_round_rate,
	.set_rate = iproc_asiu_clk_set_rate,
};

void __init iproc_asiu_setup(struct device_node *node,
			     const struct iproc_asiu_div *div,
			     const struct iproc_asiu_gate *gate,
			     unsigned int num_clks)
{
	int i, ret;
	struct iproc_asiu *asiu;

	if (WARN_ON(!gate || !div))
		return;

	asiu = kzalloc(sizeof(*asiu), GFP_KERNEL);
	if (WARN_ON(!asiu))
		return;

	asiu->clk_data = kzalloc(struct_size(asiu->clk_data, hws, num_clks),
				 GFP_KERNEL);
	if (WARN_ON(!asiu->clk_data))
		goto err_clks;
	asiu->clk_data->num = num_clks;

	asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL);
	if (WARN_ON(!asiu->clks))
		goto err_asiu_clks;

	asiu->div_base = of_iomap(node, 0);
	if (WARN_ON(!asiu->div_base))
		goto err_iomap_div;

	asiu->gate_base = of_iomap(node, 1);
	if (WARN_ON(!asiu->gate_base))
		goto err_iomap_gate;

	for (i = 0; i < num_clks; i++) {
		struct clk_init_data init;
		const char *parent_name;
		struct iproc_asiu_clk *asiu_clk;
		const char *clk_name;

		ret = of_property_read_string_index(node, "clock-output-names",
						    i, &clk_name);
		if (WARN_ON(ret))
			goto err_clk_register;

		asiu_clk = &asiu->clks[i];
		asiu_clk->name = clk_name;
		asiu_clk->asiu = asiu;
		asiu_clk->div = div[i];
		asiu_clk->gate = gate[i];
		init.name = clk_name;
		init.ops = &iproc_asiu_ops;
		init.flags = 0;
		parent_name = of_clk_get_parent_name(node, 0);
		init.parent_names = (parent_name ? &parent_name : NULL);
		init.num_parents = (parent_name ? 1 : 0);
		asiu_clk->hw.init = &init;

		ret = clk_hw_register(NULL, &asiu_clk->hw);
		if (WARN_ON(ret))
			goto err_clk_register;
		asiu->clk_data->hws[i] = &asiu_clk->hw;
	}

	ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
				     asiu->clk_data);
	if (WARN_ON(ret))
		goto err_clk_register;

	return;

err_clk_register:
	while (--i >= 0)
		clk_hw_unregister(asiu->clk_data->hws[i]);
	iounmap(asiu->gate_base);

err_iomap_gate:
	iounmap(asiu->div_base);

err_iomap_div:
	kfree(asiu->clks);

err_asiu_clks:
	kfree(asiu->clk_data);

err_clks:
	kfree(asiu);
}
