Merge "clk: qcom: Add support for gfx clock to ping pong PLLs"

This commit is contained in:
Linux Build Service Account 2016-10-06 01:07:14 -07:00 committed by Gerrit - the friendly Code Review server
commit 3ea0533e23
2 changed files with 80 additions and 0 deletions

View file

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

View file

@ -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);