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