One of the "big problem areas" has been identified in the "ARM kerneltrees is" the diversity of implementations for VA Rious things that could beshared-either within the "ARM tree" or more widely with the rest of the Thekernel. That's problem has led to a large amount of duplicated code in Thearm, both via Cut-and-paste and code this is CONCEPTU Ally similar butuses different data structures and APIs. The latter makes the creation OFA single kernel image, can boot on multiple ARM platforms impossible, Sothere are Effo RTS to consolidate these implementations. The common clockframework is one such effort.
In a typical ARM system-on-chip (SoC), there can is dozens of differentclocks for use by various I/O and other devices In the SoC. Typicallythose clocks are hooked together to elaborate tree-like. Inthose trees, clocks can sometimes only change their frequency if the parent (and no other children) are Ingly changed; Disabling certainclocks would affect other clocks in the system and. Each ARMPLATFORM/SOC has its own way of encapsulating this information andpresenting it to other parts of the the system Power and Thermalmanagement controllers), which makes it difficult to createplatform-independent solutions.
The "problem" a common clock framework faces is the sheer numberof different struct CLK definitions scattered Oughout the Armtree. There are more than two dozen definitions in arch/armcurrently, but the proposal to a commonframework not surprisingly re Duces that number to one. Implementations canwrap the struct CLK in another structure of that holdshardware-specific data, but the common structure KS 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 allowthe clocks to is arrangedinto trees, while the rate field tracks T clock frequency (in Hz). Theflags field is used to describe the clocktype (e.g. whether a rate change needs to being done on the parent clock, orthat The clock must be disabled before changing the rate). The two *_count fields are for tracking calls to the Enableand prepare, while the operations of the "bulk" are done WI Thin thestruct clk_hw_ops field (OPS).
Each of the "entries in" Clk_hw_ops structure correspond to afunction APIs for the driver-facing framework. That API doessome sanity checking before calling the corresponding operation:
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 initializethe clock to a the where it could be enabled, and this call must being Madebefore clk_en Able (), which actually starts the clock running. Clk_disable () and Clk_unprepare () do the reverse andshould is called in. The difference is this clk_prepare () can sleep, while clk_enable () must not, sohaving two separate calls the allows Initialization to be split intoatomic and non-atomic pieces.
Clk_get_parent () and clk_set_parent () do what the namesimply, simply returning or changing the ParentField, though The parent only succeeds if the clock isn't alreadyin use (Otherwise-ebusy is returned). Clk_recalc_rate () Queriesthe hardware, rather than the cached field, for the current rate of frequency. Clk_round_rate () rounds a frequency in Hz to a rate thatthe clock can actually use, and can also is used to determine the Correctfrequency for the "parent clock when changing rates. All of the those are more or less helper functionsfor clk_set_rate ().
Clk_set_rate () Changes the frequency of a clock, but it must takeinto account some other factors. If the Clk_parent_set_rate Flagvalue is SET for the clock, clk_set_rate () needs to propagate thechange to the PARENT clock (which may also have that flag set,necessitating a recursive traversal of the "tree", attempting to set the Rateat each Lev EL).
Drivers can also register their interest in being notified of rate Changeswith the Clk_notifier_register () function. Three different typesof notification can be requested:before the clock's ratechanges, after it has been, or if th E change gets aborted after Thepre-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 Thenotification callback. The patch to add notificationscreates another operation in Clk_hw_ops Calledspeculate_rate (), which notes potential rate C Hanges and sends any needed pre-changenotifications as it walks the sub-tree.
The patch set also exports the clock hierarchy into Debugfs. Eachtop-level clock gets a directory in.. /debug/clk that containsread-only files to the clock's rate, flags, prepare and enablecounts, and the number of not Ifiers registered. Subdirectories are createdfor each child clock containing the same information.
The common clock framework has been around for some as time in various forms. The current incarnation was being shepherded by Mike Turquette, but him notesthat it is based on work originally do by Jer Emy Kerr and Benherrenschmidt. Beyond "Many others contributed to Thosepatches and promptly had their work by me". Turquette has also posted a patch set Withan Examplethat replaces the OMAP4 the using the framework.
The comments onthe Most recent iteration have been fairly light, but still substantive, sowe are clearly a ways off from S Eeing a version in the mainline. It ' sclearly on the radar's ARM developers, and would clean up a fair amount ofcode duplication within "tree" so we sh Ould the something in Themainline soon-hopefully in one of the next few kernel. (Log in to post comments)