[v5,4/4] clk: basic clock hardware types

Message ID 1330763341-3437-5-git-send-email-mturquette@linaro.org
State New
Headers show

Commit Message

Mike Turquette March 3, 2012, 8:29 a.m.
Many platforms support simple gateable clocks, fixed-rate clocks,
adjustable divider clocks and multi-parent multiplexer clocks.

This patch introduces basic clock types for the above-mentioned hardware
which share some common characteristics.

Based on original work by Jeremy Kerr and contribution by Jamie Iles.
Dividers and multiplexor clocks originally contributed by Richard Zhao &
Sascha Hauer.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Mike Turquette <mturquette@ti.com>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jamie Iles <jamie@jamieiles.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/clk/Makefile         |    3 +-
 drivers/clk/clk-divider.c    |  198 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk-fixed-rate.c |   81 +++++++++++++++++
 drivers/clk/clk-gate.c       |  121 +++++++++++++++++++++++++
 drivers/clk/clk-mux.c        |  114 ++++++++++++++++++++++++
 include/linux/clk-private.h  |  124 ++++++++++++++++++++++++++
 include/linux/clk-provider.h |  125 ++++++++++++++++++++++++++
 7 files changed, 765 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/clk-divider.c
 create mode 100644 drivers/clk/clk-fixed-rate.c
 create mode 100644 drivers/clk/clk-gate.c
 create mode 100644 drivers/clk/clk-mux.c

Comments

Andrew Lunn March 4, 2012, 2:26 p.m. | #1
> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
> +				_flags, _reg, _bit_idx,		\
> +				_gate_flags, _lock)		\
> +	static struct clk _name;				\
> +	static char *_name##_parent_names[] = {			\
> +		_parent_name,					\
> +	};							\
> +	static struct clk *_name##_parents[] = {		\
> +		_parent_ptr,					\
> +	};							\
> +	static struct clk_gate _name##_hw = {			\
> +		.hw = {						\
> +			.clk = &_name,				\
> +		},						\
> +		.reg = _reg,					\
> +		.bit_idx = _bit_idx,				\
> +		.flags = _gate_flags				\

Hi Mike

Looks like a , is missing here after _gate_flags.

      Andrew
Andrew Lunn March 4, 2012, 2:35 p.m. | #2
> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
> +				_flags, _reg, _bit_idx,		\
> +				_gate_flags, _lock)		\
> +	static struct clk _name;				\
> +	static char *_name##_parent_names[] = {			\
> +		_parent_name,					\
> +	};							\
> +	static struct clk *_name##_parents[] = {		\
> +		_parent_ptr,					\
> +	};							\
> +	static struct clk_gate _name##_hw = {			\
> +		.hw = {						\
> +			.clk = &_name,				\
> +		},						\
> +		.reg = _reg,					\
> +		.bit_idx = _bit_idx,				\
> +		.flags = _gate_flags				\
> +		.lock = _lock,					\
> +	};							\
> +	static struct clk _name = {				\
> +		.name = #_name,					\
> +		.ops = &clk_gate_ops,				\
> +		.hw = &_name##_hw.hw,				\
> +		.parent_names = _name##_parent_names,		\
> +		.num_parents =					\
> +			ARRAY_SIZE(_name##parent_names),	\

Hi Mike

This should be _name##_parent_names, i.e. you are missing a _.

With this and the previous change, i get something which at least
compiles...

	Andrew
Andrew Lunn March 4, 2012, 5:42 p.m. | #3
On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> Many platforms support simple gateable clocks, fixed-rate clocks,
> adjustable divider clocks and multi-parent multiplexer clocks.
> 
> This patch introduces basic clock types for the above-mentioned hardware
> which share some common characteristics.

Hi Mike

These basic clocks don't allow the use of prepare/unprepare, from the
side of the clock provider. I think i need this.

The Orion Kirkwood SoC has clock gating for most of its on chip
peripherals, which the other older Orion devices don't have. The SATA
and PCIe also allows the PHY to be shut down, again which older Orion
devices don't have. The current code links the clock and the PHY
together, shutting both down are the same time. So i would like to
perform the PHY shutdown in the unprepare() function of the clk
driver.

Is allowing to pass prepare/unprepare functions to basic clocks
something you want to support? If i prepare a patch would you consider
it?

	Thanks
		Andrew
Mike Turquette March 5, 2012, 12:15 a.m. | #4
On Sun, Mar 4, 2012 at 6:35 AM, Andrew Lunn <andrew@lunn.ch> wrote:
>> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,    \
>> +                             _flags, _reg, _bit_idx,         \
>> +                             _gate_flags, _lock)             \
>> +     static struct clk _name;                                \
>> +     static char *_name##_parent_names[] = {                 \
>> +             _parent_name,                                   \
>> +     };                                                      \
>> +     static struct clk *_name##_parents[] = {                \
>> +             _parent_ptr,                                    \
>> +     };                                                      \
>> +     static struct clk_gate _name##_hw = {                   \
>> +             .hw = {                                         \
>> +                     .clk = &_name,                          \
>> +             },                                              \
>> +             .reg = _reg,                                    \
>> +             .bit_idx = _bit_idx,                            \
>> +             .flags = _gate_flags                            \
>> +             .lock = _lock,                                  \
>> +     };                                                      \
>> +     static struct clk _name = {                             \
>> +             .name = #_name,                                 \
>> +             .ops = &clk_gate_ops,                           \
>> +             .hw = &_name##_hw.hw,                           \
>> +             .parent_names = _name##_parent_names,           \
>> +             .num_parents =                                  \
>> +                     ARRAY_SIZE(_name##parent_names),        \
>
> Hi Mike
>
> This should be _name##_parent_names, i.e. you are missing a _.
>
> With this and the previous change, i get something which at least
> compiles...

The gate clock is the only type of the basic clocks that I do not
(currently) use in my OMAP port and it's test coverage has suffered as
a result.  My bad.

Thanks for the review and the patch in the separate thread.  I'll take
the changes in.

Regards,
Mike

>
>        Andrew
Mike Turquette March 5, 2012, 12:30 a.m. | #5
On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
>> Many platforms support simple gateable clocks, fixed-rate clocks,
>> adjustable divider clocks and multi-parent multiplexer clocks.
>>
>> This patch introduces basic clock types for the above-mentioned hardware
>> which share some common characteristics.
>
> Hi Mike
>
> These basic clocks don't allow the use of prepare/unprepare, from the
> side of the clock provider. I think i need this.

This is an interesting point and might help us nail down exactly what
we expect from clk_prepare/clk_unprepare.

>
> The Orion Kirkwood SoC has clock gating for most of its on chip
> peripherals, which the other older Orion devices don't have. The SATA
> and PCIe also allows the PHY to be shut down, again which older Orion
> devices don't have. The current code links the clock and the PHY
> together, shutting both down are the same time. So i would like to
> perform the PHY shutdown in the unprepare() function of the clk
> driver.

Do you feel it is The Right Thing to enable/disable the phy from
clk_prepare/clk_unprepare?  I had always imagined that clk_prepare's
purpose was always specific to clock-related activities; for example
maybe turn on a parent PLL that takes a long time to lock, as well as
for the sleepable cases such as clocks over i2c, etc.

However, I know that some others have already started performing
voltage scaling from clk_prepare, so clearly the api is not strict in
it's purpose.

Have you investigated powering up/down the phy from a different layer
such pm_runtime?  That might create a better layer of separation
between other resources needed by an IP block and the clock framework.
 For instance on OMAP we use pm_runtime_get(_sync) to call clk_prepare
& clk_enable and handle other power management-related resources.
Perhaps using the clock framework to power up/down your IP block is
not the right tool for the job.

>
> Is allowing to pass prepare/unprepare functions to basic clocks
> something you want to support? If i prepare a patch would you consider
> it?

My original instinct was "no".  The simple gate clock was always
supposed to be "simple" and if you need more than it provides then it
might be best for your platform to implement a specific clock type.
Especially since the purpose of clk_prepare is still up in the air.

But I'll keep an open mind and hopefully others can chime in.  Please
let me know what you think about my pm_runtime suggestion.  I've Cc'd
Rafael just in case he has something to add here from a design
perspective.

Regards,
Mike

>
>        Thanks
>                Andrew
Andrew Lunn March 5, 2012, 8:48 a.m. | #6
On Sun, Mar 04, 2012 at 04:30:08PM -0800, Turquette, Mike wrote:
> On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> > On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> >> Many platforms support simple gateable clocks, fixed-rate clocks,
> >> adjustable divider clocks and multi-parent multiplexer clocks.
> >>
> >> This patch introduces basic clock types for the above-mentioned hardware
> >> which share some common characteristics.
> >
> > Hi Mike
> >
> > These basic clocks don't allow the use of prepare/unprepare, from the
> > side of the clock provider. I think i need this.
> 
> This is an interesting point and might help us nail down exactly what
> we expect from clk_prepare/clk_unprepare.
> 
> >
> > The Orion Kirkwood SoC has clock gating for most of its on chip
> > peripherals, which the other older Orion devices don't have. The SATA
> > and PCIe also allows the PHY to be shut down, again which older Orion
> > devices don't have. The current code links the clock and the PHY
> > together, shutting both down are the same time. So i would like to
> > perform the PHY shutdown in the unprepare() function of the clk
> > driver.
> 
> Do you feel it is The Right Thing to enable/disable the phy from
> clk_prepare/clk_unprepare?  

Humm, not sure yet. I don't know all the different possibilities,
which is why i tried to describe my use case, rather than just assume
i need prepare/unprepare.

I also realized i did not explain my use case properly. 

At boot, uboot is turning on various clocks and SATA/PCIe PHYs etc, in
order to get the device booted. Linux takes over, and the
Orion/kirkwood board files, ask the kirkwood or generic Orion code to
create platform_data structures for the different devices that the
board uses. The kirkwood code keeps a bitmap of devices for which it
creates platform data for which there is a gated clock. Then in a
lateinit call, it turns on clocks which are needed, and also turns off
clocks which are no longer needed, because the board did not ask for a
driver binding for that device. If it turns off a SATA or PCIe clock,
it also turns off the PHY associated with it.

So we are talking about turning off hardware for which there is no
driver. This seems to exclude pm_runtime_get(_sync), which is about
hardware with drivers.

We touched on this subject a couple of months ago, at least with
respect to clocks. You said that is what the flag CLK_IGNORE_UNUSED
will be used for. In a lateinit call, you plan to iterate over all
clocks and turn off any which don't have CLK_IGNORE_UNUSED and have
not been enabled. I assume you will call both disable() and
unprepare(), and if i've can put code into the unprepare to turn the
PHY off, all is good.

> > Is allowing to pass prepare/unprepare functions to basic clocks
> > something you want to support? If i prepare a patch would you consider
> > it?
> 
> My original instinct was "no".  The simple gate clock was always
> supposed to be "simple" and if you need more than it provides then it
> might be best for your platform to implement a specific clock type.
> Especially since the purpose of clk_prepare is still up in the air.

I think i can wrap your simple gate clock, to make my "complex" gate
clock. What would help is if you would EXPORT_SYMBOL_GPL
clk_gate_enable() and clk_gate_disable(), since they do exactly what i
want. I can then build my own clk_ops structure, with my own
unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
then at run time, before calling __clk_init() overwrite the .ops with
my own version.

However, if others have the need for {un}prepare(), it would be good
to have a generic solution.

   Andrew
Sascha Hauer March 5, 2012, 9:29 a.m. | #7
On Mon, Mar 05, 2012 at 09:48:23AM +0100, Andrew Lunn wrote:
> On Sun, Mar 04, 2012 at 04:30:08PM -0800, Turquette, Mike wrote:
> > On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> > > On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> > >> Many platforms support simple gateable clocks, fixed-rate clocks,
> > >> adjustable divider clocks and multi-parent multiplexer clocks.
> > >>
> > >> This patch introduces basic clock types for the above-mentioned hardware
> > >> which share some common characteristics.
> > >
> > > Hi Mike
> > >
> > > These basic clocks don't allow the use of prepare/unprepare, from the
> > > side of the clock provider. I think i need this.
> > 
> > This is an interesting point and might help us nail down exactly what
> > we expect from clk_prepare/clk_unprepare.
> > 
> > >
> > > The Orion Kirkwood SoC has clock gating for most of its on chip
> > > peripherals, which the other older Orion devices don't have. The SATA
> > > and PCIe also allows the PHY to be shut down, again which older Orion
> > > devices don't have. The current code links the clock and the PHY
> > > together, shutting both down are the same time. So i would like to
> > > perform the PHY shutdown in the unprepare() function of the clk
> > > driver.
> > 
> > Do you feel it is The Right Thing to enable/disable the phy from
> > clk_prepare/clk_unprepare?  
> 
> Humm, not sure yet. I don't know all the different possibilities,
> which is why i tried to describe my use case, rather than just assume
> i need prepare/unprepare.
> 
> I also realized i did not explain my use case properly. 
> 
> At boot, uboot is turning on various clocks and SATA/PCIe PHYs etc, in
> order to get the device booted. Linux takes over, and the
> Orion/kirkwood board files, ask the kirkwood or generic Orion code to
> create platform_data structures for the different devices that the
> board uses. The kirkwood code keeps a bitmap of devices for which it
> creates platform data for which there is a gated clock. Then in a
> lateinit call, it turns on clocks which are needed, and also turns off
> clocks which are no longer needed, because the board did not ask for a
> driver binding for that device. If it turns off a SATA or PCIe clock,
> it also turns off the PHY associated with it.
> 
> So we are talking about turning off hardware for which there is no
> driver. This seems to exclude pm_runtime_get(_sync), which is about
> hardware with drivers.
> 
> We touched on this subject a couple of months ago, at least with
> respect to clocks. You said that is what the flag CLK_IGNORE_UNUSED
> will be used for. In a lateinit call, you plan to iterate over all
> clocks and turn off any which don't have CLK_IGNORE_UNUSED and have
> not been enabled. I assume you will call both disable() and
> unprepare(), and if i've can put code into the unprepare to turn the
> PHY off, all is good.
> 
> > > Is allowing to pass prepare/unprepare functions to basic clocks
> > > something you want to support? If i prepare a patch would you consider
> > > it?
> > 
> > My original instinct was "no".  The simple gate clock was always
> > supposed to be "simple" and if you need more than it provides then it
> > might be best for your platform to implement a specific clock type.
> > Especially since the purpose of clk_prepare is still up in the air.
> 
> I think i can wrap your simple gate clock, to make my "complex" gate
> clock. What would help is if you would EXPORT_SYMBOL_GPL
> clk_gate_enable() and clk_gate_disable(), since they do exactly what i
> want. I can then build my own clk_ops structure, with my own
> unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
> then at run time, before calling __clk_init() overwrite the .ops with
> my own version.

Maybe I don't get your point, but clk_unprepare should be used when
you have to sleep to disable your clock. When clk_gate_disable() is
exactly why do you want to use clk_unprepare instead of clk_disable?

Sascha
Andrew Lunn March 5, 2012, 10:17 a.m. | #8
> > I think i can wrap your simple gate clock, to make my "complex" gate
> > clock. What would help is if you would EXPORT_SYMBOL_GPL
> > clk_gate_enable() and clk_gate_disable(), since they do exactly what i
> > want. I can then build my own clk_ops structure, with my own
> > unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
> > then at run time, before calling __clk_init() overwrite the .ops with
> > my own version.
> 
> Maybe I don't get your point, but clk_unprepare should be used when
> you have to sleep to disable your clock. When clk_gate_disable() is
> exactly why do you want to use clk_unprepare instead of clk_disable?

I'm trying to avoid having to implement a new clock provider. The
whole point of the generic clk code is to consolidate code. It seems
silly to create a new clk provider which is 95% identical to Mike's
gated provider, if i can avoid it.

If i stuff it into clk_disable(), it means i cannot use the basic gate
clock Mike provides in the generic clock framework. Which is a shame,
since it does exactly what i want in terms of gating the clock.

If i can use unprepare(), which basic gate does not use, i can use
Mikes code, and just extend it. It is there, it is unused, so why not
use it?

    Andrew
Mike Turquette March 9, 2012, 11:38 p.m. | #9
On Mon, Mar 5, 2012 at 2:17 AM, Andrew Lunn <andrew@lunn.ch> wrote:
>> > I think i can wrap your simple gate clock, to make my "complex" gate
>> > clock. What would help is if you would EXPORT_SYMBOL_GPL
>> > clk_gate_enable() and clk_gate_disable(), since they do exactly what i
>> > want. I can then build my own clk_ops structure, with my own
>> > unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
>> > then at run time, before calling __clk_init() overwrite the .ops with
>> > my own version.
>>
>> Maybe I don't get your point, but clk_unprepare should be used when
>> you have to sleep to disable your clock. When clk_gate_disable() is
>> exactly why do you want to use clk_unprepare instead of clk_disable?
>
> I'm trying to avoid having to implement a new clock provider. The
> whole point of the generic clk code is to consolidate code. It seems
> silly to create a new clk provider which is 95% identical to Mike's
> gated provider, if i can avoid it.

I will export the operations in my next patchset, but I'm concerned
over how useful this might be...

Using your example of struct clk_gate, both clk_gate_enable and
clk_gate_disable call to_clk_gate.  So you would either have to re-use
struct clk_gate for your own needs (which involves hacking up a
specific struct clk_gate_foo_ops for your needs) or you could not use
struct clk_gate and pack your data identically (struct clk_hw must be
the first member) which is too horrible to imagine.

Hmm, or you could re-use struct clk_gate but provide your own struct
clk_ops AND your own registration functions (since you won't be able
to pass in the ops to your clk_register_gate).  So that sounds sane,
if a bit convoluted.  It does re-use code though...

Regards,
Mike

>
> If i stuff it into clk_disable(), it means i cannot use the basic gate
> clock Mike provides in the generic clock framework. Which is a shame,
> since it does exactly what i want in terms of gating the clock.
>
> If i can use unprepare(), which basic gate does not use, i can use
> Mikes code, and just extend it. It is there, it is unused, so why not
> use it?
>
>    Andrew

Patch

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ff362c4..1f736bc 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@ 
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
-obj-$(CONFIG_COMMON_CLK)	+= clk.o
+obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
+				   clk-mux.o clk-divider.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
new file mode 100644
index 0000000..8f02930
--- /dev/null
+++ b/drivers/clk/clk-divider.c
@@ -0,0 +1,198 @@ 
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Adjustable divider clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/*
+ * DOC: basic adjustable divider clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = parent->rate / divisor
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_divider *divider = to_clk_divider(hw);
+	unsigned int div;
+
+	div = readl(divider->reg) >> divider->shift;
+	div &= (1 << divider->width) - 1;
+
+	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+		div++;
+
+	return parent_rate / div;
+}
+
+static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+		unsigned long *best_parent_rate)
+{
+	struct clk_divider *divider = to_clk_divider(hw);
+	int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	maxdiv = (1 << divider->width);
+
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		maxdiv--;
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+		bestdiv = parent_rate / rate;
+		bestdiv = bestdiv == 0 ? 1 : bestdiv;
+		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+		goto out;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		int div;
+		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+				rate * i);
+		div = parent_rate / rate;
+		div = div > maxdiv ? maxdiv : div;
+		div = div < 1 ? 1 : div;
+		now = parent_rate / div;
+
+		if (now <= rate && now >= best) {
+			bestdiv = div;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = (1 << divider->width);
+		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
+	} else {
+		parent_rate = best * bestdiv;
+	}
+
+out:
+	if (best_parent_rate)
+		*best_parent_rate = parent_rate;
+
+	return bestdiv;
+}
+
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	unsigned long best_parent_rate;
+	int div = clk_divider_bestdiv(hw, rate, &best_parent_rate);
+	if (prate) {
+		if (best_parent_rate == __clk_get_rate(
+					__clk_get_parent(hw->clk)))
+			*prate = 0;
+		else
+			*prate = best_parent_rate;
+	}
+
+	return best_parent_rate / div;
+}
+
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+	unsigned long best_parent_rate;
+	struct clk_divider *divider = to_clk_divider(hw);
+	unsigned int div;
+	unsigned long flags = 0;
+	u32 val;
+
+	div = clk_divider_bestdiv(hw, rate, &best_parent_rate);
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+
+	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+		div--;
+
+	val = readl(divider->reg);
+	val &= ~(((1 << divider->width) - 1) << divider->shift);
+	val |= div << divider->shift;
+	writel(val, divider->reg);
+
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+
+	return 0;
+}
+
+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);
+
+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,
+		u8 clk_divider_flags, spinlock_t *lock)
+{
+	struct clk_divider *div;
+	char **parent_names = NULL;
+	u8 len;
+
+	div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
+
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_divider_ops, &div->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
new file mode 100644
index 0000000..651b06f
--- /dev/null
+++ b/drivers/clk/clk-fixed-rate.c
@@ -0,0 +1,81 @@ 
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Fixed rate clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic fixed-rate clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parents are prepared
+ * enable - clk_enable only ensures parents are enabled
+ * rate - rate is always a fixed value.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
+
+static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	return to_clk_fixed_rate(hw)->fixed_rate;
+}
+
+struct clk_ops clk_fixed_rate_ops = {
+	.recalc_rate = clk_fixed_rate_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate)
+{
+	struct clk_fixed_rate *fixed;
+	char **parent_names = NULL;
+	u8 len;
+
+	fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
+
+	if (!fixed) {
+		pr_err("%s: could not allocate fixed clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_fixed_rate assignments */
+	fixed->fixed_rate = fixed_rate;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_fixed_rate_ops, &fixed->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 0000000..e831f7b
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,121 @@ 
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Gated clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/**
+ * DOC: basic gatable clock which can gate and ungate it's ouput
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent are prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+static void clk_gate_set_bit(struct clk_gate *gate)
+{
+	u32 reg;
+
+	reg = readl(gate->reg);
+	reg |= BIT(gate->bit_idx);
+	writel(reg, gate->reg);
+}
+
+static void clk_gate_clear_bit(struct clk_gate *gate)
+{
+	u32 reg;
+
+	reg = readl(gate->reg);
+	reg &= ~BIT(gate->bit_idx);
+	writel(reg, gate->reg);
+}
+
+static int clk_gate_enable(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		clk_gate_clear_bit(gate);
+	else
+		clk_gate_set_bit(gate);
+
+	return 0;
+}
+
+static void clk_gate_disable(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		clk_gate_set_bit(gate);
+	else
+		clk_gate_clear_bit(gate);
+}
+
+struct clk_ops clk_gate_ops = {
+	.enable = clk_gate_enable,
+	.disable = clk_gate_disable,
+};
+EXPORT_SYMBOL_GPL(clk_gate_ops);
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+	struct clk_gate *gate;
+	char **parent_names = NULL;
+	u8 len;
+
+	gate = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+	if (!gate) {
+		pr_err("%s: could not allocate gated clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_gate assignments */
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->lock = lock;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_gate_ops, &gate->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
new file mode 100644
index 0000000..bb66f26
--- /dev/null
+++ b/drivers/clk/clk-mux.c
@@ -0,0 +1,114 @@ 
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple multiplexer clock implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic adjustable multiplexer clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is only affected by parent switching.  No clk_set_rate support
+ * parent - parent is adjustable through clk_set_parent
+ */
+
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+
+static u8 clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val;
+
+	/*
+	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
+	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
+	 * to 0x7 (index starts at one)
+	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+	 * val = 0x4 really means "bit 2, index starts at bit 0"
+	 */
+	val = readl(mux->reg) >> mux->shift;
+	val &= (1 << mux->width) - 1;
+
+	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+		val = ffs(val) - 1;
+
+	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+		val--;
+
+	if (val >= __clk_get_num_parents(hw->clk))
+		return -EINVAL;
+
+	return val;
+}
+
+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val;
+	unsigned long flags = 0;
+
+	if (mux->flags & CLK_MUX_INDEX_BIT)
+		index = (1 << ffs(index));
+
+	if (mux->flags & CLK_MUX_INDEX_ONE)
+		index++;
+
+	if (mux->lock)
+		spin_lock_irqsave(mux->lock, flags);
+
+	val = readl(mux->reg);
+	val &= ~(((1 << mux->width) - 1) << mux->shift);
+	val |= index << mux->shift;
+	writel(val, mux->reg);
+
+	if (mux->lock)
+		spin_unlock_irqrestore(mux->lock, flags);
+
+	return 0;
+}
+
+struct clk_ops clk_mux_ops = {
+	.get_parent = clk_mux_get_parent,
+	.set_parent = clk_mux_set_parent,
+};
+EXPORT_SYMBOL_GPL(clk_mux_ops);
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+		char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock)
+{
+	struct clk_mux *mux;
+
+	mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL);
+
+	if (!mux) {
+		pr_err("%s: could not allocate mux clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_mux assignments */
+	mux->reg = reg;
+	mux->shift = shift;
+	mux->width = width;
+	mux->flags = clk_mux_flags;
+	mux->lock = lock;
+
+	return clk_register(dev, name, &clk_mux_ops, &mux->hw,
+			parent_names, num_parents, flags);
+}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 33bf6a7..d06e6fb 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -45,6 +45,130 @@  struct clk {
 #endif
 };
 
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+extern struct clk_ops clk_fixed_rate_ops;
+
+#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
+				_fixed_rate_flags)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {};		\
+	static struct clk_fixed_rate _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.fixed_rate = _rate,				\
+		.flags = _fixed_rate_flags,			\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_fixed_rate_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_parent_names),	\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_gate_ops;
+
+#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _bit_idx,		\
+				_gate_flags, _lock)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {			\
+		_parent_name,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_gate _name##_hw = {			\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.bit_idx = _bit_idx,				\
+		.flags = _gate_flags				\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_gate_ops,				\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##parent_names),	\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_divider_ops;
+
+#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _shift, _width,	\
+				_divider_flags, _lock)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {			\
+		_parent_name,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_divider _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.shift = _shift,				\
+		.width = _width,				\
+		.flags = _divider_flags,			\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_divider_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_parent_names),	\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_mux_ops;
+
+#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
+				_reg, _shift, _width,		\
+				_mux_flags, _lock)		\
+	static struct clk _name;				\
+	static struct clk_mux _name##_hw = {			\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.shift = _shift,				\
+		.width = _width,				\
+		.flags = _mux_flags,				\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_mux_ops,				\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _parent_names,			\
+		.num_parents =					\
+			ARRAY_SIZE(_parent_names),		\
+		.parents = _parents,				\
+		.flags = _flags,				\
+	};
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c9ed582..9b7dd5e 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -128,6 +128,131 @@  struct clk_ops {
 	void		(*init)(struct clk_hw *hw);
 };
 
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+/**
+ * struct clk_fixed_rate - fixed-rate clock
+ * @hw:		handle between common and hardware-specific interfaces
+ * @fixed_rate:	constant frequency of clock
+ */
+struct clk_fixed_rate {
+	struct		clk_hw hw;
+	unsigned long	fixed_rate;
+	u8		flags;
+};
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate);
+
+/**
+ * struct clk_gate - gating clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register controlling gate
+ * @bit_idx:	single bit controlling gate
+ * @flags:	hardware-specific flags
+ * @lock:	register lock
+ *
+ * Clock which can gate its output.  Implements .enable & .disable
+ *
+ * Flags:
+ * CLK_GATE_SET_DISABLE - by default this clock sets the bit at bit_idx to
+ * 	enable the clock.  Setting this flag does the opposite: setting the bit
+ * 	disable the clock and clearing it enables the clock
+ */
+struct clk_gate {
+	struct clk_hw hw;
+	void __iomem	*reg;
+	u8		bit_idx;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_GATE_SET_TO_DISABLE		BIT(0)
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock);
+
+/**
+ * struct clk_divider - adjustable divider clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing the divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @lock:	register lock
+ *
+ * Clock with an adjustable divider affecting its output frequency.  Implements
+ * .recalc_rate, .set_rate and .round_rate
+ *
+ * Flags:
+ * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
+ * 	register plus one.  If CLK_DIVIDER_ONE_BASED is set then the divider is
+ * 	the raw value read from the register, with the value of zero considered
+ * 	invalid
+ * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from
+ * 	the hardware register
+ */
+struct clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_DIVIDER_ONE_BASED		BIT(0)
+#define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
+
+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,
+		u8 clk_divider_flags, spinlock_t *lock);
+
+/**
+ * struct clk_mux - multiplexer clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register controlling multiplexer
+ * @shift:	shift to multiplexer bit field
+ * @width:	width of mutliplexer bit field
+ * @num_clks:	number of parent clocks
+ * @lock:	register lock
+ *
+ * Clock with multiple selectable parents.  Implements .get_parent, .set_parent
+ * and .recalc_rate
+ *
+ * Flags:
+ * CLK_MUX_INDEX_ONE - register index starts at 1, not 0
+ * CLK_MUX_INDEX_BITWISE - register index is a single bit (power of two)
+ */
+struct clk_mux {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_MUX_INDEX_ONE		BIT(0)
+#define CLK_MUX_INDEX_BIT		BIT(1)
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+		char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock);
 
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie