xref: /openbsd-src/sys/dev/fdt/rkclock.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: rkclock.c,v 1.51 2020/03/01 17:57:33 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/sysctl.h>
21 #include <sys/device.h>
22 
23 #include <machine/intr.h>
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26 
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_clock.h>
29 #include <dev/ofw/ofw_misc.h>
30 #include <dev/ofw/fdt.h>
31 
32 /* RK3288 registers */
33 #define RK3288_CRU_APLL_CON(i)		(0x0000 + (i) * 4)
34 #define RK3288_CRU_CPLL_CON(i)		(0x0020 + (i) * 4)
35 #define RK3288_CRU_GPLL_CON(i)		(0x0030 + (i) * 4)
36 #define RK3288_CRU_NPLL_CON(i)		(0x0040 + (i) * 4)
37 #define  RK3288_CRU_PLL_CLKR_MASK		(0x3f << 8)
38 #define  RK3288_CRU_PLL_CLKR_SHIFT		8
39 #define  RK3288_CRU_PLL_CLKOD_MASK		(0xf << 0)
40 #define  RK3288_CRU_PLL_CLKOD_SHIFT		0
41 #define  RK3288_CRU_PLL_CLKF_MASK		(0x1fff << 0)
42 #define  RK3288_CRU_PLL_CLKF_SHIFT		0
43 #define  RK3288_CRU_PLL_RESET			(1 << 5)
44 #define RK3288_CRU_MODE_CON		0x0050
45 #define  RK3288_CRU_MODE_PLL_WORK_MODE_MASK	0x3
46 #define  RK3288_CRU_MODE_PLL_WORK_MODE_SLOW	0x0
47 #define  RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL	0x1
48 #define RK3288_CRU_CLKSEL_CON(i)	(0x0060 + (i) * 4)
49 #define RK3288_CRU_SOFTRST_CON(i)	(0x01b8 + (i) * 4)
50 
51 /* RK3328 registers */
52 #define RK3328_CRU_APLL_CON(i)		(0x0000 + (i) * 4)
53 #define RK3328_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
54 #define RK3328_CRU_CPLL_CON(i)		(0x0040 + (i) * 4)
55 #define RK3328_CRU_GPLL_CON(i)		(0x0060 + (i) * 4)
56 #define RK3328_CRU_NPLL_CON(i)		(0x00a0 + (i) * 4)
57 #define  RK3328_CRU_PLL_POSTDIV1_MASK		(0x7 << 12)
58 #define  RK3328_CRU_PLL_POSTDIV1_SHIFT		12
59 #define  RK3328_CRU_PLL_FBDIV_MASK		(0xfff << 0)
60 #define  RK3328_CRU_PLL_FBDIV_SHIFT		0
61 #define  RK3328_CRU_PLL_DSMPD			(1 << 12)
62 #define  RK3328_CRU_PLL_PLL_LOCK		(1 << 10)
63 #define  RK3328_CRU_PLL_POSTDIV2_MASK		(0x7 << 6)
64 #define  RK3328_CRU_PLL_POSTDIV2_SHIFT		6
65 #define  RK3328_CRU_PLL_REFDIV_MASK		(0x3f << 0)
66 #define  RK3328_CRU_PLL_REFDIV_SHIFT		0
67 #define  RK3328_CRU_PLL_FRACDIV_MASK		(0xffffff << 0)
68 #define  RK3328_CRU_PLL_FRACDIV_SHIFT		0
69 #define RK3328_CRU_CRU_MODE		0x0080
70 #define  RK3328_CRU_CRU_MODE_MASK		0x1
71 #define  RK3328_CRU_CRU_MODE_SLOW		0x0
72 #define  RK3328_CRU_CRU_MODE_NORMAL		0x1
73 #define RK3328_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
74 #define  RK3328_CRU_CORE_CLK_PLL_SEL_MASK	(0x3 << 6)
75 #define  RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT	6
76 #define  RK3328_CRU_CLK_CORE_DIV_CON_MASK	(0x1f << 0)
77 #define  RK3328_CRU_CLK_CORE_DIV_CON_SHIFT	0
78 #define  RK3328_CRU_ACLK_CORE_DIV_CON_MASK	(0x7 << 4)
79 #define  RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT	4
80 #define  RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK	(0xf << 0)
81 #define  RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT	0
82 #define  RK3328_CRU_VOP_DCLK_SRC_SEL_MASK	(0x1 << 1)
83 #define  RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT	1
84 #define RK3328_CRU_CLKGATE_CON(i)	(0x0200 + (i) * 4)
85 #define RK3328_CRU_SOFTRST_CON(i)	(0x0300 + (i) * 4)
86 
87 #define RK3328_GRF_SOC_CON4		0x0410
88 #define  RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN	(1 << 14)
89 #define RK3328_GRF_MAC_CON1		0x0904
90 #define  RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL	(1 << 10)
91 
92 /* RK3399 registers */
93 #define RK3399_CRU_LPLL_CON(i)		(0x0000 + (i) * 4)
94 #define RK3399_CRU_BPLL_CON(i)		(0x0020 + (i) * 4)
95 #define RK3399_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
96 #define RK3399_CRU_CPLL_CON(i)		(0x0060 + (i) * 4)
97 #define RK3399_CRU_GPLL_CON(i)		(0x0080 + (i) * 4)
98 #define RK3399_CRU_NPLL_CON(i)		(0x00a0 + (i) * 4)
99 #define RK3399_CRU_VPLL_CON(i)		(0x00c0 + (i) * 4)
100 #define  RK3399_CRU_PLL_FBDIV_MASK		(0xfff << 0)
101 #define  RK3399_CRU_PLL_FBDIV_SHIFT		0
102 #define  RK3399_CRU_PLL_POSTDIV2_MASK		(0x7 << 12)
103 #define  RK3399_CRU_PLL_POSTDIV2_SHIFT		12
104 #define  RK3399_CRU_PLL_POSTDIV1_MASK		(0x7 << 8)
105 #define  RK3399_CRU_PLL_POSTDIV1_SHIFT		8
106 #define  RK3399_CRU_PLL_REFDIV_MASK		(0x3f << 0)
107 #define  RK3399_CRU_PLL_REFDIV_SHIFT		0
108 #define  RK3399_CRU_PLL_PLL_WORK_MODE_MASK	(0x3 << 8)
109 #define  RK3399_CRU_PLL_PLL_WORK_MODE_SLOW	(0x0 << 8)
110 #define  RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL	(0x1 << 8)
111 #define  RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW	(0x2 << 8)
112 #define  RK3399_CRU_PLL_PLL_LOCK		(1U << 31)
113 #define RK3399_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
114 #define  RK3399_CRU_ACLKM_CORE_DIV_CON_MASK	(0x1f << 8)
115 #define  RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT	8
116 #define  RK3399_CRU_CORE_PLL_SEL_MASK		(0x3 << 6)
117 #define  RK3399_CRU_CORE_PLL_SEL_APLL		(0x0 << 6)
118 #define  RK3399_CRU_CORE_PLL_SEL_BPLL		(0x1 << 6)
119 #define  RK3399_CRU_CORE_PLL_SEL_DPLL		(0x2 << 6)
120 #define  RK3399_CRU_CORE_PLL_SEL_GPLL		(0x3 << 6)
121 #define  RK3399_CRU_CORE_PLL_SEL_SHIFT		6
122 #define  RK3399_CRU_CLK_CORE_DIV_CON_MASK	(0x1f << 0)
123 #define  RK3399_CRU_CLK_CORE_DIV_CON_SHIFT	0
124 #define  RK3399_CRU_PCLK_DBG_DIV_CON_MASK	(0x1f << 8)
125 #define  RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT	8
126 #define  RK3399_CRU_ATCLK_CORE_DIV_CON_MASK	(0x1f << 0)
127 #define  RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT	0
128 #define  RK3399_CRU_CLK_SD_PLL_SEL_MASK		(0x7 << 8)
129 #define  RK3399_CRU_CLK_SD_PLL_SEL_SHIFT	8
130 #define  RK3399_CRU_CLK_SD_DIV_CON_MASK		(0x7f << 0)
131 #define  RK3399_CRU_CLK_SD_DIV_CON_SHIFT	0
132 #define RK3399_CRU_CLKGATE_CON(i)	(0x0300 + (i) * 4)
133 #define RK3399_CRU_SOFTRST_CON(i)	(0x0400 + (i) * 4)
134 #define RK3399_CRU_SDMMC_CON(i)		(0x0580 + (i) * 4)
135 
136 #define RK3399_PMUCRU_PPLL_CON(i)	(0x0000 + (i) * 4)
137 #define RK3399_PMUCRU_CLKSEL_CON(i)	(0x0080 + (i) * 4)
138 
139 #include "rkclock_clocks.h"
140 
141 struct rkclock {
142 	uint16_t idx;
143 	uint16_t reg;
144 	uint16_t sel_mask;
145 	uint16_t div_mask;
146 	uint16_t parents[8];
147 	uint32_t flags;
148 };
149 
150 #define SEL(l, f)	(((1 << (l - f + 1)) - 1) << f)
151 #define DIV(l, f)	SEL(l, f)
152 
153 #define FIXED_PARENT	(1 << 0)
154 #define SET_PARENT	(1 << 1)
155 
156 #define HREAD4(sc, reg)							\
157 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
158 #define HWRITE4(sc, reg, val)						\
159 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
160 #define HSET4(sc, reg, bits)						\
161 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
162 #define HCLR4(sc, reg, bits)						\
163 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
164 
165 struct rkclock_softc {
166 	struct device		sc_dev;
167 	bus_space_tag_t		sc_iot;
168 	bus_space_handle_t	sc_ioh;
169 	struct regmap		*sc_grf;
170 
171 	uint32_t		sc_phandle;
172 	struct rkclock		*sc_clocks;
173 
174 	struct clock_device	sc_cd;
175 	struct reset_device	sc_rd;
176 };
177 
178 int rkclock_match(struct device *, void *, void *);
179 void rkclock_attach(struct device *, struct device *, void *);
180 
181 struct cfattach	rkclock_ca = {
182 	sizeof (struct rkclock_softc), rkclock_match, rkclock_attach
183 };
184 
185 struct cfdriver rkclock_cd = {
186 	NULL, "rkclock", DV_DULL
187 };
188 
189 void	rk3288_init(struct rkclock_softc *);
190 uint32_t rk3288_get_frequency(void *, uint32_t *);
191 int	rk3288_set_frequency(void *, uint32_t *, uint32_t);
192 void	rk3288_enable(void *, uint32_t *, int);
193 void	rk3288_reset(void *, uint32_t *, int);
194 
195 void	rk3328_init(struct rkclock_softc *);
196 uint32_t rk3328_get_frequency(void *, uint32_t *);
197 int	rk3328_set_frequency(void *, uint32_t *, uint32_t);
198 int	rk3328_set_parent(void *, uint32_t *, uint32_t *);
199 void	rk3328_enable(void *, uint32_t *, int);
200 void	rk3328_reset(void *, uint32_t *, int);
201 
202 void	rk3399_init(struct rkclock_softc *);
203 uint32_t rk3399_get_frequency(void *, uint32_t *);
204 int	rk3399_set_frequency(void *, uint32_t *, uint32_t);
205 void	rk3399_enable(void *, uint32_t *, int);
206 void	rk3399_reset(void *, uint32_t *, int);
207 
208 void	rk3399_pmu_init(struct rkclock_softc *);
209 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *);
210 int	rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t);
211 void	rk3399_pmu_enable(void *, uint32_t *, int);
212 void	rk3399_pmu_reset(void *, uint32_t *, int);
213 
214 struct rkclock_compat {
215 	const char *compat;
216 	int	assign;
217 	void	(*init)(struct rkclock_softc *);
218 	void	(*enable)(void *, uint32_t *, int);
219 	uint32_t (*get_frequency)(void *, uint32_t *);
220 	int	(*set_frequency)(void *, uint32_t *, uint32_t);
221 	int	(*set_parent)(void *, uint32_t *, uint32_t *);
222 	void	(*reset)(void *, uint32_t *, int);
223 };
224 
225 struct rkclock_compat rkclock_compat[] = {
226 	{
227 		"rockchip,rk3288-cru", 0, rk3288_init,
228 		rk3288_enable, rk3288_get_frequency,
229 		rk3288_set_frequency, NULL,
230 		rk3288_reset
231 	},
232 	{
233 		"rockchip,rk3328-cru", 1, rk3328_init,
234 		rk3328_enable, rk3328_get_frequency,
235 		rk3328_set_frequency, rk3328_set_parent,
236 		rk3328_reset
237 	},
238 	{
239 		"rockchip,rk3399-cru", 1, rk3399_init,
240 		rk3399_enable, rk3399_get_frequency,
241 		rk3399_set_frequency, NULL,
242 		rk3399_reset
243 	},
244 	{
245 		"rockchip,rk3399-pmucru", 1, rk3399_pmu_init,
246 		rk3399_pmu_enable, rk3399_pmu_get_frequency,
247 		rk3399_pmu_set_frequency, NULL,
248 		rk3399_pmu_reset
249 	}
250 };
251 
252 int
253 rkclock_match(struct device *parent, void *match, void *aux)
254 {
255 	struct fdt_attach_args *faa = aux;
256 	int i;
257 
258 	for (i = 0; i < nitems(rkclock_compat); i++) {
259 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat))
260 			return 10;
261 	}
262 
263 	return 0;
264 }
265 
266 void
267 rkclock_attach(struct device *parent, struct device *self, void *aux)
268 {
269 	struct rkclock_softc *sc = (struct rkclock_softc *)self;
270 	struct fdt_attach_args *faa = aux;
271 	uint32_t grf;
272 	int i;
273 
274 	if (faa->fa_nreg < 1) {
275 		printf(": no registers\n");
276 		return;
277 	}
278 
279 	sc->sc_iot = faa->fa_iot;
280 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
281 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
282 		printf(": can't map registers\n");
283 		return;
284 	}
285 
286 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
287 	sc->sc_grf = regmap_byphandle(grf);
288 
289 	printf("\n");
290 
291 	sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0);
292 
293 	for (i = 0; i < nitems(rkclock_compat); i++) {
294 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) {
295 			break;
296 		}
297 	}
298 	KASSERT(i < nitems(rkclock_compat));
299 
300 	if (rkclock_compat[i].init)
301 		rkclock_compat[i].init(sc);
302 
303 	sc->sc_cd.cd_node = faa->fa_node;
304 	sc->sc_cd.cd_cookie = sc;
305 	sc->sc_cd.cd_enable = rkclock_compat[i].enable;
306 	sc->sc_cd.cd_get_frequency = rkclock_compat[i].get_frequency;
307 	sc->sc_cd.cd_set_frequency = rkclock_compat[i].set_frequency;
308 	sc->sc_cd.cd_set_parent = rkclock_compat[i].set_parent;
309 	clock_register(&sc->sc_cd);
310 
311 	sc->sc_rd.rd_node = faa->fa_node;
312 	sc->sc_rd.rd_cookie = sc;
313 	sc->sc_rd.rd_reset = rkclock_compat[i].reset;
314 	reset_register(&sc->sc_rd);
315 
316 	if (rkclock_compat[i].assign)
317 		clock_set_assigned(faa->fa_node);
318 }
319 
320 struct rkclock *
321 rkclock_lookup(struct rkclock_softc *sc, uint32_t idx)
322 {
323 	struct rkclock *clk;
324 
325 	for (clk = sc->sc_clocks; clk->idx; clk++) {
326 		if (clk->idx == idx)
327 			return clk;
328 	}
329 
330 	return NULL;
331 }
332 
333 uint32_t
334 rkclock_div_con(struct rkclock_softc *sc, struct rkclock *clk,
335     uint32_t mux, uint32_t freq)
336 {
337 	uint32_t parent_freq, div, div_con, max_div_con;
338 	uint32_t idx = clk->parents[mux];
339 
340 	/* Derive maximum value from mask. */
341 	max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1);
342 
343 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
344 	div = (parent_freq + freq - 1) / freq;
345 	div_con = (div > 0 ? div - 1 : 0);
346 	return (div_con < max_div_con) ? div_con : max_div_con;
347 }
348 
349 uint32_t
350 rkclock_freq(struct rkclock_softc *sc, struct rkclock *clk,
351     uint32_t mux, uint32_t freq)
352 {
353 	uint32_t parent_freq, div_con;
354 	uint32_t idx = clk->parents[mux];
355 
356 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
357 	div_con = rkclock_div_con(sc, clk, mux, freq);
358 	return parent_freq / (div_con + 1);
359 }
360 
361 uint32_t
362 rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx)
363 {
364 	struct rkclock *clk;
365 	uint32_t reg, mux, div_con;
366 	int shift;
367 
368 	clk = rkclock_lookup(sc, idx);
369 	if (clk == NULL) {
370 		printf("%s: 0x%08x\n", __func__, idx);
371 		return 0;
372 	}
373 
374 	reg = HREAD4(sc, clk->reg);
375 	shift = ffs(clk->sel_mask) - 1;
376 	if (shift == -1)
377 		mux = 0;
378 	else
379 		mux = (reg & clk->sel_mask) >> shift;
380 	shift = ffs(clk->div_mask) - 1;
381 	if (shift == -1)
382 		div_con = 0;
383 	else
384 		div_con = (reg & clk->div_mask) >> shift;
385 
386 	if (clk->parents[mux] == 0) {
387 		printf("%s: parent 0x%08x\n", __func__, idx);
388 		return 0;
389 	}
390 	idx = clk->parents[mux];
391 	return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1);
392 }
393 
394 int
395 rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq)
396 {
397 	struct rkclock *clk;
398 	uint32_t reg, mux, div_con;
399 	uint32_t best_freq, best_mux, f;
400 	int sel_shift, div_shift, i;
401 
402 	clk = rkclock_lookup(sc, idx);
403 	if (clk == NULL) {
404 		printf("%s: 0x%08x\n", __func__, idx);
405 		return -1;
406 	}
407 
408 	reg = HREAD4(sc, clk->reg);
409 	sel_shift = ffs(clk->sel_mask) - 1;
410 	if (sel_shift == -1)
411 		mux = sel_shift = 0;
412 	else
413 		mux = (reg & clk->sel_mask) >> sel_shift;
414 
415 	if (clk->parents[mux] == 0) {
416 		printf("%s: parent 0x%08x\n", __func__, idx);
417 		return 0;
418 	}
419 
420 	if (clk->flags & SET_PARENT) {
421 		idx = clk->parents[mux];
422 		sc->sc_cd.cd_set_frequency(sc, &idx, freq);
423 		if (clk->div_mask == 0)
424 			return 0;
425 	}
426 
427 	if (clk->div_mask == 0) {
428 		printf("%s: 0x%08x\n", __func__, idx);
429 		return -1;
430 	}
431 
432 	/*
433 	 * Start out with the current parent.  This prevents
434 	 * unecessary switching to a different parent.
435 	 */
436 	best_freq = rkclock_freq(sc, clk, mux, freq);
437 	best_mux = mux;
438 
439 	/*
440 	 * Find the parent that allows configuration of a frequency
441 	 * closest to the target frequency.
442 	 */
443 	if ((clk->flags & FIXED_PARENT) == 0) {
444 		for (i = 0; i < nitems(clk->parents); i++) {
445 			if (clk->parents[i] == 0)
446 				continue;
447 			f = rkclock_freq(sc, clk, i, freq);
448 			if ((f > best_freq && f <= freq) ||
449 			    (f < best_freq && f >= freq)) {
450 				best_freq = f;
451 				best_mux = i;
452 			}
453 		}
454 	}
455 
456 	div_con = rkclock_div_con(sc, clk, best_mux, freq);
457 	div_shift = ffs(clk->div_mask) - 1;
458 	HWRITE4(sc, clk->reg,
459 	    clk->sel_mask << 16 | best_mux << sel_shift |
460 	    clk->div_mask << 16 | div_con << div_shift);
461 	return 0;
462 }
463 
464 int
465 rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent)
466 {
467 	struct rkclock *clk;
468 	uint32_t mux;
469 	int shift;
470 
471 	clk = rkclock_lookup(sc, idx);
472 	if (clk == NULL || clk->sel_mask == 0) {
473 		printf("%s: 0x%08x\n", __func__, idx);
474 		return -1;
475 	}
476 
477 	for (mux = 0; mux < nitems(clk->parents); mux++) {
478 		if (clk->parents[mux] == parent)
479 			break;
480 	}
481 	if (mux == nitems(clk->parents) || parent == 0) {
482 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent);
483 		return -1;
484 	}
485 
486 	shift = ffs(clk->sel_mask) - 1;
487 	HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift);
488 	return 0;
489 }
490 
491 /*
492  * Rockchip RK3288
493  */
494 
495 struct rkclock rk3288_clocks[] = {
496 	{
497 		RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11),
498 		SEL(7, 6), DIV(5, 0),
499 		{ RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M }
500 	}
501 };
502 
503 void
504 rk3288_init(struct rkclock_softc *sc)
505 {
506 	int node;
507 
508 	/*
509 	 * Since the hardware comes up with a really conservative CPU
510 	 * clock frequency, and U-Boot doesn't set it to a more
511 	 * reasonable default, try to do so here.  These defaults were
512 	 * chosen assuming that the CPU voltage is at least 1.1 V.
513 	 * Only do this on the Tinker-RK3288 for now where this is
514 	 * likely to be true given the default voltages for the
515 	 * regulators on that board.
516 	 */
517 	node = OF_finddevice("/");
518 	if (OF_is_compatible(node, "rockchip,rk3288-tinker")) {
519 		uint32_t idx;
520 
521 		/* Run at 1.2 GHz. */
522 		idx = RK3288_ARMCLK;
523 		rk3288_set_frequency(sc, &idx, 1200000000);
524 	}
525 
526 	sc->sc_clocks = rk3288_clocks;
527 }
528 
529 uint32_t
530 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
531 {
532 	uint32_t clkod, clkr, clkf;
533 	uint32_t reg;
534 
535 	reg = HREAD4(sc, base);
536 	clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >>
537 	    RK3288_CRU_PLL_CLKOD_SHIFT;
538 	clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >>
539 	    RK3288_CRU_PLL_CLKR_SHIFT;
540 	reg = HREAD4(sc, base + 4);
541 	clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >>
542 	    RK3288_CRU_PLL_CLKF_SHIFT;
543 	return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
544 }
545 
546 int
547 rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
548 {
549 	int shift = 4 * (base / RK3288_CRU_CPLL_CON(0));
550 	uint32_t no, nr, nf;
551 
552 	/*
553 	 * It is not clear whether all combinations of the clock
554 	 * dividers result in a stable clock.  Therefore this function
555 	 * only supports a limited set of PLL clock rates.  For now
556 	 * this set covers all the CPU frequencies supported by the
557 	 * Linux kernel.
558 	 */
559 	switch (freq) {
560 	case 1800000000:
561 	case 1704000000:
562 	case 1608000000:
563 	case 1512000000:
564 	case 1488000000:
565 	case 1416000000:
566 	case 1200000000:
567 		nr = no = 1;
568 		break;
569 	case 1008000000:
570 	case 816000000:
571 	case 696000000:
572 	case 600000000:
573 		nr = 1; no = 2;
574 		break;
575 	case 408000000:
576 	case 312000000:
577 		nr = 1; no = 4;
578 		break;
579 	case 216000000:
580 	case 126000000:
581 		nr = 1; no = 8;
582 		break;
583 	default:
584 		printf("%s: %u Hz\n", __func__, freq);
585 		return -1;
586 	}
587 
588 	/* Calculate feedback divider. */
589 	nf = freq * nr * no / 24000000;
590 
591 	/*
592 	 * Select slow mode to guarantee a stable clock while we're
593 	 * adjusting the PLL.
594 	 */
595 	HWRITE4(sc, RK3288_CRU_MODE_CON,
596 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
597 	     RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift);
598 
599 	/* Assert reset. */
600 	HWRITE4(sc, base + 0x000c,
601 	    RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET);
602 
603 	/* Set PLL rate. */
604 	HWRITE4(sc, base + 0x0000,
605 	    RK3288_CRU_PLL_CLKR_MASK << 16 |
606 	    (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT |
607 	    RK3288_CRU_PLL_CLKOD_MASK << 16 |
608 	    (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT);
609 	HWRITE4(sc, base + 0x0004,
610 	    RK3288_CRU_PLL_CLKF_MASK << 16 |
611 	    (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT);
612 
613 	/* Deassert reset and wait. */
614 	HWRITE4(sc, base + 0x000c,
615 	    RK3288_CRU_PLL_RESET << 16);
616 	delay((nr * 500 / 24) + 1);
617 
618 	/* Switch back to normal mode. */
619 	HWRITE4(sc, RK3288_CRU_MODE_CON,
620 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
621 	     RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift);
622 
623 	return 0;
624 }
625 
626 uint32_t
627 rk3288_get_frequency(void *cookie, uint32_t *cells)
628 {
629 	struct rkclock_softc *sc = cookie;
630 	uint32_t idx = cells[0];
631 	uint32_t reg, mux, div_con, aclk_div_con;
632 
633 	switch (idx) {
634 	case RK3288_PLL_APLL:
635 		return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0));
636 	case RK3288_PLL_CPLL:
637 		return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
638 	case RK3288_PLL_GPLL:
639 		return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
640 	case RK3288_PLL_NPLL:
641 		return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0));
642 	case RK3288_ARMCLK:
643 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
644 		mux = (reg >> 15) & 0x1;
645 		div_con = (reg >> 8) & 0x1f;
646 		idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL;
647 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
648 	case RK3288_XIN24M:
649 		return 24000000;
650 	case RK3288_CLK_UART0:
651 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
652 		mux = (reg >> 8) & 0x3;
653 		div_con = reg & 0x7f;
654 		if (mux == 2)
655 			return 24000000 / (div_con + 1);
656 		break;
657 	case RK3288_CLK_UART1:
658 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
659 		mux = (reg >> 8) & 0x3;
660 		div_con = reg & 0x7f;
661 		if (mux == 2)
662 			return 24000000 / (div_con + 1);
663 		break;
664 	case RK3288_CLK_UART2:
665 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
666 		mux = (reg >> 8) & 0x3;
667 		div_con = reg & 0x7f;
668 		if (mux == 2)
669 			return 24000000 / (div_con + 1);
670 		break;
671 	case RK3288_CLK_UART3:
672 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
673 		mux = (reg >> 8) & 0x3;
674 		div_con = reg & 0x7f;
675 		if (mux == 2)
676 			return 24000000 / (div_con + 1);
677 		break;
678 	case RK3288_CLK_UART4:
679 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
680 		mux = (reg >> 8) & 0x3;
681 		div_con = reg & 0x7f;
682 		if (mux == 2)
683 			return 24000000 / (div_con + 1);
684 		break;
685 	case RK3288_CLK_MAC:
686 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21));
687 		if (reg & 0x10)
688 			return 125000000;
689 		mux = (reg >> 0) & 0x3;
690 		div_con = (reg >> 8) & 0x1f;
691 		switch (mux) {
692 		case 0:
693 			idx = RK3288_PLL_NPLL;
694 			break;
695 		case 1:
696 			idx = RK3288_PLL_CPLL;
697 			break;
698 		case 2:
699 			idx = RK3288_PLL_GPLL;
700 			break;
701 		default:
702 			return 0;
703 		}
704 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
705 	case RK3288_PCLK_I2C0:
706 	case RK3288_PCLK_I2C2:
707 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1));
708 		mux = (reg >> 15) & 0x1;
709 		/* pd_bus_pclk_div_con */
710 		div_con = (reg >> 12) & 0x7;
711 		if (mux == 1)
712 			idx = RK3288_PLL_GPLL;
713 		else
714 			idx = RK3288_PLL_CPLL;
715 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
716 	case RK3288_PCLK_I2C1:
717 	case RK3288_PCLK_I2C3:
718 	case RK3288_PCLK_I2C4:
719 	case RK3288_PCLK_I2C5:
720 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10));
721 		mux = (reg >> 15) & 0x1;
722 		/* peri_pclk_div_con */
723 		div_con = (reg >> 12) & 0x3;
724 		/* peri_aclk_div_con */
725 		aclk_div_con = reg & 0xf;
726 		if (mux == 1)
727 			idx = RK3288_PLL_GPLL;
728 		else
729 			idx = RK3288_PLL_CPLL;
730 		return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >>
731 		    div_con;
732 	default:
733 		break;
734 	}
735 
736 	return rkclock_get_frequency(sc, idx);
737 }
738 
739 int
740 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
741 {
742 	struct rkclock_softc *sc = cookie;
743 	uint32_t idx = cells[0];
744 	int error;
745 
746 	switch (idx) {
747 	case RK3288_PLL_APLL:
748 		return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq);
749 	case RK3288_ARMCLK:
750 		idx = RK3288_PLL_APLL;
751 		error = rk3288_set_frequency(sc, &idx, freq);
752 		if (error == 0) {
753 			HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0),
754 			    ((1 << 15) | (0x1f << 8)) << 16);
755 		}
756 		return error;
757 	default:
758 		break;
759 	}
760 
761 	return rkclock_set_frequency(sc, idx, freq);
762 }
763 
764 void
765 rk3288_enable(void *cookie, uint32_t *cells, int on)
766 {
767 	uint32_t idx = cells[0];
768 
769 	switch (idx) {
770 	case RK3288_CLK_SDMMC:
771 	case RK3288_CLK_TSADC:
772 	case RK3288_CLK_UART0:
773 	case RK3288_CLK_UART1:
774 	case RK3288_CLK_UART2:
775 	case RK3288_CLK_UART3:
776 	case RK3288_CLK_UART4:
777 	case RK3288_CLK_MAC_RX:
778 	case RK3288_CLK_MAC_TX:
779 	case RK3288_CLK_SDMMC_DRV:
780 	case RK3288_CLK_SDMMC_SAMPLE:
781 	case RK3288_CLK_MAC:
782 	case RK3288_ACLK_GMAC:
783 	case RK3288_PCLK_GMAC:
784 	case RK3288_PCLK_I2C0:
785 	case RK3288_PCLK_I2C1:
786 	case RK3288_PCLK_I2C2:
787 	case RK3288_PCLK_I2C3:
788 	case RK3288_PCLK_I2C4:
789 	case RK3288_PCLK_I2C5:
790 	case RK3288_PCLK_TSADC:
791 	case RK3288_HCLK_HOST0:
792 	case RK3288_HCLK_SDMMC:
793 		/* Enabled by default. */
794 		break;
795 	default:
796 		printf("%s: 0x%08x\n", __func__, idx);
797 		break;
798 	}
799 }
800 
801 void
802 rk3288_reset(void *cookie, uint32_t *cells, int on)
803 {
804 	struct rkclock_softc *sc = cookie;
805 	uint32_t idx = cells[0];
806 	uint32_t mask = (1 << (idx % 16));
807 
808 	HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16),
809 	    mask << 16 | (on ? mask : 0));
810 }
811 
812 /*
813  * Rockchip RK3328
814  */
815 
816 struct rkclock rk3328_clocks[] = {
817 	{
818 		RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38),
819 		SEL(15, 14), DIV(13, 0),
820 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M }
821 	},
822 	{
823 		RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30),
824 		SEL(9, 8), DIV(7, 0),
825 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
826 		  RK3328_USB480M }
827 	},
828 	{
829 		RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31),
830 		SEL(9, 8), DIV(7, 0),
831 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
832 		  RK3328_USB480M }
833 	},
834 	{
835 		RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32),
836 		SEL(9, 8), DIV(7, 0),
837 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
838 		  RK3328_USB480M }
839 	},
840 	{
841 		RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22),
842 		0, DIV(9, 0),
843 		{ RK3328_CLK_24M }
844 	},
845 	{
846 		RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14),
847 		SEL(9, 8), 0,
848 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
849 	},
850 	{
851 		RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16),
852 		SEL(9, 8), 0,
853 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
854 	},
855 	{
856 		RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18),
857 		SEL(9, 8), 0,
858 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
859 	},
860 	{
861 		RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52),
862 		SEL(7, 6), DIV(5, 0),
863 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M }
864 	},
865 	{
866 		RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34),
867 		SEL(7, 7), DIV(6, 0),
868 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
869 	},
870 	{
871 		RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34),
872 		SEL(15, 15), DIV(14, 8),
873 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
874 	},
875 	{
876 		RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35),
877 		SEL(7, 7), DIV(6, 0),
878 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
879 	},
880 	{
881 		RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35),
882 		SEL(15, 15), DIV(14, 8),
883 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
884 	},
885 	{
886 		RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
887 		SEL(15, 14), DIV(12, 8),
888 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
889 		FIXED_PARENT | SET_PARENT
890 	},
891 	{
892 		RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
893 		SEL(15, 14), DIV(12, 8),
894 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
895 		  RK3328_USB480M }
896 	},
897 	{
898 		RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
899 		SEL(7, 6), DIV(4, 0),
900 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
901 		  RK3328_USB480M }
902 	},
903 	{
904 		RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
905 		SEL(15, 14), DIV(12, 8),
906 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
907 		  RK3328_USB480M }
908 	},
909 	{
910 		RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
911 		SEL(15, 14), DIV(12, 8),
912 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
913 		  RK3328_USB480M }
914 	},
915 	{
916 		RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
917 		SEL(15, 15), DIV(12, 8),
918 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
919 	},
920 	{
921 		RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
922 		SEL(7, 7), DIV(4, 0),
923 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
924 	},
925 	{
926 		RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
927 		SEL(1, 1), 0,
928 		{ RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
929 	},
930 	{
931 		RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
932 		SEL(7, 6), DIV(4, 0),
933 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
934 		  RK3328_USB480M }
935 	},
936 	{
937 		RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
938 		SEL(15, 14), DIV(12, 8),
939 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
940 		  RK3328_USB480M }
941 	},
942 	{
943 		RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
944 		SEL(14, 13), DIV(12, 8),
945 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
946 	},
947 	{
948 		RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
949 		SEL(7, 6), DIV(4, 0),
950 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
951 	},
952 	{
953 		RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
954 		SEL(7, 6), DIV(4, 0),
955 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
956 		  RK3328_USB480M }
957 	},
958 	{
959 		RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
960 		SEL(7, 6), DIV(4, 0),
961 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
962 		  RK3328_USB480M }
963 	},
964 	{
965 		RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
966 		SEL(7, 6), DIV(4, 0),
967 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
968 		  RK3328_USB480M }
969 	},
970 	{
971 		RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
972 		SEL(7, 6), DIV(4, 0),
973 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
974 		  RK3328_USB480M }
975 	},
976 	{
977 		RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
978 		0, DIV(14, 12),
979 		{ RK3328_ACLK_BUS_PRE }
980 	},
981 	{
982 		RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
983 		0, DIV(9, 8),
984 		{ RK3328_ACLK_BUS_PRE }
985 	},
986 	{
987 		RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
988 		0, DIV(6, 4),
989 		{ RK3328_ACLK_PERI_PRE }
990 	},
991 	{
992 		RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
993 		0, DIV(1, 0),
994 		{ RK3328_ACLK_PERI_PRE }
995 	},
996 	{
997 		RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
998 		0, DIV(12, 8),
999 		{ RK3328_XIN24M }
1000 	},
1001 	{
1002 		/* Sentinel */
1003 	}
1004 };
1005 
1006 void
1007 rk3328_init(struct rkclock_softc *sc)
1008 {
1009 	int i;
1010 
1011 	/* The code below assumes all clocks are enabled.  Check this!. */
1012 	for (i = 0; i <= 28; i++) {
1013 		if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1014 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1015 			    HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1016 		}
1017 	}
1018 
1019 	sc->sc_clocks = rk3328_clocks;
1020 }
1021 
1022 uint32_t
1023 rk3328_armclk_parent(uint32_t mux)
1024 {
1025 	switch (mux) {
1026 	case 0:
1027 		return RK3328_PLL_APLL;
1028 	case 1:
1029 		return RK3328_PLL_GPLL;
1030 	case 2:
1031 		return RK3328_PLL_DPLL;
1032 	case 3:
1033 		return RK3328_PLL_NPLL;
1034 	}
1035 
1036 	return 0;
1037 }
1038 
1039 uint32_t
1040 rk3328_get_armclk(struct rkclock_softc *sc)
1041 {
1042 	uint32_t reg, mux, div_con;
1043 	uint32_t idx;
1044 
1045 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1046 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1047 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1048 	div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1049 	    RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1050 	idx = rk3328_armclk_parent(mux);
1051 
1052 	return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1053 }
1054 
1055 int
1056 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1057 {
1058 	uint32_t reg, mux;
1059 	uint32_t old_freq, div;
1060 	uint32_t idx;
1061 
1062 	old_freq = rk3328_get_armclk(sc);
1063 	if (freq == old_freq)
1064 		return 0;
1065 
1066 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1067 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1068 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1069 
1070 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1071 	div = 1;
1072 	while (freq / (div + 1) > 300000000)
1073 		div++;
1074 	/* and make sure we use an odd divider. */
1075 	if ((div % 2) == 0)
1076 		div++;
1077 
1078 	/* When ramping up, set clock dividers first. */
1079 	if (freq > old_freq) {
1080 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1081 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1082 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1083 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1084 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1085 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1086 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1087 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1088 	}
1089 
1090 	/* We always use NPLL and force the switch below if needed. */
1091 	idx = RK3328_PLL_NPLL;
1092 	rk3328_set_frequency(sc, &idx, freq);
1093 
1094 	/* When ramping down, set clock dividers last. */
1095 	if (freq < old_freq || mux != 3) {
1096 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1097 		    RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1098 		    3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1099 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1100 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1101 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1102 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1103 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1104 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1105 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1106 	}
1107 
1108 	return 0;
1109 }
1110 
1111 uint32_t
1112 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1113 {
1114 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1115 	uint32_t dsmpd, fracdiv;
1116 	uint64_t frac = 0;
1117 	uint32_t reg;
1118 
1119 	reg = HREAD4(sc, base + 0x0000);
1120 	postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1121 	    RK3328_CRU_PLL_POSTDIV1_SHIFT;
1122 	fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1123 	    RK3328_CRU_PLL_FBDIV_SHIFT;
1124 	reg = HREAD4(sc, base + 0x0004);
1125 	dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1126 	postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1127 	    RK3328_CRU_PLL_POSTDIV2_SHIFT;
1128 	refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1129 	    RK3328_CRU_PLL_REFDIV_SHIFT;
1130 	reg = HREAD4(sc, base + 0x0008);
1131 	fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1132 	    RK3328_CRU_PLL_FRACDIV_SHIFT;
1133 
1134 	if (dsmpd == 0)
1135 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1136 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1137 }
1138 
1139 int
1140 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1141 {
1142 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1143 	int mode_shift = -1;
1144 
1145 	switch (base) {
1146 	case RK3328_CRU_APLL_CON(0):
1147 		mode_shift = 0;
1148 		break;
1149 	case RK3328_CRU_DPLL_CON(0):
1150 		mode_shift = 4;
1151 		break;
1152 	case RK3328_CRU_CPLL_CON(0):
1153 		mode_shift = 8;
1154 		break;
1155 	case RK3328_CRU_GPLL_CON(0):
1156 		mode_shift = 12;
1157 		break;
1158 	case RK3328_CRU_NPLL_CON(0):
1159 		mode_shift = 1;
1160 		break;
1161 	}
1162 	KASSERT(mode_shift != -1);
1163 
1164 	/*
1165 	 * It is not clear whether all combinations of the clock
1166 	 * dividers result in a stable clock.  Therefore this function
1167 	 * only supports a limited set of PLL clock rates.  For now
1168 	 * this set covers all the CPU frequencies supported by the
1169 	 * Linux kernel.
1170 	 */
1171 	switch (freq) {
1172 	case 1800000000U:
1173 	case 1704000000U:
1174 	case 1608000000U:
1175 	case 1512000000U:
1176 	case 1488000000U:
1177 	case 1416000000U:
1178 	case 1392000000U:
1179 	case 1296000000U:
1180 	case 1200000000U:
1181 	case 1104000000U:
1182 		postdiv1 = postdiv2 = refdiv = 1;
1183 		break;
1184 	case 1008000000U:
1185 	case 912000000U:
1186 	case 816000000U:
1187 	case 696000000U:
1188 		postdiv1 = 2; postdiv2 = refdiv = 1;
1189 		break;
1190 	case 600000000U:
1191 		postdiv1 = 3; postdiv2 = refdiv = 1;
1192 		break;
1193 	case 408000000U:
1194 	case 312000000U:
1195 		postdiv1 = postdiv2 = 2; refdiv = 1;
1196 		break;
1197 	case 216000000U:
1198 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1199 		break;
1200 	case 96000000U:
1201 		postdiv1 = postdiv2 = 4; refdiv = 1;
1202 		break;
1203 	default:
1204 		printf("%s: %u Hz\n", __func__, freq);
1205 		return -1;
1206 	}
1207 
1208 	/* Calculate feedback divider. */
1209 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1210 
1211 	/*
1212 	 * Select slow mode to guarantee a stable clock while we're
1213 	 * adjusting the PLL.
1214 	 */
1215 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1216 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1217 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1218 
1219 	/* Set PLL rate. */
1220 	HWRITE4(sc, base + 0x0000,
1221 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1222 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1223 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1224 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1225 	HWRITE4(sc, base + 0x0004,
1226 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1227 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1228 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1229 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1230 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1231 
1232 	/* Wait for PLL to stabilize. */
1233 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1234 		delay(10);
1235 
1236 	/* Switch back to normal mode. */
1237 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1238 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1239 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1240 
1241 	return 0;
1242 }
1243 
1244 int
1245 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1246 {
1247 	uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
1248 	int mode_shift = -1;
1249 	uint32_t reg;
1250 
1251 	switch (base) {
1252 	case RK3328_CRU_APLL_CON(0):
1253 		mode_shift = 0;
1254 		break;
1255 	case RK3328_CRU_DPLL_CON(0):
1256 		mode_shift = 4;
1257 		break;
1258 	case RK3328_CRU_CPLL_CON(0):
1259 		mode_shift = 8;
1260 		break;
1261 	case RK3328_CRU_GPLL_CON(0):
1262 		mode_shift = 12;
1263 		break;
1264 	case RK3328_CRU_NPLL_CON(0):
1265 		mode_shift = 1;
1266 		break;
1267 	}
1268 	KASSERT(mode_shift != -1);
1269 
1270 	/*
1271 	 * It is not clear whether all combinations of the clock
1272 	 * dividers result in a stable clock.  Therefore this function
1273 	 * only supports a limited set of PLL clock rates.  This set
1274 	 * set covers all the fractional PLL frequencies supported by
1275 	 * the Linux kernel.
1276 	 */
1277 	switch (freq) {
1278 	case 1016064000U:
1279 		postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
1280 		break;
1281 	case 983040000U:
1282 		postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1283 		break;
1284 	case 491520000U:
1285 		postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1286 		break;
1287 	case 61440000U:
1288 		postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
1289 		break;
1290 	case 56448000U:
1291 		postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
1292 		break;
1293 	case 40960000U:
1294 		postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
1295 		break;
1296 	default:
1297 		printf("%s: %u Hz\n", __func__, freq);
1298 		return -1;
1299 	}
1300 
1301 	/* Calculate feedback divider. */
1302 	fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
1303 
1304 	/*
1305 	 * Select slow mode to guarantee a stable clock while we're
1306 	 * adjusting the PLL.
1307 	 */
1308 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1309 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1310 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1311 
1312 	/* Set PLL rate. */
1313 	HWRITE4(sc, base + 0x0000,
1314 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1315 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1316 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1317 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1318 	HWRITE4(sc, base + 0x0004,
1319 	    RK3328_CRU_PLL_DSMPD << 16 |
1320 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1321 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1322 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1323 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1324 	reg = HREAD4(sc, base + 0x0008);
1325 	reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
1326 	reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
1327 	HWRITE4(sc, base + 0x0008, reg);
1328 
1329 	/* Wait for PLL to stabilize. */
1330 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1331 		delay(10);
1332 
1333 	/* Switch back to normal mode. */
1334 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1335 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1336 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1337 
1338 	return 0;
1339 }
1340 
1341 uint32_t
1342 rk3328_get_frequency(void *cookie, uint32_t *cells)
1343 {
1344 	struct rkclock_softc *sc = cookie;
1345 	uint32_t idx = cells[0];
1346 	uint32_t reg;
1347 
1348 	switch (idx) {
1349 	case RK3328_PLL_APLL:
1350 		return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
1351 		break;
1352 	case RK3328_PLL_DPLL:
1353 		return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
1354 		break;
1355 	case RK3328_PLL_CPLL:
1356 		return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
1357 		break;
1358 	case RK3328_PLL_GPLL:
1359 		return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
1360 		break;
1361 	case RK3328_PLL_NPLL:
1362 		return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
1363 		break;
1364 	case RK3328_ARMCLK:
1365 		return rk3328_get_armclk(sc);
1366 	case RK3328_XIN24M:
1367 		return 24000000;
1368 	case RK3328_GMAC_CLKIN:
1369 		return 125000000;
1370 	/*
1371 	 * XXX The HDMIPHY and USB480M clocks are external.  Returning
1372 	 * zero here will cause them to be ignored for reparenting
1373 	 * purposes.
1374 	 */
1375 	case RK3328_HDMIPHY:
1376 		return 0;
1377 	case RK3328_USB480M:
1378 		return 0;
1379 	case RK3328_CLK_MAC2IO:
1380 		reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
1381 		if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
1382 			idx = RK3328_GMAC_CLKIN;
1383 		else
1384 			idx = RK3328_CLK_MAC2IO_SRC;
1385 		return rk3328_get_frequency(sc, &idx);
1386 	default:
1387 		break;
1388 	}
1389 
1390 	return rkclock_get_frequency(sc, idx);
1391 }
1392 
1393 int
1394 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1395 {
1396 	struct rkclock_softc *sc = cookie;
1397 	uint32_t idx = cells[0];
1398 	uint32_t reg, mux;
1399 
1400 	switch (idx) {
1401 	case RK3328_PLL_APLL:
1402 		return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
1403 	case RK3328_PLL_DPLL:
1404 		return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
1405 	case RK3328_PLL_CPLL:
1406 		return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
1407 	case RK3328_PLL_GPLL:
1408 		return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
1409 	case RK3328_PLL_NPLL:
1410 		return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
1411 	case RK3328_ARMCLK:
1412 		return rk3328_set_armclk(sc, freq);
1413 	case RK3328_CLK_UART0:
1414 	case RK3328_CLK_UART1:
1415 	case RK3328_CLK_UART2:
1416 		if (freq == rk3328_get_frequency(sc, &idx))
1417 			return 0;
1418 		break;
1419 	case RK3328_DCLK_LCDC:
1420 		reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
1421 		mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
1422 		    RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
1423 		idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
1424 		return rk3328_set_frequency(sc, &idx, freq);
1425 	default:
1426 		break;
1427 	}
1428 
1429 	return rkclock_set_frequency(sc, idx, freq);
1430 }
1431 
1432 int
1433 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1434 {
1435 	struct rkclock_softc *sc = cookie;
1436 	uint32_t idx = cells[0];
1437 	uint32_t parent;
1438 
1439 	if (pcells[0] == sc->sc_phandle)
1440 		parent = pcells[1];
1441 	else {
1442 		char name[32];
1443 		int node;
1444 
1445 		node = OF_getnodebyphandle(pcells[0]);
1446 		if (node == 0)
1447 			return -1;
1448 		name[0] = 0;
1449 		OF_getprop(node, "clock-output-names", name, sizeof(name));
1450 		name[sizeof(name) - 1] = 0;
1451 		if (strcmp(name, "xin24m") == 0)
1452 			parent = RK3328_XIN24M;
1453 		else if (strcmp(name, "gmac_clkin") == 0)
1454 			parent = RK3328_GMAC_CLKIN;
1455 		else
1456 			return -1;
1457 	}
1458 
1459 	switch (idx) {
1460 	case RK3328_CLK_MAC2IO:
1461 		if (parent == RK3328_GMAC_CLKIN) {
1462 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1463 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
1464 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
1465 		} else {
1466 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1467 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
1468 		}
1469 		return 0;
1470 	case RK3328_CLK_MAC2IO_EXT:
1471 		if (parent == RK3328_GMAC_CLKIN) {
1472 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1473 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
1474 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
1475 		} else {
1476 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1477 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
1478 		}
1479 		return 0;
1480 	}
1481 
1482 	return rkclock_set_parent(sc, idx, parent);
1483 }
1484 
1485 void
1486 rk3328_enable(void *cookie, uint32_t *cells, int on)
1487 {
1488 	uint32_t idx = cells[0];
1489 
1490 	/*
1491 	 * All clocks are enabled by default, so there is nothing for
1492 	 * us to do until we start disabling clocks.
1493 	 */
1494 	if (!on)
1495 		printf("%s: 0x%08x\n", __func__, idx);
1496 }
1497 
1498 void
1499 rk3328_reset(void *cookie, uint32_t *cells, int on)
1500 {
1501 	struct rkclock_softc *sc = cookie;
1502 	uint32_t idx = cells[0];
1503 	uint32_t mask = (1 << (idx % 16));
1504 
1505 	HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
1506 	    mask << 16 | (on ? mask : 0));
1507 }
1508 
1509 /*
1510  * Rockchip RK3399
1511  */
1512 
1513 struct rkclock rk3399_clocks[] = {
1514 	{
1515 		RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
1516 		SEL(7, 7), DIV(6, 0),
1517 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1518 	},
1519 	{
1520 		RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
1521 		SEL(7, 7), DIV(6, 0),
1522 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1523 	},
1524 	{
1525 		RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
1526 		SEL(7, 7), DIV(6, 0),
1527 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1528 	},
1529 	{
1530 		RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
1531 		SEL(15, 15), DIV(14, 8),
1532 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1533 	},
1534 	{
1535 		RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
1536 		SEL(15, 15), DIV(14, 8),
1537 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1538 	},
1539 	{
1540 		RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
1541 		SEL(15, 15), DIV(14, 8),
1542 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1543 	},
1544 	{
1545 		RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
1546 		SEL(10, 8), DIV(6, 0),
1547 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1548 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
1549 		  RK3399_XIN24M }
1550 	},
1551 	{
1552 		RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
1553 		SEL(10, 8), DIV(6, 0),
1554 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1555 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
1556 		  RK3399_XIN24M }
1557 	},
1558 	{
1559 		RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22),
1560 		SEL(10, 8), DIV(6, 0),
1561 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1562 		  /* RK3399_USB_480M */ 0, RK3399_XIN24M }
1563 	},
1564 	{
1565 		RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27),
1566 		SEL(15, 15), DIV(9, 0),
1567 		{ RK3399_XIN24M, RK3399_CLK_32K }
1568 	},
1569 	{
1570 		RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
1571 		SEL(9, 8), 0,
1572 		{ 0, 0, RK3399_XIN24M }
1573 	},
1574 	{
1575 		RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
1576 		SEL(9, 8), 0,
1577 		{ 0, 0, RK3399_XIN24M }
1578 	},
1579 	{
1580 		RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
1581 		SEL(9, 8), 0,
1582 		{ 0, 0, RK3399_XIN24M }
1583 	},
1584 	{
1585 		RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
1586 		SEL(9, 8), 0,
1587 		{ 0, 0, RK3399_XIN24M }
1588 	},
1589 	{
1590 		RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
1591 		SEL(15, 14), DIV(12, 8),
1592 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
1593 	},
1594 	{
1595 		RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49),
1596 		SEL(11, 11), 0,
1597 		{ RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC },
1598 		SET_PARENT
1599 	},
1600 	{
1601 		RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50),
1602 		SEL(11, 11), 0,
1603 		{ RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC },
1604 		SET_PARENT
1605 	},
1606 	{
1607 		RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49),
1608 		SEL(9, 8), DIV(7, 0),
1609 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1610 	},
1611 	{
1612 		RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50),
1613 		SEL(9, 8), DIV(7, 0),
1614 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1615 	},
1616 	{
1617 		RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1618 		SEL(7, 7), DIV(4, 0),
1619 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1620 	},
1621 	{
1622 		RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1623 		SEL(7, 7), DIV(4, 0),
1624 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1625 	},
1626 	{
1627 		RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
1628 		SEL(7, 6), DIV(4, 0),
1629 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1630 	},
1631 	{
1632 		RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
1633 		SEL(7, 6), DIV(4, 0),
1634 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1635 		  RK3399_PLL_VPLL }
1636 	},
1637 	{
1638 		RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
1639 		SEL(7, 6), DIV(4, 0),
1640 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
1641 		  RK3399_PLL_NPLL }
1642 	},
1643 	{
1644 		RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
1645 		SEL(7, 6), DIV(4, 0),
1646 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
1647 		  RK3399_PLL_NPLL }
1648 	},
1649 	{
1650 		RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
1651 		SEL(15, 14), DIV(12, 8),
1652 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1653 	},
1654 	{
1655 		RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
1656 		SEL(15, 15), DIV(12, 8),
1657 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1658 	},
1659 	{
1660 		RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1661 		0, DIV(14, 12),
1662 		{ RK3399_ACLK_PERIPH }
1663 	},
1664 	{
1665 		RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1666 		0, DIV(14, 12),
1667 		{ RK3399_ACLK_PERILP0 }
1668 	},
1669 	{
1670 		RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1671 		0, DIV(10, 8),
1672 		{ RK3399_HCLK_PERILP1 }
1673 	},
1674 	{
1675 		RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
1676 		SEL(15, 15), DIV(12, 8),
1677 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1678 	},
1679 	{
1680 		RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1681 		0, DIV(9, 8),
1682 		{ RK3399_ACLK_PERIPH }
1683 	},
1684 	{
1685 		RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1686 		0, DIV(9, 8),
1687 		{ RK3399_ACLK_PERILP0 }
1688 	},
1689 	{
1690 		RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1691 		SEL(7, 7), DIV(4, 0),
1692 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1693 	},
1694 	{
1695 		RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
1696 		SEL(15, 15), DIV(12, 8),
1697 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1698 	},
1699 	{
1700 		RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
1701 		0, DIV(12, 8),
1702 		{ RK3399_ACLK_VOP0 }
1703 	},
1704 	{
1705 		RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
1706 		0, DIV(12, 8),
1707 		{ RK3399_ACLK_VOP1 }
1708 	},
1709 	{
1710 		/* Sentinel */
1711 	}
1712 };
1713 
1714 /* Some of our parent clocks live in the PMUCRU. */
1715 struct rkclock_softc *rk3399_pmucru_sc;
1716 
1717 void
1718 rk3399_init(struct rkclock_softc *sc)
1719 {
1720 	int i;
1721 
1722 	/* PMUCRU instance should attach before us. */
1723 	KASSERT(rk3399_pmucru_sc != NULL);
1724 
1725 	/*
1726 	 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
1727 	 * module is buggy and sets the parent of the clock for the
1728 	 * "big" cluster to LPLL.  Undo that mistake here such that
1729 	 * the clocks of both clusters are independent.
1730 	 */
1731 	HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
1732 	    RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
1733 	    RK3399_CRU_CORE_PLL_SEL_BPLL);
1734 
1735 	/* The code below assumes all clocks are enabled.  Check this!. */
1736 	for (i = 0; i <= 34; i++) {
1737 		if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
1738 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1739 			    HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
1740 		}
1741 	}
1742 
1743 	sc->sc_clocks = rk3399_clocks;
1744 }
1745 
1746 uint32_t
1747 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
1748 {
1749 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1750 	uint32_t pll_work_mode;
1751 	uint32_t reg;
1752 
1753 	reg = HREAD4(sc, base + 0x000c);
1754 	pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
1755 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
1756 		return 24000000;
1757 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
1758 		return 32768;
1759 
1760 	reg = HREAD4(sc, base + 0x0000);
1761 	fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
1762 	    RK3399_CRU_PLL_FBDIV_SHIFT;
1763 	reg = HREAD4(sc, base + 0x0004);
1764 	postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
1765 	    RK3399_CRU_PLL_POSTDIV2_SHIFT;
1766 	postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
1767 	    RK3399_CRU_PLL_POSTDIV1_SHIFT;
1768 	refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
1769 	    RK3399_CRU_PLL_REFDIV_SHIFT;
1770 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
1771 }
1772 
1773 int
1774 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1775 {
1776 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1777 
1778 	/*
1779 	 * It is not clear whether all combinations of the clock
1780 	 * dividers result in a stable clock.  Therefore this function
1781 	 * only supports a limited set of PLL clock rates.  For now
1782 	 * this set covers all the CPU frequencies supported by the
1783 	 * Linux kernel.
1784 	 */
1785 	switch (freq) {
1786 	case 2208000000U:
1787 	case 2184000000U:
1788 	case 2088000000U:
1789 	case 2040000000U:
1790 	case 2016000000U:
1791 	case 1992000000U:
1792 	case 1896000000U:
1793 	case 1800000000U:
1794 	case 1704000000U:
1795 	case 1608000000U:
1796 	case 1512000000U:
1797 	case 1488000000U:
1798 	case 1416000000U:
1799 	case 1200000000U:
1800 		postdiv1 = postdiv2 = refdiv = 1;
1801 		break;
1802 	case 1008000000U:
1803 	case 816000000U:
1804 	case 696000000U:
1805 		postdiv1 = 2; postdiv2 = refdiv = 1;
1806 		break;
1807 	case 676000000U:
1808 		postdiv1 = 2; postdiv2 = 1; refdiv = 3;
1809 		break;
1810 	case 1000000000U:
1811 	case 800000000U:
1812 	case 600000000U:
1813 		postdiv1 = 3; postdiv2 = refdiv = 1;
1814 		break;
1815 	case 594000000U:
1816 		postdiv1 = 4; postdiv2 = refdiv = 1;
1817 		break;
1818 	case 408000000U:
1819 		postdiv1 = postdiv2 = 2; refdiv = 1;
1820 		break;
1821 	case 297000000U:
1822 	case 216000000U:
1823 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1824 		break;
1825 	case 148500000U:
1826 	case 96000000U:
1827 		postdiv1 = postdiv2 = 4; refdiv = 1;
1828 		break;
1829 	case 74250000U:
1830 		postdiv1 = postdiv2 = 4; refdiv = 2;
1831 		break;
1832 	case 65000000U:
1833 	case 54000000U:
1834 	case 27000000U:
1835 		postdiv1 = 6; postdiv2 = 4; refdiv = 1;
1836 		break;
1837 	default:
1838 		printf("%s: %d Hz\n", __func__, freq);
1839 		return -1;
1840 	}
1841 
1842 	/* Calculate feedback divider. */
1843 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1844 
1845 	/*
1846 	 * Select slow mode to guarantee a stable clock while we're
1847 	 * adjusting the PLL.
1848 	 */
1849 	HWRITE4(sc, base + 0x000c,
1850 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1851 	    RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
1852 
1853 	/* Set PLL rate. */
1854 	HWRITE4(sc, base + 0x0000,
1855 	    RK3399_CRU_PLL_FBDIV_MASK << 16 |
1856 	    fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
1857 	HWRITE4(sc, base + 0x0004,
1858 	    RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
1859 	    postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
1860 	    RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
1861 	    postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
1862 	    RK3399_CRU_PLL_REFDIV_MASK << 16 |
1863 	    refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
1864 
1865 	/* Wait for PLL to stabilize. */
1866 	while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
1867 		delay(10);
1868 
1869 	/* Switch back to normal mode. */
1870 	HWRITE4(sc, base + 0x000c,
1871 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1872 	    RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
1873 
1874 	return 0;
1875 }
1876 
1877 uint32_t
1878 rk3399_armclk_parent(uint32_t mux)
1879 {
1880 	switch (mux) {
1881 	case 0:
1882 		return RK3399_PLL_ALPLL;
1883 	case 1:
1884 		return RK3399_PLL_ABPLL;
1885 	case 2:
1886 		return RK3399_PLL_DPLL;
1887 	case 3:
1888 		return RK3399_PLL_GPLL;
1889 	}
1890 
1891 	return 0;
1892 }
1893 
1894 uint32_t
1895 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
1896 {
1897 	uint32_t reg, mux, div_con;
1898 	uint32_t idx;
1899 
1900 	reg = HREAD4(sc, clksel);
1901 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1902 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1903 	div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
1904 	    RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
1905 	idx = rk3399_armclk_parent(mux);
1906 
1907 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
1908 }
1909 
1910 int
1911 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
1912 {
1913 	uint32_t reg, mux;
1914 	uint32_t old_freq, div;
1915 	uint32_t idx;
1916 
1917 	old_freq = rk3399_get_armclk(sc, clksel);
1918 	if (freq == old_freq)
1919 		return 0;
1920 
1921 	reg = HREAD4(sc, clksel);
1922 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1923 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1924 	idx = rk3399_armclk_parent(mux);
1925 
1926 	/* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
1927 	div = 1;
1928 	while (freq / (div + 1) > 200000000)
1929 		div++;
1930 
1931 	/* When ramping up, set clock dividers first. */
1932 	if (freq > old_freq) {
1933 		HWRITE4(sc, clksel,
1934 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1935 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
1936 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
1937 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
1938 		HWRITE4(sc, clksel + 0x0004,
1939 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
1940 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
1941 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
1942 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
1943 	}
1944 
1945 	rk3399_set_frequency(sc, &idx, freq);
1946 
1947 	/* When ramping down, set clock dividers last. */
1948 	if (freq < old_freq) {
1949 		HWRITE4(sc, clksel,
1950 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1951 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
1952 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
1953 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
1954 		HWRITE4(sc, clksel + 0x0004,
1955 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
1956 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
1957 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
1958 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
1959 	}
1960 
1961 	return 0;
1962 }
1963 
1964 uint32_t
1965 rk3399_get_frequency(void *cookie, uint32_t *cells)
1966 {
1967 	struct rkclock_softc *sc = cookie;
1968 	uint32_t idx = cells[0];
1969 
1970 	switch (idx) {
1971 	case RK3399_PLL_ALPLL:
1972 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
1973 	case RK3399_PLL_ABPLL:
1974 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
1975 	case RK3399_PLL_DPLL:
1976 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
1977 	case RK3399_PLL_CPLL:
1978 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
1979 	case RK3399_PLL_GPLL:
1980 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
1981 	case RK3399_PLL_NPLL:
1982 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
1983 	case RK3399_PLL_VPLL:
1984 		return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
1985 	case RK3399_ARMCLKL:
1986 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
1987 	case RK3399_ARMCLKB:
1988 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
1989 	case RK3399_XIN24M:
1990 		return 24000000;
1991 	case RK3399_CLK_32K:
1992 		return 32768;
1993 	default:
1994 		break;
1995 	}
1996 
1997 	return rkclock_get_frequency(sc, idx);
1998 }
1999 
2000 int
2001 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2002 {
2003 	struct rkclock_softc *sc = cookie;
2004 	uint32_t idx = cells[0];
2005 
2006 	switch (idx) {
2007 	case RK3399_PLL_ALPLL:
2008 		return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
2009 	case RK3399_PLL_ABPLL:
2010 		return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
2011 	case RK3399_PLL_CPLL:
2012 		return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
2013 	case RK3399_PLL_GPLL:
2014 		return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
2015 	case RK3399_PLL_NPLL:
2016 		return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
2017 	case RK3399_PLL_VPLL:
2018 		return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq);
2019 	case RK3399_ARMCLKL:
2020 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
2021 	case RK3399_ARMCLKB:
2022 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
2023 	default:
2024 		break;
2025 	}
2026 
2027 	return rkclock_set_frequency(sc, idx, freq);
2028 }
2029 
2030 void
2031 rk3399_enable(void *cookie, uint32_t *cells, int on)
2032 {
2033 	uint32_t idx = cells[0];
2034 
2035 	/*
2036 	 * All clocks are enabled by default, so there is nothing for
2037 	 * us to do until we start disabling clocks.
2038 	 */
2039 	if (!on)
2040 		printf("%s: 0x%08x\n", __func__, idx);
2041 }
2042 
2043 void
2044 rk3399_reset(void *cookie, uint32_t *cells, int on)
2045 {
2046 	struct rkclock_softc *sc = cookie;
2047 	uint32_t idx = cells[0];
2048 	uint32_t mask = (1 << (idx % 16));
2049 
2050 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
2051 	    mask << 16 | (on ? mask : 0));
2052 }
2053 
2054 /* PMUCRU */
2055 
2056 struct rkclock rk3399_pmu_clocks[] = {
2057 	{
2058 		RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
2059 		0, DIV(6, 0),
2060 		{ RK3399_PLL_PPLL }
2061 	},
2062 	{
2063 		RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
2064 		0, DIV(6, 0),
2065 		{ RK3399_PLL_PPLL }
2066 	},
2067 	{
2068 		RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
2069 		0, DIV(14, 8),
2070 		{ RK3399_PLL_PPLL }
2071 	},
2072 	{
2073 		RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0),
2074 		0, DIV(6, 0),
2075 		{ RK3399_PLL_PPLL }
2076 	},
2077 	{
2078 		/* Sentinel */
2079 	}
2080 };
2081 
2082 void
2083 rk3399_pmu_init(struct rkclock_softc *sc)
2084 {
2085 	sc->sc_clocks = rk3399_pmu_clocks;
2086 	rk3399_pmucru_sc = sc;
2087 }
2088 
2089 uint32_t
2090 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
2091 {
2092 	struct rkclock_softc *sc = cookie;
2093 	uint32_t idx = cells[0];
2094 
2095 	switch (idx) {
2096 	case RK3399_PLL_PPLL:
2097 		return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
2098 	default:
2099 		break;
2100 	}
2101 
2102 	return rkclock_get_frequency(sc, idx);
2103 }
2104 
2105 int
2106 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2107 {
2108 	struct rkclock_softc *sc = cookie;
2109 	uint32_t idx = cells[0];
2110 
2111 	switch (idx) {
2112 	case RK3399_PLL_PPLL:
2113 		return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
2114 		break;
2115 	default:
2116 		break;
2117 	}
2118 
2119 	return rkclock_set_frequency(sc, idx, freq);
2120 }
2121 
2122 void
2123 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
2124 {
2125 	uint32_t idx = cells[0];
2126 
2127 	switch (idx) {
2128 	case RK3399_CLK_I2C0:
2129 	case RK3399_CLK_I2C4:
2130 	case RK3399_CLK_I2C8:
2131 	case RK3399_PCLK_I2C0:
2132 	case RK3399_PCLK_I2C4:
2133 	case RK3399_PCLK_I2C8:
2134 	case RK3399_PCLK_RKPWM:
2135 		/* Enabled by default. */
2136 		break;
2137 	default:
2138 		printf("%s: 0x%08x\n", __func__, idx);
2139 		break;
2140 	}
2141 }
2142 
2143 void
2144 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
2145 {
2146 	uint32_t idx = cells[0];
2147 
2148 	printf("%s: 0x%08x\n", __func__, idx);
2149 }
2150