summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-divider.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-26 12:42:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-26 12:42:29 -0700
commit27953437059c64d14086196eb96f43c78caa9db3 (patch)
tree0cfd5fb21262a6db3de0c64462847b4c0c43e9df /drivers/clk/clk-divider.c
parent2c757fd5d1a92086f225a75a8fac7cab242d11b0 (diff)
parent3c0dec5f58b3c7b3627715126d1bf9b030a076f0 (diff)
Merge tag 'clock' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull arm-soc clock driver changes from Olof Johansson: "The new clock subsystem was merged in linux-3.4 without any users, this now moves the first three platforms over to it: imx, mxs and spear. The series also contains the changes for the clock subsystem itself, since Mike preferred to have it together with the platforms that require these changes, in order to avoid interdependencies and conflicts." Fix up trivial conflicts in arch/arm/mach-kirkwood/common.c (code removed in one branch, added OF support in another) and drivers/dma/imx-sdma.c (independent changes next to each other). * tag 'clock' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (97 commits) clk: Fix CLK_SET_RATE_GATE flag validation in clk_set_rate(). clk: Provide dummy clk_unregister() SPEAr: Update defconfigs SPEAr: Add SMI NOR partition info in dts files SPEAr: Switch to common clock framework SPEAr: Call clk_prepare() before calling clk_enable SPEAr: clk: Add General Purpose Timer Synthesizer clock SPEAr: clk: Add Fractional Synthesizer clock SPEAr: clk: Add Auxiliary Synthesizer clock SPEAr: clk: Add VCO-PLL Synthesizer clock SPEAr: Add DT bindings for SPEAr's timer ARM i.MX: remove now unused clock files ARM: i.MX6: implement clocks using common clock framework ARM i.MX35: implement clocks using common clock framework ARM i.MX5: implement clocks using common clock framework ARM: Kirkwood: Replace clock gating ARM: Orion: Audio: Add clk/clkdev support ARM: Orion: PCIE: Add support for clk ARM: Orion: XOR: Add support for clk ARM: Orion: CESA: Add support for clk ...
Diffstat (limited to 'drivers/clk/clk-divider.c')
-rw-r--r--drivers/clk/clk-divider.c68
1 files changed, 34 insertions, 34 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index d5ac6a75ea57..8ea11b444528 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -45,7 +45,6 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
return parent_rate / div;
}
-EXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
/*
* The reverse of DIV_ROUND_UP: The maximum number which
@@ -68,8 +67,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
if (divider->flags & CLK_DIVIDER_ONE_BASED)
maxdiv--;
- if (!best_parent_rate) {
- parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+ if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+ parent_rate = *best_parent_rate;
bestdiv = DIV_ROUND_UP(parent_rate, rate);
bestdiv = bestdiv == 0 ? 1 : bestdiv;
bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
@@ -109,24 +108,18 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
int div;
div = clk_divider_bestdiv(hw, rate, prate);
- if (prate)
- return *prate / div;
- else {
- unsigned long r;
- r = __clk_get_rate(__clk_get_parent(hw->clk));
- return r / div;
- }
+ return *prate / div;
}
-EXPORT_SYMBOL_GPL(clk_divider_round_rate);
-static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
struct clk_divider *divider = to_clk_divider(hw);
unsigned int div;
unsigned long flags = 0;
u32 val;
- div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate;
+ div = parent_rate / rate;
if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
div--;
@@ -147,15 +140,26 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
return 0;
}
-EXPORT_SYMBOL_GPL(clk_divider_set_rate);
-struct clk_ops clk_divider_ops = {
+const struct clk_ops clk_divider_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
.set_rate = clk_divider_set_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ops);
+/**
+ * clk_register_divider - register a divider clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
struct clk *clk_register_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
@@ -163,38 +167,34 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
{
struct clk_divider *div;
struct clk *clk;
+ struct clk_init_data init;
+ /* allocate the divider */
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
-
if (!div) {
pr_err("%s: could not allocate divider clk\n", __func__);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
+ init.name = name;
+ init.ops = &clk_divider_ops;
+ init.flags = flags;
+ init.parent_names = (parent_name ? &parent_name: NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
/* struct clk_divider assignments */
div->reg = reg;
div->shift = shift;
div->width = width;
div->flags = clk_divider_flags;
div->lock = lock;
+ div->hw.init = &init;
- if (parent_name) {
- div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
- if (!div->parent[0])
- goto out;
- }
-
- clk = clk_register(dev, name,
- &clk_divider_ops, &div->hw,
- div->parent,
- (parent_name ? 1 : 0),
- flags);
- if (clk)
- return clk;
+ /* register the clock */
+ clk = clk_register(dev, &div->hw);
-out:
- kfree(div->parent[0]);
- kfree(div);
+ if (IS_ERR(clk))
+ kfree(div);
- return NULL;
+ return clk;
}