clk: fixed-rate: add devm_clk_hw_register_fixed_rate
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Fri, 16 Sep 2022 06:17:39 +0000 (09:17 +0300)
committerStephen Boyd <sboyd@kernel.org>
Fri, 30 Sep 2022 00:55:29 +0000 (17:55 -0700)
Add devm_clk_hw_register_fixed_rate(), devres-managed helper to register
fixed-rate clock.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20220916061740.87167-3-dmitry.baryshkov@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/clk-fixed-rate.c
include/linux/clk-provider.h

index ac68a6b40f0e5d0d0b238844a2fd1d6cae88353c..7d775954e26da0e53c66c27376eb978cb8710a85 100644 (file)
@@ -49,12 +49,24 @@ const struct clk_ops clk_fixed_rate_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
 
+static void devm_clk_hw_register_fixed_rate_release(struct device *dev, void *res)
+{
+       struct clk_fixed_rate *fix = res;
+
+       /*
+        * We can not use clk_hw_unregister_fixed_rate, since it will kfree()
+        * the hw, resulting in double free. Just unregister the hw and let
+        * devres code kfree() it.
+        */
+       clk_hw_unregister(&fix->hw);
+}
+
 struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
                struct device_node *np, const char *name,
                const char *parent_name, const struct clk_hw *parent_hw,
                const struct clk_parent_data *parent_data, unsigned long flags,
                unsigned long fixed_rate, unsigned long fixed_accuracy,
-               unsigned long clk_fixed_flags)
+               unsigned long clk_fixed_flags, bool devm)
 {
        struct clk_fixed_rate *fixed;
        struct clk_hw *hw;
@@ -62,7 +74,11 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
        int ret = -EINVAL;
 
        /* allocate fixed-rate clock */
-       fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+       if (devm)
+               fixed = devres_alloc(devm_clk_hw_register_fixed_rate_release,
+                                    sizeof(*fixed), GFP_KERNEL);
+       else
+               fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
        if (!fixed)
                return ERR_PTR(-ENOMEM);
 
@@ -90,9 +106,13 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
        else
                ret = of_clk_hw_register(np, hw);
        if (ret) {
-               kfree(fixed);
+               if (devm)
+                       devres_free(fixed);
+               else
+                       kfree(fixed);
                hw = ERR_PTR(ret);
-       }
+       } else if (devm)
+               devres_add(dev, fixed);
 
        return hw;
 }
index 86140ac2f9a5e24163b859b9e658e2cea684bded..49405b336cadb81ce9f32bd528c463704b020aba 100644 (file)
@@ -350,7 +350,7 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
                const char *parent_name, const struct clk_hw *parent_hw,
                const struct clk_parent_data *parent_data, unsigned long flags,
                unsigned long fixed_rate, unsigned long fixed_accuracy,
-               unsigned long clk_fixed_flags);
+               unsigned long clk_fixed_flags, bool devm);
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                unsigned long fixed_rate);
@@ -365,7 +365,20 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
  */
 #define clk_hw_register_fixed_rate(dev, name, parent_name, flags, fixed_rate)  \
        __clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), NULL, \
-                                    NULL, (flags), (fixed_rate), 0, 0)
+                                    NULL, (flags), (fixed_rate), 0, 0, false)
+
+/**
+ * devm_clk_hw_register_fixed_rate - register fixed-rate clock with the clock
+ * framework
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @fixed_rate: non-adjustable clock rate
+ */
+#define devm_clk_hw_register_fixed_rate(dev, name, parent_name, flags, fixed_rate)  \
+       __clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name), NULL, \
+                                    NULL, (flags), (fixed_rate), 0, 0, true)
 /**
  * clk_hw_register_fixed_rate_parent_hw - register fixed-rate clock with
  * the clock framework
@@ -378,7 +391,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
 #define clk_hw_register_fixed_rate_parent_hw(dev, name, parent_hw, flags,     \
                                             fixed_rate)                      \
        __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw),  \
-                                    NULL, (flags), (fixed_rate), 0, 0)
+                                    NULL, (flags), (fixed_rate), 0, 0, false)
 /**
  * clk_hw_register_fixed_rate_parent_data - register fixed-rate clock with
  * the clock framework
@@ -392,7 +405,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                                             fixed_rate)                      \
        __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,         \
                                     (parent_data), (flags), (fixed_rate), 0, \
-                                    0)
+                                    0, false)
 /**
  * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
  * the clock framework
@@ -408,7 +421,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                                                 fixed_accuracy)              \
        __clk_hw_register_fixed_rate((dev), NULL, (name), (parent_name),      \
                                     NULL, NULL, (flags), (fixed_rate),       \
-                                    (fixed_accuracy), 0)
+                                    (fixed_accuracy), 0, false)
 /**
  * clk_hw_register_fixed_rate_with_accuracy_parent_hw - register fixed-rate
  * clock with the clock framework
@@ -423,7 +436,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                parent_hw, flags, fixed_rate, fixed_accuracy)                 \
        __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw)   \
                                     NULL, NULL, (flags), (fixed_rate),       \
-                                    (fixed_accuracy), 0)
+                                    (fixed_accuracy), 0, false)
 /**
  * clk_hw_register_fixed_rate_with_accuracy_parent_data - register fixed-rate
  * clock with the clock framework
@@ -438,7 +451,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                parent_data, flags, fixed_rate, fixed_accuracy)               \
        __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,         \
                                     (parent_data), NULL, (flags),            \
-                                    (fixed_rate), (fixed_accuracy), 0)
+                                    (fixed_rate), (fixed_accuracy), 0, false)
 /**
  * clk_hw_register_fixed_rate_parent_accuracy - register fixed-rate clock with
  * the clock framework
@@ -452,7 +465,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
                                                   flags, fixed_rate)         \
        __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,      \
                                     (parent_data), (flags), (fixed_rate), 0,    \
-                                    CLK_FIXED_RATE_PARENT_ACCURACY)
+                                    CLK_FIXED_RATE_PARENT_ACCURACY, false)
 
 void clk_unregister_fixed_rate(struct clk *clk);
 void clk_hw_unregister_fixed_rate(struct clk_hw *hw);