/*
 * Copyright (C) 2013 Freescale Semiconductor, Inc.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

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

#define to_clk_div(_hw) container_of(_hw, struct clk_divider, hw)
#define div_mask(d)	((1 << (d->width)) - 1)

/**
 * struct clk_fixup_div - imx integer fixup divider clock
 * @divider: the parent class
 * @ops: pointer to clk_ops of parent class
 * @fixup: a hook to fixup the write value
 *
 * The imx fixup divider clock is a subclass of basic clk_divider
 * with an addtional fixup hook.
 */
struct clk_fixup_div {
	struct clk_divider divider;
	const struct clk_ops *ops;
	void (*fixup)(u32 *val);
};

static inline struct clk_fixup_div *to_clk_fixup_div(struct clk_hw *hw)
{
	struct clk_divider *divider = to_clk_div(hw);

	return container_of(divider, struct clk_fixup_div, divider);
}

static unsigned long clk_fixup_div_recalc_rate(struct clk_hw *hw,
					 unsigned long parent_rate)
{
	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);

	return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate);
}

static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long *prate)
{
	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);

	return fixup_div->ops->round_rate(&fixup_div->divider.hw, rate, prate);
}

static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate,
			    unsigned long parent_rate)
{
	struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);
	struct clk_divider *div = to_clk_div(hw);
	unsigned int divider, value;
	unsigned long flags = 0;
	u32 val;

	divider = parent_rate / rate;

	/* Zero based divider */
	value = divider - 1;

	if (value > div_mask(div))
		value = div_mask(div);

	spin_lock_irqsave(div->lock, flags);

	val = readl(div->reg);
	val &= ~(div_mask(div) << div->shift);
	val |= value << div->shift;
	fixup_div->fixup(&val);
	writel(val, div->reg);

	spin_unlock_irqrestore(div->lock, flags);

	return 0;
}

static const struct clk_ops clk_fixup_div_ops = {
	.recalc_rate = clk_fixup_div_recalc_rate,
	.round_rate = clk_fixup_div_round_rate,
	.set_rate = clk_fixup_div_set_rate,
};

struct clk *imx_clk_fixup_divider(const char *name, const char *parent,
				  void __iomem *reg, u8 shift, u8 width,
				  void (*fixup)(u32 *val))
{
	struct clk_fixup_div *fixup_div;
	struct clk *clk;
	struct clk_init_data init;

	if (!fixup)
		return ERR_PTR(-EINVAL);

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

	init.name = name;
	init.ops = &clk_fixup_div_ops;
	init.flags = CLK_SET_RATE_PARENT;
	init.parent_names = parent ? &parent : NULL;
	init.num_parents = parent ? 1 : 0;

	fixup_div->divider.reg = reg;
	fixup_div->divider.shift = shift;
	fixup_div->divider.width = width;
	fixup_div->divider.lock = &imx_ccm_lock;
	fixup_div->divider.hw.init = &init;
	fixup_div->ops = &clk_divider_ops;
	fixup_div->fixup = fixup;

	clk = clk_register(NULL, &fixup_div->divider.hw);
	if (IS_ERR(clk))
		kfree(fixup_div);

	return clk;
}
