summaryrefslogtreecommitdiff
path: root/drivers/clk/qcom/clk-rcg.c
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2014-07-11 23:55:27 +0400
committerStephen Boyd <sboyd@codeaurora.org>2014-07-16 03:38:59 +0400
commit404c1ff67d241e8503fd46a09d324343aa321a8a (patch)
treeef9e18a1029de024540d02550d1a99d162d164a1 /drivers/clk/qcom/clk-rcg.c
parent24d8fba44af32163334c1f162e65ba93eb2993fd (diff)
downloadlinux-404c1ff67d241e8503fd46a09d324343aa321a8a.tar.xz
clk: qcom: Support bypass RCG configuration
In the case of HDMI clocks, we want to bypass the RCG's ability to divide the output clock and pass through the parent HDMI PLL rate. Add a simple set of clk_ops to configure the RCG to do this. This removes the need to keep adding more frequency entries to the tv_src clock whenever we want to support a new rate. Tested-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Diffstat (limited to 'drivers/clk/qcom/clk-rcg.c')
-rw-r--r--drivers/clk/qcom/clk-rcg.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index abfc2b675aea..b638c5846dbf 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -417,20 +417,25 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
}
-static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *p_rate, struct clk **p)
{
struct clk_rcg *rcg = to_clk_rcg(hw);
- const struct freq_tbl *f;
+ const struct freq_tbl *f = rcg->freq_tbl;
+
+ *p = clk_get_parent_by_index(hw->clk, f->src);
+ *p_rate = __clk_round_rate(*p, rate);
+
+ return *p_rate;
+}
+
+static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
+{
u32 ns, md, ctl;
struct mn *mn = &rcg->mn;
u32 mask = 0;
unsigned int reset_reg;
- f = find_freq(rcg->freq_tbl, rate);
- if (!f)
- return -EINVAL;
-
if (rcg->mn.reset_in_cc)
reset_reg = rcg->clkr.enable_reg;
else
@@ -466,6 +471,27 @@ static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+ const struct freq_tbl *f;
+
+ f = find_freq(rcg->freq_tbl, rate);
+ if (!f)
+ return -EINVAL;
+
+ return __clk_rcg_set_rate(rcg, f);
+}
+
+static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_rcg *rcg = to_clk_rcg(hw);
+
+ return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
+}
+
static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
{
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
@@ -503,6 +529,17 @@ const struct clk_ops clk_rcg_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg_ops);
+const struct clk_ops clk_rcg_bypass_ops = {
+ .enable = clk_enable_regmap,
+ .disable = clk_disable_regmap,
+ .get_parent = clk_rcg_get_parent,
+ .set_parent = clk_rcg_set_parent,
+ .recalc_rate = clk_rcg_recalc_rate,
+ .determine_rate = clk_rcg_bypass_determine_rate,
+ .set_rate = clk_rcg_bypass_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
+
const struct clk_ops clk_dyn_rcg_ops = {
.enable = clk_enable_regmap,
.is_enabled = clk_is_enabled_regmap,