LWN.net Logo

A common clock framework

By Jake Edge
December 21, 2011

One of the big problem areas that has been identified in the ARM kernel trees is the diversity of implementations for various things that could be shared—either within the ARM tree or more widely with the rest of the kernel. That problem has led to a large amount of duplicated code in the ARM tree, both via cut-and-paste and code that is conceptually similar but uses different data structures and APIs. The latter makes the creation of a single kernel image that can boot on multiple ARM platforms impossible, so there are efforts to consolidate these implementations. The common clock framework is one such effort.

In a typical ARM system-on-chip (SoC), there can be dozens of different clocks for use by various I/O and other devices in the SoC. Typically those clocks are hooked together into elaborate tree-like structures. In those trees, child clocks can sometimes only change their frequency if the parent (and any other children) are correspondingly changed; disabling certain clocks will affect other clocks in the system and so on. Each ARM platform/SoC has its own way of encapsulating that information and presenting it to other parts of the system (like power and thermal management controllers), which makes it difficult to create platform-independent solutions.

The first problem that a common clock framework faces is the sheer number of different struct clk definitions scattered throughout the ARM tree. There are more than two dozen definitions in arch/arm currently, but the proposal for a common framework not surprisingly reduces that number to one. Implementations can wrap the struct clk in another structure that holds hardware-specific data, but the common structure looks like:

    struct clk {
	const char                  *name;
	const struct clk_hw_ops     *ops;
	struct clk                  *parent;
	unsigned long               rate;
	unsigned long               flags;
	unsigned int                enable_count;
	unsigned int                prepare_count;
	struct hlist_head           children;
	struct hlist_node           child_node;
    };

The parent and children/child_node fields allow the clocks to be arranged into trees, while the rate field tracks the current clock frequency (in Hz). The flags field is used to describe the clock type (e.g. whether a rate change needs to be done on the parent clock, or that the clock must be disabled before changing the rate). The two *_count fields are for tracking calls to the enable and prepare operations, while the bulk of the "work" is done within the struct clk_hw_ops field (ops).

Each of the entries in the clk_hw_ops structure correspond to a function in the driver-facing API for the clock framework. That API does some sanity checking before calling the corresponding operation from clk_hw_ops:

    struct clk_hw_ops {
	int             (*prepare)(struct clk *clk);
	void            (*unprepare)(struct clk *clk);
	int             (*enable)(struct clk *clk);
	void            (*disable)(struct clk *clk);
	unsigned long   (*recalc_rate)(struct clk *clk);
	long            (*round_rate)(struct clk *clk, unsigned long,
				      unsigned long *);
	int             (*set_parent)(struct clk *clk, struct clk *);
	struct clk *    (*get_parent)(struct clk *clk);
	int             (*set_rate)(struct clk *clk, unsigned long);
    };
clk_prepare() is used to initialize the clock to a state where it could be enabled, and that call must be made before clk_enable(), which actually starts the clock running. clk_disable() and clk_unprepare() do the reverse and should be called in that order. The difference is that clk_prepare() can sleep, while clk_enable() must not, so having two separate calls allows the clock initialization to be split into atomic and non-atomic pieces.

clk_get_parent() and clk_set_parent() do what the names imply, simply returning or changing the parent field, though setting the parent only succeeds if the clock is not already in use (otherwise -EBUSY is returned). clk_recalc_rate() queries the hardware, rather than the cached rate field, for the current frequency of the clock. clk_round_rate() rounds a frequency in Hz to a rate that the clock can actually use, and can also be used to determine the correct frequency for the parent clock when changing rates. All of those are more or less helper functions for clk_set_rate().

clk_set_rate() changes the frequency of a clock, but it must take into account some other factors. If the CLK_PARENT_SET_RATE flag value is set for the clock, clk_set_rate() needs to propagate the change to the parent clock (which may also have that flag set, necessitating a recursive traversal of the tree, attempting to set the rate at each level).

Drivers can also register their interest in being notified of rate changes with the clk_notifier_register() function. Three different types of notification can be requested: before the clock's rate changes, after it has been changed, or if the change gets aborted after the pre-change notifications have been called (i.e. PRE_RATE_CHANGE, POST_RATE_CHANGE, and ABORT_RATE_CHANGE). In each case, both the old and new values for the rate get passed as part of the notification callback. The patch to add notifications creates another operation in clk_hw_ops called speculate_rate(), which notes potential rate changes and sends any needed pre-change notifications as it walks the sub-tree.

The patch set also exports the clock hierarchy into debugfs. Each top-level clock gets a directory in ../debug/clk that contains read-only files to report the clock's rate, flags, prepare and enable counts, and the number of notifiers registered. Subdirectories are created for each child clock containing the same information.

The common clock framework has been around for some time in various forms. The current incarnation is being shepherded by Mike Turquette, but he notes that it is based on work originally done by Jeremy Kerr and Ben Herrenschmidt. Beyond that: "Many others contributed to those patches and promptly had their work stolen by me". Turquette has also posted a patch set with an example that replaces the OMAP4 clocks using the framework.

The comments on the most recent iteration have been fairly light, but still substantive, so we are clearly a ways off from seeing a version in the mainline. It's clearly on the radar of ARM developers, and would clean up a fair amount of code duplication within that tree, so we should see something in the mainline soon—hopefully in one of the next few kernel releases.


(Log in to post comments)

An uncommon clock function name

Posted Dec 22, 2011 11:25 UTC (Thu) by neilbrown (subscriber, #359) [Link]

"unprepare"? Seriously?
I guess it's better than "postpare" or "dispare".
"probe"/"shutdown" might work if the "prepare" needs to examine the clock in some way. There is precedent for that.
"startup"/"shutdown" or "online"/"offline" might work too.
There are probably lots of possibilities. but "unprepare"? That's not even a word!!!!

An uncommon clock function name

Posted Dec 22, 2011 12:49 UTC (Thu) by zuki (subscriber, #41808) [Link]

It's a neologism, which is a word too :)

An uncommon clock function name

Posted Dec 22, 2011 12:52 UTC (Thu) by cesarb (subscriber, #6266) [Link]

> There are probably lots of possibilities. but "unprepare"? That's not even a word!!!!

It sounds like a perfectly cromulent word to me.

An uncommon clock function name

Posted Dec 22, 2011 14:13 UTC (Thu) by mpr22 (subscriber, #60784) [Link]

I don't like it either, but I can't deny that it's a word. Ghastly neologisms are still words - and unlike many ghastly neologisms, I can even look at it and be reasonably confident that (a) it has a strong meaning (b) the meaning would be apparent to any fluent speaker of English.

An uncommon clock function name

Posted Dec 22, 2011 16:18 UTC (Thu) by nevets (subscriber, #11875) [Link]

It may be a word, but I've never heard of it. As a native English speaker, I'm a bit confused by what it would mean.

unprepare - (v) Put yourself back into a state that you are not prepared.

??

Still, it is horrible. And I agree that much better names can be used.

An uncommon clock function name

Posted Dec 22, 2011 18:39 UTC (Thu) by dkrawchuk (subscriber, #21896) [Link]

It's what you do to become unprepared.

An uncommon clock function name

Posted Dec 23, 2011 14:19 UTC (Fri) by mpr22 (subscriber, #60784) [Link]

*blink* *blink* I cannot comprehend how one might become confused here. What else could "unprepare" as a verb mean, except to undo previous preparations?

An uncommon clock function name

Posted Dec 23, 2011 14:29 UTC (Fri) by ken (subscriber, #625) [Link]

So you mean you abort the operation you have started, now I see ;)

An uncommon clock function name

Posted Dec 23, 2011 16:18 UTC (Fri) by nevets (subscriber, #11875) [Link]

What else could "unprepare" as a verb mean

The process of making yourself unprepared.

To me, it doesn't mean that you have to be prepared in the first place. If you don't do anything to get yourself ready for a presentation, one could say: "I will unprepare myself for the presentation".

Face it, the term sucks. It's silly. startup() and shutdown() are much better terms and more recognizable. As with all technical operations, it is best not to come up with new terms that may lead to confusion. The clearer you make your function names, the clearer you code will be to understand.

An uncommon clock function name

Posted Dec 28, 2011 20:48 UTC (Wed) by robbe (guest, #16131) [Link]

> To me, it doesn't mean that you have to be prepared in the first place.

Why? You can't prepare yourself if you are already prepared, can you? So by symmetry unpreparing implies that you were prepared, and somehow undo that state.

To this non-native speaker at least.

That said, I have no beef with the alternative verbs given in this thread.

This is common situation...

Posted Dec 28, 2011 22:17 UTC (Wed) by khim (subscriber, #9252) [Link]

I've seen it many times before: you see group of people, they all talk using English and have no problems understanding each other. Suddenly someone says: "no, you can not say <this> or <that>" and then fails to explain why. Invariably that someone is native speaker and he can not explain why you can not say <this> or <that> because there are no simple explanation.

If you'll ask linguist then usually source of the problem can be found: perhaps 200 years ago word was ostracized because it was too similar to some vulgar slang. It may be 300 years ago the original world (if this <this> or <that> are some modifications of other word) had slightly different meaning and so un<this> or im<that> made do sense. Sometimes even linguists have no explanation and can just cite some 100 years old articles which said (without explanation) that "<this> or <that> is not a word, don't use it".

This phenomenon if not restricted to English, this happens with all languages, of course.

As for me, I've filed "unprepare" under "strange aberration where English does not give you right to use seemingly simple and clear word". Really: why "unstick" does mean that something was stuck and "uncork" does mean that something was corked yet "unprepare" does not mean that someone was prepared?

Apparently the answer is "for historical reason": Marriam-Webster does include this word but gives the following explanation - "to cause to be unprepared : make unfit or unready <the purpose … is precisely to unprepare the reader — W.M.Frohock>" thus apparently you don't need to be prepared before you'll be unprepared, this can happen from "normal state", too.

An uncommon clock function name

Posted Jan 3, 2012 14:36 UTC (Tue) by ibukanov (subscriber, #3942) [Link]

> What else could "unprepare" as a verb mean

As non-native English speaker I perceived "unprepare" not as to undo the preparations but rather as to go from the initial state to the state where one would spend more efforts later if he wants to prepare. "Unprepare for a trip" would mean in that interpretation not to empty a travel bag and put things from it back to the shelves where they were before, but to make even more mess at home so it would be more difficult at some later point to pack things together in preparations for the trip.

An uncommon clock function name

Posted Dec 22, 2011 23:21 UTC (Thu) by iabervon (subscriber, #722) [Link]

It's in Merriam-Webster (Unabridged): "To cause to be unprepared; to make unfit or unready." It's certainly uncommon, but I don't think it's hard to understand or suggestive of the wrong thing. It's hardly a neologism; it's got a citation to someone who's been dead for 27 years.

Copyright © 2011, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds