c9918c17d7b161cd055059cb54c4c0ccea09718b
[oweals/u-boot.git] / drivers / clk / meson / g12a.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
4  * (C) Copyright 2018 - BayLibre, SAS
5  * Author: Neil Armstrong <narmstrong@baylibre.com>
6  */
7
8 #include <common.h>
9 #include <log.h>
10 #include <asm/arch/clock-g12a.h>
11 #include <asm/io.h>
12 #include <clk-uclass.h>
13 #include <dm.h>
14 #include <regmap.h>
15 #include <syscon.h>
16 #include <div64.h>
17 #include <dt-bindings/clock/g12a-clkc.h>
18 #include <linux/err.h>
19 #include <linux/kernel.h>
20 #include "clk_meson.h"
21
22 /* This driver support only basic clock tree operations :
23  * - Can calculate clock frequency on a limited tree
24  * - Can Read muxes and basic dividers (0-based only)
25  * - Can enable/disable gates with limited propagation
26  * - Can reparent without propagation, only on muxes
27  * - Can set rates without reparenting
28  * This driver is adapted to what is actually supported by U-Boot
29  */
30
31 /* Only the clocks ids we don't want to expose, such as the internal muxes
32  * and dividers of composite clocks, will remain defined here.
33  */
34 #define CLKID_MPEG_SEL                          8
35 #define CLKID_MPEG_DIV                          9
36 #define CLKID_SD_EMMC_A_CLK0_SEL                63
37 #define CLKID_SD_EMMC_A_CLK0_DIV                64
38 #define CLKID_SD_EMMC_B_CLK0_SEL                65
39 #define CLKID_SD_EMMC_B_CLK0_DIV                66
40 #define CLKID_SD_EMMC_C_CLK0_SEL                67
41 #define CLKID_SD_EMMC_C_CLK0_DIV                68
42 #define CLKID_MPLL0_DIV                         69
43 #define CLKID_MPLL1_DIV                         70
44 #define CLKID_MPLL2_DIV                         71
45 #define CLKID_MPLL3_DIV                         72
46 #define CLKID_MPLL_PREDIV                       73
47 #define CLKID_FCLK_DIV2_DIV                     75
48 #define CLKID_FCLK_DIV3_DIV                     76
49 #define CLKID_FCLK_DIV4_DIV                     77
50 #define CLKID_FCLK_DIV5_DIV                     78
51 #define CLKID_FCLK_DIV7_DIV                     79
52 #define CLKID_FCLK_DIV2P5_DIV                   100
53 #define CLKID_FIXED_PLL_DCO                     101
54 #define CLKID_SYS_PLL_DCO                       102
55 #define CLKID_GP0_PLL_DCO                       103
56 #define CLKID_HIFI_PLL_DCO                      104
57 #define CLKID_VPU_0_DIV                         111
58 #define CLKID_VPU_1_DIV                         114
59 #define CLKID_VAPB_0_DIV                        118
60 #define CLKID_VAPB_1_DIV                        121
61 #define CLKID_HDMI_PLL_DCO                      125
62 #define CLKID_HDMI_PLL_OD                       126
63 #define CLKID_HDMI_PLL_OD2                      127
64 #define CLKID_VID_PLL_SEL                       130
65 #define CLKID_VID_PLL_DIV                       131
66 #define CLKID_VCLK_SEL                          132
67 #define CLKID_VCLK2_SEL                         133
68 #define CLKID_VCLK_INPUT                        134
69 #define CLKID_VCLK2_INPUT                       135
70 #define CLKID_VCLK_DIV                          136
71 #define CLKID_VCLK2_DIV                         137
72 #define CLKID_VCLK_DIV2_EN                      140
73 #define CLKID_VCLK_DIV4_EN                      141
74 #define CLKID_VCLK_DIV6_EN                      142
75 #define CLKID_VCLK_DIV12_EN                     143
76 #define CLKID_VCLK2_DIV2_EN                     144
77 #define CLKID_VCLK2_DIV4_EN                     145
78 #define CLKID_VCLK2_DIV6_EN                     146
79 #define CLKID_VCLK2_DIV12_EN                    147
80 #define CLKID_CTS_ENCI_SEL                      158
81 #define CLKID_CTS_ENCP_SEL                      159
82 #define CLKID_CTS_VDAC_SEL                      160
83 #define CLKID_HDMI_TX_SEL                       161
84 #define CLKID_HDMI_SEL                          166
85 #define CLKID_HDMI_DIV                          167
86 #define CLKID_MALI_0_DIV                        170
87 #define CLKID_MALI_1_DIV                        173
88
89 #define CLKID_XTAL                              0x10000000
90
91 #define XTAL_RATE 24000000
92
93 struct meson_clk {
94         struct regmap *map;
95 };
96
97 static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
98 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
99                                 ulong current_rate);
100 static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
101                                   unsigned long parent_id);
102 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
103 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
104                                       ulong rate, ulong current_rate);
105 static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
106 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
107
108 #define NUM_CLKS 178
109
110 static struct meson_gate gates[NUM_CLKS] = {
111         /* Everything Else (EE) domain gates */
112         MESON_GATE(CLKID_SPICC0, HHI_GCLK_MPEG0, 8),
113         MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
114         MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
115         MESON_GATE(CLKID_SPICC1, HHI_GCLK_MPEG0, 14),
116         MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 4),
117         MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
118         MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
119         MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
120         MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
121         MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 25),
122         MESON_GATE(CLKID_HTX_PCLK, HHI_GCLK_MPEG2, 4),
123         MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
124         MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
125
126         /* Peripheral Gates */
127         MESON_GATE(CLKID_FCLK_DIV2, HHI_FIX_PLL_CNTL1, 24),
128         MESON_GATE(CLKID_FCLK_DIV3, HHI_FIX_PLL_CNTL1, 20),
129         MESON_GATE(CLKID_FCLK_DIV4, HHI_FIX_PLL_CNTL1, 21),
130         MESON_GATE(CLKID_FCLK_DIV5, HHI_FIX_PLL_CNTL1, 22),
131         MESON_GATE(CLKID_FCLK_DIV7, HHI_FIX_PLL_CNTL1, 23),
132         MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7),
133         MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
134         MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
135         MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
136         MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
137         MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
138         MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
139         MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
140         MESON_GATE(CLKID_HDMI, HHI_HDMI_CLK_CNTL, 8),
141 };
142
143 static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
144 {
145         struct meson_clk *priv = dev_get_priv(clk->dev);
146         struct meson_gate *gate;
147
148         debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
149
150         /* Propagate through muxes */
151         switch (id) {
152         case CLKID_VPU:
153                 return meson_set_gate_by_id(clk,
154                                 meson_mux_get_parent(clk, CLKID_VPU), on);
155         case CLKID_VAPB_SEL:
156                 return meson_set_gate_by_id(clk,
157                                 meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
158         }
159
160         if (id >= ARRAY_SIZE(gates))
161                 return -ENOENT;
162
163         gate = &gates[id];
164
165         if (gate->reg == 0)
166                 return 0;
167
168         debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
169
170         regmap_update_bits(priv->map, gate->reg,
171                            BIT(gate->bit), on ? BIT(gate->bit) : 0);
172
173         /* Propagate to next gate(s) */
174         switch (id) {
175         case CLKID_VAPB:
176                 return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
177         case CLKID_VAPB_0:
178                 return meson_set_gate_by_id(clk,
179                         meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
180         case CLKID_VAPB_1:
181                 return meson_set_gate_by_id(clk,
182                         meson_mux_get_parent(clk, CLKID_VAPB_0_SEL), on);
183         case CLKID_VPU_0:
184                 return meson_set_gate_by_id(clk,
185                         meson_mux_get_parent(clk, CLKID_VPU_0_SEL), on);
186         case CLKID_VPU_1:
187                 return meson_set_gate_by_id(clk,
188                         meson_mux_get_parent(clk, CLKID_VPU_1_SEL), on);
189         }
190
191         return 0;
192 }
193
194 static int meson_clk_enable(struct clk *clk)
195 {
196         return meson_set_gate_by_id(clk, clk->id, true);
197 }
198
199 static int meson_clk_disable(struct clk *clk)
200 {
201         return meson_set_gate_by_id(clk, clk->id, false);
202 }
203
204 static struct parm meson_vpu_0_div_parm = {
205         HHI_VPU_CLK_CNTL, 0, 7,
206 };
207
208 int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
209
210 static struct parm meson_vpu_1_div_parm = {
211         HHI_VPU_CLK_CNTL, 16, 7,
212 };
213
214 int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
215
216 static struct parm meson_vapb_0_div_parm = {
217         HHI_VAPBCLK_CNTL, 0, 7,
218 };
219
220 int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
221
222 static struct parm meson_vapb_1_div_parm = {
223         HHI_VAPBCLK_CNTL, 16, 7,
224 };
225
226 int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
227
228 static struct parm meson_hdmi_div_parm = {
229         HHI_HDMI_CLK_CNTL, 0, 7,
230 };
231
232 int meson_hdmi_div_parent = CLKID_HDMI_SEL;
233
234 static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
235 {
236         struct meson_clk *priv = dev_get_priv(clk->dev);
237         unsigned int rate, parent_rate;
238         struct parm *parm;
239         int parent;
240         uint reg;
241
242         switch (id) {
243         case CLKID_VPU_0_DIV:
244                 parm = &meson_vpu_0_div_parm;
245                 parent = meson_vpu_0_div_parent;
246                 break;
247         case CLKID_VPU_1_DIV:
248                 parm = &meson_vpu_1_div_parm;
249                 parent = meson_vpu_1_div_parent;
250                 break;
251         case CLKID_VAPB_0_DIV:
252                 parm = &meson_vapb_0_div_parm;
253                 parent = meson_vapb_0_div_parent;
254                 break;
255         case CLKID_VAPB_1_DIV:
256                 parm = &meson_vapb_1_div_parm;
257                 parent = meson_vapb_1_div_parent;
258                 break;
259         case CLKID_HDMI_DIV:
260                 parm = &meson_hdmi_div_parm;
261                 parent = meson_hdmi_div_parent;
262                 break;
263         default:
264                 return -ENOENT;
265         }
266
267         regmap_read(priv->map, parm->reg_off, &reg);
268         reg = PARM_GET(parm->width, parm->shift, reg);
269
270         debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
271
272         parent_rate = meson_clk_get_rate_by_id(clk, parent);
273         if (IS_ERR_VALUE(parent_rate))
274                 return parent_rate;
275
276         debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
277
278         rate = parent_rate / (reg + 1);
279
280         debug("%s: rate of %ld is %d\n", __func__, id, rate);
281
282         return rate;
283 }
284
285 static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
286                                 ulong current_rate)
287 {
288         struct meson_clk *priv = dev_get_priv(clk->dev);
289         unsigned int new_div = -EINVAL;
290         unsigned long parent_rate;
291         struct parm *parm;
292         int parent;
293         int ret;
294
295         if (current_rate == rate)
296                 return 0;
297
298         debug("%s: setting rate of %ld from %ld to %ld\n",
299               __func__, id, current_rate, rate);
300
301         switch (id) {
302         case CLKID_VPU_0_DIV:
303                 parm = &meson_vpu_0_div_parm;
304                 parent = meson_vpu_0_div_parent;
305                 break;
306         case CLKID_VPU_1_DIV:
307                 parm = &meson_vpu_1_div_parm;
308                 parent = meson_vpu_1_div_parent;
309                 break;
310         case CLKID_VAPB_0_DIV:
311                 parm = &meson_vapb_0_div_parm;
312                 parent = meson_vapb_0_div_parent;
313                 break;
314         case CLKID_VAPB_1_DIV:
315                 parm = &meson_vapb_1_div_parm;
316                 parent = meson_vapb_1_div_parent;
317                 break;
318         case CLKID_HDMI_DIV:
319                 parm = &meson_hdmi_div_parm;
320                 parent = meson_hdmi_div_parent;
321                 break;
322         default:
323                 return -ENOENT;
324         }
325
326         parent_rate = meson_clk_get_rate_by_id(clk, parent);
327         if (IS_ERR_VALUE(parent_rate))
328                 return parent_rate;
329
330         debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
331
332         /* If can't divide, set parent instead */
333         if (!parent_rate || rate > parent_rate)
334                 return meson_clk_set_rate_by_id(clk, parent, rate,
335                                                 current_rate);
336
337         new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
338
339         debug("%s: new div of %ld is %d\n", __func__, id, new_div);
340
341         /* If overflow, try to set parent rate and retry */
342         if (!new_div || new_div > (1 << parm->width)) {
343                 ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
344                 if (IS_ERR_VALUE(ret))
345                         return ret;
346
347                 parent_rate = meson_clk_get_rate_by_id(clk, parent);
348                 if (IS_ERR_VALUE(parent_rate))
349                         return parent_rate;
350
351                 new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
352
353                 debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
354
355                 if (!new_div || new_div > (1 << parm->width))
356                         return -EINVAL;
357         }
358
359         debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
360
361         regmap_update_bits(priv->map, parm->reg_off,
362                            SETPMASK(parm->width, parm->shift),
363                            (new_div - 1) << parm->shift);
364
365         debug("%s: new rate of %ld is %ld\n",
366               __func__, id, meson_div_get_rate(clk, id));
367
368         return 0;
369 }
370
371 static struct parm meson_vpu_mux_parm = {
372         HHI_VPU_CLK_CNTL, 31, 1,
373 };
374
375 int meson_vpu_mux_parents[] = {
376         CLKID_VPU_0,
377         CLKID_VPU_1,
378 };
379
380 static struct parm meson_vpu_0_mux_parm = {
381         HHI_VPU_CLK_CNTL, 9, 3,
382 };
383
384 static struct parm meson_vpu_1_mux_parm = {
385         HHI_VPU_CLK_CNTL, 25, 3,
386 };
387
388 static int meson_vpu_0_1_mux_parents[] = {
389         CLKID_FCLK_DIV3,
390         CLKID_FCLK_DIV4,
391         CLKID_FCLK_DIV5,
392         CLKID_FCLK_DIV7,
393         -ENOENT,
394         -ENOENT,
395         -ENOENT,
396         -ENOENT,
397 };
398
399 static struct parm meson_vapb_sel_mux_parm = {
400         HHI_VAPBCLK_CNTL, 31, 1,
401 };
402
403 int meson_vapb_sel_mux_parents[] = {
404         CLKID_VAPB_0,
405         CLKID_VAPB_1,
406 };
407
408 static struct parm meson_vapb_0_mux_parm = {
409         HHI_VAPBCLK_CNTL, 9, 2,
410 };
411
412 static struct parm meson_vapb_1_mux_parm = {
413         HHI_VAPBCLK_CNTL, 25, 2,
414 };
415
416 static int meson_vapb_0_1_mux_parents[] = {
417         CLKID_FCLK_DIV4,
418         CLKID_FCLK_DIV3,
419         CLKID_FCLK_DIV5,
420         CLKID_FCLK_DIV7,
421 };
422
423 static struct parm meson_hdmi_mux_parm = {
424         HHI_HDMI_CLK_CNTL, 9, 2,
425 };
426
427 static int meson_hdmi_mux_parents[] = {
428         CLKID_XTAL,
429         CLKID_FCLK_DIV4,
430         CLKID_FCLK_DIV3,
431         CLKID_FCLK_DIV5,
432 };
433
434 static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
435 {
436         struct meson_clk *priv = dev_get_priv(clk->dev);
437         struct parm *parm;
438         int *parents;
439         uint reg;
440
441         switch (id) {
442         case CLKID_VPU:
443                 parm = &meson_vpu_mux_parm;
444                 parents = meson_vpu_mux_parents;
445                 break;
446         case CLKID_VPU_0_SEL:
447                 parm = &meson_vpu_0_mux_parm;
448                 parents = meson_vpu_0_1_mux_parents;
449                 break;
450         case CLKID_VPU_1_SEL:
451                 parm = &meson_vpu_1_mux_parm;
452                 parents = meson_vpu_0_1_mux_parents;
453                 break;
454         case CLKID_VAPB_SEL:
455                 parm = &meson_vapb_sel_mux_parm;
456                 parents = meson_vapb_sel_mux_parents;
457                 break;
458         case CLKID_VAPB_0_SEL:
459                 parm = &meson_vapb_0_mux_parm;
460                 parents = meson_vapb_0_1_mux_parents;
461                 break;
462         case CLKID_VAPB_1_SEL:
463                 parm = &meson_vapb_1_mux_parm;
464                 parents = meson_vapb_0_1_mux_parents;
465                 break;
466         case CLKID_HDMI_SEL:
467                 parm = &meson_hdmi_mux_parm;
468                 parents = meson_hdmi_mux_parents;
469                 break;
470         default:
471                 return -ENOENT;
472         }
473
474         regmap_read(priv->map, parm->reg_off, &reg);
475         reg = PARM_GET(parm->width, parm->shift, reg);
476
477         debug("%s: parent of %ld is %d (%d)\n",
478               __func__, id, parents[reg], reg);
479
480         return parents[reg];
481 }
482
483 static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
484                                   unsigned long parent_id)
485 {
486         unsigned long cur_parent = meson_mux_get_parent(clk, id);
487         struct meson_clk *priv = dev_get_priv(clk->dev);
488         unsigned int new_index = -EINVAL;
489         struct parm *parm;
490         int *parents;
491         int i;
492
493         if (IS_ERR_VALUE(cur_parent))
494                 return cur_parent;
495
496         debug("%s: setting parent of %ld from %ld to %ld\n",
497               __func__, id, cur_parent, parent_id);
498
499         if (cur_parent == parent_id)
500                 return 0;
501
502         switch (id) {
503         case CLKID_VPU:
504                 parm = &meson_vpu_mux_parm;
505                 parents = meson_vpu_mux_parents;
506                 break;
507         case CLKID_VPU_0_SEL:
508                 parm = &meson_vpu_0_mux_parm;
509                 parents = meson_vpu_0_1_mux_parents;
510                 break;
511         case CLKID_VPU_1_SEL:
512                 parm = &meson_vpu_1_mux_parm;
513                 parents = meson_vpu_0_1_mux_parents;
514                 break;
515         case CLKID_VAPB_SEL:
516                 parm = &meson_vapb_sel_mux_parm;
517                 parents = meson_vapb_sel_mux_parents;
518                 break;
519         case CLKID_VAPB_0_SEL:
520                 parm = &meson_vapb_0_mux_parm;
521                 parents = meson_vapb_0_1_mux_parents;
522                 break;
523         case CLKID_VAPB_1_SEL:
524                 parm = &meson_vapb_1_mux_parm;
525                 parents = meson_vapb_0_1_mux_parents;
526                 break;
527         case CLKID_HDMI_SEL:
528                 parm = &meson_hdmi_mux_parm;
529                 parents = meson_hdmi_mux_parents;
530                 break;
531         default:
532                 /* Not a mux */
533                 return -ENOENT;
534         }
535
536         for (i = 0 ; i < (1 << parm->width) ; ++i) {
537                 if (parents[i] == parent_id)
538                         new_index = i;
539         }
540
541         if (IS_ERR_VALUE(new_index))
542                 return new_index;
543
544         debug("%s: new index of %ld is %d\n", __func__, id, new_index);
545
546         regmap_update_bits(priv->map, parm->reg_off,
547                            SETPMASK(parm->width, parm->shift),
548                            new_index << parm->shift);
549
550         debug("%s: new parent of %ld is %ld\n",
551               __func__, id, meson_mux_get_parent(clk, id));
552
553         return 0;
554 }
555
556 static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
557 {
558         int parent = meson_mux_get_parent(clk, id);
559
560         if (IS_ERR_VALUE(parent))
561                 return parent;
562
563         return meson_clk_get_rate_by_id(clk, parent);
564 }
565
566 static unsigned long meson_clk81_get_rate(struct clk *clk)
567 {
568         struct meson_clk *priv = dev_get_priv(clk->dev);
569         unsigned long parent_rate;
570         uint reg;
571         int parents[] = {
572                 CLKID_XTAL,
573                 -1,
574                 CLKID_FCLK_DIV7,
575                 CLKID_MPLL1,
576                 CLKID_MPLL2,
577                 CLKID_FCLK_DIV4,
578                 CLKID_FCLK_DIV3,
579                 CLKID_FCLK_DIV5
580         };
581
582         /* mux */
583         regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
584         reg = (reg >> 12) & 7;
585
586         switch (reg) {
587         case 1:
588                 return -ENOENT;
589         default:
590                 parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]);
591         }
592
593         /* divider */
594         regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
595         reg = reg & ((1 << 7) - 1);
596
597         return parent_rate / reg;
598 }
599
600 static long mpll_rate_from_params(unsigned long parent_rate,
601                                   unsigned long sdm,
602                                   unsigned long n2)
603 {
604         unsigned long divisor = (SDM_DEN * n2) + sdm;
605
606         if (n2 < N2_MIN)
607                 return -EINVAL;
608
609         return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
610 }
611
612 static struct parm meson_mpll0_parm[2] = {
613         {HHI_MPLL_CNTL1, 0, 14}, /* psdm */
614         {HHI_MPLL_CNTL1, 20, 9}, /* pn2 */
615 };
616
617 static struct parm meson_mpll1_parm[2] = {
618         {HHI_MPLL_CNTL3, 0, 14}, /* psdm */
619         {HHI_MPLL_CNTL3, 20, 9}, /* pn2 */
620 };
621
622 static struct parm meson_mpll2_parm[2] = {
623         {HHI_MPLL_CNTL5, 0, 14}, /* psdm */
624         {HHI_MPLL_CNTL5, 20, 9}, /* pn2 */
625 };
626
627 /*
628  * MultiPhase Locked Loops are outputs from a PLL with additional frequency
629  * scaling capabilities. MPLL rates are calculated as:
630  *
631  * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
632  */
633 static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
634 {
635         struct meson_clk *priv = dev_get_priv(clk->dev);
636         struct parm *psdm, *pn2;
637         unsigned long sdm, n2;
638         unsigned long parent_rate;
639         uint reg;
640
641         switch (id) {
642         case CLKID_MPLL0:
643                 psdm = &meson_mpll0_parm[0];
644                 pn2 = &meson_mpll0_parm[1];
645                 break;
646         case CLKID_MPLL1:
647                 psdm = &meson_mpll1_parm[0];
648                 pn2 = &meson_mpll1_parm[1];
649                 break;
650         case CLKID_MPLL2:
651                 psdm = &meson_mpll2_parm[0];
652                 pn2 = &meson_mpll2_parm[1];
653                 break;
654         default:
655                 return -ENOENT;
656         }
657
658         parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL);
659         if (IS_ERR_VALUE(parent_rate))
660                 return parent_rate;
661
662         regmap_read(priv->map, psdm->reg_off, &reg);
663         sdm = PARM_GET(psdm->width, psdm->shift, reg);
664
665         regmap_read(priv->map, pn2->reg_off, &reg);
666         n2 = PARM_GET(pn2->width, pn2->shift, reg);
667
668         return mpll_rate_from_params(parent_rate, sdm, n2);
669 }
670
671 static struct parm meson_fixed_pll_parm[4] = {
672         {HHI_FIX_PLL_CNTL0, 0, 9}, /* pm */
673         {HHI_FIX_PLL_CNTL0, 10, 5}, /* pn */
674         {HHI_FIX_PLL_CNTL0, 16, 2}, /* pod */
675         {HHI_FIX_PLL_CNTL1, 0, 17}, /* pfrac */
676 };
677
678 static struct parm meson_sys_pll_parm[3] = {
679         {HHI_SYS_PLL_CNTL0, 0, 9}, /* pm */
680         {HHI_SYS_PLL_CNTL0, 10, 5}, /* pn */
681         {HHI_SYS_PLL_CNTL0, 16, 3}, /* pod */
682 };
683
684 static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
685 {
686         struct meson_clk *priv = dev_get_priv(clk->dev);
687         struct parm *pm, *pn, *pod, *pfrac = NULL;
688         unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
689         u16 n, m, od, frac;
690         ulong rate;
691         uint reg;
692
693         /*
694          * FIXME: Between the unit conversion and the missing frac, we know
695          * rate will be slightly off ...
696         */
697
698         switch (id) {
699         case CLKID_FIXED_PLL:
700                 pm = &meson_fixed_pll_parm[0];
701                 pn = &meson_fixed_pll_parm[1];
702                 pod = &meson_fixed_pll_parm[2];
703                 pfrac = &meson_fixed_pll_parm[3];
704                 break;
705         case CLKID_SYS_PLL:
706                 pm = &meson_sys_pll_parm[0];
707                 pn = &meson_sys_pll_parm[1];
708                 pod = &meson_sys_pll_parm[2];
709                 break;
710         default:
711                 return -ENOENT;
712         }
713
714         regmap_read(priv->map, pn->reg_off, &reg);
715         n = PARM_GET(pn->width, pn->shift, reg);
716
717         regmap_read(priv->map, pm->reg_off, &reg);
718         m = PARM_GET(pm->width, pm->shift, reg);
719
720         regmap_read(priv->map, pod->reg_off, &reg);
721         od = PARM_GET(pod->width, pod->shift, reg);
722
723         rate = parent_rate_mhz * m;
724
725         if (pfrac) {
726                 ulong frac_rate;
727
728                 regmap_read(priv->map, pfrac->reg_off, &reg);
729                 frac = PARM_GET(pfrac->width - 1, pfrac->shift, reg);
730
731                 frac_rate = DIV_ROUND_UP_ULL((u64)parent_rate_mhz * frac,
732                                              1 << (pfrac->width - 2));
733
734                 if (frac & BIT(pfrac->width - 1))
735                         rate -= frac_rate;
736                 else
737                         rate += frac_rate;
738         }
739
740         return (DIV_ROUND_UP_ULL(rate, n) >> od) * 1000000;
741 }
742
743 static struct parm meson_pcie_pll_parm[3] = {
744         {HHI_PCIE_PLL_CNTL0, 0, 8}, /* pm */
745         {HHI_PCIE_PLL_CNTL0, 10, 5}, /* pn */
746         {HHI_PCIE_PLL_CNTL0, 16, 5}, /* pod */
747 };
748
749 static ulong meson_pcie_pll_get_rate(struct clk *clk)
750 {
751         struct meson_clk *priv = dev_get_priv(clk->dev);
752         struct parm *pm, *pn, *pod;
753         unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
754         u16 n, m, od;
755         uint reg;
756
757         pm = &meson_pcie_pll_parm[0];
758         pn = &meson_pcie_pll_parm[1];
759         pod = &meson_pcie_pll_parm[2];
760
761         regmap_read(priv->map, pn->reg_off, &reg);
762         n = PARM_GET(pn->width, pn->shift, reg);
763
764         regmap_read(priv->map, pm->reg_off, &reg);
765         m = PARM_GET(pm->width, pm->shift, reg);
766
767         regmap_read(priv->map, pod->reg_off, &reg);
768         od = PARM_GET(pod->width, pod->shift, reg);
769
770         return ((parent_rate_mhz * m / n) / 2 / od / 2) * 1000000;
771 }
772
773 static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
774 {
775         ulong rate;
776
777         switch (id) {
778         case CLKID_XTAL:
779                 rate = XTAL_RATE;
780                 break;
781         case CLKID_FIXED_PLL:
782         case CLKID_SYS_PLL:
783                 rate = meson_pll_get_rate(clk, id);
784                 break;
785         case CLKID_FCLK_DIV2:
786                 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2;
787                 break;
788         case CLKID_FCLK_DIV3:
789                 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3;
790                 break;
791         case CLKID_FCLK_DIV4:
792                 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4;
793                 break;
794         case CLKID_FCLK_DIV5:
795                 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5;
796                 break;
797         case CLKID_FCLK_DIV7:
798                 rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7;
799                 break;
800         case CLKID_MPLL0:
801         case CLKID_MPLL1:
802         case CLKID_MPLL2:
803                 rate = meson_mpll_get_rate(clk, id);
804                 break;
805         case CLKID_CLK81:
806                 rate = meson_clk81_get_rate(clk);
807                 break;
808         case CLKID_PCIE_PLL:
809                 rate = meson_pcie_pll_get_rate(clk);
810                 break;
811         case CLKID_VPU_0:
812                 rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
813                 break;
814         case CLKID_VPU_1:
815                 rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
816                 break;
817         case CLKID_VAPB:
818                 rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
819                 break;
820         case CLKID_VAPB_0:
821                 rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
822                 break;
823         case CLKID_VAPB_1:
824                 rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
825                 break;
826         case CLKID_HDMI:
827                 rate = meson_div_get_rate(clk, CLKID_HDMI_DIV);
828                 break;
829         case CLKID_VPU_0_DIV:
830         case CLKID_VPU_1_DIV:
831         case CLKID_VAPB_0_DIV:
832         case CLKID_VAPB_1_DIV:
833         case CLKID_HDMI_DIV:
834                 rate = meson_div_get_rate(clk, id);
835                 break;
836         case CLKID_VPU:
837         case CLKID_VPU_0_SEL:
838         case CLKID_VPU_1_SEL:
839         case CLKID_VAPB_SEL:
840         case CLKID_VAPB_0_SEL:
841         case CLKID_VAPB_1_SEL:
842         case CLKID_HDMI_SEL:
843                 rate = meson_mux_get_rate(clk, id);
844                 break;
845         default:
846                 if (gates[id].reg != 0) {
847                         /* a clock gate */
848                         rate = meson_clk81_get_rate(clk);
849                         break;
850                 }
851                 return -ENOENT;
852         }
853
854         debug("clock %lu has rate %lu\n", id, rate);
855         return rate;
856 }
857
858 static ulong meson_clk_get_rate(struct clk *clk)
859 {
860         return meson_clk_get_rate_by_id(clk, clk->id);
861 }
862
863 static ulong meson_pcie_pll_set_rate(struct clk *clk, ulong rate)
864 {
865         struct meson_clk *priv = dev_get_priv(clk->dev);
866
867         regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x20090496);
868         regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x30090496);
869         regmap_write(priv->map, HHI_PCIE_PLL_CNTL1, 0x00000000);
870         regmap_write(priv->map, HHI_PCIE_PLL_CNTL2, 0x00001100);
871         regmap_write(priv->map, HHI_PCIE_PLL_CNTL3, 0x10058e00);
872         regmap_write(priv->map, HHI_PCIE_PLL_CNTL4, 0x000100c0);
873         regmap_write(priv->map, HHI_PCIE_PLL_CNTL5, 0x68000048);
874         regmap_write(priv->map, HHI_PCIE_PLL_CNTL5, 0x68000068);
875         udelay(20);
876         regmap_write(priv->map, HHI_PCIE_PLL_CNTL4, 0x008100c0);
877         udelay(10);
878         regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x34090496);
879         regmap_write(priv->map, HHI_PCIE_PLL_CNTL0, 0x14090496);
880         udelay(10);
881         regmap_write(priv->map, HHI_PCIE_PLL_CNTL2, 0x00001000);
882         regmap_update_bits(priv->map, HHI_PCIE_PLL_CNTL0,
883                                 0x1f << 16, 9 << 16);
884
885         return 100000000;
886 }
887
888 static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
889 {
890         return meson_mux_set_parent(clk, clk->id, parent->id);
891 }
892
893 static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
894                                       ulong rate, ulong current_rate)
895 {
896         if (current_rate == rate)
897                 return 0;
898
899         switch (id) {
900         /* Fixed clocks */
901         case CLKID_FIXED_PLL:
902         case CLKID_SYS_PLL:
903         case CLKID_FCLK_DIV2:
904         case CLKID_FCLK_DIV3:
905         case CLKID_FCLK_DIV4:
906         case CLKID_FCLK_DIV5:
907         case CLKID_FCLK_DIV7:
908         case CLKID_MPLL0:
909         case CLKID_MPLL1:
910         case CLKID_MPLL2:
911         case CLKID_CLK81:
912                 if (current_rate != rate)
913                         return -EINVAL;
914         case CLKID_PCIE_PLL:
915                 return meson_pcie_pll_set_rate(clk, rate);
916
917                 return 0;
918         case CLKID_VPU:
919                 return meson_clk_set_rate_by_id(clk,
920                                 meson_mux_get_parent(clk, CLKID_VPU), rate,
921                                                      current_rate);
922         case CLKID_VAPB:
923         case CLKID_VAPB_SEL:
924                 return meson_clk_set_rate_by_id(clk,
925                                 meson_mux_get_parent(clk, CLKID_VAPB_SEL),
926                                 rate, current_rate);
927         case CLKID_VPU_0:
928                 return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
929                                           current_rate);
930         case CLKID_VPU_1:
931                 return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
932                                           current_rate);
933         case CLKID_VAPB_0:
934                 return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
935                                           current_rate);
936         case CLKID_VAPB_1:
937                 return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
938                                           current_rate);
939         case CLKID_VPU_0_DIV:
940         case CLKID_VPU_1_DIV:
941         case CLKID_VAPB_0_DIV:
942         case CLKID_VAPB_1_DIV:
943         case CLKID_HDMI_DIV:
944                 return meson_div_set_rate(clk, id, rate, current_rate);
945         case CLKID_HDMI:
946                 return meson_clk_set_rate_by_id(clk, CLKID_HDMI_DIV,
947                                                 rate, current_rate);
948         default:
949                 return -ENOENT;
950         }
951
952         return -EINVAL;
953 }
954
955 static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
956 {
957         ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
958         int ret;
959
960         if (IS_ERR_VALUE(current_rate))
961                 return current_rate;
962
963         debug("%s: setting rate of %ld from %ld to %ld\n",
964               __func__, clk->id, current_rate, rate);
965
966         ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate);
967         if (IS_ERR_VALUE(ret))
968                 return ret;
969
970         debug("clock %lu has new rate %lu\n", clk->id,
971               meson_clk_get_rate_by_id(clk, clk->id));
972
973         return 0;
974 }
975
976 static int meson_clk_probe(struct udevice *dev)
977 {
978         struct meson_clk *priv = dev_get_priv(dev);
979
980         priv->map = syscon_node_to_regmap(dev_get_parent(dev)->node);
981         if (IS_ERR(priv->map))
982                 return PTR_ERR(priv->map);
983
984         /*
985          * Depending on the boot src, the state of the MMC clock might
986          * be different. Reset it to make sure we won't get stuck
987          */
988         regmap_write(priv->map, HHI_NAND_CLK_CNTL, 0);
989         regmap_write(priv->map, HHI_SD_EMMC_CLK_CNTL, 0);
990
991         debug("meson-clk-g12a: probed\n");
992
993         return 0;
994 }
995
996 static struct clk_ops meson_clk_ops = {
997         .disable        = meson_clk_disable,
998         .enable         = meson_clk_enable,
999         .get_rate       = meson_clk_get_rate,
1000         .set_parent     = meson_clk_set_parent,
1001         .set_rate       = meson_clk_set_rate,
1002 };
1003
1004 static const struct udevice_id meson_clk_ids[] = {
1005         { .compatible = "amlogic,g12a-clkc" },
1006         { .compatible = "amlogic,g12b-clkc" },
1007         { .compatible = "amlogic,sm1-clkc" },
1008         { }
1009 };
1010
1011 U_BOOT_DRIVER(meson_clk_g12a) = {
1012         .name           = "meson_clk_g12a",
1013         .id             = UCLASS_CLK,
1014         .of_match       = meson_clk_ids,
1015         .priv_auto_alloc_size = sizeof(struct meson_clk),
1016         .ops            = &meson_clk_ops,
1017         .probe          = meson_clk_probe,
1018 };