diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index d3eb87a12fb5..fc976ef6a893 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -15,6 +15,8 @@ struct freq_tbl { u8 pre_div; u16 m; u16 n; + unsigned long src_freq; +#define FIXED_FREQ_SRC 0 }; /** diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 7530ab056aa6..06ee52fe5acf 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -279,9 +279,10 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, enum freq_policy policy) { unsigned long clk_flags, rate = req->rate; + struct clk_rate_request parent_req = { }; struct clk_hw *p; struct clk_rcg2 *rcg = to_clk_rcg2(hw); - int index; + int index, ret = 0; switch (policy) { case FLOOR: @@ -328,6 +329,21 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, req->best_parent_rate = rate; req->rate = f->freq; + if (f->src_freq != FIXED_FREQ_SRC) { + rate = parent_req.rate = f->src_freq; + parent_req.best_parent_hw = p; + ret = __clk_determine_rate(p, &parent_req); + if (ret) + return ret; + + ret = clk_set_rate(p->clk, parent_req.rate); + if (ret) { + pr_err("Failed set rate(%lu) on parent for non-fixed source\n", + parent_req.rate); + return ret; + } + } + return 0; }