summaryrefslogtreecommitdiffstats
path: root/Documentation/clk.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/clk.txt')
-rw-r--r--Documentation/clk.txt233
1 files changed, 0 insertions, 233 deletions
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
deleted file mode 100644
index 1943fae..0000000
--- a/Documentation/clk.txt
+++ /dev/null
@@ -1,233 +0,0 @@
- The Common Clk Framework
- Mike Turquette <mturquette@ti.com>
-
-This document endeavours to explain the common clk framework details,
-and how to port a platform over to this framework. It is not yet a
-detailed explanation of the clock api in include/linux/clk.h, but
-perhaps someday it will include that information.
-
- Part 1 - introduction and interface split
-
-The common clk framework is an interface to control the clock nodes
-available on various devices today. This may come in the form of clock
-gating, rate adjustment, muxing or other operations. This framework is
-enabled with the CONFIG_COMMON_CLK option.
-
-The interface itself is divided into two halves, each shielded from the
-details of its counterpart. First is the common definition of struct
-clk which unifies the framework-level accounting and infrastructure that
-has traditionally been duplicated across a variety of platforms. Second
-is a common implementation of the clk.h api, defined in
-drivers/clk/clk.c. Finally there is struct clk_ops, whose operations
-are invoked by the clk api implementation.
-
-The second half of the interface is comprised of the hardware-specific
-callbacks registered with struct clk_ops and the corresponding
-hardware-specific structures needed to model a particular clock. For
-the remainder of this document any reference to a callback in struct
-clk_ops, such as .enable or .set_rate, implies the hardware-specific
-implementation of that code. Likewise, references to struct clk_foo
-serve as a convenient shorthand for the implementation of the
-hardware-specific bits for the hypothetical "foo" hardware.
-
-Tying the two halves of this interface together is struct clk_hw, which
-is defined in struct clk_foo and pointed to within struct clk. This
-allows easy for navigation between the two discrete halves of the common
-clock interface.
-
- Part 2 - common data structures and api
-
-Below is the common struct clk definition from
-include/linux/clk-private.h, modified for brevity:
-
- struct clk {
- const char *name;
- const struct clk_ops *ops;
- struct clk_hw *hw;
- char **parent_names;
- struct clk **parents;
- struct clk *parent;
- struct hlist_head children;
- struct hlist_node child_node;
- ...
- };
-
-The members above make up the core of the clk tree topology. The clk
-api itself defines several driver-facing functions which operate on
-struct clk. That api is documented in include/linux/clk.h.
-
-Platforms and devices utilizing the common struct clk use the struct
-clk_ops pointer in struct clk to perform the hardware-specific parts of
-the operations defined in clk.h:
-
- struct clk_ops {
- int (*prepare)(struct clk_hw *hw);
- void (*unprepare)(struct clk_hw *hw);
- int (*enable)(struct clk_hw *hw);
- void (*disable)(struct clk_hw *hw);
- int (*is_enabled)(struct clk_hw *hw);
- unsigned long (*recalc_rate)(struct clk_hw *hw,
- unsigned long parent_rate);
- long (*round_rate)(struct clk_hw *hw, unsigned long,
- unsigned long *);
- int (*set_parent)(struct clk_hw *hw, u8 index);
- u8 (*get_parent)(struct clk_hw *hw);
- int (*set_rate)(struct clk_hw *hw, unsigned long);
- void (*init)(struct clk_hw *hw);
- };
-
- Part 3 - hardware clk implementations
-
-The strength of the common struct clk comes from its .ops and .hw pointers
-which abstract the details of struct clk from the hardware-specific bits, and
-vice versa. To illustrate consider the simple gateable clk implementation in
-drivers/clk/clk-gate.c:
-
-struct clk_gate {
- struct clk_hw hw;
- void __iomem *reg;
- u8 bit_idx;
- ...
-};
-
-struct clk_gate contains struct clk_hw hw as well as hardware-specific
-knowledge about which register and bit controls this clk's gating.
-Nothing about clock topology or accounting, such as enable_count or
-notifier_count, is needed here. That is all handled by the common
-framework code and struct clk.
-
-Let's walk through enabling this clk from driver code:
-
- struct clk *clk;
- clk = clk_get(NULL, "my_gateable_clk");
-
- clk_prepare(clk);
- clk_enable(clk);
-
-The call graph for clk_enable is very simple:
-
-clk_enable(clk);
- clk->ops->enable(clk->hw);
- [resolves to...]
- clk_gate_enable(hw);
- [resolves struct clk gate with to_clk_gate(hw)]
- clk_gate_set_bit(gate);
-
-And the definition of clk_gate_set_bit:
-
-static void clk_gate_set_bit(struct clk_gate *gate)
-{
- u32 reg;
-
- reg = __raw_readl(gate->reg);
- reg |= BIT(gate->bit_idx);
- writel(reg, gate->reg);
-}
-
-Note that to_clk_gate is defined as:
-
-#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, clk)
-
-This pattern of abstraction is used for every clock hardware
-representation.
-
- Part 4 - supporting your own clk hardware
-
-When implementing support for a new type of clock it only necessary to
-include the following header:
-
-#include <linux/clk-provider.h>
-
-include/linux/clk.h is included within that header and clk-private.h
-must never be included from the code which implements the operations for
-a clock. More on that below in Part 5.
-
-To construct a clk hardware structure for your platform you must define
-the following:
-
-struct clk_foo {
- struct clk_hw hw;
- ... hardware specific data goes here ...
-};
-
-To take advantage of your data you'll need to support valid operations
-for your clk:
-
-struct clk_ops clk_foo_ops {
- .enable = &clk_foo_enable;
- .disable = &clk_foo_disable;
-};
-
-Implement the above functions using container_of:
-
-#define to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)
-
-int clk_foo_enable(struct clk_hw *hw)
-{
- struct clk_foo *foo;
-
- foo = to_clk_foo(hw);
-
- ... perform magic on foo ...
-
- return 0;
-};
-
-Below is a matrix detailing which clk_ops are mandatory based upon the
-hardware capbilities of that clock. A cell marked as "y" means
-mandatory, a cell marked as "n" implies that either including that
-callback is invalid or otherwise uneccesary. Empty cells are either
-optional or must be evaluated on a case-by-case basis.
-
- clock hardware characteristics
- -----------------------------------------------------------
- | gate | change rate | single parent | multiplexer | root |
- |------|-------------|---------------|-------------|------|
-.prepare | | | | | |
-.unprepare | | | | | |
- | | | | | |
-.enable | y | | | | |
-.disable | y | | | | |
-.is_enabled | y | | | | |
- | | | | | |
-.recalc_rate | | y | | | |
-.round_rate | | y | | | |
-.set_rate | | y | | | |
- | | | | | |
-.set_parent | | | n | y | n |
-.get_parent | | | n | y | n |
- | | | | | |
-.init | | | | | |
- -----------------------------------------------------------
-
-Finally, register your clock at run-time with a hardware-specific
-registration function. This function simply populates struct clk_foo's
-data and then passes the common struct clk parameters to the framework
-with a call to:
-
-clk_register(...)
-
-See the basic clock types in drivers/clk/clk-*.c for examples.
-
- Part 5 - static initialization of clock data
-
-For platforms with many clocks (often numbering into the hundreds) it
-may be desirable to statically initialize some clock data. This
-presents a problem since the definition of struct clk should be hidden
-from everyone except for the clock core in drivers/clk/clk.c.
-
-To get around this problem struct clk's definition is exposed in
-include/linux/clk-private.h along with some macros for more easily
-initializing instances of the basic clock types. These clocks must
-still be initialized with the common clock framework via a call to
-__clk_init.
-
-clk-private.h must NEVER be included by code which implements struct
-clk_ops callbacks, nor must it be included by any logic which pokes
-around inside of struct clk at run-time. To do so is a layering
-violation.
-
-To better enforce this policy, always follow this simple rule: any
-statically initialized clock data MUST be defined in a separate file
-from the logic that implements its ops. Basically separate the logic
-from the data and all is well.