Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8ee91fb authored by Taniya Das's avatar Taniya Das Committed by Gerrit - the friendly Code Review server
Browse files

clk: qcom: Add clk_ops to support runtime frequencies for esc clock



Some of the display panels requires multiple clock frequencies
to be derived runtime from the sources for its operation.
Add support for the same by adding esc clk_ops to calculate
the desired frequency at run time.

Change-Id: Ie3ec84bb1927f5313c887344368dceffb06035be
Signed-off-by: default avatarTaniya Das <tdas@codeaurora.org>
parent 37e541f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_dp_ops;
extern const struct clk_ops clk_rcg2_dependent_ops;
extern const struct clk_ops clk_gfx3d_src_ops;
extern const struct clk_ops clk_esc_ops;

struct clk_rcg_dfs_data {
	struct clk_rcg2 *rcg;
+70 −0
Original line number Diff line number Diff line
@@ -1794,3 +1794,73 @@ const struct clk_ops clk_rcg2_dependent_ops = {
	.bus_vote = clk_debug_bus_vote,
};
EXPORT_SYMBOL(clk_rcg2_dependent_ops);

static int clk_esc_determine_rate(struct clk_hw *hw,
	struct clk_rate_request *req)
{
	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
	unsigned long parent_rate, div;
	u32 mask = BIT(rcg->hid_width) - 1;
	struct clk_hw *p;
	unsigned long rate = req->rate;

	if (rate == 0)
		return -EINVAL;

	p = req->best_parent_hw;
	req->best_parent_rate = parent_rate = clk_hw_round_rate(p, rate);

	div = ((2 * parent_rate) / rate) - 1;
	div = min_t(u32, div, mask);

	req->rate = calc_rate(parent_rate, 0, 0, 0, div);

	return 0;
}

static int clk_esc_set_rate(struct clk_hw *hw, unsigned long rate,
	unsigned long parent_rate)
{
	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
	struct freq_tbl f = { 0 };
	unsigned long div;
	int i, num_parents = clk_hw_get_num_parents(hw);
	u32 mask = BIT(rcg->hid_width) - 1;
	u32 cfg;

	div = ((2 * parent_rate) / rate) - 1;
	div = min_t(u32, div, mask);

	f.pre_div = div;

	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
	cfg &= CFG_SRC_SEL_MASK;
	cfg >>= CFG_SRC_SEL_SHIFT;

	for (i = 0; i < num_parents; i++) {
		if (cfg == rcg->parent_map[i].cfg) {
			f.src = rcg->parent_map[i].src;
				return clk_rcg2_configure(rcg, &f);
		}
	}

	return -EINVAL;
}

static int clk_esc_set_rate_and_parent(struct clk_hw *hw,
		unsigned long rate, unsigned long parent_rate, u8 index)
{
	return clk_esc_set_rate(hw, rate, parent_rate);
}

const struct clk_ops clk_esc_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,
	.determine_rate = clk_esc_determine_rate,
	.set_rate = clk_esc_set_rate,
	.set_rate_and_parent = clk_esc_set_rate_and_parent,
	.list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL(clk_esc_ops);