void (*disable_unused)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
- long (*round_rate)(struct clk_hw *hw,
- unsigned long rate,
- unsigned long *parent_rate);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
int (*set_parent)(struct clk_hw *hw, u8 index);
+----------------+------+-------------+---------------+-------------+------+
|.recalc_rate | | y | | | |
+----------------+------+-------------+---------------+-------------+------+
- |.round_rate | | y [1]_ | | | |
- +----------------+------+-------------+---------------+-------------+------+
- |.determine_rate | | y [1]_ | | | |
+ |.determine_rate | | y | | | |
+----------------+------+-------------+---------------+-------------+------+
|.set_rate | | y | | | |
+----------------+------+-------------+---------------+-------------+------+
|.init | | | | | |
+----------------+------+-------------+---------------+-------------+------+
-.. [1] either one of round_rate or determine_rate is required.
-
Finally, register your clock at run-time with a hardware-specific
registration function. This function simply populates struct clk_foo's
data and then passes the common struct clk parameters to the framework
static int clk_core_determine_round_nolock(struct clk_core *core,
struct clk_rate_request *req)
{
- long rate;
-
lockdep_assert_held(&prepare_lock);
if (!core)
req->rate = core->rate;
} else if (core->ops->determine_rate) {
return core->ops->determine_rate(core->hw, req);
- } else if (core->ops->round_rate) {
- rate = core->ops->round_rate(core->hw, req->rate,
- &req->best_parent_rate);
- if (rate < 0)
- return rate;
-
- req->rate = rate;
} else {
return -EINVAL;
}
static bool clk_core_can_round(struct clk_core * const core)
{
- return core->ops->determine_rate || core->ops->round_rate;
+ return core->ops->determine_rate;
}
static int clk_core_round_rate_nolock(struct clk_core *core,
* use.
*
* Context: prepare_lock must be held.
- * For clk providers to call from within clk_ops such as .round_rate,
+ * For clk providers to call from within clk_ops such as
* .determine_rate.
*
- * Return: returns rounded rate of hw clk if clk supports round_rate operation
- * else returns the parent rate.
+ * Return: returns rounded rate of hw clk if clk supports determine_rate
+ * operation; else returns the parent rate.
*/
unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
{
*
* Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to
* propagate up to clk's parent; whether or not this happens depends on the
- * outcome of clk's .round_rate implementation. If *parent_rate is unchanged
- * after calling .round_rate then upstream parent propagation is ignored. If
- * *parent_rate comes back with a new rate for clk's parent then we propagate
- * up to clk's parent and set its rate. Upward propagation will continue
- * until either a clk does not support the CLK_SET_RATE_PARENT flag or
- * .round_rate stops requesting changes to clk's parent_rate.
+ * outcome of clk's .determine_rate implementation. If req->best_parent_rate
+ * is unchanged after calling .determine_rate then upstream parent propagation
+ * is ignored. If req->best_parent_rate comes back with a new rate for clk's
+ * parent then we propagate up to clk's parent and set its rate. Upward
+ * propagation will continue until either a clk does not support the
+ * CLK_SET_RATE_PARENT flag or .determine_rate stops requesting changes to
+ * clk's parent_rate.
*
* Rate changes are accomplished via tree traversal that also recalculates the
* rates for the clocks and fires off POST_RATE_CHANGE notifiers.
* FIXME:
* There is a catch. It may fail for the usual reason (clock
* broken, clock protected, etc) but also because:
- * - round_rate() was not favorable and fell on the wrong
- * side of the boundary
* - the determine_rate() callback does not really check for
* this corner case when determining the rate
*/
}
/* check that clk_ops are sane. See Documentation/driver-api/clk.rst */
- if (core->ops->set_rate &&
- !((core->ops->round_rate || core->ops->determine_rate) &&
- core->ops->recalc_rate)) {
- pr_err("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
+ if (core->ops->set_rate && !core->ops->determine_rate &&
+ core->ops->recalc_rate) {
+ pr_err("%s: %s must implement .determine_rate in addition to .recalc_rate\n",
__func__, core->name);
ret = -EINVAL;
goto out;
* 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
- * supported by the clock. The parent rate is an input/output
- * parameter.
- *
* @determine_rate: Given a target rate as input, returns the closest rate
* actually supported by the clock, and optionally the parent clock
* that should be used to provide the clock rate.
*
* @set_rate: Change the rate of this clock. The requested rate is specified
* by the second argument, which should typically be the return
- * of .round_rate call. The third argument gives the parent rate
- * which is likely helpful for most .set_rate implementation.
+ * of .determine_rate call. The third argument gives the parent
+ * rate which is likely helpful for most .set_rate implementation.
* Returns 0 on success, -EERROR otherwise.
*
* @set_rate_and_parent: Change the rate and the parent of this clock. The
* requested rate is specified by the second argument, which
- * should typically be the return of .round_rate call. The
+ * should typically be the return of clk_round_rate() call. The
* third argument gives the parent rate which is likely helpful
* for most .set_rate_and_parent implementation. The fourth
* argument gives the parent index. This callback is optional (and
void (*restore_context)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
- long (*round_rate)(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
int (*set_parent)(struct clk_hw *hw, u8 index);
* @lock: register lock
*
* Clock with an adjustable divider affecting its output frequency. Implements
- * .recalc_rate, .set_rate and .round_rate
+ * .recalc_rate, .set_rate and .determine_rate
*
* @flags:
* CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
*
* Clock with a fixed multiplier and divider. The output frequency is the
* parent clock rate divided by div and multiplied by mult.
- * Implements .recalc_rate, .set_rate, .round_rate and .recalc_accuracy
+ * Implements .recalc_rate, .set_rate, .determine_rate and .recalc_accuracy
*
* Flags:
* * CLK_FIXED_FACTOR_FIXED_ACCURACY - Use the value in @acc instead of the
* @lock: register lock
*
* Clock with an adjustable multiplier affecting its output frequency.
- * Implements .recalc_rate, .set_rate and .round_rate
+ * Implements .recalc_rate, .set_rate and .determine_rate
*
* @flags:
* CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read