Merge branches 'clk-range', 'clk-uniphier', 'clk-apple' and 'clk-qcom' into clk-next
[linux-2.6-microblaze.git] / drivers / clk / imx / clk-fracn-gppll.c
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);