xref: /openbsd-src/sys/dev/fdt/rkclock.c (revision 08b167769c18321999153a88ef267883b1cc33db)
1 /*	$OpenBSD: rkclock.c,v 1.53 2020/06/11 00:07:34 patrick 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_CRYPTO, RK3328_CRU_CLKSEL_CON(20),
887 		SEL(7, 7), DIV(4, 0),
888 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
889 	},
890 	{
891 		RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
892 		SEL(15, 14), DIV(12, 8),
893 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
894 		FIXED_PARENT | SET_PARENT
895 	},
896 	{
897 		RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
898 		SEL(15, 14), DIV(12, 8),
899 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
900 		  RK3328_USB480M }
901 	},
902 	{
903 		RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
904 		SEL(7, 6), DIV(4, 0),
905 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
906 		  RK3328_USB480M }
907 	},
908 	{
909 		RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
910 		SEL(15, 14), DIV(12, 8),
911 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
912 		  RK3328_USB480M }
913 	},
914 	{
915 		RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
916 		SEL(15, 14), DIV(12, 8),
917 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
918 		  RK3328_USB480M }
919 	},
920 	{
921 		RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
922 		SEL(15, 15), DIV(12, 8),
923 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
924 	},
925 	{
926 		RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
927 		SEL(7, 7), DIV(4, 0),
928 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
929 	},
930 	{
931 		RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
932 		SEL(1, 1), 0,
933 		{ RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
934 	},
935 	{
936 		RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
937 		SEL(7, 6), DIV(4, 0),
938 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
939 		  RK3328_USB480M }
940 	},
941 	{
942 		RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
943 		SEL(15, 14), DIV(12, 8),
944 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
945 		  RK3328_USB480M }
946 	},
947 	{
948 		RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
949 		SEL(14, 13), DIV(12, 8),
950 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
951 	},
952 	{
953 		RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
954 		SEL(7, 6), DIV(4, 0),
955 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
956 	},
957 	{
958 		RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
959 		SEL(7, 6), DIV(4, 0),
960 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
961 		  RK3328_USB480M }
962 	},
963 	{
964 		RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
965 		SEL(7, 6), DIV(4, 0),
966 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
967 		  RK3328_USB480M }
968 	},
969 	{
970 		RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
971 		SEL(7, 6), DIV(4, 0),
972 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
973 		  RK3328_USB480M }
974 	},
975 	{
976 		RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
977 		SEL(7, 6), DIV(4, 0),
978 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
979 		  RK3328_USB480M }
980 	},
981 	{
982 		RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
983 		0, DIV(14, 12),
984 		{ RK3328_ACLK_BUS_PRE }
985 	},
986 	{
987 		RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
988 		0, DIV(9, 8),
989 		{ RK3328_ACLK_BUS_PRE }
990 	},
991 	{
992 		RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
993 		0, DIV(6, 4),
994 		{ RK3328_ACLK_PERI_PRE }
995 	},
996 	{
997 		RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
998 		0, DIV(1, 0),
999 		{ RK3328_ACLK_PERI_PRE }
1000 	},
1001 	{
1002 		RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
1003 		0, DIV(12, 8),
1004 		{ RK3328_XIN24M }
1005 	},
1006 	{
1007 		/* Sentinel */
1008 	}
1009 };
1010 
1011 void
1012 rk3328_init(struct rkclock_softc *sc)
1013 {
1014 	int i;
1015 
1016 	/* The code below assumes all clocks are enabled.  Check this!. */
1017 	for (i = 0; i <= 28; i++) {
1018 		if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1019 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1020 			    HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1021 		}
1022 	}
1023 
1024 	sc->sc_clocks = rk3328_clocks;
1025 }
1026 
1027 uint32_t
1028 rk3328_armclk_parent(uint32_t mux)
1029 {
1030 	switch (mux) {
1031 	case 0:
1032 		return RK3328_PLL_APLL;
1033 	case 1:
1034 		return RK3328_PLL_GPLL;
1035 	case 2:
1036 		return RK3328_PLL_DPLL;
1037 	case 3:
1038 		return RK3328_PLL_NPLL;
1039 	}
1040 
1041 	return 0;
1042 }
1043 
1044 uint32_t
1045 rk3328_get_armclk(struct rkclock_softc *sc)
1046 {
1047 	uint32_t reg, mux, div_con;
1048 	uint32_t idx;
1049 
1050 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1051 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1052 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1053 	div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1054 	    RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1055 	idx = rk3328_armclk_parent(mux);
1056 
1057 	return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1058 }
1059 
1060 int
1061 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1062 {
1063 	uint32_t reg, mux;
1064 	uint32_t old_freq, div;
1065 	uint32_t idx;
1066 
1067 	old_freq = rk3328_get_armclk(sc);
1068 	if (freq == old_freq)
1069 		return 0;
1070 
1071 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1072 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1073 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1074 
1075 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1076 	div = 1;
1077 	while (freq / (div + 1) > 300000000)
1078 		div++;
1079 	/* and make sure we use an odd divider. */
1080 	if ((div % 2) == 0)
1081 		div++;
1082 
1083 	/* When ramping up, set clock dividers first. */
1084 	if (freq > old_freq) {
1085 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1086 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1087 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1088 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1089 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1090 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1091 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1092 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1093 	}
1094 
1095 	/* We always use NPLL and force the switch below if needed. */
1096 	idx = RK3328_PLL_NPLL;
1097 	rk3328_set_frequency(sc, &idx, freq);
1098 
1099 	/* When ramping down, set clock dividers last. */
1100 	if (freq < old_freq || mux != 3) {
1101 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1102 		    RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1103 		    3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1104 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1105 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1106 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1107 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1108 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1109 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1110 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1111 	}
1112 
1113 	return 0;
1114 }
1115 
1116 uint32_t
1117 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1118 {
1119 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1120 	uint32_t dsmpd, fracdiv;
1121 	uint64_t frac = 0;
1122 	uint32_t reg;
1123 
1124 	reg = HREAD4(sc, base + 0x0000);
1125 	postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1126 	    RK3328_CRU_PLL_POSTDIV1_SHIFT;
1127 	fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1128 	    RK3328_CRU_PLL_FBDIV_SHIFT;
1129 	reg = HREAD4(sc, base + 0x0004);
1130 	dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1131 	postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1132 	    RK3328_CRU_PLL_POSTDIV2_SHIFT;
1133 	refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1134 	    RK3328_CRU_PLL_REFDIV_SHIFT;
1135 	reg = HREAD4(sc, base + 0x0008);
1136 	fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1137 	    RK3328_CRU_PLL_FRACDIV_SHIFT;
1138 
1139 	if (dsmpd == 0)
1140 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1141 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1142 }
1143 
1144 int
1145 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1146 {
1147 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1148 	int mode_shift = -1;
1149 
1150 	switch (base) {
1151 	case RK3328_CRU_APLL_CON(0):
1152 		mode_shift = 0;
1153 		break;
1154 	case RK3328_CRU_DPLL_CON(0):
1155 		mode_shift = 4;
1156 		break;
1157 	case RK3328_CRU_CPLL_CON(0):
1158 		mode_shift = 8;
1159 		break;
1160 	case RK3328_CRU_GPLL_CON(0):
1161 		mode_shift = 12;
1162 		break;
1163 	case RK3328_CRU_NPLL_CON(0):
1164 		mode_shift = 1;
1165 		break;
1166 	}
1167 	KASSERT(mode_shift != -1);
1168 
1169 	/*
1170 	 * It is not clear whether all combinations of the clock
1171 	 * dividers result in a stable clock.  Therefore this function
1172 	 * only supports a limited set of PLL clock rates.  For now
1173 	 * this set covers all the CPU frequencies supported by the
1174 	 * Linux kernel.
1175 	 */
1176 	switch (freq) {
1177 	case 1800000000U:
1178 	case 1704000000U:
1179 	case 1608000000U:
1180 	case 1512000000U:
1181 	case 1488000000U:
1182 	case 1416000000U:
1183 	case 1392000000U:
1184 	case 1296000000U:
1185 	case 1200000000U:
1186 	case 1104000000U:
1187 		postdiv1 = postdiv2 = refdiv = 1;
1188 		break;
1189 	case 1008000000U:
1190 	case 912000000U:
1191 	case 816000000U:
1192 	case 696000000U:
1193 		postdiv1 = 2; postdiv2 = refdiv = 1;
1194 		break;
1195 	case 600000000U:
1196 		postdiv1 = 3; postdiv2 = refdiv = 1;
1197 		break;
1198 	case 408000000U:
1199 	case 312000000U:
1200 		postdiv1 = postdiv2 = 2; refdiv = 1;
1201 		break;
1202 	case 216000000U:
1203 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1204 		break;
1205 	case 96000000U:
1206 		postdiv1 = postdiv2 = 4; refdiv = 1;
1207 		break;
1208 	default:
1209 		printf("%s: %u Hz\n", __func__, freq);
1210 		return -1;
1211 	}
1212 
1213 	/* Calculate feedback divider. */
1214 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1215 
1216 	/*
1217 	 * Select slow mode to guarantee a stable clock while we're
1218 	 * adjusting the PLL.
1219 	 */
1220 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1221 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1222 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1223 
1224 	/* Set PLL rate. */
1225 	HWRITE4(sc, base + 0x0000,
1226 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1227 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1228 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1229 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1230 	HWRITE4(sc, base + 0x0004,
1231 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1232 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1233 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1234 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1235 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1236 
1237 	/* Wait for PLL to stabilize. */
1238 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1239 		delay(10);
1240 
1241 	/* Switch back to normal mode. */
1242 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1243 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1244 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1245 
1246 	return 0;
1247 }
1248 
1249 int
1250 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1251 {
1252 	uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
1253 	int mode_shift = -1;
1254 	uint32_t reg;
1255 
1256 	switch (base) {
1257 	case RK3328_CRU_APLL_CON(0):
1258 		mode_shift = 0;
1259 		break;
1260 	case RK3328_CRU_DPLL_CON(0):
1261 		mode_shift = 4;
1262 		break;
1263 	case RK3328_CRU_CPLL_CON(0):
1264 		mode_shift = 8;
1265 		break;
1266 	case RK3328_CRU_GPLL_CON(0):
1267 		mode_shift = 12;
1268 		break;
1269 	case RK3328_CRU_NPLL_CON(0):
1270 		mode_shift = 1;
1271 		break;
1272 	}
1273 	KASSERT(mode_shift != -1);
1274 
1275 	/*
1276 	 * It is not clear whether all combinations of the clock
1277 	 * dividers result in a stable clock.  Therefore this function
1278 	 * only supports a limited set of PLL clock rates.  This set
1279 	 * set covers all the fractional PLL frequencies supported by
1280 	 * the Linux kernel.
1281 	 */
1282 	switch (freq) {
1283 	case 1016064000U:
1284 		postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
1285 		break;
1286 	case 983040000U:
1287 		postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1288 		break;
1289 	case 491520000U:
1290 		postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1291 		break;
1292 	case 61440000U:
1293 		postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
1294 		break;
1295 	case 56448000U:
1296 		postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
1297 		break;
1298 	case 40960000U:
1299 		postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
1300 		break;
1301 	default:
1302 		printf("%s: %u Hz\n", __func__, freq);
1303 		return -1;
1304 	}
1305 
1306 	/* Calculate feedback divider. */
1307 	fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
1308 
1309 	/*
1310 	 * Select slow mode to guarantee a stable clock while we're
1311 	 * adjusting the PLL.
1312 	 */
1313 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1314 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1315 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1316 
1317 	/* Set PLL rate. */
1318 	HWRITE4(sc, base + 0x0000,
1319 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1320 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1321 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1322 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1323 	HWRITE4(sc, base + 0x0004,
1324 	    RK3328_CRU_PLL_DSMPD << 16 |
1325 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1326 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1327 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1328 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1329 	reg = HREAD4(sc, base + 0x0008);
1330 	reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
1331 	reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
1332 	HWRITE4(sc, base + 0x0008, reg);
1333 
1334 	/* Wait for PLL to stabilize. */
1335 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1336 		delay(10);
1337 
1338 	/* Switch back to normal mode. */
1339 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1340 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1341 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1342 
1343 	return 0;
1344 }
1345 
1346 uint32_t
1347 rk3328_get_frequency(void *cookie, uint32_t *cells)
1348 {
1349 	struct rkclock_softc *sc = cookie;
1350 	uint32_t idx = cells[0];
1351 	uint32_t reg;
1352 
1353 	switch (idx) {
1354 	case RK3328_PLL_APLL:
1355 		return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
1356 		break;
1357 	case RK3328_PLL_DPLL:
1358 		return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
1359 		break;
1360 	case RK3328_PLL_CPLL:
1361 		return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
1362 		break;
1363 	case RK3328_PLL_GPLL:
1364 		return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
1365 		break;
1366 	case RK3328_PLL_NPLL:
1367 		return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
1368 		break;
1369 	case RK3328_ARMCLK:
1370 		return rk3328_get_armclk(sc);
1371 	case RK3328_XIN24M:
1372 		return 24000000;
1373 	case RK3328_GMAC_CLKIN:
1374 		return 125000000;
1375 	/*
1376 	 * XXX The HDMIPHY and USB480M clocks are external.  Returning
1377 	 * zero here will cause them to be ignored for reparenting
1378 	 * purposes.
1379 	 */
1380 	case RK3328_HDMIPHY:
1381 		return 0;
1382 	case RK3328_USB480M:
1383 		return 0;
1384 	case RK3328_CLK_MAC2IO:
1385 		reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
1386 		if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
1387 			idx = RK3328_GMAC_CLKIN;
1388 		else
1389 			idx = RK3328_CLK_MAC2IO_SRC;
1390 		return rk3328_get_frequency(sc, &idx);
1391 	default:
1392 		break;
1393 	}
1394 
1395 	return rkclock_get_frequency(sc, idx);
1396 }
1397 
1398 int
1399 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1400 {
1401 	struct rkclock_softc *sc = cookie;
1402 	uint32_t idx = cells[0];
1403 	uint32_t reg, mux;
1404 
1405 	switch (idx) {
1406 	case RK3328_PLL_APLL:
1407 		return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
1408 	case RK3328_PLL_DPLL:
1409 		return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
1410 	case RK3328_PLL_CPLL:
1411 		return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
1412 	case RK3328_PLL_GPLL:
1413 		return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
1414 	case RK3328_PLL_NPLL:
1415 		return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
1416 	case RK3328_ARMCLK:
1417 		return rk3328_set_armclk(sc, freq);
1418 	case RK3328_CLK_UART0:
1419 	case RK3328_CLK_UART1:
1420 	case RK3328_CLK_UART2:
1421 		if (freq == rk3328_get_frequency(sc, &idx))
1422 			return 0;
1423 		break;
1424 	case RK3328_DCLK_LCDC:
1425 		reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
1426 		mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
1427 		    RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
1428 		idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
1429 		return rk3328_set_frequency(sc, &idx, freq);
1430 	case RK3328_HCLK_CRYPTO_SLV:
1431 		idx = RK3328_HCLK_BUS_PRE;
1432 		return rk3328_set_frequency(sc, &idx, freq);
1433 	default:
1434 		break;
1435 	}
1436 
1437 	return rkclock_set_frequency(sc, idx, freq);
1438 }
1439 
1440 int
1441 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1442 {
1443 	struct rkclock_softc *sc = cookie;
1444 	uint32_t idx = cells[0];
1445 	uint32_t parent;
1446 
1447 	if (pcells[0] == sc->sc_phandle)
1448 		parent = pcells[1];
1449 	else {
1450 		char name[32];
1451 		int node;
1452 
1453 		node = OF_getnodebyphandle(pcells[0]);
1454 		if (node == 0)
1455 			return -1;
1456 		name[0] = 0;
1457 		OF_getprop(node, "clock-output-names", name, sizeof(name));
1458 		name[sizeof(name) - 1] = 0;
1459 		if (strcmp(name, "xin24m") == 0)
1460 			parent = RK3328_XIN24M;
1461 		else if (strcmp(name, "gmac_clkin") == 0)
1462 			parent = RK3328_GMAC_CLKIN;
1463 		else
1464 			return -1;
1465 	}
1466 
1467 	switch (idx) {
1468 	case RK3328_CLK_MAC2IO:
1469 		if (parent == RK3328_GMAC_CLKIN) {
1470 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1471 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
1472 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
1473 		} else {
1474 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1475 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
1476 		}
1477 		return 0;
1478 	case RK3328_CLK_MAC2IO_EXT:
1479 		if (parent == RK3328_GMAC_CLKIN) {
1480 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1481 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
1482 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
1483 		} else {
1484 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1485 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
1486 		}
1487 		return 0;
1488 	}
1489 
1490 	return rkclock_set_parent(sc, idx, parent);
1491 }
1492 
1493 void
1494 rk3328_enable(void *cookie, uint32_t *cells, int on)
1495 {
1496 	uint32_t idx = cells[0];
1497 
1498 	/*
1499 	 * All clocks are enabled by default, so there is nothing for
1500 	 * us to do until we start disabling clocks.
1501 	 */
1502 	if (!on)
1503 		printf("%s: 0x%08x\n", __func__, idx);
1504 }
1505 
1506 void
1507 rk3328_reset(void *cookie, uint32_t *cells, int on)
1508 {
1509 	struct rkclock_softc *sc = cookie;
1510 	uint32_t idx = cells[0];
1511 	uint32_t mask = (1 << (idx % 16));
1512 
1513 	HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
1514 	    mask << 16 | (on ? mask : 0));
1515 }
1516 
1517 /*
1518  * Rockchip RK3399
1519  */
1520 
1521 struct rkclock rk3399_clocks[] = {
1522 	{
1523 		RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
1524 		SEL(7, 7), DIV(6, 0),
1525 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1526 	},
1527 	{
1528 		RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
1529 		SEL(7, 7), DIV(6, 0),
1530 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1531 	},
1532 	{
1533 		RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
1534 		SEL(7, 7), DIV(6, 0),
1535 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1536 	},
1537 	{
1538 		RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
1539 		SEL(15, 15), DIV(14, 8),
1540 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1541 	},
1542 	{
1543 		RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
1544 		SEL(15, 15), DIV(14, 8),
1545 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1546 	},
1547 	{
1548 		RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
1549 		SEL(15, 15), DIV(14, 8),
1550 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1551 	},
1552 	{
1553 		RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
1554 		SEL(10, 8), DIV(6, 0),
1555 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1556 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
1557 		  RK3399_XIN24M }
1558 	},
1559 	{
1560 		RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
1561 		SEL(10, 8), DIV(6, 0),
1562 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1563 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
1564 		  RK3399_XIN24M }
1565 	},
1566 	{
1567 		RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22),
1568 		SEL(10, 8), DIV(6, 0),
1569 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1570 		  /* RK3399_USB_480M */ 0, RK3399_XIN24M }
1571 	},
1572 	{
1573 		RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27),
1574 		SEL(15, 15), DIV(9, 0),
1575 		{ RK3399_XIN24M, RK3399_CLK_32K }
1576 	},
1577 	{
1578 		RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
1579 		SEL(9, 8), 0,
1580 		{ 0, 0, RK3399_XIN24M }
1581 	},
1582 	{
1583 		RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
1584 		SEL(9, 8), 0,
1585 		{ 0, 0, RK3399_XIN24M }
1586 	},
1587 	{
1588 		RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
1589 		SEL(9, 8), 0,
1590 		{ 0, 0, RK3399_XIN24M }
1591 	},
1592 	{
1593 		RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
1594 		SEL(9, 8), 0,
1595 		{ 0, 0, RK3399_XIN24M }
1596 	},
1597 	{
1598 		RK3399_CLK_I2S0_8CH, RK3399_CRU_CLKSEL_CON(28),
1599 		SEL(9, 8), 0,
1600 		{ RK3399_CLK_I2S0_DIV, 0, 0, RK3399_XIN12M },
1601 		SET_PARENT
1602 	},
1603 	{
1604 		RK3399_CLK_I2S1_8CH, RK3399_CRU_CLKSEL_CON(29),
1605 		SEL(9, 8), 0,
1606 		{ RK3399_CLK_I2S1_DIV, 0, 0, RK3399_XIN12M },
1607 		SET_PARENT
1608 	},
1609 	{
1610 		RK3399_CLK_I2S2_8CH, RK3399_CRU_CLKSEL_CON(30),
1611 		SEL(9, 8), 0,
1612 		{ RK3399_CLK_I2S2_DIV, 0, 0, RK3399_XIN12M },
1613 		SET_PARENT
1614 	},
1615 	{
1616 		RK3399_CLK_I2S_8CH_OUT, RK3399_CRU_CLKSEL_CON(31),
1617 		SEL(2, 2), 0,
1618 		{ RK3399_CLK_I2SOUT_SRC, RK3399_XIN12M },
1619 		SET_PARENT
1620 	},
1621 	{
1622 		RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
1623 		SEL(15, 14), DIV(12, 8),
1624 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
1625 	},
1626 	{
1627 		RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49),
1628 		SEL(11, 11), 0,
1629 		{ RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC },
1630 		SET_PARENT
1631 	},
1632 	{
1633 		RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50),
1634 		SEL(11, 11), 0,
1635 		{ RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC },
1636 		SET_PARENT
1637 	},
1638 	{
1639 		RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49),
1640 		SEL(9, 8), DIV(7, 0),
1641 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1642 	},
1643 	{
1644 		RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50),
1645 		SEL(9, 8), DIV(7, 0),
1646 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1647 	},
1648 	{
1649 		RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1650 		SEL(7, 7), DIV(4, 0),
1651 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1652 	},
1653 	{
1654 		RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1655 		SEL(7, 7), DIV(4, 0),
1656 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1657 	},
1658 	{
1659 		RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
1660 		SEL(7, 6), DIV(4, 0),
1661 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1662 	},
1663 	{
1664 		RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
1665 		SEL(7, 6), DIV(4, 0),
1666 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1667 		  RK3399_PLL_VPLL }
1668 	},
1669 	{
1670 		RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
1671 		SEL(7, 6), DIV(4, 0),
1672 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
1673 		  RK3399_PLL_NPLL }
1674 	},
1675 	{
1676 		RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
1677 		SEL(7, 6), DIV(4, 0),
1678 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
1679 		  RK3399_PLL_NPLL }
1680 	},
1681 	{
1682 		RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
1683 		SEL(15, 14), DIV(12, 8),
1684 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1685 	},
1686 	{
1687 		RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
1688 		SEL(15, 15), DIV(12, 8),
1689 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1690 	},
1691 	{
1692 		RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1693 		0, DIV(14, 12),
1694 		{ RK3399_ACLK_PERIPH }
1695 	},
1696 	{
1697 		RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1698 		0, DIV(14, 12),
1699 		{ RK3399_ACLK_PERILP0 }
1700 	},
1701 	{
1702 		RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1703 		0, DIV(10, 8),
1704 		{ RK3399_HCLK_PERILP1 }
1705 	},
1706 	{
1707 		RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
1708 		SEL(15, 15), DIV(12, 8),
1709 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1710 	},
1711 	{
1712 		RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1713 		0, DIV(9, 8),
1714 		{ RK3399_ACLK_PERIPH }
1715 	},
1716 	{
1717 		RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1718 		0, DIV(9, 8),
1719 		{ RK3399_ACLK_PERILP0 }
1720 	},
1721 	{
1722 		RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1723 		SEL(7, 7), DIV(4, 0),
1724 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1725 	},
1726 	{
1727 		RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
1728 		SEL(15, 15), DIV(12, 8),
1729 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1730 	},
1731 	{
1732 		RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
1733 		0, DIV(12, 8),
1734 		{ RK3399_ACLK_VOP0 }
1735 	},
1736 	{
1737 		RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
1738 		0, DIV(12, 8),
1739 		{ RK3399_ACLK_VOP1 }
1740 	},
1741 	{
1742 		RK3399_CLK_I2S0_DIV, RK3399_CRU_CLKSEL_CON(28),
1743 		SEL(7, 7), DIV(6, 0),
1744 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1745 	},
1746 	{
1747 		RK3399_CLK_I2S1_DIV, RK3399_CRU_CLKSEL_CON(29),
1748 		SEL(7, 7), DIV(6, 0),
1749 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1750 	},
1751 	{
1752 		RK3399_CLK_I2S2_DIV, RK3399_CRU_CLKSEL_CON(30),
1753 		SEL(7, 7), DIV(6, 0),
1754 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1755 	},
1756 	{
1757 		RK3399_CLK_I2SOUT_SRC, RK3399_CRU_CLKSEL_CON(31),
1758 		SEL(1, 0), 0,
1759 		{ RK3399_CLK_I2S0_8CH, RK3399_CLK_I2S1_8CH,
1760 		  RK3399_CLK_I2S2_8CH },
1761 		SET_PARENT
1762 	},
1763 	{
1764 		/* Sentinel */
1765 	}
1766 };
1767 
1768 /* Some of our parent clocks live in the PMUCRU. */
1769 struct rkclock_softc *rk3399_pmucru_sc;
1770 
1771 void
1772 rk3399_init(struct rkclock_softc *sc)
1773 {
1774 	int i;
1775 
1776 	/* PMUCRU instance should attach before us. */
1777 	KASSERT(rk3399_pmucru_sc != NULL);
1778 
1779 	/*
1780 	 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
1781 	 * module is buggy and sets the parent of the clock for the
1782 	 * "big" cluster to LPLL.  Undo that mistake here such that
1783 	 * the clocks of both clusters are independent.
1784 	 */
1785 	HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
1786 	    RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
1787 	    RK3399_CRU_CORE_PLL_SEL_BPLL);
1788 
1789 	/* The code below assumes all clocks are enabled.  Check this!. */
1790 	for (i = 0; i <= 34; i++) {
1791 		if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
1792 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1793 			    HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
1794 		}
1795 	}
1796 
1797 	sc->sc_clocks = rk3399_clocks;
1798 }
1799 
1800 uint32_t
1801 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
1802 {
1803 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1804 	uint32_t pll_work_mode;
1805 	uint32_t reg;
1806 
1807 	reg = HREAD4(sc, base + 0x000c);
1808 	pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
1809 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
1810 		return 24000000;
1811 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
1812 		return 32768;
1813 
1814 	reg = HREAD4(sc, base + 0x0000);
1815 	fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
1816 	    RK3399_CRU_PLL_FBDIV_SHIFT;
1817 	reg = HREAD4(sc, base + 0x0004);
1818 	postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
1819 	    RK3399_CRU_PLL_POSTDIV2_SHIFT;
1820 	postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
1821 	    RK3399_CRU_PLL_POSTDIV1_SHIFT;
1822 	refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
1823 	    RK3399_CRU_PLL_REFDIV_SHIFT;
1824 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
1825 }
1826 
1827 int
1828 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1829 {
1830 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1831 
1832 	/*
1833 	 * It is not clear whether all combinations of the clock
1834 	 * dividers result in a stable clock.  Therefore this function
1835 	 * only supports a limited set of PLL clock rates.  For now
1836 	 * this set covers all the CPU frequencies supported by the
1837 	 * Linux kernel.
1838 	 */
1839 	switch (freq) {
1840 	case 2208000000U:
1841 	case 2184000000U:
1842 	case 2088000000U:
1843 	case 2040000000U:
1844 	case 2016000000U:
1845 	case 1992000000U:
1846 	case 1896000000U:
1847 	case 1800000000U:
1848 	case 1704000000U:
1849 	case 1608000000U:
1850 	case 1512000000U:
1851 	case 1488000000U:
1852 	case 1416000000U:
1853 	case 1200000000U:
1854 		postdiv1 = postdiv2 = refdiv = 1;
1855 		break;
1856 	case 1008000000U:
1857 	case 816000000U:
1858 	case 696000000U:
1859 		postdiv1 = 2; postdiv2 = refdiv = 1;
1860 		break;
1861 	case 676000000U:
1862 		postdiv1 = 2; postdiv2 = 1; refdiv = 3;
1863 		break;
1864 	case 1000000000U:
1865 	case 800000000U:
1866 	case 600000000U:
1867 		postdiv1 = 3; postdiv2 = refdiv = 1;
1868 		break;
1869 	case 594000000U:
1870 		postdiv1 = 4; postdiv2 = refdiv = 1;
1871 		break;
1872 	case 408000000U:
1873 		postdiv1 = postdiv2 = 2; refdiv = 1;
1874 		break;
1875 	case 297000000U:
1876 	case 216000000U:
1877 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1878 		break;
1879 	case 148500000U:
1880 	case 96000000U:
1881 		postdiv1 = postdiv2 = 4; refdiv = 1;
1882 		break;
1883 	case 74250000U:
1884 		postdiv1 = postdiv2 = 4; refdiv = 2;
1885 		break;
1886 	case 65000000U:
1887 	case 54000000U:
1888 	case 27000000U:
1889 		postdiv1 = 6; postdiv2 = 4; refdiv = 1;
1890 		break;
1891 	default:
1892 		printf("%s: %d Hz\n", __func__, freq);
1893 		return -1;
1894 	}
1895 
1896 	/* Calculate feedback divider. */
1897 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1898 
1899 	/*
1900 	 * Select slow mode to guarantee a stable clock while we're
1901 	 * adjusting the PLL.
1902 	 */
1903 	HWRITE4(sc, base + 0x000c,
1904 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1905 	    RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
1906 
1907 	/* Set PLL rate. */
1908 	HWRITE4(sc, base + 0x0000,
1909 	    RK3399_CRU_PLL_FBDIV_MASK << 16 |
1910 	    fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
1911 	HWRITE4(sc, base + 0x0004,
1912 	    RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
1913 	    postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
1914 	    RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
1915 	    postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
1916 	    RK3399_CRU_PLL_REFDIV_MASK << 16 |
1917 	    refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
1918 
1919 	/* Wait for PLL to stabilize. */
1920 	while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
1921 		delay(10);
1922 
1923 	/* Switch back to normal mode. */
1924 	HWRITE4(sc, base + 0x000c,
1925 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1926 	    RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
1927 
1928 	return 0;
1929 }
1930 
1931 uint32_t
1932 rk3399_armclk_parent(uint32_t mux)
1933 {
1934 	switch (mux) {
1935 	case 0:
1936 		return RK3399_PLL_ALPLL;
1937 	case 1:
1938 		return RK3399_PLL_ABPLL;
1939 	case 2:
1940 		return RK3399_PLL_DPLL;
1941 	case 3:
1942 		return RK3399_PLL_GPLL;
1943 	}
1944 
1945 	return 0;
1946 }
1947 
1948 uint32_t
1949 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
1950 {
1951 	uint32_t reg, mux, div_con;
1952 	uint32_t idx;
1953 
1954 	reg = HREAD4(sc, clksel);
1955 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1956 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1957 	div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
1958 	    RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
1959 	idx = rk3399_armclk_parent(mux);
1960 
1961 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
1962 }
1963 
1964 int
1965 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
1966 {
1967 	uint32_t reg, mux;
1968 	uint32_t old_freq, div;
1969 	uint32_t idx;
1970 
1971 	old_freq = rk3399_get_armclk(sc, clksel);
1972 	if (freq == old_freq)
1973 		return 0;
1974 
1975 	reg = HREAD4(sc, clksel);
1976 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1977 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1978 	idx = rk3399_armclk_parent(mux);
1979 
1980 	/* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
1981 	div = 1;
1982 	while (freq / (div + 1) > 200000000)
1983 		div++;
1984 
1985 	/* When ramping up, set clock dividers first. */
1986 	if (freq > old_freq) {
1987 		HWRITE4(sc, clksel,
1988 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1989 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
1990 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
1991 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
1992 		HWRITE4(sc, clksel + 0x0004,
1993 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
1994 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
1995 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
1996 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
1997 	}
1998 
1999 	rk3399_set_frequency(sc, &idx, freq);
2000 
2001 	/* When ramping down, set clock dividers last. */
2002 	if (freq < old_freq) {
2003 		HWRITE4(sc, clksel,
2004 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2005 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2006 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2007 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2008 		HWRITE4(sc, clksel + 0x0004,
2009 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2010 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2011 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2012 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2013 	}
2014 
2015 	return 0;
2016 }
2017 
2018 uint32_t
2019 rk3399_get_frequency(void *cookie, uint32_t *cells)
2020 {
2021 	struct rkclock_softc *sc = cookie;
2022 	uint32_t idx = cells[0];
2023 
2024 	switch (idx) {
2025 	case RK3399_PLL_ALPLL:
2026 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
2027 	case RK3399_PLL_ABPLL:
2028 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
2029 	case RK3399_PLL_DPLL:
2030 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
2031 	case RK3399_PLL_CPLL:
2032 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
2033 	case RK3399_PLL_GPLL:
2034 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
2035 	case RK3399_PLL_NPLL:
2036 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
2037 	case RK3399_PLL_VPLL:
2038 		return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
2039 	case RK3399_ARMCLKL:
2040 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
2041 	case RK3399_ARMCLKB:
2042 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
2043 	case RK3399_XIN24M:
2044 		return 24000000;
2045 	case RK3399_CLK_32K:
2046 		return 32768;
2047 	case RK3399_XIN12M:
2048 		return 12000000;
2049 	default:
2050 		break;
2051 	}
2052 
2053 	return rkclock_get_frequency(sc, idx);
2054 }
2055 
2056 int
2057 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2058 {
2059 	struct rkclock_softc *sc = cookie;
2060 	uint32_t idx = cells[0];
2061 
2062 	switch (idx) {
2063 	case RK3399_PLL_ALPLL:
2064 		return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
2065 	case RK3399_PLL_ABPLL:
2066 		return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
2067 	case RK3399_PLL_CPLL:
2068 		return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
2069 	case RK3399_PLL_GPLL:
2070 		return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
2071 	case RK3399_PLL_NPLL:
2072 		return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
2073 	case RK3399_PLL_VPLL:
2074 		return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq);
2075 	case RK3399_ARMCLKL:
2076 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
2077 	case RK3399_ARMCLKB:
2078 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
2079 	case RK3399_XIN12M:
2080 		if (freq / (1000 * 1000) != 12)
2081 			return -1;
2082 		return 0;
2083 	default:
2084 		break;
2085 	}
2086 
2087 	return rkclock_set_frequency(sc, idx, freq);
2088 }
2089 
2090 void
2091 rk3399_enable(void *cookie, uint32_t *cells, int on)
2092 {
2093 	uint32_t idx = cells[0];
2094 
2095 	/*
2096 	 * All clocks are enabled by default, so there is nothing for
2097 	 * us to do until we start disabling clocks.
2098 	 */
2099 	if (!on)
2100 		printf("%s: 0x%08x\n", __func__, idx);
2101 }
2102 
2103 void
2104 rk3399_reset(void *cookie, uint32_t *cells, int on)
2105 {
2106 	struct rkclock_softc *sc = cookie;
2107 	uint32_t idx = cells[0];
2108 	uint32_t mask = (1 << (idx % 16));
2109 
2110 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
2111 	    mask << 16 | (on ? mask : 0));
2112 }
2113 
2114 /* PMUCRU */
2115 
2116 struct rkclock rk3399_pmu_clocks[] = {
2117 	{
2118 		RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
2119 		0, DIV(6, 0),
2120 		{ RK3399_PLL_PPLL }
2121 	},
2122 	{
2123 		RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
2124 		0, DIV(6, 0),
2125 		{ RK3399_PLL_PPLL }
2126 	},
2127 	{
2128 		RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
2129 		0, DIV(14, 8),
2130 		{ RK3399_PLL_PPLL }
2131 	},
2132 	{
2133 		RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0),
2134 		0, DIV(6, 0),
2135 		{ RK3399_PLL_PPLL }
2136 	},
2137 	{
2138 		/* Sentinel */
2139 	}
2140 };
2141 
2142 void
2143 rk3399_pmu_init(struct rkclock_softc *sc)
2144 {
2145 	sc->sc_clocks = rk3399_pmu_clocks;
2146 	rk3399_pmucru_sc = sc;
2147 }
2148 
2149 uint32_t
2150 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
2151 {
2152 	struct rkclock_softc *sc = cookie;
2153 	uint32_t idx = cells[0];
2154 
2155 	switch (idx) {
2156 	case RK3399_PLL_PPLL:
2157 		return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
2158 	default:
2159 		break;
2160 	}
2161 
2162 	return rkclock_get_frequency(sc, idx);
2163 }
2164 
2165 int
2166 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2167 {
2168 	struct rkclock_softc *sc = cookie;
2169 	uint32_t idx = cells[0];
2170 
2171 	switch (idx) {
2172 	case RK3399_PLL_PPLL:
2173 		return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
2174 		break;
2175 	default:
2176 		break;
2177 	}
2178 
2179 	return rkclock_set_frequency(sc, idx, freq);
2180 }
2181 
2182 void
2183 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
2184 {
2185 	uint32_t idx = cells[0];
2186 
2187 	switch (idx) {
2188 	case RK3399_CLK_I2C0:
2189 	case RK3399_CLK_I2C4:
2190 	case RK3399_CLK_I2C8:
2191 	case RK3399_PCLK_I2C0:
2192 	case RK3399_PCLK_I2C4:
2193 	case RK3399_PCLK_I2C8:
2194 	case RK3399_PCLK_RKPWM:
2195 		/* Enabled by default. */
2196 		break;
2197 	default:
2198 		printf("%s: 0x%08x\n", __func__, idx);
2199 		break;
2200 	}
2201 }
2202 
2203 void
2204 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
2205 {
2206 	uint32_t idx = cells[0];
2207 
2208 	printf("%s: 0x%08x\n", __func__, idx);
2209 }
2210