Merge "clk: qcom: Add support for gfx clock to ping pong PLLs"
This commit is contained in:
commit
3ea0533e23
2 changed files with 80 additions and 0 deletions
|
@ -23,6 +23,7 @@ struct freq_tbl {
|
|||
u8 pre_div;
|
||||
u16 m;
|
||||
u16 n;
|
||||
unsigned long src_freq;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -184,5 +185,6 @@ extern const struct clk_ops clk_byte_ops;
|
|||
extern const struct clk_ops clk_byte2_ops;
|
||||
extern const struct clk_ops clk_pixel_ops;
|
||||
extern const struct clk_ops clk_gfx3d_ops;
|
||||
extern const struct clk_ops clk_gfx3d_src_ops;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -865,3 +866,80 @@ const struct clk_ops clk_gfx3d_ops = {
|
|||
.determine_rate = clk_gfx3d_determine_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_gfx3d_ops);
|
||||
|
||||
static int clk_gfx3d_src_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_rate_request parent_req = { };
|
||||
struct clk_hw *p1, *p3, *xo, *curr_p;
|
||||
const struct freq_tbl *f;
|
||||
int ret;
|
||||
|
||||
xo = clk_hw_get_parent_by_index(hw, 0);
|
||||
if (req->rate == clk_hw_get_rate(xo)) {
|
||||
req->best_parent_hw = xo;
|
||||
req->best_parent_rate = req->rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
f = qcom_find_freq(rcg->freq_tbl, req->rate);
|
||||
if (!f || (req->rate != f->freq))
|
||||
return -EINVAL;
|
||||
|
||||
/* Indexes of source from the parent map */
|
||||
p1 = clk_hw_get_parent_by_index(hw, 1);
|
||||
p3 = clk_hw_get_parent_by_index(hw, 2);
|
||||
|
||||
curr_p = clk_hw_get_parent(hw);
|
||||
parent_req.rate = f->src_freq;
|
||||
|
||||
if (curr_p == xo || curr_p == p3)
|
||||
req->best_parent_hw = p1;
|
||||
else if (curr_p == p1)
|
||||
req->best_parent_hw = p3;
|
||||
|
||||
parent_req.best_parent_hw = req->best_parent_hw;
|
||||
|
||||
ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
req->best_parent_rate = parent_req.rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_gfx3d_src_set_rate_and_parent(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate, u8 index)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
const struct freq_tbl *f;
|
||||
u32 cfg;
|
||||
int ret;
|
||||
|
||||
cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
|
||||
|
||||
f = qcom_find_freq(rcg->freq_tbl, rate);
|
||||
if (!f)
|
||||
return -EINVAL;
|
||||
|
||||
/* Update the RCG-DIV */
|
||||
cfg |= f->pre_div << CFG_SRC_DIV_SHIFT;
|
||||
|
||||
ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return update_config(rcg);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_gfx3d_src_ops = {
|
||||
.is_enabled = clk_rcg2_is_enabled,
|
||||
.get_parent = clk_rcg2_get_parent,
|
||||
.set_parent = clk_rcg2_set_parent,
|
||||
.recalc_rate = clk_rcg2_recalc_rate,
|
||||
.set_rate = clk_gfx3d_set_rate,
|
||||
.set_rate_and_parent = clk_gfx3d_src_set_rate_and_parent,
|
||||
.determine_rate = clk_gfx3d_src_determine_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_gfx3d_src_ops);
|
||||
|
|
Loading…
Add table
Reference in a new issue