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, 1, 0, 3),
68 	PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8),
69 	PLL_FRACN_GP(560000000U, 70, 0, 1, 0, 3),
70 	PLL_FRACN_GP(498000000U, 83, 0, 1, 0, 4),
71 	PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
72 	PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
73 	PLL_FRACN_GP(400000000U, 50, 0, 1, 0, 3),
74 	PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5)
75 };
76 
77 struct imx_fracn_gppll_clk imx_fracn_gppll = {
78 	.rate_table = fracn_tbl,
79 	.rate_count = ARRAY_SIZE(fracn_tbl),
80 };
81 EXPORT_SYMBOL_GPL(imx_fracn_gppll);
82 
83 static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
84 {
85 	return container_of(hw, struct clk_fracn_gppll, hw);
86 }
87 
88 static const struct imx_fracn_gppll_rate_table *
89 imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
90 {
91 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
92 	int i;
93 
94 	for (i = 0; i < pll->rate_count; i++)
95 		if (rate == rate_table[i].rate)
96 			return &rate_table[i];
97 
98 	return NULL;
99 }
100 
101 static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
102 				       unsigned long *prate)
103 {
104 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
105 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
106 	int i;
107 
108 	/* Assuming rate_table is in descending order */
109 	for (i = 0; i < pll->rate_count; i++)
110 		if (rate >= rate_table[i].rate)
111 			return rate_table[i].rate;
112 
113 	/* return minimum supported value */
114 	return rate_table[pll->rate_count - 1].rate;
115 }
116 
117 static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
118 {
119 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
120 	const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
121 	u32 pll_numerator, pll_denominator, pll_div;
122 	u32 mfi, mfn, mfd, rdiv, odiv;
123 	u64 fvco = parent_rate;
124 	long rate = 0;
125 	int i;
126 
127 	pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
128 	mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
129 
130 	pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
131 	mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
132 
133 	pll_div = readl_relaxed(pll->base + PLL_DIV);
134 	mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
135 
136 	rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
137 	odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
138 
139 	/*
140 	 * Sometimes, the recalculated rate has deviation due to
141 	 * the frac part. So find the accurate pll rate from the table
142 	 * first, if no match rate in the table, use the rate calculated
143 	 * from the equation below.
144 	 */
145 	for (i = 0; i < pll->rate_count; i++) {
146 		if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi &&
147 		    rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv &&
148 		    rate_table[i].odiv == odiv)
149 			rate = rate_table[i].rate;
150 	}
151 
152 	if (rate)
153 		return (unsigned long)rate;
154 
155 	if (!rdiv)
156 		rdiv = rdiv + 1;
157 
158 	switch (odiv) {
159 	case 0:
160 		odiv = 2;
161 		break;
162 	case 1:
163 		odiv = 3;
164 		break;
165 	default:
166 		break;
167 	}
168 
169 	/* Fvco = Fref * (MFI + MFN / MFD) */
170 	fvco = fvco * mfi * mfd + fvco * mfn;
171 	do_div(fvco, mfd * rdiv * odiv);
172 
173 	return (unsigned long)fvco;
174 }
175 
176 static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
177 {
178 	u32 val;
179 
180 	return readl_poll_timeout(pll->base + PLL_STATUS, val,
181 				  val & LOCK_STATUS, 0, LOCK_TIMEOUT_US);
182 }
183 
184 static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
185 				    unsigned long prate)
186 {
187 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
188 	const struct imx_fracn_gppll_rate_table *rate;
189 	u32 tmp, pll_div, ana_mfn;
190 	int ret;
191 
192 	rate = imx_get_pll_settings(pll, drate);
193 
194 	/* Disable output */
195 	tmp = readl_relaxed(pll->base + PLL_CTRL);
196 	tmp &= ~CLKMUX_EN;
197 	writel_relaxed(tmp, pll->base + PLL_CTRL);
198 
199 	/* Power Down */
200 	tmp &= ~POWERUP_MASK;
201 	writel_relaxed(tmp, pll->base + PLL_CTRL);
202 
203 	/* Disable BYPASS */
204 	tmp &= ~CLKMUX_BYPASS;
205 	writel_relaxed(tmp, pll->base + PLL_CTRL);
206 
207 	pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
208 		FIELD_PREP(PLL_MFI_MASK, rate->mfi);
209 	writel_relaxed(pll_div, pll->base + PLL_DIV);
210 	writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
211 	writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
212 
213 	/* Wait for 5us according to fracn mode pll doc */
214 	udelay(5);
215 
216 	/* Enable Powerup */
217 	tmp |= POWERUP_MASK;
218 	writel_relaxed(tmp, pll->base + PLL_CTRL);
219 
220 	/* Wait Lock */
221 	ret = clk_fracn_gppll_wait_lock(pll);
222 	if (ret)
223 		return ret;
224 
225 	/* Enable output */
226 	tmp |= CLKMUX_EN;
227 	writel_relaxed(tmp, pll->base + PLL_CTRL);
228 
229 	ana_mfn = readl_relaxed(pll->base + PLL_STATUS);
230 	ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn);
231 
232 	WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
233 
234 	return 0;
235 }
236 
237 static int clk_fracn_gppll_prepare(struct clk_hw *hw)
238 {
239 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
240 	u32 val;
241 	int ret;
242 
243 	val = readl_relaxed(pll->base + PLL_CTRL);
244 	if (val & POWERUP_MASK)
245 		return 0;
246 
247 	val |= CLKMUX_BYPASS;
248 	writel_relaxed(val, pll->base + PLL_CTRL);
249 
250 	val |= POWERUP_MASK;
251 	writel_relaxed(val, pll->base + PLL_CTRL);
252 
253 	val |= CLKMUX_EN;
254 	writel_relaxed(val, pll->base + PLL_CTRL);
255 
256 	ret = clk_fracn_gppll_wait_lock(pll);
257 	if (ret)
258 		return ret;
259 
260 	val &= ~CLKMUX_BYPASS;
261 	writel_relaxed(val, pll->base + PLL_CTRL);
262 
263 	return 0;
264 }
265 
266 static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
267 {
268 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
269 	u32 val;
270 
271 	val = readl_relaxed(pll->base + PLL_CTRL);
272 
273 	return (val & POWERUP_MASK) ? 1 : 0;
274 }
275 
276 static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
277 {
278 	struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
279 	u32 val;
280 
281 	val = readl_relaxed(pll->base + PLL_CTRL);
282 	val &= ~POWERUP_MASK;
283 	writel_relaxed(val, pll->base + PLL_CTRL);
284 }
285 
286 static const struct clk_ops clk_fracn_gppll_ops = {
287 	.prepare	= clk_fracn_gppll_prepare,
288 	.unprepare	= clk_fracn_gppll_unprepare,
289 	.is_prepared	= clk_fracn_gppll_is_prepared,
290 	.recalc_rate	= clk_fracn_gppll_recalc_rate,
291 	.round_rate	= clk_fracn_gppll_round_rate,
292 	.set_rate	= clk_fracn_gppll_set_rate,
293 };
294 
295 struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
296 				   const struct imx_fracn_gppll_clk *pll_clk)
297 {
298 	struct clk_fracn_gppll *pll;
299 	struct clk_hw *hw;
300 	struct clk_init_data init;
301 	int ret;
302 
303 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
304 	if (!pll)
305 		return ERR_PTR(-ENOMEM);
306 
307 	init.name = name;
308 	init.flags = pll_clk->flags;
309 	init.parent_names = &parent_name;
310 	init.num_parents = 1;
311 	init.ops = &clk_fracn_gppll_ops;
312 
313 	pll->base = base;
314 	pll->hw.init = &init;
315 	pll->rate_table = pll_clk->rate_table;
316 	pll->rate_count = pll_clk->rate_count;
317 
318 	hw = &pll->hw;
319 
320 	ret = clk_hw_register(NULL, hw);
321 	if (ret) {
322 		pr_err("%s: failed to register pll %s %d\n", __func__, name, ret);
323 		kfree(pll);
324 		return ERR_PTR(ret);
325 	}
326 
327 	return hw;
328 }
329 EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);
330