OSDN Git Service

Merge branches 'clk-uniphier', 'clk-warn-critical', 'clk-ux500', 'clk-kconfig' and...
[tomoyo/tomoyo-test1.git] / drivers / clk / clk.c
index b68e200..fa99d0b 100644 (file)
@@ -3249,6 +3249,34 @@ static inline void clk_debug_unregister(struct clk_core *core)
 }
 #endif
 
+static void clk_core_reparent_orphans_nolock(void)
+{
+       struct clk_core *orphan;
+       struct hlist_node *tmp2;
+
+       /*
+        * walk the list of orphan clocks and reparent any that newly finds a
+        * parent.
+        */
+       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
+               struct clk_core *parent = __clk_init_parent(orphan);
+
+               /*
+                * We need to use __clk_set_parent_before() and _after() to
+                * to properly migrate any prepare/enable count of the orphan
+                * clock. This is important for CLK_IS_CRITICAL clocks, which
+                * are enabled during init but might not have a parent yet.
+                */
+               if (parent) {
+                       /* update the clk tree topology */
+                       __clk_set_parent_before(orphan, parent);
+                       __clk_set_parent_after(orphan, parent, NULL);
+                       __clk_recalc_accuracies(orphan);
+                       __clk_recalc_rates(orphan, 0);
+               }
+       }
+}
+
 /**
  * __clk_core_init - initialize the data structures in a struct clk_core
  * @core:      clk_core being initialized
@@ -3259,8 +3287,6 @@ static inline void clk_debug_unregister(struct clk_core *core)
 static int __clk_core_init(struct clk_core *core)
 {
        int ret;
-       struct clk_core *orphan;
-       struct hlist_node *tmp2;
        unsigned long rate;
 
        if (!core)
@@ -3312,6 +3338,26 @@ static int __clk_core_init(struct clk_core *core)
                goto out;
        }
 
+       /*
+        * optional platform-specific magic
+        *
+        * The .init callback is not used by any of the basic clock types, but
+        * exists for weird hardware that must perform initialization magic for
+        * CCF to get an accurate view of clock for any other callbacks. It may
+        * also be used needs to perform dynamic allocations. Such allocation
+        * must be freed in the terminate() callback.
+        * This callback shall not be used to initialize the parameters state,
+        * such as rate, parent, etc ...
+        *
+        * If it exist, this callback should called before any other callback of
+        * the clock
+        */
+       if (core->ops->init) {
+               ret = core->ops->init(core->hw);
+               if (ret)
+                       goto out;
+       }
+
        core->parent = __clk_init_parent(core);
 
        /*
@@ -3337,17 +3383,6 @@ static int __clk_core_init(struct clk_core *core)
        }
 
        /*
-        * optional platform-specific magic
-        *
-        * The .init callback is not used by any of the basic clock types, but
-        * exists for weird hardware that must perform initialization magic.
-        * Please consider other ways of solving initialization problems before
-        * using this callback, as its use is discouraged.
-        */
-       if (core->ops->init)
-               core->ops->init(core->hw);
-
-       /*
         * Set clk's accuracy.  The preferred method is to use
         * .recalc_accuracy. For simple clocks and lazy developers the default
         * fallback is to use the parent's accuracy.  If a clock doesn't have a
@@ -3400,34 +3435,26 @@ static int __clk_core_init(struct clk_core *core)
        if (core->flags & CLK_IS_CRITICAL) {
                unsigned long flags;
 
-               clk_core_prepare(core);
+               ret = clk_core_prepare(core);
+               if (ret) {
+                       pr_warn("%s: critical clk '%s' failed to prepare\n",
+                              __func__, core->name);
+                       goto out;
+               }
 
                flags = clk_enable_lock();
-               clk_core_enable(core);
+               ret = clk_core_enable(core);
                clk_enable_unlock(flags);
+               if (ret) {
+                       pr_warn("%s: critical clk '%s' failed to enable\n",
+                              __func__, core->name);
+                       clk_core_unprepare(core);
+                       goto out;
+               }
        }
 
-       /*
-        * walk the list of orphan clocks and reparent any that newly finds a
-        * parent.
-        */
-       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
-               struct clk_core *parent = __clk_init_parent(orphan);
+       clk_core_reparent_orphans_nolock();
 
-               /*
-                * We need to use __clk_set_parent_before() and _after() to
-                * to properly migrate any prepare/enable count of the orphan
-                * clock. This is important for CLK_IS_CRITICAL clocks, which
-                * are enabled during init but might not have a parent yet.
-                */
-               if (parent) {
-                       /* update the clk tree topology */
-                       __clk_set_parent_before(orphan, parent);
-                       __clk_set_parent_after(orphan, parent, NULL);
-                       __clk_recalc_accuracies(orphan);
-                       __clk_recalc_rates(orphan, 0);
-               }
-       }
 
        kref_init(&core->ref);
 out:
@@ -3720,6 +3747,28 @@ fail_out:
 }
 
 /**
+ * dev_or_parent_of_node() - Get device node of @dev or @dev's parent
+ * @dev: Device to get device node of
+ *
+ * Return: device node pointer of @dev, or the device node pointer of
+ * @dev->parent if dev doesn't have a device node, or NULL if neither
+ * @dev or @dev->parent have a device node.
+ */
+static struct device_node *dev_or_parent_of_node(struct device *dev)
+{
+       struct device_node *np;
+
+       if (!dev)
+               return NULL;
+
+       np = dev_of_node(dev);
+       if (!np)
+               np = dev_of_node(dev->parent);
+
+       return np;
+}
+
+/**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
  * @hw: link to hardware-specific clock data
@@ -3734,7 +3783,7 @@ fail_out:
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
-       return __clk_register(dev, dev_of_node(dev), hw);
+       return __clk_register(dev, dev_or_parent_of_node(dev), hw);
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
@@ -3750,7 +3799,8 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 int clk_hw_register(struct device *dev, struct clk_hw *hw)
 {
-       return PTR_ERR_OR_ZERO(__clk_register(dev, dev_of_node(dev), hw));
+       return PTR_ERR_OR_ZERO(__clk_register(dev, dev_or_parent_of_node(dev),
+                              hw));
 }
 EXPORT_SYMBOL_GPL(clk_hw_register);
 
@@ -3853,6 +3903,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;
@@ -3861,7 +3912,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;
@@ -3874,6 +3926,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;
@@ -4179,6 +4234,13 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
 #ifdef CONFIG_OF
+static void clk_core_reparent_orphans(void)
+{
+       clk_prepare_lock();
+       clk_core_reparent_orphans_nolock();
+       clk_prepare_unlock();
+}
+
 /**
  * struct of_clk_provider - Clock provider registration structure
  * @link: Entry in global list of clock providers
@@ -4274,6 +4336,8 @@ int of_clk_add_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clock from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);
@@ -4309,6 +4373,8 @@ int of_clk_add_hw_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clk_hw provider from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);