162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/clk.h>
462306a36Sopenharmony_ci#include <linux/clk-provider.h>
562306a36Sopenharmony_ci#include <linux/delay.h>
662306a36Sopenharmony_ci#include <linux/err.h>
762306a36Sopenharmony_ci#include <linux/io.h>
862306a36Sopenharmony_ci#include <linux/math64.h>
962306a36Sopenharmony_ci#include <linux/of.h>
1062306a36Sopenharmony_ci#include <linux/of_address.h>
1162306a36Sopenharmony_ci#include <linux/clk/ti.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "clock.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* FAPLL Control Register PLL_CTRL */
1662306a36Sopenharmony_ci#define FAPLL_MAIN_MULT_N_SHIFT	16
1762306a36Sopenharmony_ci#define FAPLL_MAIN_DIV_P_SHIFT	8
1862306a36Sopenharmony_ci#define FAPLL_MAIN_LOCK		BIT(7)
1962306a36Sopenharmony_ci#define FAPLL_MAIN_PLLEN	BIT(3)
2062306a36Sopenharmony_ci#define FAPLL_MAIN_BP		BIT(2)
2162306a36Sopenharmony_ci#define FAPLL_MAIN_LOC_CTL	BIT(0)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define FAPLL_MAIN_MAX_MULT_N	0xffff
2462306a36Sopenharmony_ci#define FAPLL_MAIN_MAX_DIV_P	0xff
2562306a36Sopenharmony_ci#define FAPLL_MAIN_CLEAR_MASK	\
2662306a36Sopenharmony_ci	((FAPLL_MAIN_MAX_MULT_N << FAPLL_MAIN_MULT_N_SHIFT) | \
2762306a36Sopenharmony_ci	 (FAPLL_MAIN_DIV_P_SHIFT << FAPLL_MAIN_DIV_P_SHIFT) | \
2862306a36Sopenharmony_ci	 FAPLL_MAIN_LOC_CTL)
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* FAPLL powerdown register PWD */
3162306a36Sopenharmony_ci#define FAPLL_PWD_OFFSET	4
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define MAX_FAPLL_OUTPUTS	7
3462306a36Sopenharmony_ci#define FAPLL_MAX_RETRIES	1000
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define to_fapll(_hw)		container_of(_hw, struct fapll_data, hw)
3762306a36Sopenharmony_ci#define to_synth(_hw)		container_of(_hw, struct fapll_synth, hw)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* The bypass bit is inverted on the ddr_pll.. */
4062306a36Sopenharmony_ci#define fapll_is_ddr_pll(va)	(((u32)(va) & 0xffff) == 0x0440)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/*
4362306a36Sopenharmony_ci * The audio_pll_clk1 input is hard wired to the 27MHz bypass clock,
4462306a36Sopenharmony_ci * and the audio_pll_clk1 synthesizer is hardwared to 32KiHz output.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_ci#define is_ddr_pll_clk1(va)	(((u32)(va) & 0xffff) == 0x044c)
4762306a36Sopenharmony_ci#define is_audio_pll_clk1(va)	(((u32)(va) & 0xffff) == 0x04a8)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Synthesizer divider register */
5062306a36Sopenharmony_ci#define SYNTH_LDMDIV1		BIT(8)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* Synthesizer frequency register */
5362306a36Sopenharmony_ci#define SYNTH_LDFREQ		BIT(31)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define SYNTH_PHASE_K		8
5662306a36Sopenharmony_ci#define SYNTH_MAX_INT_DIV	0xf
5762306a36Sopenharmony_ci#define SYNTH_MAX_DIV_M		0xff
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct fapll_data {
6062306a36Sopenharmony_ci	struct clk_hw hw;
6162306a36Sopenharmony_ci	void __iomem *base;
6262306a36Sopenharmony_ci	const char *name;
6362306a36Sopenharmony_ci	struct clk *clk_ref;
6462306a36Sopenharmony_ci	struct clk *clk_bypass;
6562306a36Sopenharmony_ci	struct clk_onecell_data outputs;
6662306a36Sopenharmony_ci	bool bypass_bit_inverted;
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistruct fapll_synth {
7062306a36Sopenharmony_ci	struct clk_hw hw;
7162306a36Sopenharmony_ci	struct fapll_data *fd;
7262306a36Sopenharmony_ci	int index;
7362306a36Sopenharmony_ci	void __iomem *freq;
7462306a36Sopenharmony_ci	void __iomem *div;
7562306a36Sopenharmony_ci	const char *name;
7662306a36Sopenharmony_ci	struct clk *clk_pll;
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic bool ti_fapll_clock_is_bypass(struct fapll_data *fd)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (fd->bypass_bit_inverted)
8462306a36Sopenharmony_ci		return !(v & FAPLL_MAIN_BP);
8562306a36Sopenharmony_ci	else
8662306a36Sopenharmony_ci		return !!(v & FAPLL_MAIN_BP);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic void ti_fapll_set_bypass(struct fapll_data *fd)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	if (fd->bypass_bit_inverted)
9462306a36Sopenharmony_ci		v &= ~FAPLL_MAIN_BP;
9562306a36Sopenharmony_ci	else
9662306a36Sopenharmony_ci		v |= FAPLL_MAIN_BP;
9762306a36Sopenharmony_ci	writel_relaxed(v, fd->base);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic void ti_fapll_clear_bypass(struct fapll_data *fd)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (fd->bypass_bit_inverted)
10562306a36Sopenharmony_ci		v |= FAPLL_MAIN_BP;
10662306a36Sopenharmony_ci	else
10762306a36Sopenharmony_ci		v &= ~FAPLL_MAIN_BP;
10862306a36Sopenharmony_ci	writel_relaxed(v, fd->base);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic int ti_fapll_wait_lock(struct fapll_data *fd)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	int retries = FAPLL_MAX_RETRIES;
11462306a36Sopenharmony_ci	u32 v;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	while ((v = readl_relaxed(fd->base))) {
11762306a36Sopenharmony_ci		if (v & FAPLL_MAIN_LOCK)
11862306a36Sopenharmony_ci			return 0;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		if (retries-- <= 0)
12162306a36Sopenharmony_ci			break;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		udelay(1);
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	pr_err("%s failed to lock\n", fd->name);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	return -ETIMEDOUT;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic int ti_fapll_enable(struct clk_hw *hw)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
13462306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	v |= FAPLL_MAIN_PLLEN;
13762306a36Sopenharmony_ci	writel_relaxed(v, fd->base);
13862306a36Sopenharmony_ci	ti_fapll_wait_lock(fd);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	return 0;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic void ti_fapll_disable(struct clk_hw *hw)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
14662306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	v &= ~FAPLL_MAIN_PLLEN;
14962306a36Sopenharmony_ci	writel_relaxed(v, fd->base);
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic int ti_fapll_is_enabled(struct clk_hw *hw)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
15562306a36Sopenharmony_ci	u32 v = readl_relaxed(fd->base);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return v & FAPLL_MAIN_PLLEN;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic unsigned long ti_fapll_recalc_rate(struct clk_hw *hw,
16162306a36Sopenharmony_ci					  unsigned long parent_rate)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
16462306a36Sopenharmony_ci	u32 fapll_n, fapll_p, v;
16562306a36Sopenharmony_ci	u64 rate;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	if (ti_fapll_clock_is_bypass(fd))
16862306a36Sopenharmony_ci		return parent_rate;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	rate = parent_rate;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	/* PLL pre-divider is P and multiplier is N */
17362306a36Sopenharmony_ci	v = readl_relaxed(fd->base);
17462306a36Sopenharmony_ci	fapll_p = (v >> 8) & 0xff;
17562306a36Sopenharmony_ci	if (fapll_p)
17662306a36Sopenharmony_ci		do_div(rate, fapll_p);
17762306a36Sopenharmony_ci	fapll_n = v >> 16;
17862306a36Sopenharmony_ci	if (fapll_n)
17962306a36Sopenharmony_ci		rate *= fapll_n;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	return rate;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic u8 ti_fapll_get_parent(struct clk_hw *hw)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	if (ti_fapll_clock_is_bypass(fd))
18962306a36Sopenharmony_ci		return 1;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	return 0;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic int ti_fapll_set_div_mult(unsigned long rate,
19562306a36Sopenharmony_ci				 unsigned long parent_rate,
19662306a36Sopenharmony_ci				 u32 *pre_div_p, u32 *mult_n)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	/*
19962306a36Sopenharmony_ci	 * So far no luck getting decent clock with PLL divider,
20062306a36Sopenharmony_ci	 * PLL does not seem to lock and the signal does not look
20162306a36Sopenharmony_ci	 * right. It seems the divider can only be used together
20262306a36Sopenharmony_ci	 * with the multiplier?
20362306a36Sopenharmony_ci	 */
20462306a36Sopenharmony_ci	if (rate < parent_rate) {
20562306a36Sopenharmony_ci		pr_warn("FAPLL main divider rates unsupported\n");
20662306a36Sopenharmony_ci		return -EINVAL;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	*mult_n = rate / parent_rate;
21062306a36Sopenharmony_ci	if (*mult_n > FAPLL_MAIN_MAX_MULT_N)
21162306a36Sopenharmony_ci		return -EINVAL;
21262306a36Sopenharmony_ci	*pre_div_p = 1;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return 0;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate,
21862306a36Sopenharmony_ci				unsigned long *parent_rate)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	u32 pre_div_p, mult_n;
22162306a36Sopenharmony_ci	int error;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	if (!rate)
22462306a36Sopenharmony_ci		return -EINVAL;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	error = ti_fapll_set_div_mult(rate, *parent_rate,
22762306a36Sopenharmony_ci				      &pre_div_p, &mult_n);
22862306a36Sopenharmony_ci	if (error)
22962306a36Sopenharmony_ci		return error;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	rate = *parent_rate / pre_div_p;
23262306a36Sopenharmony_ci	rate *= mult_n;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	return rate;
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate,
23862306a36Sopenharmony_ci			     unsigned long parent_rate)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct fapll_data *fd = to_fapll(hw);
24162306a36Sopenharmony_ci	u32 pre_div_p, mult_n, v;
24262306a36Sopenharmony_ci	int error;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (!rate)
24562306a36Sopenharmony_ci		return -EINVAL;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	error = ti_fapll_set_div_mult(rate, parent_rate,
24862306a36Sopenharmony_ci				      &pre_div_p, &mult_n);
24962306a36Sopenharmony_ci	if (error)
25062306a36Sopenharmony_ci		return error;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	ti_fapll_set_bypass(fd);
25362306a36Sopenharmony_ci	v = readl_relaxed(fd->base);
25462306a36Sopenharmony_ci	v &= ~FAPLL_MAIN_CLEAR_MASK;
25562306a36Sopenharmony_ci	v |= pre_div_p << FAPLL_MAIN_DIV_P_SHIFT;
25662306a36Sopenharmony_ci	v |= mult_n << FAPLL_MAIN_MULT_N_SHIFT;
25762306a36Sopenharmony_ci	writel_relaxed(v, fd->base);
25862306a36Sopenharmony_ci	if (ti_fapll_is_enabled(hw))
25962306a36Sopenharmony_ci		ti_fapll_wait_lock(fd);
26062306a36Sopenharmony_ci	ti_fapll_clear_bypass(fd);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic const struct clk_ops ti_fapll_ops = {
26662306a36Sopenharmony_ci	.enable = ti_fapll_enable,
26762306a36Sopenharmony_ci	.disable = ti_fapll_disable,
26862306a36Sopenharmony_ci	.is_enabled = ti_fapll_is_enabled,
26962306a36Sopenharmony_ci	.recalc_rate = ti_fapll_recalc_rate,
27062306a36Sopenharmony_ci	.get_parent = ti_fapll_get_parent,
27162306a36Sopenharmony_ci	.round_rate = ti_fapll_round_rate,
27262306a36Sopenharmony_ci	.set_rate = ti_fapll_set_rate,
27362306a36Sopenharmony_ci};
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int ti_fapll_synth_enable(struct clk_hw *hw)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
27862306a36Sopenharmony_ci	u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	v &= ~(1 << synth->index);
28162306a36Sopenharmony_ci	writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	return 0;
28462306a36Sopenharmony_ci}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic void ti_fapll_synth_disable(struct clk_hw *hw)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
28962306a36Sopenharmony_ci	u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	v |= 1 << synth->index;
29262306a36Sopenharmony_ci	writel_relaxed(v, synth->fd->base + FAPLL_PWD_OFFSET);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic int ti_fapll_synth_is_enabled(struct clk_hw *hw)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
29862306a36Sopenharmony_ci	u32 v = readl_relaxed(synth->fd->base + FAPLL_PWD_OFFSET);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	return !(v & (1 << synth->index));
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/*
30462306a36Sopenharmony_ci * See dm816x TRM chapter 1.10.3 Flying Adder PLL fore more info
30562306a36Sopenharmony_ci */
30662306a36Sopenharmony_cistatic unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
30762306a36Sopenharmony_ci						unsigned long parent_rate)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
31062306a36Sopenharmony_ci	u32 synth_div_m;
31162306a36Sopenharmony_ci	u64 rate;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */
31462306a36Sopenharmony_ci	if (!synth->div)
31562306a36Sopenharmony_ci		return 32768;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	/*
31862306a36Sopenharmony_ci	 * PLL in bypass sets the synths in bypass mode too. The PLL rate
31962306a36Sopenharmony_ci	 * can be also be set to 27MHz, so we can't use parent_rate to
32062306a36Sopenharmony_ci	 * check for bypass mode.
32162306a36Sopenharmony_ci	 */
32262306a36Sopenharmony_ci	if (ti_fapll_clock_is_bypass(synth->fd))
32362306a36Sopenharmony_ci		return parent_rate;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	rate = parent_rate;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/*
32862306a36Sopenharmony_ci	 * Synth frequency integer and fractional divider.
32962306a36Sopenharmony_ci	 * Note that the phase output K is 8, so the result needs
33062306a36Sopenharmony_ci	 * to be multiplied by SYNTH_PHASE_K.
33162306a36Sopenharmony_ci	 */
33262306a36Sopenharmony_ci	if (synth->freq) {
33362306a36Sopenharmony_ci		u32 v, synth_int_div, synth_frac_div, synth_div_freq;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		v = readl_relaxed(synth->freq);
33662306a36Sopenharmony_ci		synth_int_div = (v >> 24) & 0xf;
33762306a36Sopenharmony_ci		synth_frac_div = v & 0xffffff;
33862306a36Sopenharmony_ci		synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
33962306a36Sopenharmony_ci		rate *= 10000000;
34062306a36Sopenharmony_ci		do_div(rate, synth_div_freq);
34162306a36Sopenharmony_ci		rate *= SYNTH_PHASE_K;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	/* Synth post-divider M */
34562306a36Sopenharmony_ci	synth_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	return DIV_ROUND_UP_ULL(rate, synth_div_m);
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cistatic unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
35162306a36Sopenharmony_ci						  unsigned long parent_rate)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
35462306a36Sopenharmony_ci	unsigned long current_rate, frac_rate;
35562306a36Sopenharmony_ci	u32 post_div_m;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
35862306a36Sopenharmony_ci	post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
35962306a36Sopenharmony_ci	frac_rate = current_rate * post_div_m;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	return frac_rate;
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cistatic u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
36562306a36Sopenharmony_ci					unsigned long rate,
36662306a36Sopenharmony_ci					unsigned long parent_rate)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
37162306a36Sopenharmony_ci	post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
37262306a36Sopenharmony_ci	if (post_div_m > SYNTH_MAX_DIV_M)
37362306a36Sopenharmony_ci		return -EINVAL;
37462306a36Sopenharmony_ci	if (!post_div_m)
37562306a36Sopenharmony_ci		post_div_m = 1;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
37862306a36Sopenharmony_ci		synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
37962306a36Sopenharmony_ci						 SYNTH_PHASE_K *
38062306a36Sopenharmony_ci						 10000000,
38162306a36Sopenharmony_ci						 rate * post_div_m);
38262306a36Sopenharmony_ci		synth_frac_div = synth_int_div % 10000000;
38362306a36Sopenharmony_ci		synth_int_div /= 10000000;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci		if (synth_int_div <= SYNTH_MAX_INT_DIV)
38662306a36Sopenharmony_ci			break;
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	if (synth_int_div > SYNTH_MAX_INT_DIV)
39062306a36Sopenharmony_ci		return -EINVAL;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	v = readl_relaxed(synth->freq);
39362306a36Sopenharmony_ci	v &= ~0x1fffffff;
39462306a36Sopenharmony_ci	v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
39562306a36Sopenharmony_ci	v |= (synth_frac_div & 0xffffff);
39662306a36Sopenharmony_ci	v |= SYNTH_LDFREQ;
39762306a36Sopenharmony_ci	writel_relaxed(v, synth->freq);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	return post_div_m;
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
40362306a36Sopenharmony_ci				      unsigned long *parent_rate)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
40662306a36Sopenharmony_ci	struct fapll_data *fd = synth->fd;
40762306a36Sopenharmony_ci	unsigned long r;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
41062306a36Sopenharmony_ci		return -EINVAL;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	/* Only post divider m available with no fractional divider? */
41362306a36Sopenharmony_ci	if (!synth->freq) {
41462306a36Sopenharmony_ci		unsigned long frac_rate;
41562306a36Sopenharmony_ci		u32 synth_post_div_m;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
41862306a36Sopenharmony_ci		synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
41962306a36Sopenharmony_ci		r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
42062306a36Sopenharmony_ci		goto out;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	r = *parent_rate * SYNTH_PHASE_K;
42462306a36Sopenharmony_ci	if (rate > r)
42562306a36Sopenharmony_ci		goto out;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
42862306a36Sopenharmony_ci	if (rate < r)
42962306a36Sopenharmony_ci		goto out;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	r = rate;
43262306a36Sopenharmony_ciout:
43362306a36Sopenharmony_ci	return r;
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
43762306a36Sopenharmony_ci				   unsigned long parent_rate)
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	struct fapll_synth *synth = to_synth(hw);
44062306a36Sopenharmony_ci	struct fapll_data *fd = synth->fd;
44162306a36Sopenharmony_ci	unsigned long frac_rate, post_rate = 0;
44262306a36Sopenharmony_ci	u32 post_div_m = 0, v;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
44562306a36Sopenharmony_ci		return -EINVAL;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* Produce the rate with just post divider M? */
44862306a36Sopenharmony_ci	frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
44962306a36Sopenharmony_ci	if (frac_rate < rate) {
45062306a36Sopenharmony_ci		if (!synth->freq)
45162306a36Sopenharmony_ci			return -EINVAL;
45262306a36Sopenharmony_ci	} else {
45362306a36Sopenharmony_ci		post_div_m = DIV_ROUND_UP(frac_rate, rate);
45462306a36Sopenharmony_ci		if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
45562306a36Sopenharmony_ci			post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
45662306a36Sopenharmony_ci		if (!synth->freq && !post_rate)
45762306a36Sopenharmony_ci			return -EINVAL;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* Need to recalculate the fractional divider? */
46162306a36Sopenharmony_ci	if ((post_rate != rate) && synth->freq)
46262306a36Sopenharmony_ci		post_div_m = ti_fapll_synth_set_frac_rate(synth,
46362306a36Sopenharmony_ci							  rate,
46462306a36Sopenharmony_ci							  parent_rate);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	v = readl_relaxed(synth->div);
46762306a36Sopenharmony_ci	v &= ~SYNTH_MAX_DIV_M;
46862306a36Sopenharmony_ci	v |= post_div_m;
46962306a36Sopenharmony_ci	v |= SYNTH_LDMDIV1;
47062306a36Sopenharmony_ci	writel_relaxed(v, synth->div);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	return 0;
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_cistatic const struct clk_ops ti_fapll_synt_ops = {
47662306a36Sopenharmony_ci	.enable = ti_fapll_synth_enable,
47762306a36Sopenharmony_ci	.disable = ti_fapll_synth_disable,
47862306a36Sopenharmony_ci	.is_enabled = ti_fapll_synth_is_enabled,
47962306a36Sopenharmony_ci	.recalc_rate = ti_fapll_synth_recalc_rate,
48062306a36Sopenharmony_ci	.round_rate = ti_fapll_synth_round_rate,
48162306a36Sopenharmony_ci	.set_rate = ti_fapll_synth_set_rate,
48262306a36Sopenharmony_ci};
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cistatic struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
48562306a36Sopenharmony_ci						void __iomem *freq,
48662306a36Sopenharmony_ci						void __iomem *div,
48762306a36Sopenharmony_ci						int index,
48862306a36Sopenharmony_ci						const char *name,
48962306a36Sopenharmony_ci						const char *parent,
49062306a36Sopenharmony_ci						struct clk *pll_clk)
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	struct clk_init_data *init;
49362306a36Sopenharmony_ci	struct fapll_synth *synth;
49462306a36Sopenharmony_ci	struct clk *clk = ERR_PTR(-ENOMEM);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	init = kzalloc(sizeof(*init), GFP_KERNEL);
49762306a36Sopenharmony_ci	if (!init)
49862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	init->ops = &ti_fapll_synt_ops;
50162306a36Sopenharmony_ci	init->name = name;
50262306a36Sopenharmony_ci	init->parent_names = &parent;
50362306a36Sopenharmony_ci	init->num_parents = 1;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	synth = kzalloc(sizeof(*synth), GFP_KERNEL);
50662306a36Sopenharmony_ci	if (!synth)
50762306a36Sopenharmony_ci		goto free;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	synth->fd = fd;
51062306a36Sopenharmony_ci	synth->index = index;
51162306a36Sopenharmony_ci	synth->freq = freq;
51262306a36Sopenharmony_ci	synth->div = div;
51362306a36Sopenharmony_ci	synth->name = name;
51462306a36Sopenharmony_ci	synth->hw.init = init;
51562306a36Sopenharmony_ci	synth->clk_pll = pll_clk;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	clk = clk_register(NULL, &synth->hw);
51862306a36Sopenharmony_ci	if (IS_ERR(clk)) {
51962306a36Sopenharmony_ci		pr_err("failed to register clock\n");
52062306a36Sopenharmony_ci		goto free;
52162306a36Sopenharmony_ci	}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	return clk;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cifree:
52662306a36Sopenharmony_ci	kfree(synth);
52762306a36Sopenharmony_ci	kfree(init);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	return clk;
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_cistatic void __init ti_fapll_setup(struct device_node *node)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	struct fapll_data *fd;
53562306a36Sopenharmony_ci	struct clk_init_data *init = NULL;
53662306a36Sopenharmony_ci	const char *parent_name[2];
53762306a36Sopenharmony_ci	struct clk *pll_clk;
53862306a36Sopenharmony_ci	const char *name;
53962306a36Sopenharmony_ci	int i;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	fd = kzalloc(sizeof(*fd), GFP_KERNEL);
54262306a36Sopenharmony_ci	if (!fd)
54362306a36Sopenharmony_ci		return;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	fd->outputs.clks = kzalloc(sizeof(struct clk *) *
54662306a36Sopenharmony_ci				   MAX_FAPLL_OUTPUTS + 1,
54762306a36Sopenharmony_ci				   GFP_KERNEL);
54862306a36Sopenharmony_ci	if (!fd->outputs.clks)
54962306a36Sopenharmony_ci		goto free;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	init = kzalloc(sizeof(*init), GFP_KERNEL);
55262306a36Sopenharmony_ci	if (!init)
55362306a36Sopenharmony_ci		goto free;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	init->ops = &ti_fapll_ops;
55662306a36Sopenharmony_ci	name = ti_dt_clk_name(node);
55762306a36Sopenharmony_ci	init->name = name;
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	init->num_parents = of_clk_get_parent_count(node);
56062306a36Sopenharmony_ci	if (init->num_parents != 2) {
56162306a36Sopenharmony_ci		pr_err("%pOFn must have two parents\n", node);
56262306a36Sopenharmony_ci		goto free;
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	of_clk_parent_fill(node, parent_name, 2);
56662306a36Sopenharmony_ci	init->parent_names = parent_name;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	fd->clk_ref = of_clk_get(node, 0);
56962306a36Sopenharmony_ci	if (IS_ERR(fd->clk_ref)) {
57062306a36Sopenharmony_ci		pr_err("%pOFn could not get clk_ref\n", node);
57162306a36Sopenharmony_ci		goto free;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	fd->clk_bypass = of_clk_get(node, 1);
57562306a36Sopenharmony_ci	if (IS_ERR(fd->clk_bypass)) {
57662306a36Sopenharmony_ci		pr_err("%pOFn could not get clk_bypass\n", node);
57762306a36Sopenharmony_ci		goto free;
57862306a36Sopenharmony_ci	}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	fd->base = of_iomap(node, 0);
58162306a36Sopenharmony_ci	if (!fd->base) {
58262306a36Sopenharmony_ci		pr_err("%pOFn could not get IO base\n", node);
58362306a36Sopenharmony_ci		goto free;
58462306a36Sopenharmony_ci	}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	if (fapll_is_ddr_pll(fd->base))
58762306a36Sopenharmony_ci		fd->bypass_bit_inverted = true;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	fd->name = name;
59062306a36Sopenharmony_ci	fd->hw.init = init;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	/* Register the parent PLL */
59362306a36Sopenharmony_ci	pll_clk = clk_register(NULL, &fd->hw);
59462306a36Sopenharmony_ci	if (IS_ERR(pll_clk))
59562306a36Sopenharmony_ci		goto unmap;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	fd->outputs.clks[0] = pll_clk;
59862306a36Sopenharmony_ci	fd->outputs.clk_num++;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/*
60162306a36Sopenharmony_ci	 * Set up the child synthesizers starting at index 1 as the
60262306a36Sopenharmony_ci	 * PLL output is at index 0. We need to check the clock-indices
60362306a36Sopenharmony_ci	 * for numbering in case there are holes in the synth mapping,
60462306a36Sopenharmony_ci	 * and then probe the synth register to see if it has a FREQ
60562306a36Sopenharmony_ci	 * register available.
60662306a36Sopenharmony_ci	 */
60762306a36Sopenharmony_ci	for (i = 0; i < MAX_FAPLL_OUTPUTS; i++) {
60862306a36Sopenharmony_ci		const char *output_name;
60962306a36Sopenharmony_ci		void __iomem *freq, *div;
61062306a36Sopenharmony_ci		struct clk *synth_clk;
61162306a36Sopenharmony_ci		int output_instance;
61262306a36Sopenharmony_ci		u32 v;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		if (of_property_read_string_index(node, "clock-output-names",
61562306a36Sopenharmony_ci						  i, &output_name))
61662306a36Sopenharmony_ci			continue;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci		if (of_property_read_u32_index(node, "clock-indices", i,
61962306a36Sopenharmony_ci					       &output_instance))
62062306a36Sopenharmony_ci			output_instance = i;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci		freq = fd->base + (output_instance * 8);
62362306a36Sopenharmony_ci		div = freq + 4;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci		/* Check for hardwired audio_pll_clk1 */
62662306a36Sopenharmony_ci		if (is_audio_pll_clk1(freq)) {
62762306a36Sopenharmony_ci			freq = NULL;
62862306a36Sopenharmony_ci			div = NULL;
62962306a36Sopenharmony_ci		} else {
63062306a36Sopenharmony_ci			/* Does the synthesizer have a FREQ register? */
63162306a36Sopenharmony_ci			v = readl_relaxed(freq);
63262306a36Sopenharmony_ci			if (!v)
63362306a36Sopenharmony_ci				freq = NULL;
63462306a36Sopenharmony_ci		}
63562306a36Sopenharmony_ci		synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
63662306a36Sopenharmony_ci						 output_name, name, pll_clk);
63762306a36Sopenharmony_ci		if (IS_ERR(synth_clk))
63862306a36Sopenharmony_ci			continue;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		fd->outputs.clks[output_instance] = synth_clk;
64162306a36Sopenharmony_ci		fd->outputs.clk_num++;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		clk_register_clkdev(synth_clk, output_name, NULL);
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	/* Register the child synthesizers as the FAPLL outputs */
64762306a36Sopenharmony_ci	of_clk_add_provider(node, of_clk_src_onecell_get, &fd->outputs);
64862306a36Sopenharmony_ci	/* Add clock alias for the outputs */
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	kfree(init);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	return;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ciunmap:
65562306a36Sopenharmony_ci	iounmap(fd->base);
65662306a36Sopenharmony_cifree:
65762306a36Sopenharmony_ci	if (fd->clk_bypass)
65862306a36Sopenharmony_ci		clk_put(fd->clk_bypass);
65962306a36Sopenharmony_ci	if (fd->clk_ref)
66062306a36Sopenharmony_ci		clk_put(fd->clk_ref);
66162306a36Sopenharmony_ci	kfree(fd->outputs.clks);
66262306a36Sopenharmony_ci	kfree(fd);
66362306a36Sopenharmony_ci	kfree(init);
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ciCLK_OF_DECLARE(ti_fapll_clock, "ti,dm816-fapll-clock", ti_fapll_setup);
667