xref: /rk3399_rockchip-uboot/drivers/clk/rockchip/clk_rk3506.c (revision 826d54fb7246ec19f68b3bc16f5d93a9540c9e66)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2023 Rockchip Electronics Co., Ltd
4  * Author: Finley Xiao <finley.xiao@rock-chips.com>
5  */
6 
7 #include <common.h>
8 #include <clk-uclass.h>
9 #include <dm.h>
10 #include <syscon.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/cru_rk3506.h>
13 #include <asm/arch/grf_rk3506.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/io.h>
16 #include <dm/lists.h>
17 #include <dt-bindings/clock/rockchip,rk3506-cru.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 #define RK3506_CRU_BASE  0xFF9A0000
22 #define RK3506_SCRU_BASE 0xFF9A8000
23 
24 #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
25 
26 /*
27  * [FRAC PLL]: GPLL, V0PLL, V1PLL
28  *   - VCO Frequency: 950MHz to 3800MHZ
29  *   - Output Frequency: 19MHz to 3800MHZ
30  *   - refdiv: 1 to 63 (Int Mode), 1 to 2 (Frac Mode)
31  *   - fbdiv: 16 to 3800 (Int Mode), 20 to 380 (Frac Mode)
32  *   - post1div: 1 to 7
33  *   - post2div: 1 to 7
34  */
35 static struct rockchip_pll_rate_table rk3506_pll_rates[] = {
36 	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
37 	RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0),
38 	RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0),
39 	RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0),
40 	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
41 	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
42 	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
43 	RK3036_PLL_RATE(1350000000, 4, 225, 1, 1, 1, 0),
44 	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
45 	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
46 	RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
47 	RK3036_PLL_RATE(1179648000, 1, 49, 1, 1, 0, 2550137),
48 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
49 	RK3036_PLL_RATE(1000000000, 3, 125, 1, 1, 1, 0),
50 	RK3036_PLL_RATE(993484800, 1, 41, 1, 1, 0, 6630355),
51 	RK3036_PLL_RATE(983040000, 1, 40, 1, 1, 0, 16106127),
52 	RK3036_PLL_RATE(960000000, 1, 80, 2, 1, 1, 0),
53 	RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
54 	RK3036_PLL_RATE(903168000, 1, 75, 2, 1, 0, 4429185),
55 	RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
56 	RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0),
57 	RK3036_PLL_RATE(600000000, 1, 50, 2, 1, 1, 0),
58 	RK3036_PLL_RATE(594000000, 2, 99, 2, 1, 1, 0),
59 	RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
60 	RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
61 	RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
62 	RK3036_PLL_RATE(96000000, 1, 48, 6, 2, 1, 0),
63 	{ /* sentinel */ },
64 };
65 
66 static struct rockchip_pll_clock rk3506_pll_clks[] = {
67 	[GPLL] = PLL(pll_rk3328, PLL_GPLL, RK3506_PLL_CON(0),
68 		     RK3506_MODE_CON, 0, 10, 0, rk3506_pll_rates),
69 	[V0PLL] = PLL(pll_rk3328, PLL_V0PLL, RK3506_PLL_CON(8),
70 		     RK3506_MODE_CON, 2, 10, 0, rk3506_pll_rates),
71 	[V1PLL] = PLL(pll_rk3328, PLL_V1PLL, RK3506_PLL_CON(16),
72 		     RK3506_MODE_CON, 4, 10, 0, rk3506_pll_rates),
73 };
74 
75 #define RK3506_CPUCLK_RATE(_rate, _aclk_m_core, _pclk_dbg)	\
76 {								\
77 	.rate = _rate##U,					\
78 	.aclk_div = _aclk_m_core,				\
79 	.pclk_div = _pclk_dbg,					\
80 }
81 
82 /* SIGN-OFF: aclk_core: 500M, pclk_core: 125M, */
83 static struct rockchip_cpu_rate_table rk3506_cpu_rates[] = {
84 	RK3506_CPUCLK_RATE(1179648000, 1, 6),
85 	RK3506_CPUCLK_RATE(903168000, 1, 5),
86 	RK3506_CPUCLK_RATE(800000000, 1, 4),
87 	RK3506_CPUCLK_RATE(589824000, 1, 3),
88 	RK3506_CPUCLK_RATE(400000000, 1, 2),
89 	RK3506_CPUCLK_RATE(200000000, 1, 1),
90 	{ /* sentinel */ },
91 };
92 
93 #ifndef CONFIG_SPL_BUILD
94 #define RK3506_CLK_DUMP(_id, _name)		\
95 {						\
96 	.id = _id,				\
97 	.name = _name,				\
98 }
99 
100 static const struct rk3506_clk_info clks_dump[] = {
101 	RK3506_CLK_DUMP(PLL_GPLL, "gpll"),
102 	RK3506_CLK_DUMP(PLL_V0PLL, "v0pll"),
103 	RK3506_CLK_DUMP(PLL_V1PLL, "v1pll"),
104 	RK3506_CLK_DUMP(CLK_GPLL_DIV, "clk_gpll_div"),
105 	RK3506_CLK_DUMP(CLK_GPLL_DIV_100M, "clk_gpll_div_100m"),
106 	RK3506_CLK_DUMP(CLK_V0PLL_DIV, "clk_v0pll_div"),
107 	RK3506_CLK_DUMP(CLK_V1PLL_DIV, "clk_v1pll_div"),
108 	RK3506_CLK_DUMP(ACLK_BUS_ROOT, "aclk_bus_root"),
109 	RK3506_CLK_DUMP(HCLK_BUS_ROOT, "hclk_bus_root"),
110 	RK3506_CLK_DUMP(PCLK_BUS_ROOT, "pclk_bus_root"),
111 	RK3506_CLK_DUMP(ACLK_HSPERI_ROOT, "aclk_hsperi_root"),
112 	RK3506_CLK_DUMP(HCLK_LSPERI_ROOT, "hclk_ksperi_root"),
113 };
114 
115 /**
116  * soc_clk_dump() - Print clock frequencies
117  * Returns zero on success
118  *
119  * Implementation for the clk dump command.
120  */
soc_clk_dump(void)121 int soc_clk_dump(void)
122 {
123 	const struct rk3506_clk_info *clk_dump;
124 	struct rk3506_clk_priv *priv;
125 	struct udevice *cru_dev;
126 	struct clk clk;
127 	ulong clk_count = ARRAY_SIZE(clks_dump);
128 	ulong rate;
129 	int i, ret;
130 	u32 sel;
131 
132 	ret = uclass_get_device_by_driver(UCLASS_CLK,
133 					  DM_GET_DRIVER(rockchip_rk3506_cru),
134 					  &cru_dev);
135 	if (ret) {
136 		printf("%s failed to get cru device\n", __func__);
137 		return ret;
138 	}
139 
140 	priv = dev_get_priv(cru_dev);
141 	sel = (readl(&priv->cru->clksel_con[15]) &
142 	       CLK_CORE_SRC_PVTMUX_SEL_MASK) >>
143 	       CLK_CORE_SRC_PVTMUX_SEL_SHIFT;
144 	if (sel == CLK_CORE_PVTPLL_SRC)
145 		printf("CLK: (arm clk use pvtpll, rate = 1200M)\n");
146 	else
147 		printf("CLK: (%s. arm: enter %lu KHz, init %lu KHz, kernel %lu%s)\n",
148 		       priv->sync_kernel ? "sync kernel" : "uboot",
149 		       priv->armclk_enter_hz / 1000,
150 		       priv->armclk_init_hz / 1000,
151 		       priv->set_armclk_rate ? priv->armclk_hz / 1000 : 0,
152 		       priv->set_armclk_rate ? " KHz" : "N/A");
153 	for (i = 0; i < clk_count; i++) {
154 		clk_dump = &clks_dump[i];
155 		if (clk_dump->name) {
156 			clk.id = clk_dump->id;
157 			ret = clk_request(cru_dev, &clk);
158 			if (ret < 0)
159 				return ret;
160 
161 			rate = clk_get_rate(&clk);
162 			clk_free(&clk);
163 			if (i == 0) {
164 				if (rate < 0)
165 					printf("  %s %s\n", clk_dump->name,
166 					       "unknown");
167 				else
168 					printf("  %s %lu KHz\n", clk_dump->name,
169 					       rate / 1000);
170 			} else {
171 				if (rate < 0)
172 					printf("  %s %s\n", clk_dump->name,
173 					       "unknown");
174 				else
175 					printf("  %s %lu KHz\n", clk_dump->name,
176 					       rate / 1000);
177 			}
178 		}
179 	}
180 
181 	return 0;
182 }
183 #endif
184 
rk3506_armclk_get_rate(struct rk3506_clk_priv * priv)185 static int rk3506_armclk_get_rate(struct rk3506_clk_priv *priv)
186 {
187 	struct rk3506_cru *cru = priv->cru;
188 	u32 sel, con, div;
189 	ulong prate;
190 
191 	con = readl(&cru->clksel_con[15]);
192 	sel = (con & CLK_CORE_SRC_SEL_MASK) >> CLK_CORE_SRC_SEL_SHIFT;
193 	div = (con & CLK_CORE_SRC_DIV_MASK) >> CLK_CORE_SRC_DIV_SHIFT;
194 
195 	if (sel == CLK_CORE_SEL_GPLL)
196 		prate = priv->gpll_hz;
197 	else if (sel ==  CLK_CORE_SEL_V0PLL)
198 		prate = priv->v0pll_hz;
199 	else if (sel ==  CLK_CORE_SEL_V1PLL)
200 		prate = priv->v1pll_hz;
201 	else
202 		return -EINVAL;
203 
204 	return DIV_TO_RATE(prate, div);
205 }
206 
rk3506_armclk_set_rate(struct rk3506_clk_priv * priv,ulong new_rate)207 static int rk3506_armclk_set_rate(struct rk3506_clk_priv *priv, ulong new_rate)
208 {
209 	const struct rockchip_cpu_rate_table *rate;
210 	struct rk3506_cru *cru = priv->cru;
211 	ulong old_rate, prate;
212 	u32 con, sel, div, old_div;
213 
214 	rate = rockchip_get_cpu_settings(rk3506_cpu_rates, new_rate);
215 	if (!rate) {
216 		printf("%s unsupported rate\n", __func__);
217 		return -EINVAL;
218 	}
219 
220 	/*
221 	 * set up dependent divisors for PCLK and ACLK clocks.
222 	 */
223 	old_rate = rk3506_armclk_get_rate(priv);
224 	if (new_rate >= old_rate) {
225 		rk_clrsetreg(&cru->clksel_con[15], ACLK_CORE_DIV_MASK,
226 			     rate->aclk_div << ACLK_CORE_DIV_SHIFT);
227 		rk_clrsetreg(&cru->clksel_con[16], PCLK_CORE_DIV_MASK,
228 			     rate->pclk_div << PCLK_CORE_DIV_SHIFT);
229 	}
230 
231 	if (new_rate == 589824000 || new_rate == 1179648000) {
232 		sel = CLK_CORE_SEL_V0PLL;
233 		div = DIV_ROUND_UP(priv->v0pll_hz, new_rate);
234 		prate = priv->v0pll_hz;
235 	} else if (new_rate == 903168000) {
236 		sel = CLK_CORE_SEL_V1PLL;
237 		div = DIV_ROUND_UP(priv->v1pll_hz, new_rate);
238 		prate = priv->v1pll_hz;
239 	} else {
240 		sel = CLK_CORE_SEL_GPLL;
241 		div = DIV_ROUND_UP(priv->gpll_hz, new_rate);
242 		prate = priv->gpll_hz;
243 	}
244 	assert(div - 1 <= 31);
245 
246 	con = readl(&cru->clksel_con[15]);
247 	old_div = (con & CLK_CORE_SRC_DIV_MASK) >> CLK_CORE_SRC_DIV_SHIFT;
248 	if (DIV_TO_RATE(prate, old_div) > new_rate) {
249 		rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_DIV_MASK,
250 			     (div - 1) << CLK_CORE_SRC_DIV_SHIFT);
251 		rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_SEL_MASK,
252 			     sel << CLK_CORE_SRC_SEL_SHIFT);
253 	} else {
254 		rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_SEL_MASK,
255 			     sel << CLK_CORE_SRC_SEL_SHIFT);
256 		rk_clrsetreg(&cru->clksel_con[15], CLK_CORE_SRC_DIV_MASK,
257 			     (div - 1) << CLK_CORE_SRC_DIV_SHIFT);
258 	}
259 
260 	if (new_rate < old_rate) {
261 		rk_clrsetreg(&cru->clksel_con[15], ACLK_CORE_DIV_MASK,
262 			     rate->aclk_div << ACLK_CORE_DIV_SHIFT);
263 		rk_clrsetreg(&cru->clksel_con[16], PCLK_CORE_DIV_MASK,
264 			     rate->pclk_div << PCLK_CORE_DIV_SHIFT);
265 	}
266 
267 	return 0;
268 }
269 
rk3506_pll_div_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)270 static ulong rk3506_pll_div_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
271 {
272 	struct rk3506_cru *cru = priv->cru;
273 	u32 con, div;
274 	ulong prate;
275 
276 	switch (clk_id) {
277 	case CLK_GPLL_DIV:
278 		con = readl(&cru->clksel_con[0]);
279 		div = (con & CLK_GPLL_DIV_MASK) >> CLK_GPLL_DIV_SHIFT;
280 		prate = priv->gpll_hz;
281 		break;
282 	case CLK_GPLL_DIV_100M:
283 		con = readl(&cru->clksel_con[0]);
284 		div = (con & CLK_GPLL_DIV_100M_MASK) >> CLK_GPLL_DIV_100M_SHIFT;
285 		prate = priv->gpll_div_hz;
286 		break;
287 	case CLK_V0PLL_DIV:
288 		con = readl(&cru->clksel_con[1]);
289 		div = (con & CLK_V0PLL_DIV_MASK) >> CLK_V0PLL_DIV_SHIFT;
290 		prate = priv->v0pll_hz;
291 		break;
292 	case CLK_V1PLL_DIV:
293 		con = readl(&cru->clksel_con[1]);
294 		div = (con & CLK_V1PLL_DIV_MASK) >> CLK_V1PLL_DIV_SHIFT;
295 		prate = priv->v1pll_hz;
296 		break;
297 	default:
298 		return -ENOENT;
299 	}
300 
301 	return DIV_TO_RATE(prate, div);
302 }
303 
rk3506_pll_div_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)304 static ulong rk3506_pll_div_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
305 				 ulong rate)
306 {
307 	struct rk3506_cru *cru = priv->cru;
308 	u32 div;
309 
310 	switch (clk_id) {
311 	case CLK_GPLL_DIV:
312 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
313 		assert(div - 1 <= 15);
314 		rk_clrsetreg(&cru->clksel_con[0], CLK_GPLL_DIV_MASK,
315 			     ((div - 1) << CLK_GPLL_DIV_SHIFT));
316 		break;
317 	case CLK_GPLL_DIV_100M:
318 		div = DIV_ROUND_UP(priv->gpll_div_hz, rate);
319 		assert(div - 1 <= 15);
320 		rk_clrsetreg(&cru->clksel_con[0], CLK_GPLL_DIV_100M_MASK,
321 			     ((div - 1) << CLK_GPLL_DIV_100M_SHIFT));
322 		break;
323 	case CLK_V0PLL_DIV:
324 		div = DIV_ROUND_UP(priv->v0pll_hz, rate);
325 		assert(div - 1 <= 15);
326 		rk_clrsetreg(&cru->clksel_con[1], CLK_V0PLL_DIV_MASK,
327 			     ((div - 1) << CLK_V0PLL_DIV_SHIFT));
328 		break;
329 	case CLK_V1PLL_DIV:
330 		div = DIV_ROUND_UP(priv->v1pll_hz, rate);
331 		assert(div - 1 <= 15);
332 		rk_clrsetreg(&cru->clksel_con[1], CLK_V1PLL_DIV_MASK,
333 			     ((div - 1) << CLK_V1PLL_DIV_SHIFT));
334 		break;
335 	default:
336 		return -ENOENT;
337 	}
338 
339 	return rk3506_pll_div_get_rate(priv, clk_id);
340 }
341 
rk3506_bus_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)342 static ulong rk3506_bus_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
343 {
344 	struct rk3506_cru *cru = priv->cru;
345 	u32 sel, con, div;
346 	ulong prate;
347 
348 	switch (clk_id) {
349 	case ACLK_BUS_ROOT:
350 		con = readl(&cru->clksel_con[21]);
351 		sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT;
352 		div = (con & ACLK_BUS_DIV_MASK) >> ACLK_BUS_DIV_SHIFT;
353 		break;
354 	case HCLK_BUS_ROOT:
355 		con = readl(&cru->clksel_con[21]);
356 		sel = (con & HCLK_BUS_SEL_MASK) >> HCLK_BUS_SEL_SHIFT;
357 		div = (con & HCLK_BUS_DIV_MASK) >> HCLK_BUS_DIV_SHIFT;
358 		break;
359 	case PCLK_BUS_ROOT:
360 		con = readl(&cru->clksel_con[22]);
361 		sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT;
362 		div = (con & PCLK_BUS_DIV_MASK) >> PCLK_BUS_DIV_SHIFT;
363 		break;
364 	default:
365 		return -ENOENT;
366 	}
367 
368 	if (sel == ACLK_BUS_SEL_GPLL_DIV)
369 		prate = priv->gpll_div_hz;
370 	else if (sel == ACLK_BUS_SEL_V0PLL_DIV)
371 		prate = priv->v0pll_div_hz;
372 	else if (sel == ACLK_BUS_SEL_V1PLL_DIV)
373 		prate = priv->v1pll_div_hz;
374 	else
375 		return -EINVAL;
376 
377 	return DIV_TO_RATE(prate, div);
378 }
379 
rk3506_bus_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)380 static ulong rk3506_bus_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
381 				 ulong rate)
382 {
383 	struct rk3506_cru *cru = priv->cru;
384 	u32 sel, div;
385 
386 	if (priv->v0pll_div_hz % rate == 0) {
387 		sel = ACLK_BUS_SEL_V0PLL_DIV;
388 		div = DIV_ROUND_UP(priv->v0pll_div_hz, rate);
389 	} else if (priv->v1pll_div_hz % rate == 0) {
390 		sel= ACLK_BUS_SEL_V1PLL_DIV;
391 		div = DIV_ROUND_UP(priv->v1pll_div_hz, rate);
392 	} else {
393 		sel= ACLK_BUS_SEL_GPLL_DIV;
394 		div = DIV_ROUND_UP(priv->gpll_div_hz, rate);
395 	}
396 	assert(div - 1 <= 31);
397 
398 	switch (clk_id) {
399 	case ACLK_BUS_ROOT:
400 		rk_clrsetreg(&cru->clksel_con[21],
401 			     ACLK_BUS_DIV_MASK | ACLK_BUS_SEL_MASK,
402 			     (sel << ACLK_BUS_SEL_SHIFT) |
403 			     ((div - 1) << ACLK_BUS_DIV_SHIFT));
404 		break;
405 	case HCLK_BUS_ROOT:
406 		rk_clrsetreg(&cru->clksel_con[21],
407 			     HCLK_BUS_SEL_MASK | HCLK_BUS_DIV_MASK,
408 			     (sel << HCLK_BUS_SEL_SHIFT) |
409 			     ((div - 1) << HCLK_BUS_DIV_SHIFT));
410 		break;
411 	case PCLK_BUS_ROOT:
412 		rk_clrsetreg(&cru->clksel_con[22],
413 			     PCLK_BUS_SEL_MASK | PCLK_BUS_DIV_MASK,
414 			     (sel << PCLK_BUS_SEL_SHIFT) |
415 			     ((div - 1) << PCLK_BUS_DIV_SHIFT));
416 		break;
417 	default:
418 		return -ENOENT;
419 	}
420 
421 	return rk3506_bus_get_rate(priv, clk_id);
422 }
423 
rk3506_peri_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)424 static ulong rk3506_peri_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
425 {
426 	struct rk3506_cru *cru = priv->cru;
427 	u32 sel, con, div;
428 	ulong prate;
429 
430 	switch (clk_id) {
431 	case ACLK_HSPERI_ROOT:
432 		con = readl(&cru->clksel_con[49]);
433 		sel = (con & ACLK_HSPERI_SEL_MASK) >> ACLK_HSPERI_SEL_SHIFT;
434 		div = (con & ACLK_HSPERI_DIV_MASK) >> ACLK_HSPERI_DIV_SHIFT;
435 		break;
436 	case HCLK_LSPERI_ROOT:
437 		con = readl(&cru->clksel_con[29]);
438 		sel = (con & HCLK_LSPERI_SEL_MASK) >> HCLK_LSPERI_SEL_SHIFT;
439 		div = (con & HCLK_LSPERI_DIV_MASK) >> HCLK_LSPERI_DIV_SHIFT;
440 		break;
441 	default:
442 		return -ENOENT;
443 	}
444 
445 	if (sel == ACLK_HSPERI_SEL_GPLL_DIV)
446 		prate = priv->gpll_div_hz;
447 	else if (sel == ACLK_HSPERI_SEL_V0PLL_DIV)
448 		prate = priv->v0pll_div_hz;
449 	else if (sel == ACLK_HSPERI_SEL_V1PLL_DIV)
450 		prate = priv->v1pll_div_hz;
451 	else
452 		return -EINVAL;
453 
454 	return DIV_TO_RATE(prate, div);
455 }
456 
rk3506_peri_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)457 static ulong rk3506_peri_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
458 				  ulong rate)
459 {
460 	struct rk3506_cru *cru = priv->cru;
461 	u32 sel, div;
462 
463 	if (priv->v0pll_div_hz % rate == 0) {
464 		sel = ACLK_BUS_SEL_V0PLL_DIV;
465 		div = DIV_ROUND_UP(priv->v0pll_div_hz, rate);
466 	} else if (priv->v1pll_div_hz % rate == 0) {
467 		sel = ACLK_BUS_SEL_V1PLL_DIV;
468 		div = DIV_ROUND_UP(priv->v1pll_div_hz, rate);
469 	} else {
470 		sel = ACLK_BUS_SEL_GPLL_DIV;
471 		div = DIV_ROUND_UP(priv->gpll_div_hz, rate);
472 	}
473 	assert(div - 1 <= 31);
474 
475 	switch (clk_id) {
476 	case ACLK_HSPERI_ROOT:
477 		rk_clrsetreg(&cru->clksel_con[49],
478 			     ACLK_HSPERI_SEL_MASK | ACLK_HSPERI_DIV_MASK,
479 			     (sel << ACLK_HSPERI_SEL_SHIFT) |
480 			     ((div - 1) << ACLK_HSPERI_DIV_SHIFT));
481 		break;
482 	case HCLK_LSPERI_ROOT:
483 		rk_clrsetreg(&cru->clksel_con[29],
484 			     HCLK_LSPERI_SEL_MASK | HCLK_LSPERI_DIV_MASK,
485 			     (sel << HCLK_LSPERI_SEL_SHIFT) |
486 			     ((div - 1) << HCLK_LSPERI_DIV_SHIFT));
487 		break;
488 	default:
489 		return -ENOENT;
490 	}
491 
492 	return rk3506_peri_get_rate(priv, clk_id);
493 }
494 
rk3506_sdmmc_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)495 static ulong rk3506_sdmmc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
496 {
497 	struct rk3506_cru *cru = priv->cru;
498 	u32 sel, con, div;
499 	ulong prate;
500 
501 	con = readl(&cru->clksel_con[49]);
502 	sel = (con & CCLK_SDMMC_SEL_MASK) >> CCLK_SDMMC_SEL_SHIFT;
503 	div = (con & CCLK_SDMMC_DIV_MASK) >> CCLK_SDMMC_DIV_SHIFT;
504 
505 	if (sel == CCLK_SDMMC_SEL_24M)
506 		prate = OSC_HZ;
507 	else if (sel == CCLK_SDMMC_SEL_GPLL)
508 		prate = priv->gpll_hz;
509 	else if (sel == CCLK_SDMMC_SEL_V0PLL)
510 		prate = priv->v0pll_hz;
511 	else if (sel == CCLK_SDMMC_SEL_V1PLL)
512 		prate = priv->v1pll_hz;
513 	else
514 		return -EINVAL;
515 
516 	return DIV_TO_RATE(prate, div);
517 }
518 
rk3506_sdmmc_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)519 static ulong rk3506_sdmmc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
520 				  ulong rate)
521 {
522 	struct rk3506_cru *cru = priv->cru;
523 	u32 sel, div;
524 
525 	if (OSC_HZ % rate == 0) {
526 		sel = CCLK_SDMMC_SEL_24M;
527 		div = DIV_ROUND_UP(OSC_HZ, rate);
528 	} else if (priv->v0pll_hz % rate == 0) {
529 		sel = CCLK_SDMMC_SEL_V0PLL;
530 		div = DIV_ROUND_UP(priv->v0pll_hz, rate);
531 	} else if (priv->v1pll_hz % rate == 0) {
532 		sel= CCLK_SDMMC_SEL_V1PLL;
533 		div = DIV_ROUND_UP(priv->v1pll_hz, rate);
534 	} else {
535 		sel= CCLK_SDMMC_SEL_GPLL;
536 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
537 	}
538 	assert(div - 1 <= 63);
539 
540 	rk_clrsetreg(&cru->clksel_con[49],
541 		     CCLK_SDMMC_SEL_MASK | CCLK_SDMMC_DIV_MASK,
542 		     (sel << CCLK_SDMMC_SEL_SHIFT) |
543 		     ((div - 1) << CCLK_SDMMC_DIV_SHIFT));
544 
545 	return rk3506_sdmmc_get_rate(priv, clk_id);
546 }
547 
rk3506_saradc_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)548 static ulong rk3506_saradc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
549 {
550 	struct rk3506_cru *cru = priv->cru;
551 	u32 div, con, sel;
552 	ulong prate;
553 
554 	con = readl(&cru->clksel_con[54]);
555 	div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
556 	sel = (con & CLK_SARADC_SEL_MASK) >> CLK_SARADC_SEL_SHIFT;
557 
558 	if (sel == CLK_SARADC_SEL_24M)
559 		prate = OSC_HZ;
560 	else if (sel == CLK_SARADC_SEL_400K)
561 		prate = 400000;
562 	else if (sel == CLK_SARADC_SEL_32K)
563 		prate = 32000;
564 	else
565 		return -EINVAL;
566 
567 	return DIV_TO_RATE(prate, div);
568 }
569 
rk3506_saradc_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)570 static ulong rk3506_saradc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
571 				    ulong rate)
572 {
573 	struct rk3506_cru *cru = priv->cru;
574 	u32 div, sel;
575 
576 	if (32000 % rate == 0) {
577 		sel = CLK_SARADC_SEL_32K;
578 		div = 1;
579 	} else if (400000 % rate == 0) {
580 		sel = CLK_SARADC_SEL_400K;
581 		div = 1;
582 	} else {
583 		sel= CLK_SARADC_SEL_24M;
584 		div = DIV_ROUND_UP(OSC_HZ, rate);
585 	}
586 	assert(div - 1 <= 15);
587 
588 	rk_clrsetreg(&cru->clksel_con[54],
589 		     CLK_SARADC_SEL_MASK | CLK_SARADC_DIV_MASK,
590 		     (sel << CLK_SARADC_SEL_SHIFT) |
591 		     ((div - 1) << CLK_SARADC_DIV_SHIFT));
592 
593 	return rk3506_saradc_get_rate(priv, clk_id);
594 }
595 
rk3506_tsadc_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)596 static ulong rk3506_tsadc_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
597 {
598 	struct rk3506_cru *cru = priv->cru;
599 	u32 div, con;
600 
601 	con = readl(&cru->clksel_con[61]);
602 	switch (clk_id) {
603 	case CLK_TSADC_TSEN:
604 		div = (con & CLK_TSADC_TSEN_DIV_MASK) >> CLK_TSADC_TSEN_DIV_SHIFT;
605 		break;
606 	case CLK_TSADC:
607 		div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT;
608 		break;
609 	default:
610 		return -ENOENT;
611 	}
612 
613 	return DIV_TO_RATE(OSC_HZ, div);
614 }
615 
rk3506_tsadc_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)616 static ulong rk3506_tsadc_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
617 				   ulong rate)
618 {
619 	struct rk3506_cru *cru = priv->cru;
620 	u32 div;
621 
622 	switch (clk_id) {
623 	case CLK_TSADC_TSEN:
624 		div = DIV_ROUND_UP(OSC_HZ, rate);
625 		assert(div - 1 <= 7);
626 		rk_clrsetreg(&cru->clksel_con[61], CLK_TSADC_TSEN_DIV_MASK,
627 			     (div - 1) << CLK_TSADC_TSEN_DIV_SHIFT);
628 		break;
629 	case CLK_TSADC:
630 		div = DIV_ROUND_UP(OSC_HZ, rate);
631 		assert(div - 1 <= 255);
632 		rk_clrsetreg(&cru->clksel_con[61], CLK_TSADC_DIV_MASK,
633 			     (div - 1) << CLK_TSADC_DIV_SHIFT);
634 		break;
635 	default:
636 		return -ENOENT;
637 	}
638 
639 
640 	return rk3506_tsadc_get_rate(priv, clk_id);
641 }
642 
rk3506_i2c_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)643 static ulong rk3506_i2c_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
644 {
645 	struct rk3506_cru *cru = priv->cru;
646 	u32 sel, con, div;
647 	ulong prate;
648 
649 	switch (clk_id) {
650 	case CLK_I2C0:
651 		con = readl(&cru->clksel_con[32]);
652 		sel = (con & CLK_I2C0_SEL_MASK) >> CLK_I2C0_SEL_SHIFT;
653 		div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
654 	case CLK_I2C1:
655 		con = readl(&cru->clksel_con[32]);
656 		sel = (con & CLK_I2C1_SEL_MASK) >> CLK_I2C1_SEL_SHIFT;
657 		div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT;
658 	case CLK_I2C2:
659 		con = readl(&cru->clksel_con[33]);
660 		sel = (con & CLK_I2C2_SEL_MASK) >> CLK_I2C2_SEL_SHIFT;
661 		div = (con & CLK_I2C2_DIV_MASK) >> CLK_I2C2_DIV_SHIFT;
662 		break;
663 	default:
664 		return -ENOENT;
665 	}
666 
667 	if (sel == CLK_I2C_SEL_GPLL)
668 		prate = priv->gpll_hz;
669 	else if (sel == CLK_I2C_SEL_V0PLL)
670 		prate = priv->v0pll_hz;
671 	else if (sel == CLK_I2C_SEL_V1PLL)
672 		prate = priv->v1pll_hz;
673 	else
674 		return -EINVAL;
675 
676 	return DIV_TO_RATE(prate, div);
677 }
678 
rk3506_i2c_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)679 static ulong rk3506_i2c_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
680 				 ulong rate)
681 {
682 	struct rk3506_cru *cru = priv->cru;
683 	u32 sel, div;
684 
685 	if (priv->v0pll_hz % rate == 0) {
686 		sel = CLK_I2C_SEL_V0PLL;
687 		div = DIV_ROUND_UP(priv->v0pll_hz, rate);
688 	} else if (priv->v1pll_hz % rate == 0) {
689 		sel = CLK_I2C_SEL_V1PLL;
690 		div = DIV_ROUND_UP(priv->v1pll_hz, rate);
691 	} else {
692 		sel = CLK_I2C_SEL_GPLL;
693 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
694 	}
695 	assert(div - 1 <= 15);
696 
697 	switch (clk_id) {
698 	case CLK_I2C0:
699 		rk_clrsetreg(&cru->clksel_con[32],
700 			     CLK_I2C0_SEL_MASK | CLK_I2C0_DIV_MASK,
701 			     (sel << CLK_I2C0_SEL_SHIFT) |
702 			     ((div - 1) << CLK_I2C0_DIV_SHIFT));
703 		break;
704 	case CLK_I2C1:
705 		rk_clrsetreg(&cru->clksel_con[32],
706 			     CLK_I2C1_SEL_MASK | CLK_I2C1_DIV_MASK,
707 			     (sel << CLK_I2C1_SEL_SHIFT) |
708 			     ((div - 1) << CLK_I2C1_DIV_SHIFT));
709 		break;
710 	case CLK_I2C2:
711 		rk_clrsetreg(&cru->clksel_con[33],
712 			     CLK_I2C2_SEL_MASK | CLK_I2C2_DIV_MASK,
713 			     (sel << CLK_I2C2_SEL_SHIFT) |
714 			     ((div - 1) << CLK_I2C2_DIV_SHIFT));
715 		break;
716 	default:
717 		return -ENOENT;
718 	}
719 
720 
721 	return rk3506_i2c_get_rate(priv, clk_id);
722 }
723 
rk3506_pwm_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)724 static ulong rk3506_pwm_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
725 {
726 	struct rk3506_cru *cru = priv->cru;
727 	u32 sel, con, div;
728 	ulong prate;
729 
730 	switch (clk_id) {
731 	case CLK_PWM0:
732 		con = readl(&cru->pmuclksel_con[0]);
733 		div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
734 		prate = priv->gpll_div_100mhz;
735 		break;
736 	case CLK_PWM1:
737 		con = readl(&cru->clksel_con[33]);
738 		sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
739 		div = (con & CLK_PWM1_DIV_MASK) >> CLK_PWM1_DIV_SHIFT;
740 		if (sel == CLK_PWM1_SEL_GPLL_DIV)
741 			prate = priv->gpll_div_hz;
742 		else if (sel == CLK_PWM1_SEL_V0PLL_DIV)
743 			prate = priv->v0pll_div_hz;
744 		else if (sel == CLK_PWM1_SEL_V1PLL_DIV)
745 			prate = priv->v1pll_div_hz;
746 		else
747 			return -EINVAL;
748 		break;
749 	default:
750 		return -ENOENT;
751 	}
752 
753 	return DIV_TO_RATE(prate, div);
754 }
755 
rk3506_pwm_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)756 static ulong rk3506_pwm_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
757 				 ulong rate)
758 {
759 	struct rk3506_cru *cru = priv->cru;
760 	u32 sel, div;
761 
762 	switch (clk_id) {
763 	case CLK_PWM0:
764 		div = DIV_ROUND_UP(priv->gpll_div_100mhz, rate);
765 		assert(div - 1 <= 15);
766 		rk_clrsetreg(&cru->pmuclksel_con[0], CLK_PWM0_DIV_MASK,
767 			     (div - 1) << CLK_PWM0_DIV_SHIFT);
768 		break;
769 	case CLK_PWM1:
770 		if (priv->v0pll_hz % rate == 0) {
771 			sel = CLK_PWM1_SEL_V0PLL_DIV;
772 			div = DIV_ROUND_UP(priv->v0pll_div_hz, rate);
773 		} else if (priv->v1pll_hz % rate == 0) {
774 			sel = CLK_PWM1_SEL_V1PLL_DIV;
775 			div = DIV_ROUND_UP(priv->v1pll_div_hz, rate);
776 		} else {
777 			sel = CLK_PWM1_SEL_GPLL_DIV;
778 			div = DIV_ROUND_UP(priv->gpll_div_hz, rate);
779 		}
780 		assert(div - 1 <= 15);
781 		rk_clrsetreg(&cru->clksel_con[33],
782 			     CLK_PWM1_SEL_MASK | CLK_PWM1_DIV_MASK,
783 			     (sel << CLK_PWM1_SEL_SHIFT) |
784 			     ((div - 1) << CLK_PWM1_DIV_SHIFT));
785 		break;
786 	default:
787 		return -ENOENT;
788 	}
789 
790 	return rk3506_pwm_get_rate(priv, clk_id);
791 }
792 
rk3506_spi_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)793 static ulong rk3506_spi_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
794 {
795 	struct rk3506_cru *cru = priv->cru;
796 	u32 sel, con, div;
797 	ulong prate;
798 
799 	switch (clk_id) {
800 	case CLK_SPI0:
801 		con = readl(&cru->clksel_con[34]);
802 		sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT;
803 		div = (con & CLK_SPI0_DIV_MASK) >> CLK_SPI0_DIV_SHIFT;
804 		break;
805 	case CLK_SPI1:
806 		con = readl(&cru->clksel_con[34]);
807 		sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT;
808 		div = (con & CLK_SPI1_DIV_MASK) >> CLK_SPI1_DIV_SHIFT;
809 		break;
810 	default:
811 		return -ENOENT;
812 	}
813 
814 	if (sel == CLK_SPI_SEL_24M)
815 		prate = OSC_HZ;
816 	else if (sel == CLK_SPI_SEL_GPLL_DIV)
817 		prate = priv->gpll_div_hz;
818 	else if (sel == CLK_SPI_SEL_V0PLL_DIV)
819 		prate = priv->v0pll_div_hz;
820 	else if (sel == CLK_SPI_SEL_V1PLL_DIV)
821 		prate = priv->v1pll_div_hz;
822 	else
823 		return -EINVAL;
824 
825 	return DIV_TO_RATE(prate, div);
826 }
827 
rk3506_spi_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)828 static ulong rk3506_spi_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
829 				 ulong rate)
830 {
831 	struct rk3506_cru *cru = priv->cru;
832 	u32 sel, div;
833 
834 	if (OSC_HZ % rate == 0) {
835 		sel = CLK_SPI_SEL_24M;
836 		div = DIV_ROUND_UP(OSC_HZ, rate);
837 	} else if (priv->v0pll_div_hz % rate == 0) {
838 		sel = CLK_SPI_SEL_V0PLL_DIV;
839 		div = DIV_ROUND_UP(priv->v0pll_div_hz, rate);
840 	} else if (priv->v1pll_div_hz % rate == 0) {
841 		sel = CLK_SPI_SEL_V1PLL_DIV;
842 		div = DIV_ROUND_UP(priv->v1pll_div_hz, rate);
843 	} else {
844 		sel = CLK_SPI_SEL_GPLL_DIV;
845 		div = DIV_ROUND_UP(priv->gpll_div_hz, rate);
846 	}
847 	assert(div - 1 <= 15);
848 
849 	switch (clk_id) {
850 	case CLK_SPI0:
851 		rk_clrsetreg(&cru->clksel_con[34],
852 			     CLK_SPI0_SEL_MASK | CLK_SPI0_DIV_MASK,
853 			     (sel << CLK_SPI0_SEL_SHIFT) |
854 			     ((div - 1) << CLK_SPI0_DIV_SHIFT));
855 		break;
856 	case CLK_SPI1:
857 		rk_clrsetreg(&cru->clksel_con[34],
858 			     CLK_SPI1_SEL_MASK | CLK_SPI1_DIV_MASK,
859 			     (sel << CLK_SPI1_SEL_SHIFT) |
860 			     ((div - 1) << CLK_SPI1_DIV_SHIFT));
861 		break;
862 	default:
863 		return -ENOENT;
864 	}
865 
866 	return rk3506_spi_get_rate(priv, clk_id);
867 }
868 
rk3506_fspi_get_rate(struct rk3506_clk_priv * priv)869 static ulong rk3506_fspi_get_rate(struct rk3506_clk_priv *priv)
870 {
871 	struct rk3506_cru *cru = priv->cru;
872 	u32 div, sel, con, prate;
873 
874 	con = readl(&cru->clksel_con[50]);
875 	div = (con & SCLK_FSPI_DIV_MASK) >> SCLK_FSPI_DIV_SHIFT;
876 	sel = (con & SCLK_FSPI_SEL_MASK) >> SCLK_FSPI_SEL_SHIFT;
877 	if (sel == SCLK_FSPI_SEL_24M)
878 		prate = OSC_HZ;
879 	else if (sel == SCLK_FSPI_SEL_GPLL)
880 		prate = priv->gpll_hz;
881 	else if (sel == SCLK_FSPI_SEL_V0PLL)
882 		prate = priv->v0pll_hz;
883 	else if (sel == SCLK_FSPI_SEL_V1PLL)
884 		prate = priv->v1pll_hz;
885 	else
886 		return -EINVAL;
887 
888 	return DIV_TO_RATE(prate, div);
889 }
890 
rk3506_fspi_set_rate(struct rk3506_clk_priv * priv,ulong rate)891 static ulong rk3506_fspi_set_rate(struct rk3506_clk_priv *priv, ulong rate)
892 {
893 	struct rk3506_cru *cru = priv->cru;
894 	int div, sel;
895 
896 	if (OSC_HZ % rate == 0) {
897 		sel = SCLK_FSPI_SEL_24M;
898 		div = DIV_ROUND_UP(OSC_HZ, rate);
899 	} else if ((priv->v0pll_hz % rate) == 0) {
900 		sel = SCLK_FSPI_SEL_V0PLL;
901 		div = DIV_ROUND_UP(priv->v0pll_hz, rate);
902 	} else if ((priv->v1pll_hz % rate) == 0) {
903 		sel = SCLK_FSPI_SEL_V1PLL;
904 		div = DIV_ROUND_UP(priv->v1pll_hz, rate);
905 	} else {
906 		sel = SCLK_FSPI_SEL_GPLL;
907 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
908 	}
909 	assert(div - 1 <= 31);
910 
911 	rk_clrsetreg(&cru->clksel_con[50],
912 		     SCLK_FSPI_SEL_MASK | SCLK_FSPI_DIV_MASK,
913 		     sel << SCLK_FSPI_SEL_SHIFT |
914 		     (div - 1) << SCLK_FSPI_DIV_SHIFT);
915 
916 	return rk3506_fspi_get_rate(priv);
917 }
918 
rk3506_vop_dclk_get_rate(struct rk3506_clk_priv * priv)919 static ulong rk3506_vop_dclk_get_rate(struct rk3506_clk_priv *priv)
920 {
921 	struct rk3506_cru *cru = priv->cru;
922 	u32 div, sel, con, prate;
923 
924 	con = readl(&cru->clksel_con[60]);
925 	div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
926 	sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
927 
928 	if (sel == DCLK_VOP_SEL_24M)
929 		prate = OSC_HZ;
930 	else if (sel == DCLK_VOP_SEL_GPLL)
931 		prate = priv->gpll_hz;
932 	else if (sel == DCLK_VOP_SEL_V0PLL)
933 		prate = priv->v0pll_hz;
934 	else if (sel == DCLK_VOP_SEL_V1PLL)
935 		prate = priv->v1pll_hz;
936 	else
937 		return -EINVAL;
938 
939 	return DIV_TO_RATE(prate, div);
940 }
941 
rk3506_vop_dclk_set_rate(struct rk3506_clk_priv * priv,ulong rate)942 static ulong rk3506_vop_dclk_set_rate(struct rk3506_clk_priv *priv, ulong rate)
943 {
944 	struct rk3506_cru *cru = priv->cru;
945 	int div, sel;
946 
947 	if (OSC_HZ % rate == 0) {
948 		sel = DCLK_VOP_SEL_24M;
949 		div = DIV_ROUND_UP(OSC_HZ, rate);
950 	} else if ((priv->v0pll_hz % rate) == 0) {
951 		sel = DCLK_VOP_SEL_V0PLL;
952 		div = DIV_ROUND_UP(priv->v0pll_hz, rate);
953 	} else if ((priv->v1pll_hz % rate) == 0) {
954 		sel = DCLK_VOP_SEL_V1PLL;
955 		div = DIV_ROUND_UP(priv->v1pll_hz, rate);
956 	} else {
957 		sel = DCLK_VOP_SEL_GPLL;
958 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
959 	}
960 	assert(div - 1 <= 255);
961 
962 	rk_clrsetreg(&cru->clksel_con[60],
963 		     DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK,
964 		     sel << DCLK_VOP_SEL_SHIFT |
965 		     (div - 1) << DCLK_VOP_DIV_SHIFT);
966 
967 	return rk3506_vop_dclk_get_rate(priv);
968 }
969 
rk3506_mac_get_rate(struct rk3506_clk_priv * priv,ulong clk_id)970 static ulong rk3506_mac_get_rate(struct rk3506_clk_priv *priv, ulong clk_id)
971 {
972 	struct rk3506_cru *cru = priv->cru;
973 	u32 div, con;
974 
975 	switch (clk_id) {
976 	case CLK_MAC0:
977 	case CLK_MAC1:
978 		con = readl(&cru->clksel_con[50]);
979 		div = (con & CLK_MAC_DIV_MASK) >> CLK_MAC_DIV_SHIFT;
980 		break;
981 	case CLK_MAC_OUT:
982 		con = readl(&cru->pmuclksel_con[0]);
983 		div = (con & CLK_MAC_OUT_DIV_MASK) >> CLK_MAC_OUT_DIV_SHIFT;
984 		break;
985 	default:
986 		return -ENOENT;
987 	}
988 
989 	return DIV_TO_RATE(priv->gpll_hz, div);
990 }
991 
rk3506_mac_set_rate(struct rk3506_clk_priv * priv,ulong clk_id,ulong rate)992 static ulong rk3506_mac_set_rate(struct rk3506_clk_priv *priv, ulong clk_id,
993 				 ulong rate)
994 {
995 	struct rk3506_cru *cru = priv->cru;
996 	u32 div;
997 
998 	switch (clk_id) {
999 	case CLK_MAC0:
1000 	case CLK_MAC1:
1001 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1002 		rk_clrsetreg(&cru->clksel_con[50], CLK_MAC_DIV_MASK,
1003 			     ((div - 1) << CLK_MAC_DIV_SHIFT));
1004 		break;
1005 	case CLK_MAC_OUT:
1006 		div = DIV_ROUND_UP(priv->gpll_hz, rate);
1007 		rk_clrsetreg(&cru->pmuclksel_con[0], CLK_MAC_OUT_DIV_MASK,
1008 			     ((div - 1) << CLK_MAC_OUT_DIV_SHIFT));
1009 		break;
1010 	default:
1011 		return -ENOENT;
1012 	}
1013 
1014 	return rk3506_mac_get_rate(priv, clk_id);
1015 }
1016 
rk3506_clk_get_rate(struct clk * clk)1017 static ulong rk3506_clk_get_rate(struct clk *clk)
1018 {
1019 	struct rk3506_clk_priv *priv = dev_get_priv(clk->dev);
1020 	ulong rate = 0;
1021 
1022 	if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) {
1023 		printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n",
1024 		       __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz);
1025 		return -ENOENT;
1026 	}
1027 
1028 	switch (clk->id) {
1029 	case PLL_GPLL:
1030 		rate = priv->gpll_hz;
1031 		break;
1032 	case PLL_V0PLL:
1033 		rate = priv->v0pll_hz;
1034 		break;
1035 	case PLL_V1PLL:
1036 		rate = priv->v1pll_hz;
1037 		break;
1038 	case ARMCLK:
1039 		rate = rk3506_armclk_get_rate(priv);
1040 		break;
1041 	case CLK_GPLL_DIV:
1042 	case CLK_GPLL_DIV_100M:
1043 	case CLK_V0PLL_DIV:
1044 	case CLK_V1PLL_DIV:
1045 		rate = rk3506_pll_div_get_rate(priv, clk->id);
1046 		break;
1047 	case ACLK_BUS_ROOT:
1048 	case HCLK_BUS_ROOT:
1049 	case PCLK_BUS_ROOT:
1050 		rate = rk3506_bus_get_rate(priv, clk->id);
1051 		break;
1052 	case ACLK_HSPERI_ROOT:
1053 	case HCLK_LSPERI_ROOT:
1054 		rate = rk3506_peri_get_rate(priv, clk->id);
1055 		break;
1056 	case HCLK_SDMMC:
1057 	case CCLK_SRC_SDMMC:
1058 		rate = rk3506_sdmmc_get_rate(priv, clk->id);
1059 		break;
1060 	case CLK_SARADC:
1061 		rate = rk3506_saradc_get_rate(priv, clk->id);
1062 		break;
1063 	case CLK_TSADC:
1064 	case CLK_TSADC_TSEN:
1065 		rate = rk3506_tsadc_get_rate(priv, clk->id);
1066 		break;
1067 	case CLK_I2C0:
1068 	case CLK_I2C1:
1069 	case CLK_I2C2:
1070 		rate = rk3506_i2c_get_rate(priv, clk->id);
1071 		break;
1072 	case CLK_PWM0:
1073 	case CLK_PWM1:
1074 		rate = rk3506_pwm_get_rate(priv, clk->id);
1075 		break;
1076 	case CLK_SPI0:
1077 	case CLK_SPI1:
1078 		rate = rk3506_spi_get_rate(priv, clk->id);
1079 		break;
1080 	case SCLK_FSPI:
1081 		rate = rk3506_fspi_get_rate(priv);
1082 		break;
1083 	case DCLK_VOP:
1084 		rate = rk3506_vop_dclk_get_rate(priv);
1085 		break;
1086 	case CLK_MAC0:
1087 	case CLK_MAC1:
1088 	case CLK_MAC_OUT:
1089 		rate = rk3506_mac_get_rate(priv, clk->id);
1090 		break;
1091 	default:
1092 		return -ENOENT;
1093 	}
1094 
1095 	return rate;
1096 };
1097 
rk3506_clk_set_rate(struct clk * clk,ulong rate)1098 static ulong rk3506_clk_set_rate(struct clk *clk, ulong rate)
1099 {
1100 	struct rk3506_clk_priv *priv = dev_get_priv(clk->dev);
1101 	ulong ret = 0;
1102 
1103 	if (!priv->gpll_hz || !priv->v0pll_hz || !priv->v1pll_hz) {
1104 		printf("%s: gpll=%lu, v0pll=%lu, v1pll=%lu\n",
1105 		       __func__, priv->gpll_hz, priv->v0pll_hz, priv->v1pll_hz);
1106 		return -ENOENT;
1107 	}
1108 
1109 	debug("%s: id=%ld, rate=%ld\n", __func__, clk->id, rate);
1110 
1111 	switch (clk->id) {
1112 	case ARMCLK:
1113 		if (priv->armclk_hz)
1114 			rk3506_armclk_set_rate(priv, rate);
1115 		priv->armclk_hz = rate;
1116 		break;
1117 	case CLK_GPLL_DIV:
1118 	case CLK_GPLL_DIV_100M:
1119 	case CLK_V0PLL_DIV:
1120 	case CLK_V1PLL_DIV:
1121 		ret = rk3506_pll_div_set_rate(priv, clk->id, rate);
1122 		break;
1123 	case ACLK_BUS_ROOT:
1124 	case HCLK_BUS_ROOT:
1125 	case PCLK_BUS_ROOT:
1126 		ret = rk3506_bus_set_rate(priv, clk->id, rate);
1127 		break;
1128 	case ACLK_HSPERI_ROOT:
1129 	case HCLK_LSPERI_ROOT:
1130 		ret = rk3506_peri_set_rate(priv, clk->id, rate);
1131 		break;
1132 	case HCLK_SDMMC:
1133 	case CCLK_SRC_SDMMC:
1134 		ret = rk3506_sdmmc_set_rate(priv, clk->id, rate);
1135 		break;
1136 	case CLK_SARADC:
1137 		ret = rk3506_saradc_set_rate(priv, clk->id, rate);
1138 		break;
1139 	case CLK_TSADC:
1140 	case CLK_TSADC_TSEN:
1141 		ret = rk3506_tsadc_set_rate(priv, clk->id, rate);
1142 		break;
1143 	case CLK_I2C0:
1144 	case CLK_I2C1:
1145 	case CLK_I2C2:
1146 		ret = rk3506_i2c_set_rate(priv, clk->id, rate);
1147 		break;
1148 	case CLK_PWM0:
1149 	case CLK_PWM1:
1150 		ret = rk3506_pwm_set_rate(priv, clk->id, rate);
1151 		break;
1152 	case CLK_SPI0:
1153 	case CLK_SPI1:
1154 		ret = rk3506_spi_set_rate(priv, clk->id, rate);
1155 		break;
1156 	case HCLK_FSPI:
1157 	case SCLK_FSPI:
1158 		ret = rk3506_fspi_set_rate(priv, rate);
1159 		break;
1160 	case DCLK_VOP:
1161 		ret = rk3506_vop_dclk_set_rate(priv, rate);
1162 		break;
1163 	case CLK_MAC0:
1164 	case CLK_MAC1:
1165 	case CLK_MAC_OUT:
1166 		ret = rk3506_mac_set_rate(priv, clk->id, rate);
1167 		break;
1168 	default:
1169 		return -ENOENT;
1170 	}
1171 
1172 	return ret;
1173 };
1174 
1175 static struct clk_ops rk3506_clk_ops = {
1176 	.get_rate = rk3506_clk_get_rate,
1177 	.set_rate = rk3506_clk_set_rate,
1178 };
1179 
rk3506_clk_init(struct rk3506_clk_priv * priv)1180 static void rk3506_clk_init(struct rk3506_clk_priv *priv)
1181 {
1182 	priv->sync_kernel = false;
1183 
1184 	if (!priv->gpll_hz) {
1185 		priv->gpll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[GPLL],
1186 						      priv->cru, GPLL);
1187 		priv->gpll_hz = roundup(priv->gpll_hz, 1000);
1188 	}
1189 	if (!priv->v0pll_hz) {
1190 		priv->v0pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V0PLL],
1191 						       priv->cru, V0PLL);
1192 		priv->v0pll_hz = roundup(priv->v0pll_hz, 1000);
1193 	}
1194 	if (!priv->v1pll_hz) {
1195 		priv->v1pll_hz = rockchip_pll_get_rate(&rk3506_pll_clks[V1PLL],
1196 						       priv->cru, V1PLL);
1197 		priv->v1pll_hz = roundup(priv->v1pll_hz, 1000);
1198 	}
1199 	if (!priv->gpll_div_hz) {
1200 		priv->gpll_div_hz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV);
1201 		priv->gpll_div_hz = roundup(priv->gpll_div_hz, 1000);
1202 	}
1203 	if (!priv->gpll_div_100mhz) {
1204 		priv->gpll_div_100mhz = rk3506_pll_div_get_rate(priv, CLK_GPLL_DIV_100M);
1205 		priv->gpll_div_100mhz = roundup(priv->gpll_div_100mhz, 1000);
1206 	}
1207 	if (!priv->v0pll_div_hz) {
1208 		priv->v0pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V0PLL_DIV);
1209 		priv->v0pll_div_hz = roundup(priv->v0pll_div_hz, 1000);
1210 	}
1211 	if (!priv->v1pll_div_hz) {
1212 		priv->v1pll_div_hz = rk3506_pll_div_get_rate(priv, CLK_V1PLL_DIV);
1213 		priv->v1pll_div_hz = roundup(priv->v1pll_div_hz, 1000);
1214 	}
1215 
1216 	if (!priv->armclk_enter_hz) {
1217 		priv->armclk_enter_hz = rk3506_armclk_get_rate(priv);
1218 		priv->armclk_init_hz = priv->armclk_enter_hz;
1219 	}
1220 }
1221 
rk3506_clk_probe(struct udevice * dev)1222 static int rk3506_clk_probe(struct udevice *dev)
1223 {
1224 	struct rk3506_clk_priv *priv = dev_get_priv(dev);
1225 	int ret;
1226 
1227 #ifdef CONFIG_SPL_BUILD
1228 	/* Init pka crypto rate, sel=v0pll, div=3 */
1229 	writel(0x3f801180, RK3506_SCRU_BASE + 0x0010);
1230 	/* Change clk core src rate, sel=gpll, div=3 */
1231 	writel(0x007f0003, RK3506_CRU_BASE + 0x033c);
1232 #endif
1233 	rk3506_clk_init(priv);
1234 
1235 	/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
1236 	ret = clk_set_defaults(dev);
1237 	if (ret)
1238 		debug("%s clk_set_defaults failed %d\n", __func__, ret);
1239 	else
1240 		priv->sync_kernel = true;
1241 
1242 	return 0;
1243 }
1244 
rk3506_clk_ofdata_to_platdata(struct udevice * dev)1245 static int rk3506_clk_ofdata_to_platdata(struct udevice *dev)
1246 {
1247 	struct rk3506_clk_priv *priv = dev_get_priv(dev);
1248 
1249 	priv->cru = dev_read_addr_ptr(dev);
1250 
1251 	return 0;
1252 }
1253 
rk3506_clk_bind(struct udevice * dev)1254 static int rk3506_clk_bind(struct udevice *dev)
1255 {
1256 	struct udevice *sys_child, *sf_child;
1257 	struct softreset_reg *sf_priv;
1258 	struct sysreset_reg *priv;
1259 	int ret;
1260 
1261 	/* The reset driver does not have a device node, so bind it here */
1262 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
1263 				 &sys_child);
1264 	if (ret) {
1265 		debug("Warning: No sysreset driver: ret=%d\n", ret);
1266 	} else {
1267 		priv = malloc(sizeof(struct sysreset_reg));
1268 		priv->glb_srst_fst_value = offsetof(struct rk3506_cru,
1269 						    glb_srst_fst);
1270 		priv->glb_srst_snd_value = offsetof(struct rk3506_cru,
1271 						    glb_srst_snd);
1272 		sys_child->priv = priv;
1273 	}
1274 
1275 	ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
1276 					 dev_ofnode(dev), &sf_child);
1277 	if (ret) {
1278 		debug("Warning: No rockchip reset driver: ret=%d\n", ret);
1279 	} else {
1280 		sf_priv = malloc(sizeof(struct softreset_reg));
1281 		sf_priv->sf_reset_offset = offsetof(struct rk3506_cru,
1282 						    softrst_con[0]);
1283 		sf_priv->sf_reset_num = 23;
1284 		sf_child->priv = sf_priv;
1285 	}
1286 
1287 	return 0;
1288 }
1289 
1290 static const struct udevice_id rk3506_clk_ids[] = {
1291 	{ .compatible = "rockchip,rk3506-cru" },
1292 	{ }
1293 };
1294 
1295 U_BOOT_DRIVER(rockchip_rk3506_cru) = {
1296 	.name		= "rockchip_rk3506_cru",
1297 	.id		= UCLASS_CLK,
1298 	.of_match	= rk3506_clk_ids,
1299 	.priv_auto_alloc_size = sizeof(struct rk3506_clk_priv),
1300 	.ofdata_to_platdata = rk3506_clk_ofdata_to_platdata,
1301 	.ops		= &rk3506_clk_ops,
1302 	.bind		= rk3506_clk_bind,
1303 	.probe		= rk3506_clk_probe,
1304 };
1305