On Tue, Mar 6, 2012 at 11:00 AM, Sascha Hauer<s.hauer@xxxxxxxxxxxxxx> wrote:On Mon, Mar 05, 2012 at 12:03:15PM -0800, Turquette, Mike wrote:On Sun, Mar 4, 2012 at 11:38 PM, Sascha Hauer<s.hauer@xxxxxxxxxxxxxx> wrote:On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
I believe this patch already does what you suggest, but I might be
missing your point.
In include/linux/clk-private.h you expose struct clk outside the core.
This has to be done to make static initializers possible. There is a big
warning in this file that it must not be included from files implementing
struct clk_ops. You can simply avoid this warning by declaring struct clk
with only a single member:
include/linux/clk.h:
struct clk {
struct clk_internal *internal;
};
This way everybody knows struct clk (thus can embed it in their static
initializers), but doesn't know anything about the internal members. Now
in drivers/clk/clk.c you declare struct clk_internal exactly like struct
clk was declared before:
struct clk_internal {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct clk *parent;
char **parent_names;
struct clk **parents;
u8 num_parents;
unsigned long rate;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;
struct hlist_head children;
struct hlist_node child_node;
unsigned int notifier_count;
#ifdef CONFIG_COMMON_CLK_DEBUG
struct dentry *dentry;
#endif
};
An instance of struct clk_internal will be allocated in
__clk_init/clk_register. Now the private data stays completely inside
the core and noone can abuse it.
Hi Sascha,
I see the disconnect here. For OMAP (and possibly other platforms) at
least some clock data is necessary during early boot, before the
regular allocation methods are available (timers for instance).
We had this problem on i.MX aswell. It turned out that the timer clock
is the only clock that is needed so early. We solved this by moving the
clock init to the system timer init function.
When you say "mov[ed] the clock init to the system timer init
function" do you mean that you statically allocated struct clk and
used the clk framework api, or instead you just did some direct
register writes to initialize things properly?
I meant that on i.MX we do the clock tree initialization when kmalloc is
available, see the attached patch for omap4 based on your branch which
does the same for Omap. The first clock you need is the one for the
timer, so you can initialize the clocktree at the beginning of
time_init() and don't need statically initialized clocks anymore.
Well, the file is work in progress, you probably fix this before sending
it out, but I bet people will include clk-private.h and nobody else
notices it.
clock44xx_data.c does not violate that rule. None of the logic that
implements ops for those clocks is present clock44xx_data.c.
Indeed, I missed that. It only has the ops but not the individual
functions.
All of
the code in that file is simply initialization and registration of
OMAP4 clocks. Many of the clocks are basic clock types (divider,
multiplexer and fixed-rate are used in that file) with protected code
drivers/clk/clk-*.c and the remaining clocks are of the struct
clk_hw_omap variety, which has code spread across several files:
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll4xxx.c
All of the above files include linux/clk-provider.h, not
linux/clk-private.h. That code makes heavy use of the
__clk_get_whatever helpers and shows how a platform might honor the
layer of separation between struct clk and stuct clk_ops/struct
clk_foo. You are correct that the code is a work-in-progress, but
there are no layering violations that I can see.
I also think we are talking past each other to some degree. One point
I would like to make (and maybe you already know this from code
review) is that it is unnecessary to have pointers to your parent
struct clk*'s when either initializing or registering your clocks. In
fact the existing clk_register_foo functions don't even allow you to
pass in parent pointers and rely wholly on string name matching. I
just wanted to point that out in case it went unnoticed, as it is a
new way of doing things from the previous series and was born out of
Thomas' review of V4 and multi-parent handling. This also keeps
device-tree in mind where we might not know the struct clk *pointer at
compile time for "connecting" discrete devices.
Yes, I've seen this and I really like it. Also the change that
multiplexers return an index to an array instead of the parent
clock is very nice.
Sascha
8<-----------------------------------------------------
ARM omap4: move clocktree init to timer init time so we don't need static clocks
Signed-off-by: Sascha Hauer<s.hauer@xxxxxxxxxxxxxx>
Hi Sascha,
Thanks for the example code. This is in fact something I had
considered doing before, but it is a bit complicated for my platform.
We set up all of the OMAP clocks with __clk_init because this is a
dependency of OMAP's hwmod code which models and interacts with
specific resources for hardware modules, such as clocks. There are
other dependencies such as our clockdomain code, which needs the
clocks to be fully initialized. Some aspects of these layers get
init'd before we can allocate memory.
Admittedly I think that the OMAP code could migrate some of these bits
to a lazy-registration model, specifically the hwmod object instances,
but that requires an awful lot of refactoring for a fairly large stack
of platform code. This might be something to achieve in the future
but for now we *need* initialisation to be fully static.
Assuming that some day OMAP code can be refactored to allow for lazy
(or at least initcall-based) registration of clocks then perhaps your
suggestion can take root. Which leads me to this question: are there
any other platforms out there that require the level of expose to
struct clk present in this patchset? OMAP does, for now, but if that
changes then I need to know if others require this as well.