1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2021 NXP
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/clk-provider.h>
8 #include <linux/err.h>
9 #include <linux/export.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/slab.h>
13 #include <asm/div64.h>
14 
15 #include "clk.h"
16 
17 #define PLL_CTRL		0x0
18 #define CLKMUX_BYPASS		BIT(2)
19 #define CLKMUX_EN		BIT(1)
20 #define POWERUP_MASK		BIT(0)
21 
22 #define PLL_ANA_PRG		0x10
23 #define PLL_SPREAD_SPECTRUM	0x30
24 
25 #define PLL_NUMERATOR		0x40
26 #define PLL_MFN_MASK		GENMASK(31, 2)
27 
28 #define PLL_DENOMINATOR		0x50
29 #define PLL_MFD_MASK		GENMASK(29, 0)
30 
31 #define PLL_DIV			0x60
32 #define PLL_MFI_MASK		GENMASK(24, 16)
33 #define PLL_RDIV_MASK		GENMASK(15, 13)
34 #define PLL_ODIV_MASK		GENMASK(7, 0)
35 
36 #define PLL_DFS_CTRL(x)		(0x70 + (x) * 0x10)
37 
38 #define PLL_STATUS		0xF0
39 #define LOCK_STATUS		BIT(0)
40 
41 #define DFS_STATUS		0xF4
42 
43 #define LOCK_TIMEOUT_US		200
44 
45 #define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv)	\
46 	{							\
47 		.rate	=	(_rate),			\
48 		.mfi	=	(_mfi),				\
49 		.mfn	=	(_mfn),				\
50 		.mfd	=	(_mfd),				\
51 		.rdiv	=	(_rdiv),			\
52 		.odiv	=	(_odiv),			\
53 	}
54 
55 struct clk_fracn_gppll {
56 	struct clk_hw			hw;
57 	void __iomem			*base;
58 	const struct imx_fracn_gppll_rate_table *rate_table;
59 	int rate_count;
60 };
61 
62 /*
63  * Fvco = Fref * (MFI + MFN / MFD)
64  * Fout = Fvco / (rdiv * odiv)
65  */
66 static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
67 	PLL_FRACN_GP(650000000U, 81, 0, 0, 0, 3),
68 	PLL_FRACN_GP(594000000U, 198, 0, 0, 0, 8),
69 	PLL_FRACN_GP(560000000U, 70, 0, 0, 0, 3),
70 	PLL_FRACN_GP(400000000U, 50, 0, 0, 0, 3),
71 	PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5)
72 };
73 
74 struct imx_fracn_gppll_clk imx_fracn_gppll = {
75 	.rate_table = fracn_tbl,
76 	.rate_count = ARRAY_SIZE(fracn_tbl),
77 };
78 EXPORT_SYMBOL_GPL(imx_fracn_gppll);
79 
80 static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
81 {
82 	return container_of(hw, struct clk_fracn_gppll, hw);
83 }
84 
85 static const struct imx_fracn_gppll_rate_table *
86 imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
87 {
88 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
89 	int i;
90 
91 	for (i = 0; i < pll->rate_count; i++)
92 		if (rate == rate_table[i].rate)
93 			return &rate_table[i];
94 
95 	return NULL;
96 }
97 
98 static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
99 				       unsigned long *prate)
100 {
101 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
102 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
103 	int i;
104 
105 	/* Assuming rate_table is in descending order */
106 	for (i = 0; i < pll->rate_count; i++)
107 		if (rate >= rate_table[i].rate)
108 			return rate_table[i].rate;
109 
110 	/* return minimum supported value */
111 	return rate_table[pll->rate_count - 1].rate;
112 }
113 
114 static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
115 {
116 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
117 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
118 	u32 pll_numerator, pll_denominator, pll_div;
119 	u32 mfi, mfn, mfd, rdiv, odiv;
120 	u64 fvco = parent_rate;
121 	long rate = 0;
122 	int i;
123 
124 	pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
125 	mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
126 
127 	pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
128 	mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
129 
130 	pll_div = readl_relaxed(pll->base + PLL_DIV);
131 	mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
132 
133 	rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
134 	rdiv = rdiv + 1;
135 	odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
136 	switch (odiv) {
137 	case 0:
138 		odiv = 2;
139 		break;
140 	case 1:
141 		odiv = 3;
142 		break;
143 	default:
144 		break;
145 	}
146 
147 	/*
148 	 * Sometimes, the recalculated rate has deviation due to
149 	 * the frac part. So find the accurate pll rate from the table
150 	 * first, if no match rate in the table, use the rate calculated
151 	 * from the equation below.
152 	 */
153 	for (i = 0; i < pll->rate_count; i++) {
154 		if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi &&
155 		    rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv &&
156 		    rate_table[i].odiv == odiv)
157 			rate = rate_table[i].rate;
158 	}
159 
160 	if (rate)
161 		return (unsigned long)rate;
162 
163 	/* Fvco = Fref * (MFI + MFN / MFD) */
164 	fvco = fvco * mfi * mfd + fvco * mfn;
165 	do_div(fvco, mfd * rdiv * odiv);
166 
167 	return (unsigned long)fvco;
168 }
169 
170 static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
171 {
172 	u32 val;
173 
174 	return readl_poll_timeout(pll->base + PLL_STATUS, val,
175 				  val & LOCK_STATUS, 0, LOCK_TIMEOUT_US);
176 }
177 
178 static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
179 				    unsigned long prate)
180 {
181 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
182 	const struct imx_fracn_gppll_rate_table *rate;
183 	u32 tmp, pll_div, ana_mfn;
184 	int ret;
185 
186 	rate = imx_get_pll_settings(pll, drate);
187 
188 	/* Disable output */
189 	tmp = readl_relaxed(pll->base + PLL_CTRL);
190 	tmp &= ~CLKMUX_EN;
191 	writel_relaxed(tmp, pll->base + PLL_CTRL);
192 
193 	/* Power Down */
194 	tmp &= ~POWERUP_MASK;
195 	writel_relaxed(tmp, pll->base + PLL_CTRL);
196 
197 	/* Disable BYPASS */
198 	tmp &= ~CLKMUX_BYPASS;
199 	writel_relaxed(tmp, pll->base + PLL_CTRL);
200 
201 	pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
202 		FIELD_PREP(PLL_MFI_MASK, rate->mfi);
203 	writel_relaxed(pll_div, pll->base + PLL_DIV);
204 	writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
205 	writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
206 
207 	/* Wait for 5us according to fracn mode pll doc */
208 	udelay(5);
209 
210 	/* Enable Powerup */
211 	tmp |= POWERUP_MASK;
212 	writel_relaxed(tmp, pll->base + PLL_CTRL);
213 
214 	/* Wait Lock */
215 	ret = clk_fracn_gppll_wait_lock(pll);
216 	if (ret)
217 		return ret;
218 
219 	/* Enable output */
220 	tmp |= CLKMUX_EN;
221 	writel_relaxed(tmp, pll->base + PLL_CTRL);
222 
223 	ana_mfn = readl_relaxed(pll->base + PLL_STATUS);
224 	ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn);
225 
226 	WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
227 
228 	return 0;
229 }
230 
231 static int clk_fracn_gppll_prepare(struct clk_hw *hw)
232 {
233 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
234 	u32 val;
235 	int ret;
236 
237 	val = readl_relaxed(pll->base + PLL_CTRL);
238 	if (val & POWERUP_MASK)
239 		return 0;
240 
241 	val |= CLKMUX_BYPASS;
242 	writel_relaxed(val, pll->base + PLL_CTRL);
243 
244 	val |= POWERUP_MASK;
245 	writel_relaxed(val, pll->base + PLL_CTRL);
246 
247 	val |= CLKMUX_EN;
248 	writel_relaxed(val, pll->base + PLL_CTRL);
249 
250 	ret = clk_fracn_gppll_wait_lock(pll);
251 	if (ret)
252 		return ret;
253 
254 	val &= ~CLKMUX_BYPASS;
255 	writel_relaxed(val, pll->base + PLL_CTRL);
256 
257 	return 0;
258 }
259 
260 static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
261 {
262 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
263 	u32 val;
264 
265 	val = readl_relaxed(pll->base + PLL_CTRL);
266 
267 	return (val & POWERUP_MASK) ? 1 : 0;
268 }
269 
270 static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
271 {
272 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
273 	u32 val;
274 
275 	val = readl_relaxed(pll->base + PLL_CTRL);
276 	val &= ~POWERUP_MASK;
277 	writel_relaxed(val, pll->base + PLL_CTRL);
278 }
279 
280 static const struct clk_ops clk_fracn_gppll_ops = {
281 	.prepare	= clk_fracn_gppll_prepare,
282 	.unprepare	= clk_fracn_gppll_unprepare,
283 	.is_prepared	= clk_fracn_gppll_is_prepared,
284 	.recalc_rate	= clk_fracn_gppll_recalc_rate,
285 	.round_rate	= clk_fracn_gppll_round_rate,
286 	.set_rate	= clk_fracn_gppll_set_rate,
287 };
288 
289 struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
290 				   const struct imx_fracn_gppll_clk *pll_clk)
291 {
292 	struct clk_fracn_gppll *pll;
293 	struct clk_hw *hw;
294 	struct clk_init_data init;
295 	int ret;
296 
297 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
298 	if (!pll)
299 		return ERR_PTR(-ENOMEM);
300 
301 	init.name = name;
302 	init.flags = pll_clk->flags;
303 	init.parent_names = &parent_name;
304 	init.num_parents = 1;
305 	init.ops = &clk_fracn_gppll_ops;
306 
307 	pll->base = base;
308 	pll->hw.init = &init;
309 	pll->rate_table = pll_clk->rate_table;
310 	pll->rate_count = pll_clk->rate_count;
311 
312 	hw = &pll->hw;
313 
314 	ret = clk_hw_register(NULL, hw);
315 	if (ret) {
316 		pr_err("%s: failed to register pll %s %d\n", __func__, name, ret);
317 		kfree(pll);
318 		return ERR_PTR(ret);
319 	}
320 
321 	return hw;
322 }
323 EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);
324