--- zzzz-none-000/linux-3.10.107/Documentation/clk.txt 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/Documentation/clk.txt 2021-02-04 17:41:59.000000000 +0000 @@ -32,7 +32,7 @@ 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 +allows for easy navigation between the two discrete halves of the common clock interface. Part 2 - common data structures and api @@ -68,12 +68,25 @@ 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 *); + long (*round_rate)(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate); + int (*determine_rate)(struct clk_hw *hw, + struct clk_rate_request *req); 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); + int (*set_rate)(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate); + int (*set_rate_and_parent)(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate, + u8 index); + unsigned long (*recalc_accuracy)(struct clk_hw *hw, + unsigned long parent_accuracy); void (*init)(struct clk_hw *hw); + int (*debug_init)(struct clk_hw *hw, + struct dentry *dentry); }; Part 3 - hardware clk implementations @@ -179,26 +192,30 @@ callback is invalid or otherwise unnecessary. 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 | | | | | | - ----------------------------------------------------------- + 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 [1] | | | | +.determine_rate | | y [1] | | | | +.set_rate | | y | | | | + | | | | | | +.set_parent | | | n | y | n | +.get_parent | | | n | y | n | + | | | | | | +.recalc_accuracy| | | | | | + | | | | | | +.init | | | | | | + ----------------------------------------------------------- +[1] either one of round_rate or determine_rate is required. Finally, register your clock at run-time with a hardware-specific registration function. This function simply populates struct clk_foo's @@ -209,30 +226,7 @@ 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. - - Part 6 - Disabling clock gating of unused clocks + Part 5 - Disabling clock gating of unused clocks Sometimes during development it can be useful to be able to bypass the default disabling of unused clocks. For example, if drivers aren't enabling @@ -242,3 +236,37 @@ To bypass this disabling, include "clk_ignore_unused" in the bootargs to the kernel. + + Part 6 - Locking + +The common clock framework uses two global locks, the prepare lock and the +enable lock. + +The enable lock is a spinlock and is held across calls to the .enable, +.disable and .is_enabled operations. Those operations are thus not allowed to +sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API +functions are allowed in atomic context. + +The prepare lock is a mutex and is held across calls to all other operations. +All those operations are allowed to sleep, and calls to the corresponding API +functions are not allowed in atomic context. + +This effectively divides operations in two groups from a locking perspective. + +Drivers don't need to manually protect resources shared between the operations +of one group, regardless of whether those resources are shared by multiple +clocks or not. However, access to resources that are shared between operations +of the two groups needs to be protected by the drivers. An example of such a +resource would be a register that controls both the clock rate and the clock +enable/disable state. + +The clock framework is reentrant, in that a driver is allowed to call clock +framework functions from within its implementation of clock operations. This +can for instance cause a .set_rate operation of one clock being called from +within the .set_rate operation of another clock. This case must be considered +in the driver implementations, but the code flow is usually controlled by the +driver in that case. + +Note that locking must also be considered when code outside of the common +clock framework needs to access resources used by the clock operations. This +is considered out of scope of this document.