blob: c526fc1cce47a0a701ae3e8103edfebeef81b7de [file] [log] [blame]
Peng Fanbbb58712019-08-19 07:53:58 +00001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2017-2019 NXP.
4 *
5 * Peng Fan <peng.fan@nxp.com>
6 */
7
8#include <common.h>
9#include <asm/io.h>
10#include <malloc.h>
11#include <clk-uclass.h>
12#include <dm/device.h>
Simon Glass61b29b82020-02-03 07:36:15 -070013#include <dm/devres.h>
Peng Fanbbb58712019-08-19 07:53:58 +000014#include <linux/clk-provider.h>
Simon Glassc05ed002020-05-10 11:40:11 -060015#include <linux/delay.h>
Simon Glass61b29b82020-02-03 07:36:15 -070016#include <linux/err.h>
Peng Fanbbb58712019-08-19 07:53:58 +000017#include <linux/iopoll.h>
18#include <clk.h>
19#include <div64.h>
20
21#include "clk.h"
22
23#define UBOOT_DM_CLK_IMX_PLL1443X "imx_clk_pll1443x"
24#define UBOOT_DM_CLK_IMX_PLL1416X "imx_clk_pll1416x"
25
26#define GNRL_CTL 0x0
27#define DIV_CTL 0x4
28#define LOCK_STATUS BIT(31)
29#define LOCK_SEL_MASK BIT(29)
30#define CLKE_MASK BIT(11)
31#define RST_MASK BIT(9)
32#define BYPASS_MASK BIT(4)
33#define MDIV_SHIFT 12
34#define MDIV_MASK GENMASK(21, 12)
35#define PDIV_SHIFT 4
36#define PDIV_MASK GENMASK(9, 4)
37#define SDIV_SHIFT 0
38#define SDIV_MASK GENMASK(2, 0)
39#define KDIV_SHIFT 0
40#define KDIV_MASK GENMASK(15, 0)
41
42#define LOCK_TIMEOUT_US 10000
43
44struct clk_pll14xx {
45 struct clk clk;
46 void __iomem *base;
47 enum imx_pll14xx_type type;
48 const struct imx_pll14xx_rate_table *rate_table;
49 int rate_count;
50};
51
52#define to_clk_pll14xx(_clk) container_of(_clk, struct clk_pll14xx, clk)
53
54static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
55 struct clk_pll14xx *pll, unsigned long rate)
56{
57 const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
58 int i;
59
60 for (i = 0; i < pll->rate_count; i++)
61 if (rate == rate_table[i].rate)
62 return &rate_table[i];
63
64 return NULL;
65}
66
67static unsigned long clk_pll1416x_recalc_rate(struct clk *clk)
68{
69 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
70 u64 fvco = clk_get_parent_rate(clk);
71 u32 mdiv, pdiv, sdiv, pll_div;
72
73 pll_div = readl(pll->base + 4);
74 mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
75 pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
76 sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
77
78 fvco *= mdiv;
79 do_div(fvco, pdiv << sdiv);
80
81 return fvco;
82}
83
84static unsigned long clk_pll1443x_recalc_rate(struct clk *clk)
85{
86 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
87 u64 fvco = clk_get_parent_rate(clk);
88 u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
89 short int kdiv;
90
91 pll_div_ctl0 = readl(pll->base + 4);
92 pll_div_ctl1 = readl(pll->base + 8);
93 mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
94 pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
95 sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
96 kdiv = pll_div_ctl1 & KDIV_MASK;
97
98 /* fvco = (m * 65536 + k) * Fin / (p * 65536) */
99 fvco *= (mdiv * 65536 + kdiv);
100 pdiv *= 65536;
101
102 do_div(fvco, pdiv << sdiv);
103
104 return fvco;
105}
106
107static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
108 u32 pll_div)
109{
110 u32 old_mdiv, old_pdiv;
111
112 old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
113 old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
114
115 return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
116}
117
118static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
119 u32 pll_div_ctl0, u32 pll_div_ctl1)
120{
121 u32 old_mdiv, old_pdiv, old_kdiv;
122
123 old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
124 old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
125 old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
126
127 return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
128 rate->kdiv != old_kdiv;
129}
130
131static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
132 u32 pll_div_ctl0, u32 pll_div_ctl1)
133{
134 u32 old_mdiv, old_pdiv, old_kdiv;
135
136 old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
137 old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
138 old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
139
140 return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
141 rate->kdiv != old_kdiv;
142}
143
144static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
145{
146 u32 val;
147
148 return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US,
149 LOCK_TIMEOUT_US);
150}
151
152static ulong clk_pll1416x_set_rate(struct clk *clk, unsigned long drate)
153{
154 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
155 const struct imx_pll14xx_rate_table *rate;
156 u32 tmp, div_val;
157 int ret;
158
159 rate = imx_get_pll_settings(pll, drate);
160 if (!rate) {
161 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
162 drate, "xxxx");
163 return -EINVAL;
164 }
165
166 tmp = readl(pll->base + 4);
167
168 if (!clk_pll1416x_mp_change(rate, tmp)) {
169 tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
170 tmp |= rate->sdiv << SDIV_SHIFT;
171 writel(tmp, pll->base + 4);
172
173 return clk_pll1416x_recalc_rate(clk);
174 }
175
176 /* Bypass clock and set lock to pll output lock */
177 tmp = readl(pll->base);
178 tmp |= LOCK_SEL_MASK;
179 writel(tmp, pll->base);
180
181 /* Enable RST */
182 tmp &= ~RST_MASK;
183 writel(tmp, pll->base);
184
185 /* Enable BYPASS */
186 tmp |= BYPASS_MASK;
187 writel(tmp, pll->base);
188
189
190 div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
191 (rate->sdiv << SDIV_SHIFT);
192 writel(div_val, pll->base + 0x4);
193
194 /*
195 * According to SPEC, t3 - t2 need to be greater than
196 * 1us and 1/FREF, respectively.
197 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
198 * 3us.
199 */
200 udelay(3);
201
202 /* Disable RST */
203 tmp |= RST_MASK;
204 writel(tmp, pll->base);
205
206 /* Wait Lock */
207 ret = clk_pll14xx_wait_lock(pll);
208 if (ret)
209 return ret;
210
211 /* Bypass */
212 tmp &= ~BYPASS_MASK;
213 writel(tmp, pll->base);
214
215 return clk_pll1416x_recalc_rate(clk);
216}
217
218static ulong clk_pll1443x_set_rate(struct clk *clk, unsigned long drate)
219{
220 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
221 const struct imx_pll14xx_rate_table *rate;
222 u32 tmp, div_val;
223 int ret;
224
225 rate = imx_get_pll_settings(pll, drate);
226 if (!rate) {
227 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
228 drate, "===");
229 return -EINVAL;
230 }
231
232 tmp = readl(pll->base + 4);
233 div_val = readl(pll->base + 8);
234
235 if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
236 tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
237 tmp |= rate->sdiv << SDIV_SHIFT;
238 writel(tmp, pll->base + 4);
239
240 return clk_pll1443x_recalc_rate(clk);
241 }
242
243 tmp = readl(pll->base);
244
245 /* Enable RST */
246 tmp &= ~RST_MASK;
247 writel(tmp, pll->base);
248
249 /* Enable BYPASS */
250 tmp |= BYPASS_MASK;
251 writel(tmp, pll->base);
252
253 div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
254 (rate->sdiv << SDIV_SHIFT);
255 writel(div_val, pll->base + 0x4);
256 writel(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
257
258 /*
259 * According to SPEC, t3 - t2 need to be greater than
260 * 1us and 1/FREF, respectively.
261 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
262 * 3us.
263 */
264 udelay(3);
265
266 /* Disable RST */
267 tmp |= RST_MASK;
268 writel(tmp, pll->base);
269
270 /* Wait Lock*/
271 ret = clk_pll14xx_wait_lock(pll);
272 if (ret)
273 return ret;
274
275 /* Bypass */
276 tmp &= ~BYPASS_MASK;
277 writel(tmp, pll->base);
278
279 return clk_pll1443x_recalc_rate(clk);
280}
281
282static int clk_pll14xx_prepare(struct clk *clk)
283{
284 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
285 u32 val;
286
287 /*
288 * RESETB = 1 from 0, PLL starts its normal
289 * operation after lock time
290 */
291 val = readl(pll->base + GNRL_CTL);
292 val |= RST_MASK;
293 writel(val, pll->base + GNRL_CTL);
294
295 return clk_pll14xx_wait_lock(pll);
296}
297
298static int clk_pll14xx_unprepare(struct clk *clk)
299{
300 struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
301 u32 val;
302
303 /*
304 * Set RST to 0, power down mode is enabled and
305 * every digital block is reset
306 */
307 val = readl(pll->base + GNRL_CTL);
308 val &= ~RST_MASK;
309 writel(val, pll->base + GNRL_CTL);
310
311 return 0;
312}
313
314static const struct clk_ops clk_pll1416x_ops = {
315 .enable = clk_pll14xx_prepare,
316 .disable = clk_pll14xx_unprepare,
317 .set_rate = clk_pll1416x_set_rate,
318 .get_rate = clk_pll1416x_recalc_rate,
319};
320
321static const struct clk_ops clk_pll1443x_ops = {
322 .enable = clk_pll14xx_prepare,
323 .disable = clk_pll14xx_unprepare,
324 .set_rate = clk_pll1443x_set_rate,
325 .get_rate = clk_pll1443x_recalc_rate,
326};
327
328struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
329 void __iomem *base,
330 const struct imx_pll14xx_clk *pll_clk)
331{
332 struct clk_pll14xx *pll;
333 struct clk *clk;
334 char *type_name;
335 int ret;
336
337 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
338 if (!pll)
339 return ERR_PTR(-ENOMEM);
340
341 switch (pll_clk->type) {
342 case PLL_1416X:
343 type_name = UBOOT_DM_CLK_IMX_PLL1416X;
344 break;
345 case PLL_1443X:
346 type_name = UBOOT_DM_CLK_IMX_PLL1443X;
347 break;
348 default:
349 pr_err("%s: Unknown pll type for pll clk %s\n",
350 __func__, name);
351 return ERR_PTR(-EINVAL);
352 };
353
354 pll->base = base;
355 pll->type = pll_clk->type;
356 pll->rate_table = pll_clk->rate_table;
357 pll->rate_count = pll_clk->rate_count;
358
359 clk = &pll->clk;
360
361 ret = clk_register(clk, type_name, name, parent_name);
362 if (ret) {
363 pr_err("%s: failed to register pll %s %d\n",
364 __func__, name, ret);
365 kfree(pll);
366 return ERR_PTR(ret);
367 }
368
369 return clk;
370}
371
372U_BOOT_DRIVER(clk_pll1443x) = {
373 .name = UBOOT_DM_CLK_IMX_PLL1443X,
374 .id = UCLASS_CLK,
375 .ops = &clk_pll1443x_ops,
376 .flags = DM_FLAG_PRE_RELOC,
377};
378
379U_BOOT_DRIVER(clk_pll1416x) = {
380 .name = UBOOT_DM_CLK_IMX_PLL1416X,
381 .id = UCLASS_CLK,
382 .ops = &clk_pll1416x_ops,
383 .flags = DM_FLAG_PRE_RELOC,
384};