<p><br>
On Feb 6, 2011 10:08 PM, &quot;Jeremy Kerr&quot; &lt;<a href="mailto:jeremy.kerr@canonical.com">jeremy.kerr@canonical.com</a>&gt; wrote:<br>
&gt;<br>
&gt; We currently have ~21 definitions of struct clk in the ARM architecture,<br>
&gt; each defined on a per-platform basis. This makes it difficult to define<br>
&gt; platform- (or architecture-) independent clock sources without making<br>
&gt; assumptions about struct clk, and impossible to compile two<br>
&gt; platforms with different struct clks into a single image.<br>
&gt;<br>
&gt; This change is an effort to unify struct clk where possible, by defining<br>
&gt; a common struct clk, containing a set of clock operations. Different<br>
&gt; clock implementations can set their own operations, and have a standard<br>
&gt; interface for generic code. The callback interface is exposed to the<br>
&gt; kernel proper, while the clock implementations only need to be seen by<br>
&gt; the platform internals.<br>
&gt;<br>
&gt; This allows us to share clock code among platforms, and makes it<br>
&gt; possible to dynamically create clock devices in platform-independent<br>
&gt; code.<br>
&gt;<br>
&gt; Platforms can enable the generic struct clock through<br>
&gt; CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure<br>
&gt; consists of a common struct clk:<br>
&gt;<br>
&gt; struct clk {<br>
&gt;        const struct clk_ops    *ops;<br>
&gt;        unsigned int            enable_count;<br>
&gt;        unsigned int            prepare_count;<br>
&gt;        spinlock_t              enable_lock;<br>
&gt;        struct mutex            prepare_lock;<br>
&gt; };<br>
&gt;<br>
&gt; And a set of clock operations (defined per type of clock):<br>
&gt;<br>
&gt; struct clk_ops {<br>
&gt;        int             (*enable)(struct clk *);<br>
&gt;        void            (*disable)(struct clk *);<br>
&gt;        unsigned long   (*get_rate)(struct clk *);<br>
&gt;        [...]<br>
&gt; };<br>
&gt;<br>
&gt; To define a hardware-specific clock, machine code can &quot;subclass&quot; the<br>
&gt; struct clock into a new struct (adding any device-specific data), and<br>
&gt; provide a set of operations:<br>
&gt;<br>
&gt; struct clk_foo {<br>
&gt;        struct clk      clk;<br>
&gt;        void __iomem    *some_register;<br>
&gt; };<br>
&gt;<br>
&gt; struct clk_ops clk_foo_ops = {<br>
&gt;        .get_rate = clk_foo_get_rate,<br>
&gt; };<br>
&gt;<br>
&gt; The common clock definitions are based on a development patch from Ben<br>
&gt; Herrenschmidt &lt;<a href="mailto:benh@kernel.crashing.org">benh@kernel.crashing.org</a>&gt;.<br>
&gt;<br>
&gt; Signed-off-by: Jeremy Kerr &lt;<a href="mailto:jeremy.kerr@canonical.com">jeremy.kerr@canonical.com</a>&gt;<br>
&gt;<br>
&gt; ---<br>
&gt;  drivers/clk/Kconfig  |    3<br>
&gt;  drivers/clk/Makefile |    1<br>
&gt;  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++<br>
&gt;  drivers/clk/clkdev.c |    5 +<br>
&gt;  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---<br>
&gt;  5 files changed, 318 insertions(+), 9 deletions(-)<br>
&gt;<br>
&gt; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig<br>
&gt; index 4168c88..6e3ae54 100644<br>
&gt; --- a/drivers/clk/Kconfig<br>
&gt; +++ b/drivers/clk/Kconfig<br>
&gt; @@ -2,3 +2,6 @@<br>
&gt;  config CLKDEV_LOOKUP<br>
&gt;        bool<br>
&gt;        select HAVE_CLK<br>
&gt; +<br>
&gt; +config USE_COMMON_STRUCT_CLK<br>
&gt; +       bool<br>
&gt; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile<br>
&gt; index 07613fa..a1a06d3 100644<br>
&gt; --- a/drivers/clk/Makefile<br>
&gt; +++ b/drivers/clk/Makefile<br>
&gt; @@ -1,2 +1,3 @@<br>
&gt;<br>
&gt;  obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o<br>
&gt; +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o<br>
&gt; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c<br>
&gt; new file mode 100644<br>
&gt; index 0000000..12e0daf<br>
&gt; --- /dev/null<br>
&gt; +++ b/drivers/clk/clk.c<br>
&gt; @@ -0,0 +1,134 @@<br>
&gt; +/*<br>
&gt; + * Copyright (C) 2010-2011 Canonical Ltd &lt;<a href="mailto:jeremy.kerr@canonical.com">jeremy.kerr@canonical.com</a>&gt;<br>
&gt; + *<br>
&gt; + * This program is free software; you can redistribute it and/or modify<br>
&gt; + * it under the terms of the GNU General Public License version 2 as<br>
&gt; + * published by the Free Software Foundation.<br>
&gt; + *<br>
&gt; + * Standard functionality for the common clock API.<br>
&gt; + */<br>
&gt; +<br>
&gt; +#include &lt;linux/clk.h&gt;<br>
&gt; +#include &lt;linux/module.h&gt;<br>
&gt; +<br>
&gt; +int clk_prepare(struct clk *clk)<br>
&gt; +{<br>
&gt; +       int ret = 0;<br>
&gt; +<br>
&gt; +       if (!clk-&gt;ops-&gt;prepare)<br>
&gt; +               return 0;<br>
&gt; +<br>
&gt; +       mutex_lock(&amp;clk-&gt;prepare_lock);<br>
&gt; +       if (clk-&gt;prepare_count == 0)<br>
&gt; +               ret = clk-&gt;ops-&gt;prepare(clk);<br>
&gt; +<br>
&gt; +       if (!ret)<br>
&gt; +               clk-&gt;prepare_count++;<br>
&gt; +       mutex_unlock(&amp;clk-&gt;prepare_lock);<br>
&gt; +<br>
&gt; +       return 0;</p>
<p>return ret;</p>
<p>&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_prepare);<br>
&gt; +<br>
&gt; +void clk_unprepare(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (!clk-&gt;ops-&gt;unprepare)<br>
&gt; +               return;<br>
&gt; +<br>
&gt; +       mutex_lock(&amp;clk-&gt;prepare_lock);<br>
&gt; +       if (--clk-&gt;prepare_count == 0)<br>
&gt; +               clk-&gt;ops-&gt;unprepare(clk);<br>
&gt; +<br>
&gt; +       mutex_unlock(&amp;clk-&gt;prepare_lock);<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_unprepare);<br>
&gt; +<br>
&gt; +int clk_enable(struct clk *clk)<br>
&gt; +{<br>
&gt; +       int ret = 0;<br>
&gt; +<br>
&gt; +       if (!clk-&gt;ops-&gt;enable)<br>
&gt; +               return 0;<br>
&gt; +<br>
&gt; +       spin_lock(&amp;clk-&gt;enable_lock);<br>
&gt; +       if (!clk-&gt;enable_count)<br>
&gt; +               ret = clk-&gt;ops-&gt;enable(clk);<br>
&gt; +<br>
&gt; +       if (!ret)<br>
&gt; +               clk-&gt;enable_count++;<br>
&gt; +       spin_unlock(&amp;clk-&gt;enable_lock);<br>
&gt; +<br>
&gt; +       return ret;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_enable);<br>
&gt; +<br>
&gt; +void clk_disable(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (!clk-&gt;ops-&gt;disable)<br>
&gt; +               return;<br>
&gt; +<br>
&gt; +       spin_lock(&amp;clk-&gt;enable_lock);<br>
&gt; +<br>
&gt; +       WARN_ON(!clk-&gt;enable_count);<br>
&gt; +<br>
&gt; +       if (!--clk-&gt;enable_count)<br>
&gt; +               clk-&gt;ops-&gt;disable(clk);<br>
&gt; +<br>
&gt; +       spin_unlock(&amp;clk-&gt;enable_lock);<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_disable);<br>
&gt; +<br>
&gt; +unsigned long clk_get_rate(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;get_rate)<br>
&gt; +               return clk-&gt;ops-&gt;get_rate(clk);<br>
&gt; +       return 0;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_get_rate);<br>
&gt; +<br>
&gt; +int __clk_get(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;get)<br>
&gt; +               return clk-&gt;ops-&gt;get(clk);<br>
&gt; +       return 1;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(__clk_get);<br>
&gt; +<br>
&gt; +void clk_put(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;put)<br>
&gt; +               clk-&gt;ops-&gt;put(clk);<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_put);<br>
&gt; +<br>
&gt; +long clk_round_rate(struct clk *clk, unsigned long rate)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;round_rate)<br>
&gt; +               return clk-&gt;ops-&gt;round_rate(clk, rate);<br>
&gt; +       return -ENOSYS;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_round_rate);<br>
&gt; +<br>
&gt; +int clk_set_rate(struct clk *clk, unsigned long rate)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;set_rate)<br>
&gt; +               return clk-&gt;ops-&gt;set_rate(clk, rate);<br>
&gt; +       return -ENOSYS;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_set_rate);<br>
&gt; +<br>
&gt; +int clk_set_parent(struct clk *clk, struct clk *parent)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;set_parent)<br>
&gt; +               return clk-&gt;ops-&gt;set_parent(clk, parent);<br>
&gt; +       return -ENOSYS;<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_set_parent);<br>
&gt; +<br>
&gt; +struct clk *clk_get_parent(struct clk *clk)<br>
&gt; +{<br>
&gt; +       if (clk-&gt;ops-&gt;get_parent)<br>
&gt; +               return clk-&gt;ops-&gt;get_parent(clk);<br>
&gt; +       return ERR_PTR(-ENOSYS);<br>
&gt; +}<br>
&gt; +EXPORT_SYMBOL_GPL(clk_get_parent);<br>
&gt; diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c<br>
&gt; index 0fc0a79..17619c7 100644<br>
&gt; --- a/drivers/clk/clkdev.c<br>
&gt; +++ b/drivers/clk/clkdev.c<br>
&gt; @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)<br>
&gt;  }<br>
&gt;  EXPORT_SYMBOL(clk_get);<br>
&gt;<br>
&gt; +#ifndef CONFIG_USE_COMMON_STRUCT_CLK<br>
&gt; +/* For the common struct clk case, clk_put is provided by clk.c */<br>
&gt; +<br>
&gt;  void clk_put(struct clk *clk)<br>
&gt;  {<br>
&gt;        __clk_put(clk);<br>
&gt;  }<br>
&gt;  EXPORT_SYMBOL(clk_put);<br>
&gt;<br>
&gt; +#endif<br>
&gt; +<br>
&gt;  void clkdev_add(struct clk_lookup *cl)<br>
&gt;  {<br>
&gt;        mutex_lock(&amp;clocks_mutex);<br>
&gt; diff --git a/include/linux/clk.h b/include/linux/clk.h<br>
&gt; index 1d37f42..e081ca1 100644<br>
&gt; --- a/include/linux/clk.h<br>
&gt; +++ b/include/linux/clk.h<br>
&gt; @@ -3,6 +3,7 @@<br>
&gt;  *<br>
&gt;  *  Copyright (C) 2004 ARM Limited.<br>
&gt;  *  Written by Deep Blue Solutions Limited.<br>
&gt; + *  Copyright (c) 2010-2011 Jeremy Kerr &lt;<a href="mailto:jeremy.kerr@canonical.com">jeremy.kerr@canonical.com</a>&gt;<br>
&gt;  *<br>
&gt;  * This program is free software; you can redistribute it and/or modify<br>
&gt;  * it under the terms of the GNU General Public License version 2 as<br>
&gt; @@ -11,18 +12,189 @@<br>
&gt;  #ifndef __LINUX_CLK_H<br>
&gt;  #define __LINUX_CLK_H<br>
&gt;<br>
&gt; +#include &lt;linux/err.h&gt;<br>
&gt; +#include &lt;linux/mutex.h&gt;<br>
&gt; +#include &lt;linux/spinlock.h&gt;<br>
&gt; +<br>
&gt;  struct device;<br>
&gt;<br>
&gt; -/*<br>
&gt; - * The base API.<br>
&gt; +#ifdef CONFIG_USE_COMMON_STRUCT_CLK<br>
&gt; +<br>
&gt; +/* If we&#39;re using the common struct clk, we define the base clk object here */<br>
&gt; +<br>
&gt; +/**<br>
&gt; + * struct clk - hardware independent clock structure<br>
&gt; + * @ops:               implementation-specific ops for this clock<br>
&gt; + * @enable_count:      count of clk_enable() calls active on this clock<br>
&gt; + * @flags:             platform-independent flags<br>
&gt; + * @lock:              lock for enable/disable or other HW-specific ops<br>
&gt; + *<br>
&gt; + * The base clock object, used by drivers for hardware-independent manipulation<br>
&gt; + * of clock lines. This will be &#39;subclassed&#39; by device-specific implementations,<br>
&gt; + * which add device-specific data to struct clk. For example:<br>
&gt; + *<br>
&gt; + *  struct clk_foo {<br>
&gt; + *      struct clk;<br>
&gt; + *      [device specific fields]<br>
&gt; + *  };<br>
&gt; + *<br>
&gt; + * The clock driver code will manage the device-specific data, and pass<br>
&gt; + * clk_foo.clk to the common clock code. The clock driver will be called<br>
&gt; + * through the @ops callbacks.<br>
&gt; + *<br>
&gt; + * The @lock member provides either a spinlock or a mutex to protect (at least)<br>
&gt; + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is<br>
&gt; + * set, then the core clock code will use a spinlock, otherwise a mutex. This<br>
&gt; + * lock will be acquired during clk_enable and clk_disable, so for atomic<br>
&gt; + * clocks, these ops callbacks must not sleep.<br>
&gt; + *<br>
&gt; + * The choice of atomic or non-atomic clock depends on how the clock is enabled.<br>
&gt; + * Typically, you&#39;ll want to use a non-atomic clock. For clocks that need to be<br>
&gt; + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic<br>
&gt; + * clocks with parents will typically cascade enable/disable operations to<br>
&gt; + * their parent, so the parent of an atomic clock *must* be atomic too.<br>
&gt;  */<br>
&gt; +struct clk {<br>
&gt; +       const struct clk_ops    *ops;<br>
&gt; +       unsigned int            enable_count;<br>
&gt; +       unsigned int            prepare_count;<br>
&gt; +       spinlock_t              enable_lock;<br>
&gt; +       struct mutex            prepare_lock;<br>
&gt; +};<br>
&gt; +<br>
&gt; +/* static initialiser for non-atomic clocks */<br>
&gt; +#define INIT_CLK(name, o) {                                            \<br>
&gt; +       .ops            = &amp;o,                                           \<br>
&gt; +       .enable_count   = 0,                                            \<br>
&gt; +       .prepare_count  = 0,                                            \<br>
&gt; +       .enable_lock    = __SPIN_LOCK_UNLOCKED(name.enable_lock),       \<br>
&gt; +       .prepare_lock   = __MUTEX_INITIALIZER(name.prepare_lock),       \<br>
&gt; +}<br>
&gt;<br>
&gt; +/**<br>
&gt; + * struct clk_ops -  Callback operations for clocks; these are to be provided<br>
&gt; + * by the clock implementation, and will be called by drivers through the clk_*<br>
&gt; + * API.<br>
&gt; + *<br>
&gt; + * @prepare:   Prepare the clock for enabling. This must not return until<br>
&gt; + *             the clock is fully prepared, and it&#39;s safe to call clk_enable.<br>
&gt; + *             This callback is intended to allow clock implementations to<br>
&gt; + *             do any initialisation that may block. Called with<br>
&gt; + *             clk-&gt;prepare_lock held.<br>
&gt; + *<br>
&gt; + * @unprepare: Release the clock from its prepared state. This will typically<br>
&gt; + *             undo any work done in the @prepare callback. Called with<br>
&gt; + *             clk-&gt;prepare_lock held.<br>
&gt; + *<br>
&gt; + * @enable:    Enable the clock atomically. This must not return until the<br>
&gt; + *             clock is generating a valid clock signal, usable by consumer<br>
&gt; + *             devices. Called with clk-&gt;enable_lock held.<br>
&gt; + *<br>
&gt; + * @disable:   Disable the clock atomically. Called with clk-&gt;enable_lock held.<br>
&gt; + *<br>
&gt; + * @get:       Called by the core clock code when a device driver acquires a<br>
&gt; + *             clock via clk_get(). Optional.<br>
&gt; + *<br>
&gt; + * @put:       Called by the core clock code when a devices driver releases a<br>
&gt; + *             clock via clk_put(). Optional.<br>
&gt; + *<br>
&gt; + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow<br>
&gt; + * implementations to split any work between atomic (enable) and sleepable<br>
&gt; + * (prepare) contexts.  If a clock requires blocking code to be turned on, this<br>
&gt; + * should be done in clk_prepare. Switching that will not block should be done<br>
&gt; + * in clk_enable.<br>
&gt; + *<br>
&gt; + * Typically, drivers will call clk_prepare when a clock may be needed later<br>
&gt; + * (eg. when a device is opened), and clk_enable when the clock is actually<br>
&gt; + * required (eg. from an interrupt).<br>
&gt; + *<br>
&gt; + * For other callbacks, see the corresponding clk_* functions. Parameters and<br>
&gt; + * return values are passed directly from/to these API functions, or<br>
&gt; + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback<br>
&gt; + * is NULL, see kernel/clk.c for implementation details. All are optional.<br>
&gt; + */<br>
&gt; +struct clk_ops {<br>
&gt; +       int             (*prepare)(struct clk *);<br>
&gt; +       void            (*unprepare)(struct clk *);<br>
&gt; +       int             (*enable)(struct clk *);<br>
&gt; +       void            (*disable)(struct clk *);<br>
&gt; +       int             (*get)(struct clk *);<br>
&gt; +       void            (*put)(struct clk *);<br>
&gt; +       unsigned long   (*get_rate)(struct clk *);<br>
&gt; +       long            (*round_rate)(struct clk *, unsigned long);<br>
&gt; +       int             (*set_rate)(struct clk *, unsigned long);<br>
&gt; +       int             (*set_parent)(struct clk *, struct clk *);<br>
&gt; +       struct clk *    (*get_parent)(struct clk *);<br>
&gt; +};<br>
&gt; +<br>
&gt; +/**<br>
&gt; + * __clk_get - update clock-specific refcounter<br>
&gt; + *<br>
&gt; + * @clk: The clock to refcount<br>
&gt; + *<br>
&gt; + * Before a clock is returned from clk_get, this function should be called<br>
&gt; + * to update any clock-specific refcounting.<br>
&gt; + *<br>
&gt; + * Returns non-zero on success, zero on failure.<br>
&gt; + *<br>
&gt; + * Drivers should not need this function; it is only needed by the<br>
&gt; + * arch-specific clk_get() implementations.<br>
&gt; + */<br>
&gt; +int __clk_get(struct clk *clk);<br>
&gt; +<br>
&gt; +/**<br>
&gt; + * clk_prepare - prepare clock for atomic enabling.<br>
&gt; + *<br>
&gt; + * @clk: The clock to prepare<br>
&gt; + *<br>
&gt; + * Do any blocking initialisation on @clk, allowing the clock to be later<br>
&gt; + * enabled atomically (via clk_enable). This function may sleep.<br>
&gt; + */<br>
&gt; +int clk_prepare(struct clk *clk);<br>
&gt; +<br>
&gt; +/**<br>
&gt; + * clk_unprepare - release clock from prepared state<br>
&gt; + *<br>
&gt; + * @clk: The clock to release<br>
&gt; + *<br>
&gt; + * Do any (possbly blocking) cleanup on clk. This function may sleep.<br>
&gt; + */<br>
&gt; +void clk_unprepare(struct clk *clk);<br>
&gt; +<br>
&gt; +/**<br>
&gt; + * clk_common_init - initialise a clock for driver usage<br>
&gt; + *<br>
&gt; + * @clk: The clock to initialise<br>
&gt; + *<br>
&gt; + * Used for runtime intialization of clocks; you don&#39;t need to call this<br>
&gt; + * if your clock has been (statically) initialized with INIT_CLK.<br>
&gt; + */<br>
&gt; +static inline void clk_common_init(struct clk *clk)<br>
&gt; +{<br>
&gt; +       clk-&gt;enable_count = clk-&gt;prepare_count = 0;<br>
&gt; +       spin_lock_init(&amp;clk-&gt;enable_lock);<br>
&gt; +       mutex_init(&amp;clk-&gt;prepare_lock);<br>
&gt; +}<br>
&gt; +<br>
&gt; +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */<br>
&gt;<br>
&gt;  /*<br>
&gt; - * struct clk - an machine class defined object / cookie.<br>
&gt; + * Global clock object, actual structure is declared per-machine<br>
&gt;  */<br>
&gt;  struct clk;<br>
&gt;<br>
&gt; +static inline void clk_common_init(struct clk *clk) { }<br>
&gt; +<br>
&gt; +/*<br>
&gt; + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don&#39;t enforce any atomicity<br>
&gt; + * requirements for clk_enable/clk_disable, so the prepare and unprepare<br>
&gt; + * functions are no-ops<br>
&gt; + */<br>
&gt; +int clk_prepare(struct clk *clk) { return 0; }<br>
&gt; +void clk_unprepare(struct clk *clk) { }<br>
&gt; +<br>
&gt; +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */<br>
&gt; +<br>
&gt;  /**<br>
&gt;  * clk_get - lookup and obtain a reference to a clock producer.<br>
&gt;  * @dev: device for clock &quot;consumer&quot;<br>
&gt; @@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);<br>
&gt;  */<br>
&gt;  void clk_put(struct clk *clk);<br>
&gt;<br>
&gt; -<br>
&gt; -/*<br>
&gt; - * The remaining APIs are optional for machine class support.<br>
&gt; - */<br>
&gt; -<br>
&gt; -<br>
&gt;  /**<br>
&gt;  * clk_round_rate - adjust a rate to the exact rate a clock can provide<br>
&gt;  * @clk: clock source<br>
</p>