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