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