From 51ca8f68495d48d79755225d2eba9a9963c039e7 Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 27 Mar 2019 15:46:41 -0700 Subject: [PATCH 1/2] clk: qcom: add null pointer checks for parent clocks Add null pointer checks for the parent clock pointers returned by clk_hw_get_parent() and clk_hw_get_parent_by_index() in several qcom clock drivers. Change-Id: I869c9e35b7ec083b34bcc70d18601aec64c3ac97 Signed-off-by: David Collins --- drivers/clk/qcom/clk-alpha-pll.c | 10 ++++++++-- drivers/clk/qcom/clk-rcg.c | 6 +++++- drivers/clk/qcom/clk-rcg2.c | 11 +++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 6b7fc49be25b..dd8893b070d8 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1112,6 +1112,7 @@ clk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); + struct clk_hw *parent_hw; u32 ctl, div; regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); @@ -1120,8 +1121,13 @@ clk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate, ctl &= BIT(pll->width) - 1; div = 1 << fls(ctl); - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) - *prate = clk_hw_round_rate(clk_hw_get_parent(hw), div * rate); + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + parent_hw = clk_hw_get_parent(hw); + if (!parent_hw) + return -EINVAL; + + *prate = clk_hw_round_rate(parent_hw, div * rate); + } return DIV_ROUND_UP_ULL((u64)*prate, div); } diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c index a9d181d6be21..782380a7452d 100644 --- a/drivers/clk/qcom/clk-rcg.c +++ b/drivers/clk/qcom/clk-rcg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2019, The Linux Foundation. All rights reserved. */ #include @@ -414,6 +414,8 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, clk_flags = clk_hw_get_flags(hw); p = clk_hw_get_parent_by_index(hw, index); + if (!p) + return -EINVAL; if (clk_flags & CLK_SET_RATE_PARENT) { rate = rate * f->pre_div; if (f->n) { @@ -465,6 +467,8 @@ static int clk_rcg_bypass_determine_rate(struct clk_hw *hw, int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src); req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index); + if (!p) + return -EINVAL; req->best_parent_rate = clk_hw_round_rate(p, req->rate); req->rate = req->best_parent_rate; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 5d65e32c4a8c..f6b97489e80a 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -692,6 +692,8 @@ static int clk_edp_pixel_determine_rate(struct clk_hw *hw, /* Force the correct parent */ req->best_parent_hw = clk_hw_get_parent_by_index(hw, index); + if (!req->best_parent_hw) + return -EINVAL; req->best_parent_rate = clk_hw_get_rate(req->best_parent_hw); if (req->best_parent_rate == 810000000) @@ -746,6 +748,8 @@ static int clk_byte_determine_rate(struct clk_hw *hw, return -EINVAL; req->best_parent_hw = p = clk_hw_get_parent_by_index(hw, index); + if (!p) + return -EINVAL; req->best_parent_rate = parent_rate = clk_hw_round_rate(p, req->rate); div = DIV_ROUND_UP((2 * parent_rate), req->rate) - 1; @@ -1041,6 +1045,8 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw, int ret; xo = clk_hw_get_parent_by_index(hw, 0); + if (!xo) + return -EINVAL; if (req->rate == clk_hw_get_rate(xo)) { req->best_parent_hw = xo; return 0; @@ -1049,6 +1055,8 @@ static int clk_gfx3d_determine_rate(struct clk_hw *hw, p9 = clk_hw_get_parent_by_index(hw, 2); p2 = clk_hw_get_parent_by_index(hw, 3); p8 = clk_hw_get_parent_by_index(hw, 4); + if (!p9 || !p2 || !p8) + return -EINVAL; /* PLL9 is a fixed rate PLL */ p9_rate = clk_hw_get_rate(p9); @@ -1444,6 +1452,9 @@ static int clk_rcg2_dependent_set_parent(struct clk_hw *hw, u8 index) return ret; p_hw = clk_hw_get_parent_by_index(rcg->clkr.dependent_hw, index); + if (!p_hw) + return -EINVAL; + return clk_set_parent(rcg->clkr.dependent_hw->clk, p_hw->clk); } From 90ded952e1d3a81814773adc03193b960caaff56 Mon Sep 17 00:00:00 2001 From: Shefali Jain Date: Tue, 11 Sep 2018 10:26:35 +0530 Subject: [PATCH 2/2] clk: qcom: rcg2: Add DIV_ROUND_CLOSEST_ULL to roundoff RCG frequency The Alpha BW for Fabia PLL is 16 bit and the calculated hw rate has additional KHz of frequency. Due to this additional frequency, the source is wrongly selected. Truncate the additional KHz using the DIV_ROUND_CLOSEST_ULL. Change-Id: Ic9c523c87277c4813b676cf8a52a1207e8f1ecc2 Signed-off-by: Shefali Jain --- drivers/clk/qcom/clk-rcg2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index f6b97489e80a..d96dd1884b9c 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -440,7 +440,8 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, } if (rcg->flags & FORCE_ENABLE_RCG) { - rcg->current_freq = clk_get_rate(hw->clk); + rcg->current_freq = DIV_ROUND_CLOSEST_ULL( + clk_get_rate(hw->clk), 1000) * 1000; if (rcg->current_freq == cxo_f.freq) curr_src_index = 0; else {