sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget"/translations/zh_CN/driver-api/clkmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/zh_TW/driver-api/clkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/it_IT/driver-api/clkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/ja_JP/driver-api/clkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/ko_KR/driver-api/clkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/pt_BR/driver-api/clkmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/sp_SP/driver-api/clkmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(hThe Common Clk Frameworkh]hThe Common Clk Framework}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhh h]h paragraph)}(h"Mike Turquette h](hMike Turquette <}(hhhhhNhNubh reference)}(hmturquette@ti.comh]hmturquette@ti.com}(hhhhhNhNubah}(h]h ]h"]h$]h&]refurimailto:mturquette@ti.comuh1hhhubh>}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(hThis 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.h]hThis 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.}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h Introduction and interface splith]h Introduction and interface split}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj1hhhhhK ubh)}(hThe 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.h]hThe 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.}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubh)}(hXThe 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.h]hXThe 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.}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubh)}(hXThe 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.h]hXThe 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.}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1hhubh)}(hTying the two halves of this interface together is struct clk_hw, which is defined in struct clk_foo and pointed to within struct clk_core. This allows for easy navigation between the two discrete halves of the common clock interface.h]hTying the two halves of this interface together is struct clk_hw, which is defined in struct clk_foo and pointed to within struct clk_core. This allows for easy navigation between the two discrete halves of the common clock interface.}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK%hj1hhubeh}(h] introduction-and-interface-splitah ]h"] introduction and interface splitah$]h&]uh1hhhhhhhhK ubh)}(hhh](h)}(hCommon data structures and apih]hCommon data structures and api}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK+ubhindex)}(hhh]h}(h]h ]h"]h$]h&]entries](singleclk_core (C struct) c.clk_corehNtauh1jhjhhhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chNubhdesc)}(hhh](hdesc_signature)}(hclk_coreh]hdesc_signature_line)}(hstruct clk_coreh](hdesc_sig_keyword)}(hstructh]hstruct}(hjhhhNhNubah}(h]h ]kah"]h$]h&]uh1jhjhhhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKubhdesc_sig_space)}(h h]h }(hjhhhNhNubah}(h]h ]wah"]h$]h&]uh1jhjhhhjhKubh desc_name)}(hclk_coreh]h desc_sig_name)}(hjh]hclk_core}(hjhhhNhNubah}(h]h ]nah"]h$]h&]uh1jhjubah}(h]h ](sig-namedescnameeh"]h$]h&] xml:spacepreserveuh1jhjhhhjhKubeh}(h]h ]h"]h$]h&]jj add_permalinkuh1jsphinx_line_type declaratorhjhhhjhKubah}(h]jah ](sig sig-objecteh"]h$]h&] is_multiline _toc_parts) _toc_namehuh1jhjhKhjhhubh desc_content)}(hhh]h)}(h,The internal state of a clk in the clk tree.h]h,The internal state of a clk in the clk tree.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKChjhhubah}(h]h ]h"]h$]h&]uh1j hjhhhjhKubeh}(h]h ](cstructeh"]h$]h&]domainj*objtypej+desctypej+noindex noindexentrynocontentsentryuh1jhhhjhjhNubh container)}(hX**Definition**:: struct clk_core { const char *name; const struct clk_ops *ops; struct clk_hw *hw; struct module *owner; struct device *dev; struct hlist_node rpm_node; struct device_node *of_node; struct clk_core *parent; struct clk_parent_map *parents; u8 num_parents; u8 new_parent_index; unsigned long rate; unsigned long req_rate; unsigned long new_rate; struct clk_core *new_parent; struct clk_core *new_child; unsigned long flags; bool orphan; bool rpm_enabled; unsigned int enable_count; unsigned int prepare_count; unsigned int protect_count; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; int phase; struct clk_duty duty; struct hlist_head children; struct hlist_node child_node; struct hlist_node hashtable_node; struct hlist_head clks; unsigned int notifier_count; #ifdef CONFIG_DEBUG_FS; struct dentry *dentry; struct hlist_node debug_node; #endif; struct kref ref; }; **Members** ``name`` Unique name of the clk for identification. ``ops`` Pointer to hardware-specific operations for this clk. ``hw`` Pointer for traversing from a struct clk to its corresponding hardware-specific structure. ``owner`` Kernel module owning this clk (for reference counting). ``dev`` Device associated with this clk (optional) ``rpm_node`` Node for runtime power management list management. ``of_node`` Device tree node associated with this clk (if applicable) ``parent`` Pointer to the current parent in the clock tree. ``parents`` Array of possible parents (for muxes/selectable parents). ``num_parents`` Number of possible parents. ``new_parent_index`` Index of the new parent during parent change operations. ``rate`` Current cached clock rate (Hz). ``req_rate`` The last rate requested by a call to clk_set_rate(). It's initialized to clk_core->rate. It's also updated to clk_core->rate every time the clock is reparented, and when we're doing the orphan -> !orphan transition. ``new_rate`` New rate to be set during a rate change operation. ``new_parent`` Pointer to new parent during parent change. This is also used when a clk's rate is changed. ``new_child`` Pointer to new child during reparenting. This is also used when a clk's rate is changed. ``flags`` Clock property and capability flags. See `clk framework flags`. ``orphan`` True if this clk is currently orphaned. ``rpm_enabled`` True if runtime power management is enabled for this clk. ``enable_count`` Reference count of enables. ``prepare_count`` Reference count of prepares. ``protect_count`` Protection reference count against disable. ``min_rate`` Minimum supported clock rate (Hz). ``max_rate`` Maximum supported clock rate (Hz). ``accuracy`` Accuracy of the clock rate (parts per billion). ``phase`` Current phase (degrees). ``duty`` Current duty cycle configuration (as ratio: num/den). ``children`` All of the children of this clk. ``child_node`` Node for linking as a child in the parent's list. ``hashtable_node`` Node for hash table that allows fast clk lookup by name. ``clks`` All of the clk consumers registered. ``notifier_count`` Number of notifiers registered for this clk. ``dentry`` DebugFS entry for this clk. ``debug_node`` DebugFS node for this clk. ``ref`` Reference count for structure lifetime management.h](h)}(h**Definition**::h](hstrong)}(h**Definition**h]h Definition}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1j?hj;ubh:}(hj;hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKGhj7ubh literal_block)}(hXstruct clk_core { const char *name; const struct clk_ops *ops; struct clk_hw *hw; struct module *owner; struct device *dev; struct hlist_node rpm_node; struct device_node *of_node; struct clk_core *parent; struct clk_parent_map *parents; u8 num_parents; u8 new_parent_index; unsigned long rate; unsigned long req_rate; unsigned long new_rate; struct clk_core *new_parent; struct clk_core *new_child; unsigned long flags; bool orphan; bool rpm_enabled; unsigned int enable_count; unsigned int prepare_count; unsigned int protect_count; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; int phase; struct clk_duty duty; struct hlist_head children; struct hlist_node child_node; struct hlist_node hashtable_node; struct hlist_head clks; unsigned int notifier_count; #ifdef CONFIG_DEBUG_FS; struct dentry *dentry; struct hlist_node debug_node; #endif; struct kref ref; };h]hXstruct clk_core { const char *name; const struct clk_ops *ops; struct clk_hw *hw; struct module *owner; struct device *dev; struct hlist_node rpm_node; struct device_node *of_node; struct clk_core *parent; struct clk_parent_map *parents; u8 num_parents; u8 new_parent_index; unsigned long rate; unsigned long req_rate; unsigned long new_rate; struct clk_core *new_parent; struct clk_core *new_child; unsigned long flags; bool orphan; bool rpm_enabled; unsigned int enable_count; unsigned int prepare_count; unsigned int protect_count; unsigned long min_rate; unsigned long max_rate; unsigned long accuracy; int phase; struct clk_duty duty; struct hlist_head children; struct hlist_node child_node; struct hlist_node hashtable_node; struct hlist_head clks; unsigned int notifier_count; #ifdef CONFIG_DEBUG_FS; struct dentry *dentry; struct hlist_node debug_node; #endif; struct kref ref; };}hj\sbah}(h]h ]h"]h$]h&]jjuh1jZhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKIhj7ubh)}(h **Members**h]j@)}(hjmh]hMembers}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1j?hjkubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKqhj7ubhdefinition_list)}(hhh](hdefinition_list_item)}(h4``name`` Unique name of the clk for identification. h](hterm)}(h``name``h]hliteral)}(hjh]hname}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKEhjubh definition)}(hhh]h)}(h*Unique name of the clk for identification.h]h*Unique name of the clk for identification.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKEhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKEhjubj)}(h>``ops`` Pointer to hardware-specific operations for this clk. h](j)}(h``ops``h]j)}(hjh]hops}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKFhjubj)}(hhh]h)}(h5Pointer to hardware-specific operations for this clk.h]h5Pointer to hardware-specific operations for this clk.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKFhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKFhjubj)}(hb``hw`` Pointer for traversing from a struct clk to its corresponding hardware-specific structure. h](j)}(h``hw``h]j)}(hjh]hhw}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKHhjubj)}(hhh]h)}(hZPointer for traversing from a struct clk to its corresponding hardware-specific structure.h]hZPointer for traversing from a struct clk to its corresponding hardware-specific structure.}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKGhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKHhjubj)}(hB``owner`` Kernel module owning this clk (for reference counting). h](j)}(h ``owner``h]j)}(hjBh]howner}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj@ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKIhj<ubj)}(hhh]h)}(h7Kernel module owning this clk (for reference counting).h]h7Kernel module owning this clk (for reference counting).}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjWhKIhjXubah}(h]h ]h"]h$]h&]uh1jhj<ubeh}(h]h ]h"]h$]h&]uh1jhjWhKIhjubj)}(h3``dev`` Device associated with this clk (optional) h](j)}(h``dev``h]j)}(hj{h]hdev}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKJhjuubj)}(hhh]h)}(h*Device associated with this clk (optional)h]h*Device associated with this clk (optional)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKJhjubah}(h]h ]h"]h$]h&]uh1jhjuubeh}(h]h ]h"]h$]h&]uh1jhjhKJhjubj)}(h@``rpm_node`` Node for runtime power management list management. h](j)}(h ``rpm_node``h]j)}(hjh]hrpm_node}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKKhjubj)}(hhh]h)}(h2Node for runtime power management list management.h]h2Node for runtime power management list management.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKKhjubj)}(hF``of_node`` Device tree node associated with this clk (if applicable) h](j)}(h ``of_node``h]j)}(hjh]hof_node}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKLhjubj)}(hhh]h)}(h9Device tree node associated with this clk (if applicable)h]h9Device tree node associated with this clk (if applicable)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKLhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKLhjubj)}(h<``parent`` Pointer to the current parent in the clock tree. h](j)}(h ``parent``h]j)}(hj&h]hparent}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj$ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKMhj ubj)}(hhh]h)}(h0Pointer to the current parent in the clock tree.h]h0Pointer to the current parent in the clock tree.}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj;hKMhj<ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj;hKMhjubj)}(hF``parents`` Array of possible parents (for muxes/selectable parents). h](j)}(h ``parents``h]j)}(hj_h]hparents}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1jhj]ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKNhjYubj)}(hhh]h)}(h9Array of possible parents (for muxes/selectable parents).h]h9Array of possible parents (for muxes/selectable parents).}(hjxhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjthKNhjuubah}(h]h ]h"]h$]h&]uh1jhjYubeh}(h]h ]h"]h$]h&]uh1jhjthKNhjubj)}(h,``num_parents`` Number of possible parents. h](j)}(h``num_parents``h]j)}(hjh]h num_parents}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKOhjubj)}(hhh]h)}(hNumber of possible parents.h]hNumber of possible parents.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKOhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKOhjubj)}(hN``new_parent_index`` Index of the new parent during parent change operations. h](j)}(h``new_parent_index``h]j)}(hjh]hnew_parent_index}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKPhjubj)}(hhh]h)}(h8Index of the new parent during parent change operations.h]h8Index of the new parent during parent change operations.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKPhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKPhjubj)}(h)``rate`` Current cached clock rate (Hz). h](j)}(h``rate``h]j)}(hj h]hrate}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKQhjubj)}(hhh]h)}(hCurrent cached clock rate (Hz).h]hCurrent cached clock rate (Hz).}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKQhj ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKQhjubj)}(h``req_rate`` The last rate requested by a call to clk_set_rate(). It's initialized to clk_core->rate. It's also updated to clk_core->rate every time the clock is reparented, and when we're doing the orphan -> !orphan transition. h](j)}(h ``req_rate``h]j)}(hjCh]hreq_rate}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjAubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKUhj=ubj)}(hhh]h)}(hThe last rate requested by a call to clk_set_rate(). It's initialized to clk_core->rate. It's also updated to clk_core->rate every time the clock is reparented, and when we're doing the orphan -> !orphan transition.h]hThe last rate requested by a call to clk_set_rate(). It’s initialized to clk_core->rate. It’s also updated to clk_core->rate every time the clock is reparented, and when we’re doing the orphan -> !orphan transition.}(hj\hhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKRhjYubah}(h]h ]h"]h$]h&]uh1jhj=ubeh}(h]h ]h"]h$]h&]uh1jhjXhKUhjubj)}(h@``new_rate`` New rate to be set during a rate change operation. h](j)}(h ``new_rate``h]j)}(hj}h]hnew_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj{ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKVhjwubj)}(hhh]h)}(h2New rate to be set during a rate change operation.h]h2New rate to be set during a rate change operation.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKVhjubah}(h]h ]h"]h$]h&]uh1jhjwubeh}(h]h ]h"]h$]h&]uh1jhjhKVhjubj)}(hk``new_parent`` Pointer to new parent during parent change. This is also used when a clk's rate is changed. h](j)}(h``new_parent``h]j)}(hjh]h new_parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKXhjubj)}(hhh]h)}(h[Pointer to new parent during parent change. This is also used when a clk's rate is changed.h]h]Pointer to new parent during parent change. This is also used when a clk’s rate is changed.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKWhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKXhjubj)}(hg``new_child`` Pointer to new child during reparenting. This is also used when a clk's rate is changed. h](j)}(h ``new_child``h]j)}(hjh]h new_child}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKZhjubj)}(hhh]h)}(hXPointer to new child during reparenting. This is also used when a clk's rate is changed.h]hZPointer to new child during reparenting. This is also used when a clk’s rate is changed.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKYhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKZhjubj)}(hJ``flags`` Clock property and capability flags. See `clk framework flags`. h](j)}(h ``flags``h]j)}(hj*h]hflags}(hj,hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj(ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK\hj$ubj)}(hhh]h)}(h?Clock property and capability flags. See `clk framework flags`.h](h)Clock property and capability flags. See }(hjChhhNhNubhtitle_reference)}(h`clk framework flags`h]hclk framework flags}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1jKhjCubh.}(hjChhhNhNubeh}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK[hj@ubah}(h]h ]h"]h$]h&]uh1jhj$ubeh}(h]h ]h"]h$]h&]uh1jhj?hK\hjubj)}(h3``orphan`` True if this clk is currently orphaned. h](j)}(h ``orphan``h]j)}(hjxh]horphan}(hjzhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjvubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK]hjrubj)}(hhh]h)}(h'True if this clk is currently orphaned.h]h'True if this clk is currently orphaned.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhK]hjubah}(h]h ]h"]h$]h&]uh1jhjrubeh}(h]h ]h"]h$]h&]uh1jhjhK]hjubj)}(hJ``rpm_enabled`` True if runtime power management is enabled for this clk. h](j)}(h``rpm_enabled``h]j)}(hjh]h rpm_enabled}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK^hjubj)}(hhh]h)}(h9True if runtime power management is enabled for this clk.h]h9True if runtime power management is enabled for this clk.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhK^hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhK^hjubj)}(h-``enable_count`` Reference count of enables. h](j)}(h``enable_count``h]j)}(hjh]h enable_count}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK_hjubj)}(hhh]h)}(hReference count of enables.h]hReference count of enables.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhK_hjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhK_hjubj)}(h/``prepare_count`` Reference count of prepares. h](j)}(h``prepare_count``h]j)}(hj#h]h prepare_count}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj!ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chK`hjubj)}(hhh]h)}(hReference count of prepares.h]hReference count of prepares.}(hj<hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj8hK`hj9ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj8hK`hjubj)}(h>``protect_count`` Protection reference count against disable. h](j)}(h``protect_count``h]j)}(hj\h]h protect_count}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjZubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKahjVubj)}(hhh]h)}(h+Protection reference count against disable.h]h+Protection reference count against disable.}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjqhKahjrubah}(h]h ]h"]h$]h&]uh1jhjVubeh}(h]h ]h"]h$]h&]uh1jhjqhKahjubj)}(h0``min_rate`` Minimum supported clock rate (Hz). h](j)}(h ``min_rate``h]j)}(hjh]hmin_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKbhjubj)}(hhh]h)}(h"Minimum supported clock rate (Hz).h]h"Minimum supported clock rate (Hz).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKbhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKbhjubj)}(h0``max_rate`` Maximum supported clock rate (Hz). h](j)}(h ``max_rate``h]j)}(hjh]hmax_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKchjubj)}(hhh]h)}(h"Maximum supported clock rate (Hz).h]h"Maximum supported clock rate (Hz).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKchjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKchjubj)}(h=``accuracy`` Accuracy of the clock rate (parts per billion). h](j)}(h ``accuracy``h]j)}(hjh]haccuracy}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKdhjubj)}(hhh]h)}(h/Accuracy of the clock rate (parts per billion).h]h/Accuracy of the clock rate (parts per billion).}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKdhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKdhjubj)}(h#``phase`` Current phase (degrees). h](j)}(h ``phase``h]j)}(hj@h]hphase}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj>ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKehj:ubj)}(hhh]h)}(hCurrent phase (degrees).h]hCurrent phase (degrees).}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjUhKehjVubah}(h]h ]h"]h$]h&]uh1jhj:ubeh}(h]h ]h"]h$]h&]uh1jhjUhKehjubj)}(h?``duty`` Current duty cycle configuration (as ratio: num/den). h](j)}(h``duty``h]j)}(hjyh]hduty}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjwubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKfhjsubj)}(hhh]h)}(h5Current duty cycle configuration (as ratio: num/den).h]h5Current duty cycle configuration (as ratio: num/den).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKfhjubah}(h]h ]h"]h$]h&]uh1jhjsubeh}(h]h ]h"]h$]h&]uh1jhjhKfhjubj)}(h.``children`` All of the children of this clk. h](j)}(h ``children``h]j)}(hjh]hchildren}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKghjubj)}(hhh]h)}(h All of the children of this clk.h]h All of the children of this clk.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKghjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKghjubj)}(hA``child_node`` Node for linking as a child in the parent's list. h](j)}(h``child_node``h]j)}(hjh]h child_node}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKhhjubj)}(hhh]h)}(h1Node for linking as a child in the parent's list.h]h3Node for linking as a child in the parent’s list.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKhhj ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj hKhhjubj)}(hL``hashtable_node`` Node for hash table that allows fast clk lookup by name. h](j)}(h``hashtable_node``h]j)}(hj$ h]hhashtable_node}(hj& hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj" ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKihj ubj)}(hhh]h)}(h8Node for hash table that allows fast clk lookup by name.h]h8Node for hash table that allows fast clk lookup by name.}(hj= hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj9 hKihj: ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj9 hKihjubj)}(h.``clks`` All of the clk consumers registered. h](j)}(h``clks``h]j)}(hj] h]hclks}(hj_ hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj[ ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKjhjW ubj)}(hhh]h)}(h$All of the clk consumers registered.h]h$All of the clk consumers registered.}(hjv hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjr hKjhjs ubah}(h]h ]h"]h$]h&]uh1jhjW ubeh}(h]h ]h"]h$]h&]uh1jhjr hKjhjubj)}(h@``notifier_count`` Number of notifiers registered for this clk. h](j)}(h``notifier_count``h]j)}(hj h]hnotifier_count}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKkhj ubj)}(hhh]h)}(h,Number of notifiers registered for this clk.h]h,Number of notifiers registered for this clk.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKkhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKkhjubj)}(h'``dentry`` DebugFS entry for this clk. h](j)}(h ``dentry``h]j)}(hj h]hdentry}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKlhj ubj)}(hhh]h)}(hDebugFS entry for this clk.h]hDebugFS entry for this clk.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKlhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKlhjubj)}(h*``debug_node`` DebugFS node for this clk. h](j)}(h``debug_node``h]j)}(hj h]h debug_node}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKmhj ubj)}(hhh]h)}(hDebugFS node for this clk.h]hDebugFS node for this clk.}(hj! hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hKmhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKmhjubj)}(h:``ref`` Reference count for structure lifetime management.h](j)}(h``ref``h]j)}(hjA h]href}(hjC hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj? ubah}(h]h ]h"]h$]h&]uh1jhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKmhj; ubj)}(hhh]h)}(h2Reference count for structure lifetime management.h]h2Reference count for structure lifetime management.}(hjZ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKnhjW ubah}(h]h ]h"]h$]h&]uh1jhj; ubeh}(h]h ]h"]h$]h&]uh1jhjV hKmhjubeh}(h]h ]h"]h$]h&]uh1jhj7ubeh}(h]h ] kernelindentah"]h$]h&]uh1j5hjhhhjhNubh)}(h**Description**h]j@)}(hj h]h Description}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j?hj ubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKqhjhhubh)}(hX Managed by the clk framework. Clk providers and consumers do not interact with this structure directly. Instead, clk operations flow through the framework and the framework manipulates this structure to keep track of parent/child relationships, rate, enable state, etc.h]hX Managed by the clk framework. Clk providers and consumers do not interact with this structure directly. Instead, clk operations flow through the framework and the framework manipulates this structure to keep track of parent/child relationships, rate, enable state, etc.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhP/var/lib/git/docbuild/linux/Documentation/driver-api/clk:45: ./drivers/clk/clk.chKnhjhhubh)}(hThe 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.h]hThe 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.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK0hjhhubh)}(hXPlatforms and devices utilizing the common struct clk_core use the struct clk_ops pointer in struct clk_core to perform the hardware-specific parts of the operations defined in clk-provider.h, and can set one or more framework-level flags documented below.h]hXPlatforms and devices utilizing the common struct clk_core use the struct clk_ops pointer in struct clk_core to perform the hardware-specific parts of the operations defined in clk-provider.h, and can set one or more framework-level flags documented below.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK4hjhhubj)}(hhh]h}(h]h ]h"]h$]h&]entries](jclk_ops (C struct) c.clk_opshNtauh1jhjhhh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhNubj)}(hhh](j)}(hclk_opsh]j)}(hstruct clk_opsh](j)}(hjh]hstruct}(hj hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj hhh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKubj)}(h h]h }(hj hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj hhhj hKubj)}(hclk_opsh]j)}(hj h]hclk_ops}(hj hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubah}(h]h ](jjeh"]h$]h&]jjuh1jhj hhhj hKubeh}(h]h ]h"]h$]h&]jjjuh1jjjhj hhhj hKubah}(h]j ah ](jjeh"]h$]h&]j j )j huh1jhj hKhj hhubj)}(hhh]h)}(hCallback operations for hardware clocks; these are to be provided by the clock implementation, and will be called by drivers through the clk_* api.h]hCallback operations for hardware clocks; these are to be provided by the clock implementation, and will be called by drivers through the clk_* api.}(hj! hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKyhj hhubah}(h]h ]h"]h$]h&]uh1j hj hhhj hKubeh}(h]h ](j*structeh"]h$]h&]j/j*j0j9 j1j9 j2j3j4uh1jhhhjhj hNubj6)}(hX**Definition**:: struct clk_ops { int (*prepare)(struct clk_hw *hw); void (*unprepare)(struct clk_hw *hw); int (*is_prepared)(struct clk_hw *hw); void (*unprepare_unused)(struct clk_hw *hw); int (*enable)(struct clk_hw *hw); void (*disable)(struct clk_hw *hw); int (*is_enabled)(struct clk_hw *hw); void (*disable_unused)(struct clk_hw *hw); int (*save_context)(struct clk_hw *hw); void (*restore_context)(struct clk_hw *hw); unsigned long (*recalc_rate)(struct clk_hw *hw, 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 rate, unsigned long parent_rate); int (*set_rate_and_parent)(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index); int (*set_spread_spectrum)(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf); unsigned long (*recalc_accuracy)(struct clk_hw *hw, unsigned long parent_accuracy); int (*get_phase)(struct clk_hw *hw); int (*set_phase)(struct clk_hw *hw, int degrees); int (*get_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*set_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*init)(struct clk_hw *hw); void (*terminate)(struct clk_hw *hw); void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); }; **Members** ``prepare`` Prepare the clock for enabling. This must not return until the clock is fully prepared, and it's safe to call clk_enable. This callback is intended to allow clock implementations to do any initialisation that may sleep. Called with prepare_lock held. ``unprepare`` Release the clock from its prepared state. This will typically undo any work done in the **prepare** callback. Called with prepare_lock held. ``is_prepared`` Queries the hardware to determine if the clock is prepared. This function is allowed to sleep. Optional, if this op is not set then the prepare count will be used. ``unprepare_unused`` Unprepare the clock atomically. Only called from clk_disable_unused for prepare clocks with special needs. Called with prepare mutex held. This function may sleep. ``enable`` Enable the clock atomically. This must not return until the clock is generating a valid clock signal, usable by consumer devices. Called with enable_lock held. This function must not sleep. ``disable`` Disable the clock atomically. Called with enable_lock held. This function must not sleep. ``is_enabled`` Queries the hardware to determine if the clock is enabled. This function must not sleep. Optional, if this op is not set then the enable count will be used. ``disable_unused`` Disable the clock atomically. Only called from clk_disable_unused for gate clocks with special needs. Called with enable_lock held. This function must not sleep. ``save_context`` Save the context of the clock in prepration for poweroff. ``restore_context`` Restore the context of the clock after a restoration of power. ``recalc_rate`` Recalculate the rate of this clock, by querying hardware. The parent rate is an input parameter. It is up to the caller to ensure that the prepare_mutex is held across this call. If the driver cannot figure out a rate for this clock, it must return 0. Returns the calculated rate. Optional, but recommended - if this op is not set then clock rate will be initialized to 0. ``determine_rate`` Given a target rate as input, returns the closest rate actually supported by the clock, and optionally the parent clock that should be used to provide the clock rate. ``set_parent`` Change the input source of this clock; for clocks with multiple possible parents specify a new parent by passing in the index as a u8 corresponding to the parent in either the .parent_names or .parents arrays. This function in affect translates an array index into the value programmed into the hardware. Returns 0 on success, -EERROR otherwise. ``get_parent`` Queries the hardware to determine the parent of a clock. The return value is a u8 which specifies the index corresponding to the parent clock. This index can be applied to either the .parent_names or .parents arrays. In short, this function translates the parent value read from hardware into an array index. Currently only called when the clock is initialized by __clk_init. This callback is mandatory for clocks with multiple parents. It is optional (and unnecessary) for clocks with 0 or 1 parents. ``set_rate`` Change the rate of this clock. The requested rate is specified by the second argument, which should typically be the return of .determine_rate call. The third argument gives the parent rate which is likely helpful for most .set_rate implementation. Returns 0 on success, -EERROR otherwise. ``set_rate_and_parent`` Change the rate and the parent of this clock. The requested rate is specified by the second argument, which should typically be the return of clk_round_rate() call. The third argument gives the parent rate which is likely helpful for most .set_rate_and_parent implementation. The fourth argument gives the parent index. This callback is optional (and unnecessary) for clocks with 0 or 1 parents as well as for clocks that can tolerate switching the rate and the parent separately via calls to .set_parent and .set_rate. Returns 0 on success, -EERROR otherwise. ``set_spread_spectrum`` Optional callback used to configure the spread spectrum modulation frequency, percentage, and method to reduce EMI by spreading the clock frequency over a wider range. Returns 0 on success, -EERROR otherwise. ``recalc_accuracy`` Recalculate the accuracy of this clock. The clock accuracy is expressed in ppb (parts per billion). The parent accuracy is an input parameter. Returns the calculated accuracy. Optional - if this op is not set then clock accuracy will be initialized to parent accuracy or 0 (perfect clock) if clock has no parent. ``get_phase`` Queries the hardware to get the current phase of a clock. Returned values are 0-359 degrees on success, negative error codes on failure. ``set_phase`` Shift the phase this clock signal in degrees specified by the second argument. Valid values for degrees are 0-359. Return 0 on success, otherwise -EERROR. ``get_duty_cycle`` Queries the hardware to get the current duty cycle ratio of a clock. Returned values denominator cannot be 0 and must be superior or equal to the numerator. ``set_duty_cycle`` Apply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument). Argument must be a valid ratio (denominator > 0 and >= numerator) Return 0 on success, otherwise -EERROR. ``init`` Perform platform-specific initialization magic. This is not used by any of the basic clock types. This callback exist for HW which needs to perform some initialisation magic for CCF to get an accurate view of the clock. It may also be used dynamic resource allocation is required. It shall not used to deal with clock parameters, such as rate or parents. Returns 0 on success, -EERROR otherwise. ``terminate`` Free any resource allocated by init. ``debug_init`` Set up type-specific debugfs entries for this clock. This is called once, after the debugfs directory entry for this clock has been created. The dentry pointer representing that directory is provided as an argument. Called with prepare_lock held. Returns 0 on success, -EERROR otherwise.h](h)}(h**Definition**::h](j@)}(h**Definition**h]h Definition}(hjE hhhNhNubah}(h]h ]h"]h$]h&]uh1j?hjA ubh:}(hjA hhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhK}hj= ubj[)}(hXstruct clk_ops { int (*prepare)(struct clk_hw *hw); void (*unprepare)(struct clk_hw *hw); int (*is_prepared)(struct clk_hw *hw); void (*unprepare_unused)(struct clk_hw *hw); int (*enable)(struct clk_hw *hw); void (*disable)(struct clk_hw *hw); int (*is_enabled)(struct clk_hw *hw); void (*disable_unused)(struct clk_hw *hw); int (*save_context)(struct clk_hw *hw); void (*restore_context)(struct clk_hw *hw); unsigned long (*recalc_rate)(struct clk_hw *hw, 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 rate, unsigned long parent_rate); int (*set_rate_and_parent)(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index); int (*set_spread_spectrum)(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf); unsigned long (*recalc_accuracy)(struct clk_hw *hw, unsigned long parent_accuracy); int (*get_phase)(struct clk_hw *hw); int (*set_phase)(struct clk_hw *hw, int degrees); int (*get_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*set_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*init)(struct clk_hw *hw); void (*terminate)(struct clk_hw *hw); void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); };h]hXstruct clk_ops { int (*prepare)(struct clk_hw *hw); void (*unprepare)(struct clk_hw *hw); int (*is_prepared)(struct clk_hw *hw); void (*unprepare_unused)(struct clk_hw *hw); int (*enable)(struct clk_hw *hw); void (*disable)(struct clk_hw *hw); int (*is_enabled)(struct clk_hw *hw); void (*disable_unused)(struct clk_hw *hw); int (*save_context)(struct clk_hw *hw); void (*restore_context)(struct clk_hw *hw); unsigned long (*recalc_rate)(struct clk_hw *hw, 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 rate, unsigned long parent_rate); int (*set_rate_and_parent)(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index); int (*set_spread_spectrum)(struct clk_hw *hw, const struct clk_spread_spectrum *ss_conf); unsigned long (*recalc_accuracy)(struct clk_hw *hw, unsigned long parent_accuracy); int (*get_phase)(struct clk_hw *hw); int (*set_phase)(struct clk_hw *hw, int degrees); int (*get_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*set_duty_cycle)(struct clk_hw *hw, struct clk_duty *duty); int (*init)(struct clk_hw *hw); void (*terminate)(struct clk_hw *hw); void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); };}hj^ sbah}(h]h ]h"]h$]h&]jjuh1jZh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj= ubh)}(h **Members**h]j@)}(hjo h]hMembers}(hjq hhhNhNubah}(h]h ]h"]h$]h&]uh1j?hjm ubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj= ubj)}(hhh](j)}(hX``prepare`` Prepare the clock for enabling. This must not return until the clock is fully prepared, and it's safe to call clk_enable. This callback is intended to allow clock implementations to do any initialisation that may sleep. Called with prepare_lock held. h](j)}(h ``prepare``h]j)}(hj h]hprepare}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hPrepare the clock for enabling. This must not return until the clock is fully prepared, and it's safe to call clk_enable. This callback is intended to allow clock implementations to do any initialisation that may sleep. Called with prepare_lock held.h]hPrepare the clock for enabling. This must not return until the clock is fully prepared, and it’s safe to call clk_enable. This callback is intended to allow clock implementations to do any initialisation that may sleep. Called with prepare_lock held.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhK~hj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(h``unprepare`` Release the clock from its prepared state. This will typically undo any work done in the **prepare** callback. Called with prepare_lock held. h](j)}(h ``unprepare``h]j)}(hj h]h unprepare}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hRelease the clock from its prepared state. This will typically undo any work done in the **prepare** callback. Called with prepare_lock held.h](hYRelease the clock from its prepared state. This will typically undo any work done in the }(hj hhhNhNubj@)}(h **prepare**h]hprepare}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j?hj ubh) callback. Called with prepare_lock held.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(h``is_prepared`` Queries the hardware to determine if the clock is prepared. This function is allowed to sleep. Optional, if this op is not set then the prepare count will be used. h](j)}(h``is_prepared``h]j)}(hj h]h is_prepared}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hQueries the hardware to determine if the clock is prepared. This function is allowed to sleep. Optional, if this op is not set then the prepare count will be used.h]hQueries the hardware to determine if the clock is prepared. This function is allowed to sleep. Optional, if this op is not set then the prepare count will be used.}(hj- hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj* ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj) hKhj ubj)}(h``unprepare_unused`` Unprepare the clock atomically. Only called from clk_disable_unused for prepare clocks with special needs. Called with prepare mutex held. This function may sleep. h](j)}(h``unprepare_unused``h]j)}(hjN h]hunprepare_unused}(hjP hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjL ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjH ubj)}(hhh]h)}(hUnprepare the clock atomically. Only called from clk_disable_unused for prepare clocks with special needs. Called with prepare mutex held. This function may sleep.h]hUnprepare the clock atomically. Only called from clk_disable_unused for prepare clocks with special needs. Called with prepare mutex held. This function may sleep.}(hjg hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjd ubah}(h]h ]h"]h$]h&]uh1jhjH ubeh}(h]h ]h"]h$]h&]uh1jhjc hKhj ubj)}(h``enable`` Enable the clock atomically. This must not return until the clock is generating a valid clock signal, usable by consumer devices. Called with enable_lock held. This function must not sleep. h](j)}(h ``enable``h]j)}(hj h]henable}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hEnable the clock atomically. This must not return until the clock is generating a valid clock signal, usable by consumer devices. Called with enable_lock held. This function must not sleep.h]hEnable the clock atomically. This must not return until the clock is generating a valid clock signal, usable by consumer devices. Called with enable_lock held. This function must not sleep.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(hf``disable`` Disable the clock atomically. Called with enable_lock held. This function must not sleep. h](j)}(h ``disable``h]j)}(hj h]hdisable}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hYDisable the clock atomically. Called with enable_lock held. This function must not sleep.h]hYDisable the clock atomically. Called with enable_lock held. This function must not sleep.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(h``is_enabled`` Queries the hardware to determine if the clock is enabled. This function must not sleep. Optional, if this op is not set then the enable count will be used. h](j)}(h``is_enabled``h]j)}(hj h]h is_enabled}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hQueries the hardware to determine if the clock is enabled. This function must not sleep. Optional, if this op is not set then the enable count will be used.h]hQueries the hardware to determine if the clock is enabled. This function must not sleep. Optional, if this op is not set then the enable count will be used.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(h``disable_unused`` Disable the clock atomically. Only called from clk_disable_unused for gate clocks with special needs. Called with enable_lock held. This function must not sleep. h](j)}(h``disable_unused``h]j)}(hj6 h]hdisable_unused}(hj8 hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj4 ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj0 ubj)}(hhh]h)}(hDisable the clock atomically. Only called from clk_disable_unused for gate clocks with special needs. Called with enable_lock held. This function must not sleep.h]hDisable the clock atomically. Only called from clk_disable_unused for gate clocks with special needs. Called with enable_lock held. This function must not sleep.}(hjO hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjL ubah}(h]h ]h"]h$]h&]uh1jhj0 ubeh}(h]h ]h"]h$]h&]uh1jhjK hKhj ubj)}(hK``save_context`` Save the context of the clock in prepration for poweroff. h](j)}(h``save_context``h]j)}(hjp h]h save_context}(hjr hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjn ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjj ubj)}(hhh]h)}(h9Save the context of the clock in prepration for poweroff.h]h9Save the context of the clock in prepration for poweroff.}(hj hhhNhNubah}(h]h ]h"]h$]h&]u+h1hhj hKhj ubah}(h]h ]h"]h$]h&]uh1jhjj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(hS``restore_context`` Restore the context of the clock after a restoration of power. h](j)}(h``restore_context``h]j)}(hj h]hrestore_context}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(h>Restore the context of the clock after a restoration of power.h]h>Restore the context of the clock after a restoration of power.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(hX``recalc_rate`` Recalculate the rate of this clock, by querying hardware. The parent rate is an input parameter. It is up to the caller to ensure that the prepare_mutex is held across this call. If the driver cannot figure out a rate for this clock, it must return 0. Returns the calculated rate. Optional, but recommended - if this op is not set then clock rate will be initialized to 0. h](j)}(h``recalc_rate``h]j)}(hj h]h recalc_rate}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubj)}(hhh]h)}(hXuRecalculate the rate of this clock, by querying hardware. The parent rate is an input parameter. It is up to the caller to ensure that the prepare_mutex is held across this call. If the driver cannot figure out a rate for this clock, it must return 0. Returns the calculated rate. Optional, but recommended - if this op is not set then clock rate will be initialized to 0.h]hXuRecalculate the rate of this clock, by querying hardware. The parent rate is an input parameter. It is up to the caller to ensure that the prepare_mutex is held across this call. If the driver cannot figure out a rate for this clock, it must return 0. Returns the calculated rate. Optional, but recommended - if this op is not set then clock rate will be initialized to 0.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj hKhj ubj)}(h``determine_rate`` Given a target rate as input, returns the closest rate actually supported by the clock, and optionally the parent clock that should be used to provide the clock rate. h](j)}(h``determine_rate``h]j)}(hjh]hdetermine_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hGiven a target rate as input, returns the closest rate actually supported by the clock, and optionally the parent clock that should be used to provide the clock rate.h]hGiven a target rate as input, returns the closest rate actually supported by the clock, and optionally the parent clock that should be used to provide the clock rate.}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj3ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj2hKhj ubj)}(hXj``set_parent`` Change the input source of this clock; for clocks with multiple possible parents specify a new parent by passing in the index as a u8 corresponding to the parent in either the .parent_names or .parents arrays. This function in affect translates an array index into the value programmed into the hardware. Returns 0 on success, -EERROR otherwise. h](j)}(h``set_parent``h]j)}(hjWh]h set_parent}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjUubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjQubj)}(hhh]h)}(hXZChange the input source of this clock; for clocks with multiple possible parents specify a new parent by passing in the index as a u8 corresponding to the parent in either the .parent_names or .parents arrays. This function in affect translates an array index into the value programmed into the hardware. Returns 0 on success, -EERROR otherwise.h]hXZChange the input source of this clock; for clocks with multiple possible parents specify a new parent by passing in the index as a u8 corresponding to the parent in either the .parent_names or .parents arrays. This function in affect translates an array index into the value programmed into the hardware. Returns 0 on success, -EERROR otherwise.}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjmubah}(h]h ]h"]h$]h&]uh1jhjQubeh}(h]h ]h"]h$]h&]uh1jhjlhKhj ubj)}(hX ``get_parent`` Queries the hardware to determine the parent of a clock. The return value is a u8 which specifies the index corresponding to the parent clock. This index can be applied to either the .parent_names or .parents arrays. In short, this function translates the parent value read from hardware into an array index. Currently only called when the clock is initialized by __clk_init. This callback is mandatory for clocks with multiple parents. It is optional (and unnecessary) for clocks with 0 or 1 parents. h](j)}(h``get_parent``h]j)}(hjh]h get_parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hXQueries the hardware to determine the parent of a clock. The return value is a u8 which specifies the index corresponding to the parent clock. This index can be applied to either the .parent_names or .parents arrays. In short, this function translates the parent value read from hardware into an array index. Currently only called when the clock is initialized by __clk_init. This callback is mandatory for clocks with multiple parents. It is optional (and unnecessary) for clocks with 0 or 1 parents.h]hXQueries the hardware to determine the parent of a clock. The return value is a u8 which specifies the index corresponding to the parent clock. This index can be applied to either the .parent_names or .parents arrays. In short, this function translates the parent value read from hardware into an array index. Currently only called when the clock is initialized by __clk_init. This callback is mandatory for clocks with multiple parents. It is optional (and unnecessary) for clocks with 0 or 1 parents.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(hX0``set_rate`` Change the rate of this clock. The requested rate is specified by the second argument, which should typically be the return of .determine_rate call. The third argument gives the parent rate which is likely helpful for most .set_rate implementation. Returns 0 on success, -EERROR otherwise. h](j)}(h ``set_rate``h]j)}(hjh]hset_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hX"Change the rate of this clock. The requested rate is specified by the second argument, which should typically be the return of .determine_rate call. The third argument gives the parent rate which is likely helpful for most .set_rate implementation. Returns 0 on success, -EERROR otherwise.h]hX"Change the rate of this clock. The requested rate is specified by the second argument, which should typically be the return of .determine_rate call. The third argument gives the parent rate which is likely helpful for most .set_rate implementation. Returns 0 on success, -EERROR otherwise.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(hXJ``set_rate_and_parent`` Change the rate and the parent of this clock. The requested rate is specified by the second argument, which should typically be the return of clk_round_rate() call. The third argument gives the parent rate which is likely helpful for most .set_rate_and_parent implementation. The fourth argument gives the parent index. This callback is optional (and unnecessary) for clocks with 0 or 1 parents as well as for clocks that can tolerate switching the rate and the parent separately via calls to .set_parent and .set_rate. Returns 0 on success, -EERROR otherwise. h](j)}(h``set_rate_and_parent``h]j)}(hjh]hset_rate_and_parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hX1Change the rate and the parent of this clock. The requested rate is specified by the second argument, which should typically be the return of clk_round_rate() call. The third argument gives the parent rate which is likely helpful for most .set_rate_and_parent implementation. The fourth argument gives the parent index. This callback is optional (and unnecessary) for clocks with 0 or 1 parents as well as for clocks that can tolerate switching the rate and the parent separately via calls to .set_parent and .set_rate. Returns 0 on success, -EERROR otherwise.h]hX1Change the rate and the parent of this clock. The requested rate is specified by the second argument, which should typically be the return of clk_round_rate() call. The third argument gives the parent rate which is likely helpful for most .set_rate_and_parent implementation. The fourth argument gives the parent index. This callback is optional (and unnecessary) for clocks with 0 or 1 parents as well as for clocks that can tolerate switching the rate and the parent separately via calls to .set_parent and .set_rate. Returns 0 on success, -EERROR otherwise.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(h``set_spread_spectrum`` Optional callback used to configure the spread spectrum modulation frequency, percentage, and method to reduce EMI by spreading the clock frequency over a wider range. Returns 0 on success, -EERROR otherwise. h](j)}(h``set_spread_spectrum``h]j)}(hj?h]hset_spread_spectrum}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj=ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj9ubj)}(hhh]h)}(hOptional callback used to configure the spread spectrum modulation frequency, percentage, and method to reduce EMI by spreading the clock frequency over a wider range. Returns 0 on success, -EERROR otherwise.h]hOptional callback used to configure the spread spectrum modulation frequency, percentage, and method to reduce EMI by spreading the clock frequency over a wider range. Returns 0 on success, -EERROR otherwise.}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjUubah}(h]h ]h"]h$]h&]uh1jhj9ubeh}(h]h ]h"]h$]h&]uh1jhjThKhj ubj)}(hXN``recalc_accuracy`` Recalculate the accuracy of this clock. The clock accuracy is expressed in ppb (parts per billion). The parent accuracy is an input parameter. Returns the calculated accuracy. Optional - if this op is not set then clock accuracy will be initialized to parent accuracy or 0 (perfect clock) if clock has no parent. h](j)}(h``recalc_accuracy``h]j)}(hjyh]hrecalc_accuracy}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjwubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjsubj)}(hhh]h)}(hX9Recalculate the accuracy of this clock. The clock accuracy is expressed in ppb (parts per billion). The parent accuracy is an input parameter. Returns the calculated accuracy. Optional - if this op is not set then clock accuracy will be initialized to parent accuracy or 0 (perfect clock) if clock has no parent.h]hX9Recalculate the accuracy of this clock. The clock accuracy is expressed in ppb (parts per billion). The parent accuracy is an input parameter. Returns the calculated accuracy. Optional - if this op is not set then clock accuracy will be initialized to parent accuracy or 0 (perfect clock) if clock has no parent.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjsubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(h``get_phase`` Queries the hardware to get the current phase of a clock. Returned values are 0-359 degrees on success, negative error codes on failure. h](j)}(h ``get_phase``h]j)}(hjh]h get_phase}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hQueries the hardware to get the current phase of a clock. Returned values are 0-359 degrees on success, negative error codes on failure.h]hQueries the hardware to get the current phase of a clock. Returned values are 0-359 degrees on success, negative error codes on failure.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(h``set_phase`` Shift the phase this clock signal in degrees specified by the second argument. Valid values for degrees are 0-359. Return 0 on success, otherwise -EERROR. h](j)}(h ``set_phase``h]j)}(hjh]h set_phase}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hShift the phase this clock signal in degrees specified by the second argument. Valid values for degrees are 0-359. Return 0 on success, otherwise -EERROR.h]hShift the phase this clock signal in degrees specified by the second argument. Valid values for degrees are 0-359. Return 0 on success, otherwise -EERROR.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(h``get_duty_cycle`` Queries the hardware to get the current duty cycle ratio of a clock. Returned values denominator cannot be 0 and must be superior or equal to the numerator. h](j)}(h``get_duty_cycle``h]j)}(hj'h]hget_duty_cycle}(hj)hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj%ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj!ubj)}(hhh]h)}(hQueries the hardware to get the current duty cycle ratio of a clock. Returned values denominator cannot be 0 and must be superior or equal to the numerator.h]hQueries the hardware to get the current duty cycle ratio of a clock. Returned values denominator cannot be 0 and must be superior or equal to the numerator.}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj=ubah}(h]h ]h"]h$]h&]uh1jhj!ubeh}(h]h ]h"]h$]h&]uh1jhj<hKhj ubj)}(h``set_duty_cycle`` Apply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument). Argument must be a valid ratio (denominator > 0 and >= numerator) Return 0 on success, otherwise -EERROR. h](j)}(h``set_duty_cycle``h]j)}(hjah]hset_duty_cycle}(hjchhhNhNubah}(h]h ]h"]h$]h&]uh1jhj_ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj[ubj)}(hhh]h)}(hApply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument). Argument must be a valid ratio (denominator > 0 and >= numerator) Return 0 on success, otherwise -EERROR.h]hApply the duty cycle ratio to this clock signal specified by the numerator (2nd argurment) and denominator (3rd argument). Argument must be a valid ratio (denominator > 0 and >= numerator) Return 0 on success, otherwise -EERROR.}(hjzhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjwubah}(h]h ]h"]h$]h&]uh1jhj[ubeh}(h]h ]h"]h$]h&]uh1jhjvhKhj ubj)}(hX``init`` Perform platform-specific initialization magic. This is not used by any of the basic clock types. This callback exist for HW which needs to perform some initialisation magic for CCF to get an accurate view of the clock. It may also be used dynamic resource allocation is required. It shall not used to deal with clock parameters, such as rate or parents. Returns 0 on success, -EERROR otherwise. h](j)}(h``init``h]j)}(hjh]hinit}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hXPerform platform-specific initialization magic. This is not used by any of the basic clock types. This callback exist for HW which needs to perform some initialisation magic for CCF to get an accurate view of the clock. It may also be used dynamic resource allocation is required. It shall not used to deal with clock parameters, such as rate or parents. Returns 0 on success, -EERROR otherwise.h]hXPerform platform-specific initialization magic. This is not used by any of the basic clock types. This callback exist for HW which needs to perform some initialisation magic for CCF to get an accurate view of the clock. It may also be used dynamic resource allocation is required. It shall not used to deal with clock parameters, such as rate or parents. Returns 0 on success, -EERROR otherwise.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(h3``terminate`` Free any resource allocated by init. h](j)}(h ``terminate``h]j)}(hjh]h terminate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(h$Free any resource allocated by init.h]h$Free any resource allocated by init.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhj ubj)}(hX2``debug_init`` Set up type-specific debugfs entries for this clock. This is called once, after the debugfs directory entry for this clock has been created. The dentry pointer representing that directory is provided as an argument. Called with prepare_lock held. Returns 0 on success, -EERROR otherwise.h](j)}(h``debug_init``h]j)}(hjh]h debug_init}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhjubj)}(hhh]h)}(hX#Set up type-specific debugfs entries for this clock. This is called once, after the debugfs directory entry for this clock has been created. The dentry pointer representing that directory is provided as an argument. Called with prepare_lock held. Returns 0 on success, -EERROR otherwise.h]hX#Set up type-specific debugfs entries for this clock. This is called once, after the debugfs directory entry for this clock has been created. The dentry pointer representing that directory is provided as an argument. Called with prepare_lock held. Returns 0 on success, -EERROR otherwise.}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhKhj$ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj#hKhj ubeh}(h]h ]h"]h$]h&]uh1jhj= ubeh}(h]h ] kernelindentah"]h$]h&]uh1j5hjhhhj hNubh)}(h**Description**h]j@)}(hjQh]h Description}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1j?hjOubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhMhjhhubh)}(hX]The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow implementations to split any work between atomic (enable) and sleepable (prepare) contexts. If enabling a clock requires code that might sleep, this must be done in clk_prepare. Clock enable code that will never be called in a sleepable context may be implemented in clk_enable.h]hX]The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow implementations to split any work between atomic (enable) and sleepable (prepare) contexts. If enabling a clock requires code that might sleep, this must be done in clk_prepare. Clock enable code that will never be called in a sleepable context may be implemented in clk_enable.}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhMhjhhubh)}(hTypically, drivers will call clk_prepare when a clock may be needed later (eg. when a device is opened), and clk_enable when the clock is actually required (eg. from an interrupt). Note that clk_prepare MUST have been called before clk_enable.h]hTypically, drivers will call clk_prepare when a clock may be needed later (eg. when a device is opened), and clk_enable when the clock is actually required (eg. from an interrupt). Note that clk_prepare MUST have been called before clk_enable.}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:57: ./include/linux/clk-provider.hhMhjhhubeh}(h]common-data-structures-and-apiah ]h"]common data structures and apiah$]h&]uh1hhhhhhhhK+ubh)}(hhh](h)}(h Core flagsh]h Core flags}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK=ubh)}(hFlags used across common struct clk. These flags should only affect the top-level framework. Custom flags for dealing with hardware specifics belong in struct clk_foo.h]hFlags used across common struct clk. These flags should only affect the top-level framework. Custom flags for dealing with hardware specifics belong in struct clk_foo.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjhhubh bullet_list)}(hhh](h list_item)}(h4CLK_SET_RATE_GATE - must be gated across rate changeh]h)}(hjh]h4CLK_SET_RATE_GATE - must be gated across rate change}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h4CLK_SET_PARENT_GATE - must be gated across re-parenth]h)}(hjh]h4CLK_SET_PARENT_GATE - must be gated across re-parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h8CLK_SET_RATE_PARENT - propagate rate change up one levelh]h)}(hjh]h8CLK_SET_RATE_PARENT - propagate rate change up one level}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h.CLK_IGNORE_UNUSED - do not gate even if unusedh]h)}(hjh]h.CLK_IGNORE_UNUSED - do not gate even if unused}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h5CLK_GET_RATE_NOCACHE - do not use the cached clk rateh]h)}(hjh]h5CLK_GET_RATE_NOCACHE - do not use the cached clk rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h9CLK_SET_RATE_NO_REPARENT - don't re-parent on rate changeh]h)}(hj.h]h;CLK_SET_RATE_NO_REPARENT - don’t re-parent on rate change}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhj,ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h=CLK_GET_ACCURACY_NOCACHE - do not use the cached clk accuracyh]h)}(hjFh]h=CLK_GET_ACCURACY_NOCACHE - do not use the cached clk accuracy}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjDubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h7CLK_RECALC_NEW_RATES - recalc rates after notificationsh]h)}(hj^h]h7CLK_RECALC_NEW_RATES - recalc rates after notifications}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhj\ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h4CLK_SET_RATE_UNGATE - clock needs to run to set rateh]h)}(hjvh]h4CLK_SET_RATE_UNGATE - clock needs to run to set rate}(hjxhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjtubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h#CLK_IS_CRITICAL - do not gate, everh]h)}(hjh]h#CLK_IS_CRITICAL - do not gate, ever}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hVCLK_OPS_PARENT_ENABLE - parents need enable during gate/ungate, set rate and re-parenth]h)}(hjh]hVCLK_OPS_PARENT_ENABLE - parents need enable during gate/ungate, set rate and re-parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hNCLK_DUTY_CYCLE_PARENT - duty cycle call may be forwarded to the parent clock h]h)}(hLCLK_DUTY_CYCLE_PARENT - duty cycle call may be forwarded to the parent clockh]hLCLK_DUTY_CYCLE_PARENT - duty cycle call may be forwarded to the parent clock}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/driver-api/clk:63: ./include/linux/clk-provider.hhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]bullet*uh1jhjhKhjhhubeh}(h] core-flagsah ]h"] core flagsah$]h&]uh1hhhhhhhhK=ubh)}(hhh](h)}(hHardware clk implementationsh]hHardware clk implementations}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKCubh)}(hXThe strength of the common struct clk_core 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::h]hXThe strength of the common struct clk_core 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:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEhjhhubj[)}(h{struct clk_gate { struct clk_hw hw; void __iomem *reg; u8 bit_idx; ... };h]h{struct clk_gate { struct clk_hw hw; void __iomem *reg; u8 bit_idx; ... };}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKJhjhhubh)}(hX4struct 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_core.h]hX6struct 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_core.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKQhjhhubh)}(h7Let's walk through enabling this clk from driver code::h]h8Let’s walk through enabling this clk from driver code:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKWhjhhubj[)}(h\struct clk *clk; clk = clk_get(NULL, "my_gateable_clk"); clk_prepare(clk); clk_enable(clk);h]h\struct clk *clk; clk = clk_get(NULL, "my_gateable_clk"); clk_prepare(clk); clk_enable(clk);}hj.sbah}(h]h ]h"]h$]h&]jjuh1jZhhhKYhjhhubh)}(h.The call graph for clk_enable is very simple::h]h-The call graph for clk_enable is very simple:}(hj<hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK_hjhhubj[)}(hclk_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);h]hclk_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);}hjJsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKahjhhubh)}(h(And the definition of clk_gate_set_bit::h]h'And the definition of clk_gate_set_bit:}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhjhhubj[)}(hstatic 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); }h]hstatic 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); }}hjfsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKjhjhhubh)}(h%Note that to_clk_gate is defined as::h]h$Note that to_clk_gate is defined as:}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKshjhhubj[)}(h?#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)h]h?#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKuhjhhubh)}(hLThis pattern of abstraction is used for every clock hardware representation.h]hLThis pattern of abstraction is used for every clock hardware representation.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKwhjhhubeh}(h]hardware-clk-implementationsah ]h"]hardware clk implementationsah$]h&]uh1hhhhhhhhKCubh)}(hhh](h)}(h Supporting your own clk hardwareh]h Supporting your own clk hardware}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK{ubh)}(hhWhen implementing support for a new type of clock it is only necessary to include the following header::h]hgWhen implementing support for a new type of clock it is only necessary to include the following header:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjhhubj[)}(h#include h]h#include }hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(hWTo construct a clk hardware structure for your platform you must define the following::h]hVTo construct a clk hardware structure for your platform you must define the following:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj[)}(h^struct clk_foo { struct clk_hw hw; ... hardware specific data goes here ... };h]h^struct clk_foo { struct clk_hw hw; ... hardware specific data goes here ... };}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(hUTo take advantage of your data you'll need to support valid operations for your clk::h]hVTo take advantage of your data you’ll need to support valid operations for your clk:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj[)}(hxstruct clk_ops clk_foo_ops = { .enable = &clk_foo_enable, .disable = &clk_foo_disable, };h]hxstruct clk_ops clk_foo_ops = { .enable = &clk_foo_enable, .disable = &clk_foo_disable, };}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(h2Implement the above functions using container_of::h]h1Implement the above functions using container_of:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj[)}(h#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; };h]h#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; };}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(hXGBelow is a matrix detailing which clk_ops are mandatory based upon the hardware capabilities 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 unnecessary. Empty cells are either optional or must be evaluated on a case-by-case basis.h]hXOBelow is a matrix detailing which clk_ops are mandatory based upon the hardware capabilities 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 unnecessary. Empty cells are either optional or must be evaluated on a case-by-case basis.}(hj'hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubhtable)}(hhh](h)}(hclock hardware characteristicsh]hclock hardware characteristics}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj7ubhtgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jMhjJubjN)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jMhjJubjN)}(hhh]h}(h]h ]h"]h$]h&]colwidthK uh1jMhjJubjN)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jMhjJubjN)}(hhh]h}(h]h ]h"]h$]h&]colwidthK uh1jMhjJubjN)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1jMhjJubhthead)}(hhh]hrow)}(hhh](hentry)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hgateh]hgate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(h change rateh]h change rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(h single parenth]h single parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(h multiplexerh]h multiplexer}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hrooth]hroot}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhjJubhtbody)}(hhh](j)}(hhh](j)}(hhh]h)}(h.prepareh]h.prepare}(hj*hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj'ubah}(h]h ]h"]h$]h&]uh1jhj$ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj$ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj$ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj$ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj$ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj$ubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .unprepareh]h .unprepare}(hjwhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjtubah}(h]h ]h"]h$]h&]uh1jhjqubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjqubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjqubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjqubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjqubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjqubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h.enableh]h.enable}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hyh]hy}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h.disableh]h.disable}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj[ubah}(h]h ]h"]h$]h&]uh1jhjXubj)}(hhh]h)}(hjh]hy}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjrubah}(h]h ]h"]h$]h&]uh1jhjXubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjXubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjXubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjXubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjXubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .is_enabledh]h .is_enabled}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hy}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .recalc_rateh]h .recalc_rate}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjNubah}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h)}(hjh]hy}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjnubah}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h.determine_rateh]h.determine_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hy}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .set_rateh]h .set_rate}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hy}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj"ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjYubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .set_parenth]h .set_parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hn}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hy}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h)}(hjh]hn}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h .get_parenth]h .get_parent}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h)}(hjh]hn}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj8ubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h)}(hjh]hy}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjNubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h)}(hjh]hn}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjdubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h.recalc_accuracyh]h.recalc_accuracy}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]uh1jhj!ubj)}(hhh](j)}(hhh]h)}(h.inith]h.init}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjNubah}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubj)}(hhh]h}(h]h ]h"]h$]h&]uh1jhjKubeh}(h]h ]h"]h$]h&]uh1jhj!ubeh}(h]h ]h"]h$]h&]uh1jhjJubeh}(h]h ]h"]h$]h&]colsKuh1jHhj7ubeh}(h]id1ah ]h"]h$]h&]uh1j5hjhhhhhNubh)}(hFinally, 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::h]hFinally, 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:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj[)}(hclk_register(...)h]hclk_register(...)}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(hBSee the basic clock types in ``drivers/clk/clk-*.c`` for examples.h](hSee the basic clock types in }(hjhhhNhNubj)}(h``drivers/clk/clk-*.c``h]hdrivers/clk/clk-*.c}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh for examples.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h] supporting-your-own-clk-hardwareah ]h"] supporting your own clk hardwareah$]h&]uh1hhhhhhhhK{ubh)}(hhh](h)}(h'Disabling clock gating of unused clocksh]h'Disabling clock gating of unused clocks}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hX7Sometimes during development it can be useful to be able to bypass the default disabling of unused clocks. For example, if drivers aren't enabling clocks properly but rely on them being on from the bootloader, bypassing the disabling means that the driver will remain functional while the issues are sorted out.h]hX9Sometimes during development it can be useful to be able to bypass the default disabling of unused clocks. For example, if drivers aren’t enabling clocks properly but rely on them being on from the bootloader, bypassing the disabling means that the driver will remain functional while the issues are sorted out.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hZYou can see which clocks have been disabled by booting your kernel with these parameters::h]hYYou can see which clocks have been disabled by booting your kernel with these parameters:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj[)}(h%tp_printk trace_event=clk:clk_disableh]h%tp_printk trace_event=clk:clk_disable}hjsbah}(h]h ]h"]h$]h&]jjuh1jZhhhKhjhhubh)}(hTTo bypass this disabling, include "clk_ignore_unused" in the bootargs to the kernel.h]hXTo bypass this disabling, include “clk_ignore_unused” in the bootargs to the kernel.}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]'disabling-clock-gating-of-unused-clocksah ]h"]'disabling clock gating of unused clocksah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hLockingh]hLocking}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjAhhhhhKubh)}(hWThe common clock framework uses two global locks, the prepare lock and the enable lock.h]hWThe common clock framework uses two global locks, the prepare lock and the enable lock.}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hThe enable lock is a spinlock and is held across calls to the .enable, .disable operations. Those operations are thus not allowed to sleep, and calls to the clk_enable(), clk_disable() API functions are allowed in atomic context.h]hThe enable lock is a spinlock and is held across calls to the .enable, .disable operations. Those operations are thus not allowed to sleep, and calls to the clk_enable(), clk_disable() API functions are allowed in atomic context.}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hXfFor clk_is_enabled() API, it is also designed to be allowed to be used in atomic context. However, it doesn't really make any sense to hold the enable lock in core, unless you want to do something else with the information of the enable state with that lock held. Otherwise, seeing if a clk is enabled is a one-shot read of the enabled state, which could just as easily change after the function returns because the lock is released. Thus the user of this API needs to handle synchronizing the read of the state with whatever they're using it for to make sure that the enable state doesn't change during that time.h]hXlFor clk_is_enabled() API, it is also designed to be allowed to be used in atomic context. However, it doesn’t really make any sense to hold the enable lock in core, unless you want to do something else with the information of the enable state with that lock held. Otherwise, seeing if a clk is enabled is a one-shot read of the enabled state, which could just as easily change after the function returns because the lock is released. Thus the user of this API needs to handle synchronizing the read of the state with whatever they’re using it for to make sure that the enable state doesn’t change during that time.}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hThe 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.h]hThe 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.}(hj|hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hMThis effectively divides operations in two groups from a locking perspective.h]hMThis effectively divides operations in two groups from a locking perspective.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hXDrivers 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.h]hXDrivers 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAhhubh)}(hXThe 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.h]hXThe 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjAhhubh)}(hNote 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.h]hNote 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hjAhhubeh}(h]lockingah ]h"]lockingah$]h&]uh1hhhhhhhhKubeh}(h]the-common-clk-frameworkah ]h"]the common clk frameworkah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksjfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehʌ _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjj|jjjjjjjjj>j;jju nametypes}(jjjjjjj>juh}(jhj|j1jjjjj j jjjjjjj;jjjAjj7u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jKsRparse_messages]transform_messages] transformerN include_log] decorationNhhub.