Commit a7b78bef authored by Stephen Boyd's avatar Stephen Boyd

Merge branch 'clk-rate-range' into clk-next

 - 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
  ...
parents c461c677 b05ea331
...@@ -136,7 +136,6 @@ static int clk_generated_determine_rate(struct clk_hw *hw, ...@@ -136,7 +136,6 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
{ {
struct clk_generated *gck = to_clk_generated(hw); struct clk_generated *gck = to_clk_generated(hw);
struct clk_hw *parent = NULL; struct clk_hw *parent = NULL;
struct clk_rate_request req_parent = *req;
long best_rate = -EINVAL; long best_rate = -EINVAL;
unsigned long min_rate, parent_rate; unsigned long min_rate, parent_rate;
int best_diff = -1; int best_diff = -1;
...@@ -192,7 +191,9 @@ static int clk_generated_determine_rate(struct clk_hw *hw, ...@@ -192,7 +191,9 @@ static int clk_generated_determine_rate(struct clk_hw *hw,
goto end; goto end;
for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { 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)) if (__clk_determine_rate(parent, &req_parent))
continue; continue;
clk_generated_best_diff(req, parent, req_parent.rate, div, clk_generated_best_diff(req, parent, req_parent.rate, div,
......
...@@ -581,7 +581,6 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw, ...@@ -581,7 +581,6 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req) struct clk_rate_request *req)
{ {
struct clk_master *master = to_clk_master(hw); struct clk_master *master = to_clk_master(hw);
struct clk_rate_request req_parent = *req;
struct clk_hw *parent; struct clk_hw *parent;
long best_rate = LONG_MIN, best_diff = LONG_MIN; long best_rate = LONG_MIN, best_diff = LONG_MIN;
unsigned long parent_rate; unsigned long parent_rate;
...@@ -618,11 +617,15 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw, ...@@ -618,11 +617,15 @@ static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
goto end; goto end;
for (div = 0; div < MASTER_PRES_MAX + 1; div++) { for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
struct clk_rate_request req_parent;
unsigned long req_rate;
if (div == MASTER_PRES_MAX) if (div == MASTER_PRES_MAX)
req_parent.rate = req->rate * 3; req_rate = req->rate * 3;
else else
req_parent.rate = req->rate << div; req_rate = req->rate << div;
clk_hw_forward_rate_request(hw, req, parent, &req_parent, req_rate);
if (__clk_determine_rate(parent, &req_parent)) if (__clk_determine_rate(parent, &req_parent))
continue; continue;
......
...@@ -269,7 +269,6 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw, ...@@ -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_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
struct clk_hw *parent = clk_hw_get_parent(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 parent_rate = clk_hw_get_rate(parent);
unsigned long tmp_rate; unsigned long tmp_rate;
long best_rate = LONG_MIN; long best_rate = LONG_MIN;
...@@ -302,8 +301,9 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw, ...@@ -302,8 +301,9 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
goto end; goto end;
for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) { 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)) if (__clk_determine_rate(parent, &req_parent))
continue; continue;
......
...@@ -85,10 +85,11 @@ static int clk_composite_determine_rate(struct clk_hw *hw, ...@@ -85,10 +85,11 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
req->best_parent_hw = NULL; req->best_parent_hw = NULL;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { 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); 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, ret = clk_composite_determine_rate_for_parent(rate_hw,
&tmp_req, &tmp_req,
parent, parent,
...@@ -104,12 +105,13 @@ static int clk_composite_determine_rate(struct clk_hw *hw, ...@@ -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++) { 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); parent = clk_hw_get_parent_by_index(mux_hw, i);
if (!parent) if (!parent)
continue; continue;
clk_hw_forward_rate_request(hw, req, parent, &tmp_req, req->rate);
ret = clk_composite_determine_rate_for_parent(rate_hw, ret = clk_composite_determine_rate_for_parent(rate_hw,
&tmp_req, &tmp_req,
parent, parent,
......
...@@ -386,13 +386,13 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, ...@@ -386,13 +386,13 @@ long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
const struct clk_div_table *table, const struct clk_div_table *table,
u8 width, unsigned long flags) u8 width, unsigned long flags)
{ {
struct clk_rate_request req = { struct clk_rate_request req;
.rate = rate,
.best_parent_rate = *prate,
.best_parent_hw = parent,
};
int ret; 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); ret = divider_determine_rate(hw, &req, table, width, flags);
if (ret) if (ret)
return ret; return ret;
...@@ -408,13 +408,13 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, ...@@ -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, const struct clk_div_table *table, u8 width,
unsigned long flags, unsigned int val) unsigned long flags, unsigned int val)
{ {
struct clk_rate_request req = { struct clk_rate_request req;
.rate = rate,
.best_parent_rate = *prate,
.best_parent_hw = parent,
};
int ret; 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); ret = divider_ro_determine_rate(hw, &req, table, width, flags, val);
if (ret) if (ret)
return ret; return ret;
......
This diff is collapsed.
This diff is collapsed.
...@@ -129,9 +129,18 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index) ...@@ -129,9 +129,18 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
return 0; 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 = { const struct clk_ops mtk_mux_clr_set_upd_ops = {
.get_parent = mtk_clk_mux_get_parent, .get_parent = mtk_clk_mux_get_parent,
.set_parent = mtk_clk_mux_set_parent_setclr_lock, .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); EXPORT_SYMBOL_GPL(mtk_mux_clr_set_upd_ops);
...@@ -141,6 +150,7 @@ const struct clk_ops mtk_mux_gate_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, .is_enabled = mtk_clk_mux_is_enabled,
.get_parent = mtk_clk_mux_get_parent, .get_parent = mtk_clk_mux_get_parent,
.set_parent = mtk_clk_mux_set_parent_setclr_lock, .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); EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops);
......
...@@ -915,6 +915,15 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw, ...@@ -915,6 +915,15 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw,
req->best_parent_hw = p2; 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); ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
if (ret) if (ret)
return ret; return ret;
......
...@@ -42,6 +42,8 @@ struct dentry; ...@@ -42,6 +42,8 @@ struct dentry;
* struct clk_rate_request - Structure encoding the clk constraints that * struct clk_rate_request - Structure encoding the clk constraints that
* a clock user might require. * 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 * @rate: Requested clock rate. This field will be adjusted by
* clock drivers according to hardware capabilities. * clock drivers according to hardware capabilities.
* @min_rate: Minimum rate imposed by clk users. * @min_rate: Minimum rate imposed by clk users.
...@@ -60,6 +62,15 @@ struct clk_rate_request { ...@@ -60,6 +62,15 @@ struct clk_rate_request {
struct clk_hw *best_parent_hw; 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 * struct clk_duty - Struture encoding the duty cycle ratio of a clock
* *
...@@ -118,8 +129,9 @@ struct clk_duty { ...@@ -118,8 +129,9 @@ struct clk_duty {
* *
* @recalc_rate Recalculate the rate of this clock, by querying hardware. The * @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 * parent rate is an input parameter. It is up to the caller to
* ensure that the prepare_mutex is held across this call. * ensure that the prepare_mutex is held across this call. If the
* Returns the calculated rate. Optional, but recommended - if * 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. * 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 * @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, ...@@ -1303,6 +1315,8 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
struct clk_rate_request *req, struct clk_rate_request *req,
unsigned long flags); unsigned long flags);
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent); 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, void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
unsigned long max_rate); unsigned long max_rate);
......
...@@ -799,7 +799,7 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate); ...@@ -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. * 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 * clk_set_rate_range - set a rate range for a clock source
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment