19d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette/*
29d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
39d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
49d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
59d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette *
69d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * This program is free software; you can redistribute it and/or modify
79d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * it under the terms of the GNU General Public License version 2 as
89d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * published by the Free Software Foundation.
99d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette *
109d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * Adjustable divider clock implementation
119d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette */
129d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
139d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/clk-provider.h>
149d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/module.h>
159d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/slab.h>
169d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/io.h>
179d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/err.h>
189d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#include <linux/string.h>
199d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
209d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette/*
219d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * DOC: basic adjustable divider clock that cannot gate
229d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette *
239d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * Traits of this clock:
249d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * prepare - clk_prepare only ensures that parents are prepared
259d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * enable - clk_enable only ensures that parents are enabled
269d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * rate - rate is adjustable.  clk->rate = parent->rate / divisor
279d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * parent - fixed parent.  No clk_set_parent support
289d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette */
299d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
309d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
319d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
329d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#define div_mask(d)	((1 << (d->width)) - 1)
339d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
349d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestatic unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
359d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		unsigned long parent_rate)
369d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette{
379d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	struct clk_divider *divider = to_clk_divider(hw);
389d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	unsigned int div;
399d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
409d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div = readl(divider->reg) >> divider->shift;
419d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div &= div_mask(divider);
429d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
439d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
449d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		div++;
459d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
469d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	return parent_rate / div;
479d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette}
489d9f78ed9af0e465d2fd15550471956e7f559b9fMike TurquetteEXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
499d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
509d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette/*
519d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * The reverse of DIV_ROUND_UP: The maximum number which
529d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette * divided by m is r
539d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette */
549d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
559d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
569d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestatic int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
579d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		unsigned long *best_parent_rate)
589d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette{
599d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	struct clk_divider *divider = to_clk_divider(hw);
609d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	int i, bestdiv = 0;
619d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	unsigned long parent_rate, best = 0, now, maxdiv;
629d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
639d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!rate)
649d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		rate = 1;
659d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
669d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	maxdiv = (1 << divider->width);
679d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
689d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (divider->flags & CLK_DIVIDER_ONE_BASED)
699d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		maxdiv--;
709d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
719d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!best_parent_rate) {
729d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
739d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		bestdiv = DIV_ROUND_UP(parent_rate, rate);
749d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		bestdiv = bestdiv == 0 ? 1 : bestdiv;
759d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
769d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		return bestdiv;
779d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
789d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
799d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	/*
809d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	 * The maximum divider we can use without overflowing
819d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	 * unsigned long in rate * i below
829d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	 */
839d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	maxdiv = min(ULONG_MAX / rate, maxdiv);
849d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
859d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	for (i = 1; i <= maxdiv; i++) {
869d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
879d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette				MULT_ROUND_UP(rate, i));
889d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		now = parent_rate / i;
899d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		if (now <= rate && now > best) {
909d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			bestdiv = i;
919d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			best = now;
929d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			*best_parent_rate = parent_rate;
939d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		}
949d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
959d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
969d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!bestdiv) {
979d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		bestdiv = (1 << divider->width);
989d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		if (divider->flags & CLK_DIVIDER_ONE_BASED)
999d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			bestdiv--;
1009d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		*best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
1019d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
1029d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1039d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	return bestdiv;
1049d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette}
1059d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1069d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestatic long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
1079d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette				unsigned long *prate)
1089d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette{
1099d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	int div;
1109d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div = clk_divider_bestdiv(hw, rate, prate);
1119d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1129d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (prate)
1139d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		return *prate / div;
1149d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	else {
1159d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		unsigned long r;
1169d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		r = __clk_get_rate(__clk_get_parent(hw->clk));
1179d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		return r / div;
1189d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
1199d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette}
1209d9f78ed9af0e465d2fd15550471956e7f559b9fMike TurquetteEXPORT_SYMBOL_GPL(clk_divider_round_rate);
1219d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1229d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestatic int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
1239d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette{
1249d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	struct clk_divider *divider = to_clk_divider(hw);
1259d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	unsigned int div;
1269d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	unsigned long flags = 0;
1279d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	u32 val;
1289d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1299d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate;
1309d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1319d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
1329d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		div--;
1339d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1349d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (div > div_mask(divider))
1359d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		div = div_mask(divider);
1369d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1379d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (divider->lock)
1389d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		spin_lock_irqsave(divider->lock, flags);
1399d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1409d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	val = readl(divider->reg);
1419d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	val &= ~(div_mask(divider) << divider->shift);
1429d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	val |= div << divider->shift;
1439d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	writel(val, divider->reg);
1449d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1459d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (divider->lock)
1469d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		spin_unlock_irqrestore(divider->lock, flags);
1479d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1489d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	return 0;
1499d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette}
1509d9f78ed9af0e465d2fd15550471956e7f559b9fMike TurquetteEXPORT_SYMBOL_GPL(clk_divider_set_rate);
1519d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1529d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestruct clk_ops clk_divider_ops = {
1539d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	.recalc_rate = clk_divider_recalc_rate,
1549d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	.round_rate = clk_divider_round_rate,
1559d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	.set_rate = clk_divider_set_rate,
1569d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette};
1579d9f78ed9af0e465d2fd15550471956e7f559b9fMike TurquetteEXPORT_SYMBOL_GPL(clk_divider_ops);
1589d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1599d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquettestruct clk *clk_register_divider(struct device *dev, const char *name,
1609d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		const char *parent_name, unsigned long flags,
1619d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		void __iomem *reg, u8 shift, u8 width,
1629d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		u8 clk_divider_flags, spinlock_t *lock)
1639d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette{
1649d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	struct clk_divider *div;
1659d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	struct clk *clk;
1669d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1679d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
1689d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1699d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (!div) {
1709d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		pr_err("%s: could not allocate divider clk\n", __func__);
1719d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		return NULL;
1729d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
1739d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1749d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	/* struct clk_divider assignments */
1759d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div->reg = reg;
1769d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div->shift = shift;
1779d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div->width = width;
1789d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div->flags = clk_divider_flags;
1799d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	div->lock = lock;
1809d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1819d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (parent_name) {
1829d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
1839d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		if (!div->parent[0])
1849d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			goto out;
1859d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	}
1869d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1879d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	clk = clk_register(dev, name,
1889d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			&clk_divider_ops, &div->hw,
1899d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			div->parent,
1909d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			(parent_name ? 1 : 0),
1919d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette			flags);
1929d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	if (clk)
1939d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette		return clk;
1949d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1959d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquetteout:
1969d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	kfree(div->parent[0]);
1979d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	kfree(div);
1989d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette
1999d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette	return NULL;
2009d9f78ed9af0e465d2fd15550471956e7f559b9fMike Turquette}
201