This is the final part of the clk patches for this merge window.

The clk rate range series needed another week to fully bake. Maxime
 fixed the bug that broke clk notifiers and prevented this from being
 included in the first pull request. He also added a unit test on top to
 make sure it doesn't break so easily again. The majority of the series
 fixes up how the clk_set_rate_*() APIs work, particularly around when
 the rate constraints are dropped and how they move around when
 reparenting clks. Overall it's a much needed improvement to the clk rate
 range APIs that used to be pretty broken if you looked sideways.
 
 Beyond the core changes there are a few driver fixes for a compilation
 issue or improper data causing clks to fail to register or have the
 wrong parents. These are good to get in before the first -rc so that the
 system actually boots on the affected devices.
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmNLfwARHHNib3lkQGtl
 cm5lbC5vcmcACgkQrQKIl8bklSW1uhAA0QMgI8Ywv18PfZi2vWGpAO9sB62DfmdU
 sbmsXrfEHdJmXmqT66Ydr8area6loeCagK4Vm/dEcgsf2DwI/xCdDra/ARZjLU49
 9VjgC332YLZzk6bHXsY2eqCA2TS6nV4ZoVsonkQv2vezYNLNk7FTgByzIcWpYiY8
 RuKEVHnp2yWwk5HrX+pELR0dMDCLTB3p+WVHmnQpyYVK+rcfaSNuDxLTSNXb3yEl
 tGTUu4eL09FMwyRZ4iGmRXpvzIacbthYmnGmEtnOYDeFV3k3wBwHPbEizstvS0MI
 vv89aHdsOnGgTdzPUZtA6UppByajyoDKbYzb3hw8pUPNNykbq6XmaeBTV7U2O9De
 ihfeHVlDjN2HCv1HXfDsCaqlD6WM25T+pmKPT45Zj9b+rKkxloVxsOBuLmMzDgNd
 fa1X3qfGfzm5jpZ1SVSTLdRSqOT5Q00nzAgQailUiDoumgdTSN5ZDNPHcIv/Crvn
 me+pabVldp0tgYvuNWYr46u7ugwnzUMBVJfnQ+xZTl8xqLQ/yRmkkhB/rsS5RDY1
 z6NZ66JyHpSwnaev4Ozjyj8GlRdgDUVHGa/4Vm1jJSbUb7THZGSzjCklZXPxkn8I
 VqHNJN+luzaf6bKe85yrgUJKOi8NMZZS//MKWDnOdhDqgqtI0pM4hJX+Tvb2Bc4B
 2SA7XzHesKg=
 =ZG8Y
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull more clk updates from Stephen Boyd:
 "This is the final part of the clk patches for this merge window.

  The clk rate range series needed another week to fully bake. Maxime
  fixed the bug that broke clk notifiers and prevented this from being
  included in the first pull request. He also added a unit test on top
  to make sure it doesn't break so easily again. The majority of the
  series fixes up how the clk_set_rate_*() APIs work, particularly
  around when the rate constraints are dropped and how they move around
  when reparenting clks. Overall it's a much needed improvement to the
  clk rate range APIs that used to be pretty broken if you looked
  sideways.

  Beyond the core changes there are a few driver fixes for a compilation
  issue or improper data causing clks to fail to register or have the
  wrong parents. These are good to get in before the first -rc so that
  the system actually boots on the affected devices"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (31 commits)
  clk: tegra: Fix Tegra PWM parent clock
  clk: at91: fix the build with binutils 2.27
  clk: qcom: gcc-msm8660: Drop hardcoded fixed board clocks
  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()
  ...
This commit is contained in:
Linus Torvalds 2022-10-16 11:08:19 -07:00
commit 2fcd8f108f
18 changed files with 1833 additions and 131 deletions

View File

@ -136,7 +136,6 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
{
struct clk_generated *gck = to_clk_generated(hw);
struct clk_hw *parent = NULL;
struct clk_rate_request req_parent = *req;
long best_rate = -EINVAL;
unsigned long min_rate, parent_rate;
int best_diff = -1;
@ -192,7 +191,9 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
goto end;
for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
req_parent.rate = req->rate * div;
struct clk_rate_request req_parent;
clk_hw_forward_rate_request(hw, req, parent, &req_parent, req->rate * div);
if (__clk_determine_rate(parent, &req_parent))
continue;
clk_generated_best_diff(req, parent, req_parent.rate, div,

View File

@ -581,7 +581,6 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_master *master = to_clk_master(hw);
struct clk_rate_request req_parent = *req;
struct clk_hw *parent;
long best_rate = LONG_MIN, best_diff = LONG_MIN;
unsigned long parent_rate;
@ -618,11 +617,15 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
goto end;
for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
if (div == MASTER_PRES_MAX)
req_parent.rate = req->rate * 3;
else
req_parent.rate = req->rate << div;
struct clk_rate_request req_parent;
unsigned long req_rate;
if (div == MASTER_PRES_MAX)
req_rate = req->rate * 3;
else
req_rate = req->rate << div;
clk_hw_forward_rate_request(hw, req, parent, &req_parent, req_rate);
if (__clk_determine_rate(parent, &req_parent))
continue;

View File

@ -269,7 +269,6 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
{
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
struct clk_hw *parent = clk_hw_get_parent(hw);
struct clk_rate_request req_parent = *req;
unsigned long parent_rate = clk_hw_get_rate(parent);
unsigned long tmp_rate;
long best_rate = LONG_MIN;
@ -302,8 +301,9 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
goto end;
for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
req_parent.rate = req->rate << shift;
struct clk_rate_request req_parent;
clk_hw_forward_rate_request(hw, req, parent, &req_parent, req->rate << shift);
if (__clk_determine_rate(parent, &req_parent))
continue;

View File

@ -85,10 +85,11 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
req->best_parent_hw = NULL;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
struct clk_rate_request tmp_req = *req;
struct clk_rate_request tmp_req;
parent = clk_hw_get_parent(mux_hw);
clk_hw_forward_rate_request(hw, req, parent, &tmp_req, req->rate);
ret = clk_composite_determine_rate_for_parent(rate_hw,
&tmp_req,
parent,
@ -104,12 +105,13 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
}
for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
struct clk_rate_request tmp_req = *req;
struct clk_rate_request tmp_req;
parent = clk_hw_get_parent_by_index(mux_hw, i);
if (!parent)
continue;
clk_hw_forward_rate_request(hw, req, parent, &tmp_req, req->rate);
ret = clk_composite_determine_rate_for_parent(rate_hw,
&tmp_req,
parent,

View File

@ -386,13 +386,13 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
const struct clk_div_table *table,
u8 width, unsigned long flags)
{
struct clk_rate_request req = {
.rate = rate,
.best_parent_rate = *prate,
.best_parent_hw = parent,
};
struct clk_rate_request req;
int ret;
clk_hw_init_rate_request(hw, &req, rate);
req.best_parent_rate = *prate;
req.best_parent_hw = parent;
ret = divider_determine_rate(hw, &req, table, width, flags);
if (ret)
return ret;
@ -408,13 +408,13 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
const struct clk_div_table *table, u8 width,
unsigned long flags, unsigned int val)
{
struct clk_rate_request req = {
.rate = rate,
.best_parent_rate = *prate,
.best_parent_hw = parent,
};
struct clk_rate_request req;
int ret;
clk_hw_init_rate_request(hw, &req, rate);
req.best_parent_rate = *prate;
req.best_parent_hw = parent;
ret = divider_ro_determine_rate(hw, &req, table, width, flags, val);
if (ret)
return ret;

View File

@ -536,6 +536,53 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
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)
@ -543,14 +590,20 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
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;
@ -567,23 +620,29 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
/* 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 @@ static void clk_core_get_boundaries(struct clk_core *core,
*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)
@ -1340,7 +1415,19 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
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
@ -1367,13 +1454,19 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
}
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;
@ -1384,6 +1477,51 @@ static void clk_core_init_rate_req(struct clk_core * const core,
}
}
/**
* 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;
@ -1392,6 +1530,8 @@ static bool clk_core_can_round(struct clk_core * const core)
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) {
@ -1399,12 +1539,22 @@ static int clk_core_round_rate_nolock(struct clk_core *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;
@ -1448,8 +1598,7 @@ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
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)
@ -1481,8 +1630,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
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);
@ -1611,6 +1759,7 @@ static unsigned long clk_recalc(struct clk_core *core,
/**
* __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
@ -1620,7 +1769,8 @@ static unsigned long clk_recalc(struct clk_core *core,
* 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;
@ -1634,6 +1784,8 @@ static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
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
@ -1643,13 +1795,13 @@ static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
__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);
}
@ -1659,8 +1811,9 @@ static unsigned long clk_core_get_rate_recalc(struct clk_core *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)
{
@ -1864,6 +2017,7 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
flags = clk_enable_lock();
clk_reparent(core, old_parent);
clk_enable_unlock(flags);
__clk_set_parent_after(core, old_parent, parent);
return ret;
@ -1969,11 +2123,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
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)
@ -2172,8 +2322,7 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
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);
@ -2324,19 +2473,15 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate)
}
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;
@ -2349,8 +2494,6 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
return -EINVAL;
}
clk_prepare_lock();
if (clk->exclusive_count)
clk_core_rate_unprotect(clk->core);
@ -2365,6 +2508,10 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
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
@ -2382,7 +2529,7 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
* - 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 */
@ -2394,6 +2541,28 @@ out:
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;
@ -2473,7 +2642,7 @@ static void clk_core_reparent(struct clk_core *core,
{
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)
@ -2494,27 +2663,13 @@ 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);
@ -2571,9 +2726,9 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
/* 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);
}
@ -3470,7 +3625,7 @@ static void clk_core_reparent_orphans_nolock(void)
__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
@ -4346,9 +4501,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);

File diff suppressed because it is too large Load Diff

View File

@ -129,9 +129,18 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
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 +150,7 @@ const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
.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);

View File

@ -915,6 +915,15 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw,
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;

View File

@ -2767,17 +2767,6 @@ MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
static int gcc_msm8660_probe(struct platform_device *pdev)
{
int ret;
struct device *dev = &pdev->dev;
ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
if (ret)
return ret;
ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
if (ret)
return ret;
return qcom_cc_probe(pdev, &gcc_msm8660_desc);
}

View File

@ -1166,6 +1166,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA114_CLK_I2S3_SYNC, TEGRA114_CLK_CLK_MAX, 24000000, 0 },
{ TEGRA114_CLK_I2S4_SYNC, TEGRA114_CLK_CLK_MAX, 24000000, 0 },
{ TEGRA114_CLK_VIMCLK_SYNC, TEGRA114_CLK_CLK_MAX, 24000000, 0 },
{ TEGRA114_CLK_PWM, TEGRA114_CLK_PLL_P, 408000000, 0 },
/* must be the last entry */
{ TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 },
};

View File

@ -1330,6 +1330,7 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
{ TEGRA124_CLK_I2S3_SYNC, TEGRA124_CLK_CLK_MAX, 24576000, 0 },
{ TEGRA124_CLK_I2S4_SYNC, TEGRA124_CLK_CLK_MAX, 24576000, 0 },
{ TEGRA124_CLK_VIMCLK_SYNC, TEGRA124_CLK_CLK_MAX, 24576000, 0 },
{ TEGRA124_CLK_PWM, TEGRA124_CLK_PLL_P, 408000000, 0 },
/* must be the last entry */
{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
};

View File

@ -1044,6 +1044,7 @@ static struct tegra_clk_init_table init_table[] = {
{ TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
{ TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
{ TEGRA20_CLK_VDE, TEGRA20_CLK_PLL_C, 300000000, 0 },
{ TEGRA20_CLK_PWM, TEGRA20_CLK_PLL_P, 48000000, 0 },
/* must be the last entry */
{ TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
};

View File

@ -3597,6 +3597,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_VIMCLK_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
{ TEGRA210_CLK_HDA, TEGRA210_CLK_PLL_P, 51000000, 0 },
{ TEGRA210_CLK_HDA2CODEC_2X, TEGRA210_CLK_PLL_P, 48000000, 0 },
{ TEGRA210_CLK_PWM, TEGRA210_CLK_PLL_P, 48000000, 0 },
/* This MUST be the last entry. */
{ TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
};

View File

@ -1237,6 +1237,7 @@ static struct tegra_clk_init_table init_table[] = {
{ TEGRA30_CLK_VIMCLK_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
{ TEGRA30_CLK_HDA, TEGRA30_CLK_PLL_P, 102000000, 0 },
{ TEGRA30_CLK_HDA2CODEC_2X, TEGRA30_CLK_PLL_P, 48000000, 0 },
{ TEGRA30_CLK_PWM, TEGRA30_CLK_PLL_P, 48000000, 0 },
/* must be the last entry */
{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
};

View File

@ -42,6 +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 @@ 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 @@ 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
@ -1303,6 +1315,8 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
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);

View File

@ -799,7 +799,7 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate);
*
* 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);
/**
* clk_set_rate_range - set a rate range for a clock source

View File

@ -12,6 +12,8 @@
#ifndef AT91_PMC_H
#define AT91_PMC_H
#include <linux/bits.h>
#define AT91_PMC_V1 (1) /* PMC version 1 */
#define AT91_PMC_V2 (2) /* PMC version 2 [SAM9X60] */
@ -45,8 +47,8 @@
#define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */
#define AT91_PMC_PLL_ACR 0x18 /* PLL Analog Control Register [for SAM9X60] */
#define AT91_PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL /* Default PLL ACR value for UPLL */
#define AT91_PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL /* Default PLL ACR value for PLLA */
#define AT91_PMC_PLL_ACR_DEFAULT_UPLL UL(0x12020010) /* Default PLL ACR value for UPLL */
#define AT91_PMC_PLL_ACR_DEFAULT_PLLA UL(0x00020010) /* Default PLL ACR value for PLLA */
#define AT91_PMC_PLL_ACR_UTMIVR (1 << 12) /* UPLL Voltage regulator Control */
#define AT91_PMC_PLL_ACR_UTMIBG (1 << 13) /* UPLL Bandgap Control */