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

Commit d4f76de3 authored by Georgi Djakov's avatar Georgi Djakov Committed by Stephen Boyd
Browse files

clk: qcom: Add support for SR2 PLLs



Add support for SR2 type pll operations. SR2 is optimized for Time Interval
Error (TIE) or absolute jitter.

Signed-off-by: default avatarGeorgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
parent a8a8db47
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -292,3 +292,78 @@ void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
		clk_pll_set_fsm_mode(pll, regmap, 0);
}
EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);

static int clk_pll_sr2_enable(struct clk_hw *hw)
{
	struct clk_pll *pll = to_clk_pll(hw);
	int ret;
	u32 mode;

	ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
	if (ret)
		return ret;

	/* Disable PLL bypass mode. */
	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
				 PLL_BYPASSNL);
	if (ret)
		return ret;

	/*
	 * H/W requires a 5us delay between disabling the bypass and
	 * de-asserting the reset. Delay 10us just to be safe.
	 */
	udelay(10);

	/* De-assert active-low PLL reset. */
	ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
				 PLL_RESET_N);
	if (ret)
		return ret;

	ret = wait_for_pll(pll);
	if (ret)
		return ret;

	/* Enable PLL output. */
	return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
				 PLL_OUTCTRL);
}

static int
clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
{
	struct clk_pll *pll = to_clk_pll(hw);
	const struct pll_freq_tbl *f;
	bool enabled;
	u32 mode;
	u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;

	f = find_freq(pll->freq_tbl, rate);
	if (!f)
		return -EINVAL;

	regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
	enabled = (mode & enable_mask) == enable_mask;

	if (enabled)
		clk_pll_disable(hw);

	regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
	regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
	regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);

	if (enabled)
		clk_pll_sr2_enable(hw);

	return 0;
}

const struct clk_ops clk_pll_sr2_ops = {
	.enable = clk_pll_sr2_enable,
	.disable = clk_pll_disable,
	.set_rate = clk_pll_sr2_set_rate,
	.recalc_rate = clk_pll_recalc_rate,
	.determine_rate = clk_pll_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct clk_pll {

extern const struct clk_ops clk_pll_ops;
extern const struct clk_ops clk_pll_vote_ops;
extern const struct clk_ops clk_pll_sr2_ops;

#define to_clk_pll(_hw) container_of(to_clk_regmap(_hw), struct clk_pll, clkr)