1
0
Fork 0

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>
hifive-unleashed-5.1
Stephen Boyd 2014-07-11 12:55:27 -07:00
parent 24d8fba44a
commit 404c1ff67d
3 changed files with 47 additions and 14 deletions

View File

@ -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,

View File

@ -95,6 +95,7 @@ struct clk_rcg {
};
extern const struct clk_ops clk_rcg_ops;
extern const struct clk_ops clk_rcg_bypass_ops;
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)

View File

@ -1218,12 +1218,7 @@ static const char *mmcc_pxo_hdmi[] = {
};
static struct freq_tbl clk_tbl_tv[] = {
{ 25200000, P_HDMI_PLL, 1, 0, 0 },
{ 27000000, P_HDMI_PLL, 1, 0, 0 },
{ 27030000, P_HDMI_PLL, 1, 0, 0 },
{ 74250000, P_HDMI_PLL, 1, 0, 0 },
{ 108000000, P_HDMI_PLL, 1, 0, 0 },
{ 148500000, P_HDMI_PLL, 1, 0, 0 },
{ .src = P_HDMI_PLL, .pre_div = 1 },
{ }
};
@ -1254,7 +1249,7 @@ static struct clk_rcg tv_src = {
.name = "tv_src",
.parent_names = mmcc_pxo_hdmi,
.num_parents = 2,
.ops = &clk_rcg_ops,
.ops = &clk_rcg_bypass_ops,
.flags = CLK_SET_RATE_PARENT,
},
},