diff options
author | Taniya Das <tdas@codeaurora.org> | 2018-04-23 09:29:58 +0530 |
---|---|---|
committer | Taniya Das <tdas@codeaurora.org> | 2018-04-24 12:44:50 +0530 |
commit | 278e58fc5c456fcf92e7ad2ddcb2c3d9010e3d68 (patch) | |
tree | 3b43bdc3962469430fcbe608eef8be917ecacdb1 | |
parent | 9be90e52bccaa2ac185922ff3339508576ace5d6 (diff) |
clk: qcom: Retrieve pre_div from freq_tbl for shared RCG
There could be cases where a simultaneous clk_disable and clk_set_rate on
the same rcg could result in a wrong recalc rate. So for shared rcgs
get the pre_div value based on the current frequency from the frequency
table.
Change-Id: I575855a3a054bb405f54e1ae0d5feba755aada18
Signed-off-by: Taniya Das <tdas@codeaurora.org>
-rw-r--r-- | drivers/clk/qcom/clk-rcg2.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index ff0c8327fabe..3c3cf8e04eea 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2018, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -210,9 +210,11 @@ static unsigned long clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_tbl *f_curr; u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask; - if (rcg->enable_safe_config && !clk_hw_is_prepared(hw)) { + if (rcg->enable_safe_config && (!clk_hw_is_prepared(hw) + || !clk_hw_is_enabled(hw))) { if (!rcg->current_freq) rcg->current_freq = cxo_f.freq; return rcg->current_freq; @@ -232,9 +234,17 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) mode >>= CFG_MODE_SHIFT; } - mask = BIT(rcg->hid_width) - 1; - hid_div = cfg >> CFG_SRC_DIV_SHIFT; - hid_div &= mask; + if (rcg->enable_safe_config) { + f_curr = qcom_find_freq(rcg->freq_tbl, rcg->current_freq); + if (!f_curr) + return -EINVAL; + + hid_div = f_curr->pre_div; + } else { + mask = BIT(rcg->hid_width) - 1; + hid_div = cfg >> CFG_SRC_DIV_SHIFT; + hid_div &= mask; + } return calc_rate(parent_rate, m, n, mode, hid_div); } |