clk: add terminate callback to clk_ops
authorJerome Brunet <jbrunet@baylibre.com>
Tue, 24 Sep 2019 12:39:54 +0000 (14:39 +0200)
committerStephen Boyd <sboyd@kernel.org>
Tue, 24 Dec 2019 02:53:13 +0000 (18:53 -0800)
Add a terminate callback to the clk_ops to release the resources
claimed in .init()

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lkml.kernel.org/r/20190924123954.31561-4-jbrunet@baylibre.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/clk.c
include/linux/clk-provider.h

index b8dc848..ef44167 100644 (file)
@@ -3862,6 +3862,7 @@ static void clk_core_evict_parent_cache(struct clk_core *core)
 void clk_unregister(struct clk *clk)
 {
        unsigned long flags;
+       const struct clk_ops *ops;
 
        if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
                return;
@@ -3870,7 +3871,8 @@ void clk_unregister(struct clk *clk)
 
        clk_prepare_lock();
 
-       if (clk->core->ops == &clk_nodrv_ops) {
+       ops = clk->core->ops;
+       if (ops == &clk_nodrv_ops) {
                pr_err("%s: unregistered clock: %s\n", __func__,
                       clk->core->name);
                goto unlock;
@@ -3883,6 +3885,9 @@ void clk_unregister(struct clk *clk)
        clk->core->ops = &clk_nodrv_ops;
        clk_enable_unlock(flags);
 
+       if (ops->terminate)
+               ops->terminate(clk->core->hw);
+
        if (!hlist_empty(&clk->core->children)) {
                struct clk_core *child;
                struct hlist_node *t;
index eed243c..013dc66 100644 (file)
@@ -197,6 +197,8 @@ struct clk_duty {
  *             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
@@ -248,6 +250,7 @@ struct clk_ops {
        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);
 };