]> Git Repo - linux.git/commitdiff
Merge branch 'clk-rate-range' into clk-next
authorStephen Boyd <[email protected]>
Fri, 14 Oct 2022 20:44:44 +0000 (13:44 -0700)
committerStephen Boyd <[email protected]>
Fri, 14 Oct 2022 20:44:44 +0000 (13:44 -0700)
 - Various clk rate range fixes
 - Drop clk rate range constraints on clk_put() (redux)

* clk-rate-range: (28 commits)
  clk: mediatek: clk-mux: Add .determine_rate() callback
  clk: tests: Add tests for notifiers
  clk: Update req_rate on __clk_recalc_rates()
  clk: tests: Add missing test case for ranges
  clk: qcom: clk-rcg2: Take clock boundaries into consideration for gfx3d
  clk: Introduce the clk_hw_get_rate_range function
  clk: Zero the clk_rate_request structure
  clk: Stop forwarding clk_rate_requests to the parent
  clk: Constify clk_has_parent()
  clk: Introduce clk_core_has_parent()
  clk: Switch from __clk_determine_rate to clk_core_round_rate_nolock
  clk: Add our request boundaries in clk_core_init_rate_req
  clk: Introduce clk_hw_init_rate_request()
  clk: Move clk_core_init_rate_req() from clk_core_round_rate_nolock() to its caller
  clk: Change clk_core_init_rate_req prototype
  clk: Set req_rate on reparenting
  clk: Take into account uncached clocks in clk_set_rate_range()
  clk: tests: Add some tests for orphan with multiple parents
  clk: tests: Add tests for mux with multiple parents
  clk: tests: Add tests for single parent mux
  ...

1  2 
drivers/clk/clk.c
drivers/clk/mediatek/clk-mux.c
drivers/clk/qcom/clk-rcg2.c
include/linux/clk-provider.h

diff --combined drivers/clk/clk.c
index 3c869191b258387b571108ade9fb41ca39c8ea58,47b33c5b28e16444887cf3f11a3b15dbc5098f3d..d0cf097a8a5003961faea5c184551e71a470892e
@@@ -536,6 -536,53 +536,53 @@@ static bool mux_is_better_rate(unsigne
        return now <= rate && now > best;
  }
  
+ static void clk_core_init_rate_req(struct clk_core * const core,
+                                  struct clk_rate_request *req,
+                                  unsigned long rate);
+ static int clk_core_round_rate_nolock(struct clk_core *core,
+                                     struct clk_rate_request *req);
+ static bool clk_core_has_parent(struct clk_core *core, const struct clk_core *parent)
+ {
+       struct clk_core *tmp;
+       unsigned int i;
+       /* Optimize for the case where the parent is already the parent. */
+       if (core->parent == parent)
+               return true;
+       for (i = 0; i < core->num_parents; i++) {
+               tmp = clk_core_get_parent_by_index(core, i);
+               if (!tmp)
+                       continue;
+               if (tmp == parent)
+                       return true;
+       }
+       return false;
+ }
+ static void
+ clk_core_forward_rate_req(struct clk_core *core,
+                         const struct clk_rate_request *old_req,
+                         struct clk_core *parent,
+                         struct clk_rate_request *req,
+                         unsigned long parent_rate)
+ {
+       if (WARN_ON(!clk_core_has_parent(core, parent)))
+               return;
+       clk_core_init_rate_req(parent, req, parent_rate);
+       if (req->min_rate < old_req->min_rate)
+               req->min_rate = old_req->min_rate;
+       if (req->max_rate > old_req->max_rate)
+               req->max_rate = old_req->max_rate;
+ }
  int clk_mux_determine_rate_flags(struct clk_hw *hw,
                                 struct clk_rate_request *req,
                                 unsigned long flags)
        struct clk_core *core = hw->core, *parent, *best_parent = NULL;
        int i, num_parents, ret;
        unsigned long best = 0;
-       struct clk_rate_request parent_req = *req;
  
        /* if NO_REPARENT flag set, pass through to current parent */
        if (core->flags & CLK_SET_RATE_NO_REPARENT) {
                parent = core->parent;
                if (core->flags & CLK_SET_RATE_PARENT) {
-                       ret = __clk_determine_rate(parent ? parent->hw : NULL,
-                                                  &parent_req);
+                       struct clk_rate_request parent_req;
+                       if (!parent) {
+                               req->rate = 0;
+                               return 0;
+                       }
+                       clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate);
+                       ret = clk_core_round_rate_nolock(parent, &parent_req);
                        if (ret)
                                return ret;
  
        /* find the parent that can provide the fastest rate <= rate */
        num_parents = core->num_parents;
        for (i = 0; i < num_parents; i++) {
+               unsigned long parent_rate;
                parent = clk_core_get_parent_by_index(core, i);
                if (!parent)
                        continue;
  
                if (core->flags & CLK_SET_RATE_PARENT) {
-                       parent_req = *req;
-                       ret = __clk_determine_rate(parent->hw, &parent_req);
+                       struct clk_rate_request parent_req;
+                       clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate);
+                       ret = clk_core_round_rate_nolock(parent, &parent_req);
                        if (ret)
                                continue;
+                       parent_rate = parent_req.rate;
                } else {
-                       parent_req.rate = clk_core_get_rate_nolock(parent);
+                       parent_rate = clk_core_get_rate_nolock(parent);
                }
  
-               if (mux_is_better_rate(req->rate, parent_req.rate,
+               if (mux_is_better_rate(req->rate, parent_rate,
                                       best, flags)) {
                        best_parent = parent;
-                       best = parent_req.rate;
+                       best = parent_rate;
                }
        }
  
@@@ -625,6 -684,22 +684,22 @@@ static void clk_core_get_boundaries(str
                *max_rate = min(*max_rate, clk_user->max_rate);
  }
  
+ /*
+  * clk_hw_get_rate_range() - returns the clock rate range for a hw clk
+  * @hw: the hw clk we want to get the range from
+  * @min_rate: pointer to the variable that will hold the minimum
+  * @max_rate: pointer to the variable that will hold the maximum
+  *
+  * Fills the @min_rate and @max_rate variables with the minimum and
+  * maximum that clock can reach.
+  */
+ void clk_hw_get_rate_range(struct clk_hw *hw, unsigned long *min_rate,
+                          unsigned long *max_rate)
+ {
+       clk_core_get_boundaries(hw->core, min_rate, max_rate);
+ }
+ EXPORT_SYMBOL_GPL(clk_hw_get_rate_range);
  static bool clk_core_check_boundaries(struct clk_core *core,
                                      unsigned long min_rate,
                                      unsigned long max_rate)
@@@ -1341,7 -1416,19 +1416,19 @@@ static int clk_core_determine_round_nol
        if (!core)
                return 0;
  
-       req->rate = clamp(req->rate, req->min_rate, req->max_rate);
+       /*
+        * Some clock providers hand-craft their clk_rate_requests and
+        * might not fill min_rate and max_rate.
+        *
+        * If it's the case, clamping the rate is equivalent to setting
+        * the rate to 0 which is bad. Skip the clamping but complain so
+        * that it gets fixed, hopefully.
+        */
+       if (!req->min_rate && !req->max_rate)
+               pr_warn("%s: %s: clk_rate_request has initialized min or max rate.\n",
+                       __func__, core->name);
+       else
+               req->rate = clamp(req->rate, req->min_rate, req->max_rate);
  
        /*
         * At this point, core protection will be disabled
  }
  
  static void clk_core_init_rate_req(struct clk_core * const core,
-                                  struct clk_rate_request *req)
+                                  struct clk_rate_request *req,
+                                  unsigned long rate)
  {
        struct clk_core *parent;
  
        if (WARN_ON(!core || !req))
                return;
  
+       memset(req, 0, sizeof(*req));
+       req->rate = rate;
+       clk_core_get_boundaries(core, &req->min_rate, &req->max_rate);
        parent = core->parent;
        if (parent) {
                req->best_parent_hw = parent->hw;
        }
  }
  
+ /**
+  * clk_hw_init_rate_request - Initializes a clk_rate_request
+  * @hw: the clk for which we want to submit a rate request
+  * @req: the clk_rate_request structure we want to initialise
+  * @rate: the rate which is to be requested
+  *
+  * Initializes a clk_rate_request structure to submit to
+  * __clk_determine_rate() or similar functions.
+  */
+ void clk_hw_init_rate_request(const struct clk_hw *hw,
+                             struct clk_rate_request *req,
+                             unsigned long rate)
+ {
+       if (WARN_ON(!hw || !req))
+               return;
+       clk_core_init_rate_req(hw->core, req, rate);
+ }
+ EXPORT_SYMBOL_GPL(clk_hw_init_rate_request);
+ /**
+  * clk_hw_forward_rate_request - Forwards a clk_rate_request to a clock's parent
+  * @hw: the original clock that got the rate request
+  * @old_req: the original clk_rate_request structure we want to forward
+  * @parent: the clk we want to forward @old_req to
+  * @req: the clk_rate_request structure we want to initialise
+  * @parent_rate: The rate which is to be requested to @parent
+  *
+  * Initializes a clk_rate_request structure to submit to a clock parent
+  * in __clk_determine_rate() or similar functions.
+  */
+ void clk_hw_forward_rate_request(const struct clk_hw *hw,
+                                const struct clk_rate_request *old_req,
+                                const struct clk_hw *parent,
+                                struct clk_rate_request *req,
+                                unsigned long parent_rate)
+ {
+       if (WARN_ON(!hw || !old_req || !parent || !req))
+               return;
+       clk_core_forward_rate_req(hw->core, old_req,
+                                 parent->core, req,
+                                 parent_rate);
+ }
  static bool clk_core_can_round(struct clk_core * const core)
  {
        return core->ops->determine_rate || core->ops->round_rate;
  static int clk_core_round_rate_nolock(struct clk_core *core,
                                      struct clk_rate_request *req)
  {
+       int ret;
        lockdep_assert_held(&prepare_lock);
  
        if (!core) {
                return 0;
        }
  
-       clk_core_init_rate_req(core, req);
        if (clk_core_can_round(core))
                return clk_core_determine_round_nolock(core, req);
-       else if (core->flags & CLK_SET_RATE_PARENT)
-               return clk_core_round_rate_nolock(core->parent, req);
+       if (core->flags & CLK_SET_RATE_PARENT) {
+               struct clk_rate_request parent_req;
+               clk_core_forward_rate_req(core, req, core->parent, &parent_req, req->rate);
+               ret = clk_core_round_rate_nolock(core->parent, &parent_req);
+               if (ret)
+                       return ret;
+               req->best_parent_rate = parent_req.rate;
+               req->rate = parent_req.rate;
+               return 0;
+       }
  
        req->rate = core->rate;
        return 0;
@@@ -1449,8 -1599,7 +1599,7 @@@ unsigned long clk_hw_round_rate(struct 
        int ret;
        struct clk_rate_request req;
  
-       clk_core_get_boundaries(hw->core, &req.min_rate, &req.max_rate);
-       req.rate = rate;
+       clk_core_init_rate_req(hw->core, &req, rate);
  
        ret = clk_core_round_rate_nolock(hw->core, &req);
        if (ret)
@@@ -1482,8 -1631,7 +1631,7 @@@ long clk_round_rate(struct clk *clk, un
        if (clk->exclusive_count)
                clk_core_rate_unprotect(clk->core);
  
-       clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
-       req.rate = rate;
+       clk_core_init_rate_req(clk->core, &req, rate);
  
        ret = clk_core_round_rate_nolock(clk->core, &req);
  
@@@ -1612,6 -1760,7 +1760,7 @@@ static unsigned long clk_recalc(struct 
  /**
   * __clk_recalc_rates
   * @core: first clk in the subtree
+  * @update_req: Whether req_rate should be updated with the new rate
   * @msg: notification type (see include/linux/clk.h)
   *
   * Walks the subtree of clks starting with clk and recalculates rates as it
   * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
   * if necessary.
   */
- static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
+ static void __clk_recalc_rates(struct clk_core *core, bool update_req,
+                              unsigned long msg)
  {
        unsigned long old_rate;
        unsigned long parent_rate = 0;
                parent_rate = core->parent->rate;
  
        core->rate = clk_recalc(core, parent_rate);
+       if (update_req)
+               core->req_rate = core->rate;
  
        /*
         * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
                __clk_notify(core, msg, old_rate, core->rate);
  
        hlist_for_each_entry(child, &core->children, child_node)
-               __clk_recalc_rates(child, msg);
+               __clk_recalc_rates(child, update_req, msg);
  }
  
  static unsigned long clk_core_get_rate_recalc(struct clk_core *core)
  {
        if (core && (core->flags & CLK_GET_RATE_NOCACHE))
-               __clk_recalc_rates(core, 0);
+               __clk_recalc_rates(core, false, 0);
  
        return clk_core_get_rate_nolock(core);
  }
   * @clk: the clk whose rate is being returned
   *
   * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
-  * is set, which means a recalc_rate will be issued.
-  * If clk is NULL then returns 0.
+  * is set, which means a recalc_rate will be issued. Can be called regardless of
+  * the clock enabledness. If clk is NULL, or if an error occurred, then returns
+  * 0.
   */
  unsigned long clk_get_rate(struct clk *clk)
  {
@@@ -1865,6 -2018,7 +2018,7 @@@ static int __clk_set_parent(struct clk_
                flags = clk_enable_lock();
                clk_reparent(core, old_parent);
                clk_enable_unlock(flags);
                __clk_set_parent_after(core, old_parent, parent);
  
                return ret;
@@@ -1970,11 -2124,7 +2124,7 @@@ static struct clk_core *clk_calc_new_ra
        if (clk_core_can_round(core)) {
                struct clk_rate_request req;
  
-               req.rate = rate;
-               req.min_rate = min_rate;
-               req.max_rate = max_rate;
-               clk_core_init_rate_req(core, &req);
+               clk_core_init_rate_req(core, &req, rate);
  
                ret = clk_core_determine_round_nolock(core, &req);
                if (ret < 0)
@@@ -2173,8 -2323,7 +2323,7 @@@ static unsigned long clk_core_req_round
        if (cnt < 0)
                return cnt;
  
-       clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
-       req.rate = req_rate;
+       clk_core_init_rate_req(core, &req, req_rate);
  
        ret = clk_core_round_rate_nolock(core, &req);
  
@@@ -2189,7 -2338,7 +2338,7 @@@ static int clk_core_set_rate_nolock(str
  {
        struct clk_core *top, *fail_clk;
        unsigned long rate;
 -      int ret = 0;
 +      int ret;
  
        if (!core)
                return 0;
@@@ -2325,19 -2474,15 +2474,15 @@@ int clk_set_rate_exclusive(struct clk *
  }
  EXPORT_SYMBOL_GPL(clk_set_rate_exclusive);
  
- /**
-  * clk_set_rate_range - set a rate range for a clock source
-  * @clk: clock source
-  * @min: desired minimum clock rate in Hz, inclusive
-  * @max: desired maximum clock rate in Hz, inclusive
-  *
-  * Returns success (0) or negative errno.
-  */
- int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+ static int clk_set_rate_range_nolock(struct clk *clk,
+                                    unsigned long min,
+                                    unsigned long max)
  {
        int ret = 0;
        unsigned long old_min, old_max, rate;
  
+       lockdep_assert_held(&prepare_lock);
        if (!clk)
                return 0;
  
                return -EINVAL;
        }
  
-       clk_prepare_lock();
        if (clk->exclusive_count)
                clk_core_rate_unprotect(clk->core);
  
                goto out;
        }
  
+       rate = clk->core->req_rate;
+       if (clk->core->flags & CLK_GET_RATE_NOCACHE)
+               rate = clk_core_get_rate_recalc(clk->core);
        /*
         * Since the boundaries have been changed, let's give the
         * opportunity to the provider to adjust the clock rate based on
         * - the determine_rate() callback does not really check for
         *   this corner case when determining the rate
         */
-       rate = clamp(clk->core->req_rate, min, max);
+       rate = clamp(rate, min, max);
        ret = clk_core_set_rate_nolock(clk->core, rate);
        if (ret) {
                /* rollback the changes */
        if (clk->exclusive_count)
                clk_core_rate_protect(clk->core);
  
+       return ret;
+ }
+ /**
+  * clk_set_rate_range - set a rate range for a clock source
+  * @clk: clock source
+  * @min: desired minimum clock rate in Hz, inclusive
+  * @max: desired maximum clock rate in Hz, inclusive
+  *
+  * Return: 0 for success or negative errno on failure.
+  */
+ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+ {
+       int ret;
+       if (!clk)
+               return 0;
+       clk_prepare_lock();
+       ret = clk_set_rate_range_nolock(clk, min, max);
        clk_prepare_unlock();
  
        return ret;
@@@ -2474,7 -2643,7 +2643,7 @@@ static void clk_core_reparent(struct cl
  {
        clk_reparent(core, new_parent);
        __clk_recalc_accuracies(core);
-       __clk_recalc_rates(core, POST_RATE_CHANGE);
+       __clk_recalc_rates(core, true, POST_RATE_CHANGE);
  }
  
  void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
   *
   * Returns true if @parent is a possible parent for @clk, false otherwise.
   */
- bool clk_has_parent(struct clk *clk, struct clk *parent)
+ bool clk_has_parent(const struct clk *clk, const struct clk *parent)
  {
-       struct clk_core *core, *parent_core;
-       int i;
        /* NULL clocks should be nops, so return success if either is NULL. */
        if (!clk || !parent)
                return true;
  
-       core = clk->core;
-       parent_core = parent->core;
-       /* Optimize for the case where the parent is already the parent. */
-       if (core->parent == parent_core)
-               return true;
-       for (i = 0; i < core->num_parents; i++)
-               if (!strcmp(core->parents[i].name, parent_core->name))
-                       return true;
-       return false;
+       return clk_core_has_parent(clk->core, parent->core);
  }
  EXPORT_SYMBOL_GPL(clk_has_parent);
  
@@@ -2572,9 -2727,9 +2727,9 @@@ static int clk_core_set_parent_nolock(s
  
        /* propagate rate an accuracy recalculation accordingly */
        if (ret) {
-               __clk_recalc_rates(core, ABORT_RATE_CHANGE);
+               __clk_recalc_rates(core, true, ABORT_RATE_CHANGE);
        } else {
-               __clk_recalc_rates(core, POST_RATE_CHANGE);
+               __clk_recalc_rates(core, true, POST_RATE_CHANGE);
                __clk_recalc_accuracies(core);
        }
  
@@@ -3462,7 -3617,7 +3617,7 @@@ static void clk_core_reparent_orphans_n
  
                /*
                 * We need to use __clk_set_parent_before() and _after() to
 -               * to properly migrate any prepare/enable count of the orphan
 +               * 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.
                 */
                        __clk_set_parent_before(orphan, parent);
                        __clk_set_parent_after(orphan, parent, NULL);
                        __clk_recalc_accuracies(orphan);
-                       __clk_recalc_rates(orphan, 0);
+                       __clk_recalc_rates(orphan, true, 0);
  
                        /*
                         * __clk_init_parent() will set the initial req_rate to
@@@ -3672,6 -3827,7 +3827,6 @@@ static int __clk_core_init(struct clk_c
  
        clk_core_reparent_orphans_nolock();
  
 -
        kref_init(&core->ref);
  out:
        clk_pm_runtime_put(core);
@@@ -4347,9 -4503,10 +4502,10 @@@ void __clk_put(struct clk *clk
        }
  
        hlist_del(&clk->clks_node);
-       if (clk->min_rate > clk->core->req_rate ||
-           clk->max_rate < clk->core->req_rate)
-               clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+       /* If we had any boundaries on that clock, let's drop them. */
+       if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX)
+               clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
  
        owner = clk->core->owner;
        kref_put(&clk->core->ref, __clk_release);
@@@ -4750,6 -4907,32 +4906,6 @@@ void of_clk_del_provider(struct device_
  }
  EXPORT_SYMBOL_GPL(of_clk_del_provider);
  
 -static int devm_clk_provider_match(struct device *dev, void *res, void *data)
 -{
 -      struct device_node **np = res;
 -
 -      if (WARN_ON(!np || !*np))
 -              return 0;
 -
 -      return *np == data;
 -}
 -
 -/**
 - * devm_of_clk_del_provider() - Remove clock provider registered using devm
 - * @dev: Device to whose lifetime the clock provider was bound
 - */
 -void devm_of_clk_del_provider(struct device *dev)
 -{
 -      int ret;
 -      struct device_node *np = get_clk_provider_node(dev);
 -
 -      ret = devres_release(dev, devm_of_clk_release_provider,
 -                           devm_clk_provider_match, np);
 -
 -      WARN_ON(ret);
 -}
 -EXPORT_SYMBOL(devm_of_clk_del_provider);
 -
  /**
   * of_parse_clkspec() - Parse a DT clock specifier for a given device node
   * @np: device node to parse clock specifier from
index 4421e4859257603990c28c3a76a316f267e494ea,5d217f7377ee15cf1b3706f0d4254144d7c23c0d..ba1720b9e23101929a54b4c09955f0ec93d52342
@@@ -4,7 -4,6 +4,7 @@@
   * Author: Owen Chen <[email protected]>
   */
  
 +#include <linux/clk.h>
  #include <linux/clk-provider.h>
  #include <linux/compiler_types.h>
  #include <linux/container_of.h>
@@@ -129,9 -128,18 +129,18 @@@ static int mtk_clk_mux_set_parent_setcl
        return 0;
  }
  
+ static int mtk_clk_mux_determine_rate(struct clk_hw *hw,
+                                     struct clk_rate_request *req)
+ {
+       struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
+       return clk_mux_determine_rate_flags(hw, req, mux->data->flags);
+ }
  const struct clk_ops mtk_mux_clr_set_upd_ops = {
        .get_parent = mtk_clk_mux_get_parent,
        .set_parent = mtk_clk_mux_set_parent_setclr_lock,
+       .determine_rate = mtk_clk_mux_determine_rate,
  };
  EXPORT_SYMBOL_GPL(mtk_mux_clr_set_upd_ops);
  
@@@ -141,6 -149,7 +150,7 @@@ const struct clk_ops mtk_mux_gate_clr_s
        .is_enabled = mtk_clk_mux_is_enabled,
        .get_parent = mtk_clk_mux_get_parent,
        .set_parent = mtk_clk_mux_set_parent_setclr_lock,
+       .determine_rate = mtk_clk_mux_determine_rate,
  };
  EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops);
  
@@@ -260,41 -269,4 +270,41 @@@ void mtk_clk_unregister_muxes(const str
  }
  EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes);
  
 +/*
 + * This clock notifier is called when the frequency of the parent
 + * PLL clock is to be changed. The idea is to switch the parent to a
 + * stable clock, such as the main oscillator, while the PLL frequency
 + * stabilizes.
 + */
 +static int mtk_clk_mux_notifier_cb(struct notifier_block *nb,
 +                                 unsigned long event, void *_data)
 +{
 +      struct clk_notifier_data *data = _data;
 +      struct clk_hw *hw = __clk_get_hw(data->clk);
 +      struct mtk_mux_nb *mux_nb = to_mtk_mux_nb(nb);
 +      int ret = 0;
 +
 +      switch (event) {
 +      case PRE_RATE_CHANGE:
 +              mux_nb->original_index = mux_nb->ops->get_parent(hw);
 +              ret = mux_nb->ops->set_parent(hw, mux_nb->bypass_index);
 +              break;
 +      case POST_RATE_CHANGE:
 +      case ABORT_RATE_CHANGE:
 +              ret = mux_nb->ops->set_parent(hw, mux_nb->original_index);
 +              break;
 +      }
 +
 +      return notifier_from_errno(ret);
 +}
 +
 +int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
 +                                     struct mtk_mux_nb *mux_nb)
 +{
 +      mux_nb->nb.notifier_call = mtk_clk_mux_notifier_cb;
 +
 +      return devm_clk_notifier_register(dev, clk, &mux_nb->nb);
 +}
 +EXPORT_SYMBOL_GPL(devm_mtk_clk_mux_notifier_register);
 +
  MODULE_LICENSE("GPL");
index 609c10f8d0d9407cbd4d853b0818a806716ff282,ee536b4579523118ab56bad03d62e75616531617..76551534f10dfe0dc09a9917a3df974b80f2bd58
@@@ -509,13 -509,6 +509,13 @@@ const struct clk_ops clk_rcg2_floor_op
  };
  EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
  
 +const struct clk_ops clk_rcg2_mux_closest_ops = {
 +      .determine_rate = __clk_mux_determine_rate_closest,
 +      .get_parent = clk_rcg2_get_parent,
 +      .set_parent = clk_rcg2_set_parent,
 +};
 +EXPORT_SYMBOL_GPL(clk_rcg2_mux_closest_ops);
 +
  struct frac_entry {
        int num;
        int den;
@@@ -915,6 -908,15 +915,15 @@@ static int clk_gfx3d_determine_rate(str
                req->best_parent_hw = p2;
        }
  
+       clk_hw_get_rate_range(req->best_parent_hw,
+                             &parent_req.min_rate, &parent_req.max_rate);
+       if (req->min_rate > parent_req.min_rate)
+               parent_req.min_rate = req->min_rate;
+       if (req->max_rate < parent_req.max_rate)
+               parent_req.max_rate = req->max_rate;
        ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
        if (ret)
                return ret;
index 2108b56953271799fbec379e13343cefbef2d325,8724a3547a79fbae7773dd14564f50c1d38a2e85..267cd06b54a0196704e1d395f44ee20c1fed263c
@@@ -42,6 -42,8 +42,8 @@@ struct dentry
   * struct clk_rate_request - Structure encoding the clk constraints that
   * a clock user might require.
   *
+  * Should be initialized by calling clk_hw_init_rate_request().
+  *
   * @rate:             Requested clock rate. This field will be adjusted by
   *                    clock drivers according to hardware capabilities.
   * @min_rate:         Minimum rate imposed by clk users.
@@@ -60,6 -62,15 +62,15 @@@ struct clk_rate_request 
        struct clk_hw *best_parent_hw;
  };
  
+ void clk_hw_init_rate_request(const struct clk_hw *hw,
+                             struct clk_rate_request *req,
+                             unsigned long rate);
+ void clk_hw_forward_rate_request(const struct clk_hw *core,
+                                const struct clk_rate_request *old_req,
+                                const struct clk_hw *parent,
+                                struct clk_rate_request *req,
+                                unsigned long parent_rate);
  /**
   * struct clk_duty - Struture encoding the duty cycle ratio of a clock
   *
@@@ -118,8 -129,9 +129,9 @@@ struct clk_duty 
   *
   * @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.
-  *            Returns the calculated rate.  Optional, but recommended - if
+  *            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.
   *
   * @round_rate:       Given a target rate as input, returns the closest rate actually
@@@ -350,7 -362,7 +362,7 @@@ struct clk_hw *__clk_hw_register_fixed_
                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);
   */
  #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
  #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
                                             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
                                                 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
                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
                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
 + * @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 clk_hw_register_fixed_rate_parent_accuracy(dev, name, parent_data,    \
 +                                                 flags, fixed_rate)         \
 +      __clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL,      \
 +                                   (parent_data), (flags), (fixed_rate), 0,    \
 +                                   CLK_FIXED_RATE_PARENT_ACCURACY, false)
  
  void clk_unregister_fixed_rate(struct clk *clk);
  void clk_hw_unregister_fixed_rate(struct clk_hw *hw);
@@@ -984,13 -969,6 +996,13 @@@ struct clk *clk_register_mux_table(stru
                              (parent_names), NULL, NULL, (flags), (reg),     \
                              (shift), (mask), (clk_mux_flags), (table),      \
                              (lock))
 +#define clk_hw_register_mux_table_parent_data(dev, name, parent_data,       \
 +                                num_parents, flags, reg, shift, mask,       \
 +                                clk_mux_flags, table, lock)                 \
 +      __clk_hw_register_mux((dev), NULL, (name), (num_parents),             \
 +                            NULL, NULL, (parent_data), (flags), (reg),      \
 +                            (shift), (mask), (clk_mux_flags), (table),      \
 +                            (lock))
  #define clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
                            shift, width, clk_mux_flags, lock)                \
        __clk_hw_register_mux((dev), NULL, (name), (num_parents),             \
        __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
                              (parent_data), (flags), (reg), (shift),         \
                              BIT((width)) - 1, (clk_mux_flags), NULL, (lock))
 +#define clk_hw_register_mux_parent_data_table(dev, name, parent_data,       \
 +                                            num_parents, flags, reg, shift, \
 +                                            width, clk_mux_flags, table,    \
 +                                            lock)                           \
 +      __clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL, NULL, \
 +                            (parent_data), (flags), (reg), (shift),         \
 +                            BIT((width)) - 1, (clk_mux_flags), table, (lock))
  #define devm_clk_hw_register_mux(dev, name, parent_names, num_parents, flags, reg, \
                            shift, width, clk_mux_flags, lock)                \
        __devm_clk_hw_register_mux((dev), NULL, (name), (num_parents),        \
                                   (parent_hws), NULL, (flags), (reg),        \
                                   (shift), BIT((width)) - 1,                 \
                                   (clk_mux_flags), NULL, (lock))
 +#define devm_clk_hw_register_mux_parent_data_table(dev, name, parent_data,    \
 +                                            num_parents, flags, reg, shift, \
 +                                            width, clk_mux_flags, table,    \
 +                                            lock)                           \
 +      __devm_clk_hw_register_mux((dev), NULL, (name), (num_parents), NULL,  \
 +                            NULL, (parent_data), (flags), (reg), (shift),   \
 +                            BIT((width)) - 1, (clk_mux_flags), table, (lock))
  
  int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags,
                         unsigned int val);
@@@ -1303,6 -1267,8 +1315,8 @@@ int clk_mux_determine_rate_flags(struc
                                 struct clk_rate_request *req,
                                 unsigned long flags);
  void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
+ void clk_hw_get_rate_range(struct clk_hw *hw, unsigned long *min_rate,
+                          unsigned long *max_rate);
  void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
                           unsigned long max_rate);
  
@@@ -1502,7 -1468,7 +1516,7 @@@ int devm_of_clk_add_hw_provider(struct 
                                                 void *data),
                           void *data);
  void of_clk_del_provider(struct device_node *np);
 -void devm_of_clk_del_provider(struct device *dev);
 +
  struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
                                  void *data);
  struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec,
@@@ -1539,7 -1505,7 +1553,7 @@@ static inline int devm_of_clk_add_hw_pr
        return 0;
  }
  static inline void of_clk_del_provider(struct device_node *np) {}
 -static inline void devm_of_clk_del_provider(struct device *dev) {}
 +
  static inline struct clk *of_clk_src_simple_get(
        struct of_phandle_args *clkspec, void *data)
  {
This page took 0.1118 seconds and 4 git commands to generate.