xref: /openbsd/sys/dev/fdt/rkclock.c (revision 274d7c50)
1 /*	$OpenBSD: rkclock.c,v 1.46 2019/09/20 20:45:28 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 || clk->div_mask == 0) {
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 	}
424 
425 	/*
426 	 * Start out with the current parent.  This prevents
427 	 * unecessary switching to a different parent.
428 	 */
429 	best_freq = rkclock_freq(sc, clk, mux, freq);
430 	best_mux = mux;
431 
432 	/*
433 	 * Find the parent that allows configuration of a frequency
434 	 * closest to the target frequency.
435 	 */
436 	if ((clk->flags & FIXED_PARENT) == 0) {
437 		for (i = 0; i < nitems(clk->parents); i++) {
438 			if (clk->parents[i] == 0)
439 				continue;
440 			f = rkclock_freq(sc, clk, i, freq);
441 			if ((f > best_freq && f <= freq) ||
442 			    (f < best_freq && f >= freq)) {
443 				best_freq = f;
444 				best_mux = i;
445 			}
446 		}
447 	}
448 
449 	div_con = rkclock_div_con(sc, clk, best_mux, freq);
450 	div_shift = ffs(clk->div_mask) - 1;
451 	HWRITE4(sc, clk->reg,
452 	    clk->sel_mask << 16 | best_mux << sel_shift |
453 	    clk->div_mask << 16 | div_con << div_shift);
454 	return 0;
455 }
456 
457 int
458 rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent)
459 {
460 	struct rkclock *clk;
461 	uint32_t mux;
462 	int shift;
463 
464 	clk = rkclock_lookup(sc, idx);
465 	if (clk == NULL || clk->sel_mask == 0) {
466 		printf("%s: 0x%08x\n", __func__, idx);
467 		return -1;
468 	}
469 
470 	for (mux = 0; mux < nitems(clk->parents); mux++) {
471 		if (clk->parents[mux] == parent)
472 			break;
473 	}
474 	if (mux == nitems(clk->parents) || parent == 0) {
475 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent);
476 		return -1;
477 	}
478 
479 	shift = ffs(clk->sel_mask) - 1;
480 	HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift);
481 	return 0;
482 }
483 
484 /*
485  * Rockchip RK3288
486  */
487 
488 struct rkclock rk3288_clocks[] = {
489 	{
490 		RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11),
491 		SEL(7, 6), DIV(5, 0),
492 		{ RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M }
493 	}
494 };
495 
496 void
497 rk3288_init(struct rkclock_softc *sc)
498 {
499 	int node;
500 
501 	/*
502 	 * Since the hardware comes up with a really conservative CPU
503 	 * clock frequency, and U-Boot doesn't set it to a more
504 	 * reasonable default, try to do so here.  These defaults were
505 	 * chosen assuming that the CPU voltage is at least 1.1 V.
506 	 * Only do this on the Tinker-RK3288 for now where this is
507 	 * likely to be true given the default voltages for the
508 	 * regulators on that board.
509 	 */
510 	node = OF_finddevice("/");
511 	if (OF_is_compatible(node, "rockchip,rk3288-tinker")) {
512 		uint32_t idx;
513 
514 		/* Run at 1.2 GHz. */
515 		idx = RK3288_ARMCLK;
516 		rk3288_set_frequency(sc, &idx, 1200000000);
517 	}
518 
519 	sc->sc_clocks = rk3288_clocks;
520 }
521 
522 uint32_t
523 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
524 {
525 	uint32_t clkod, clkr, clkf;
526 	uint32_t reg;
527 
528 	reg = HREAD4(sc, base);
529 	clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >>
530 	    RK3288_CRU_PLL_CLKOD_SHIFT;
531 	clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >>
532 	    RK3288_CRU_PLL_CLKR_SHIFT;
533 	reg = HREAD4(sc, base + 4);
534 	clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >>
535 	    RK3288_CRU_PLL_CLKF_SHIFT;
536 	return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
537 }
538 
539 int
540 rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
541 {
542 	int shift = 4 * (base / RK3288_CRU_CPLL_CON(0));
543 	uint32_t no, nr, nf;
544 
545 	/*
546 	 * It is not clear whether all combinations of the clock
547 	 * dividers result in a stable clock.  Therefore this function
548 	 * only supports a limited set of PLL clock rates.  For now
549 	 * this set covers all the CPU frequencies supported by the
550 	 * Linux kernel.
551 	 */
552 	switch (freq) {
553 	case 1800000000:
554 	case 1704000000:
555 	case 1608000000:
556 	case 1512000000:
557 	case 1488000000:
558 	case 1416000000:
559 	case 1200000000:
560 		nr = no = 1;
561 		break;
562 	case 1008000000:
563 	case 816000000:
564 	case 696000000:
565 	case 600000000:
566 		nr = 1; no = 2;
567 		break;
568 	case 408000000:
569 	case 312000000:
570 		nr = 1; no = 4;
571 		break;
572 	case 216000000:
573 	case 126000000:
574 		nr = 1; no = 8;
575 		break;
576 	default:
577 		printf("%s: %u Hz\n", __func__, freq);
578 		return -1;
579 	}
580 
581 	/* Calculate feedback divider. */
582 	nf = freq * nr * no / 24000000;
583 
584 	/*
585 	 * Select slow mode to guarantee a stable clock while we're
586 	 * adjusting the PLL.
587 	 */
588 	HWRITE4(sc, RK3288_CRU_MODE_CON,
589 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
590 	     RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift);
591 
592 	/* Assert reset. */
593 	HWRITE4(sc, base + 0x000c,
594 	    RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET);
595 
596 	/* Set PLL rate. */
597 	HWRITE4(sc, base + 0x0000,
598 	    RK3288_CRU_PLL_CLKR_MASK << 16 |
599 	    (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT |
600 	    RK3288_CRU_PLL_CLKOD_MASK << 16 |
601 	    (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT);
602 	HWRITE4(sc, base + 0x0004,
603 	    RK3288_CRU_PLL_CLKF_MASK << 16 |
604 	    (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT);
605 
606 	/* Deassert reset and wait. */
607 	HWRITE4(sc, base + 0x000c,
608 	    RK3288_CRU_PLL_RESET << 16);
609 	delay((nr * 500 / 24) + 1);
610 
611 	/* Switch back to normal mode. */
612 	HWRITE4(sc, RK3288_CRU_MODE_CON,
613 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
614 	     RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift);
615 
616 	return 0;
617 }
618 
619 uint32_t
620 rk3288_get_frequency(void *cookie, uint32_t *cells)
621 {
622 	struct rkclock_softc *sc = cookie;
623 	uint32_t idx = cells[0];
624 	uint32_t reg, mux, div_con, aclk_div_con;
625 
626 	switch (idx) {
627 	case RK3288_PLL_APLL:
628 		return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0));
629 	case RK3288_PLL_CPLL:
630 		return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
631 	case RK3288_PLL_GPLL:
632 		return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
633 	case RK3288_PLL_NPLL:
634 		return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0));
635 	case RK3288_ARMCLK:
636 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
637 		mux = (reg >> 15) & 0x1;
638 		div_con = (reg >> 8) & 0x1f;
639 		idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL;
640 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
641 	case RK3288_XIN24M:
642 		return 24000000;
643 	case RK3288_CLK_UART0:
644 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
645 		mux = (reg >> 8) & 0x3;
646 		div_con = reg & 0x7f;
647 		if (mux == 2)
648 			return 24000000 / (div_con + 1);
649 		break;
650 	case RK3288_CLK_UART1:
651 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
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_UART2:
658 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
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_UART3:
665 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
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_UART4:
672 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
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_MAC:
679 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21));
680 		if (reg & 0x10)
681 			return 125000000;;
682 		mux = (reg >> 0) & 0x3;
683 		div_con = (reg >> 8) & 0x1f;
684 		switch (mux) {
685 		case 0:
686 			idx = RK3288_PLL_NPLL;
687 			break;
688 		case 1:
689 			idx = RK3288_PLL_CPLL;
690 			break;
691 		case 2:
692 			idx = RK3288_PLL_GPLL;
693 			break;
694 		default:
695 			return 0;
696 		}
697 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
698 	case RK3288_PCLK_I2C0:
699 	case RK3288_PCLK_I2C2:
700 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1));
701 		mux = (reg >> 15) & 0x1;
702 		/* pd_bus_pclk_div_con */
703 		div_con = (reg >> 12) & 0x7;
704 		if (mux == 1)
705 			idx = RK3288_PLL_GPLL;
706 		else
707 			idx = RK3288_PLL_CPLL;
708 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
709 	case RK3288_PCLK_I2C1:
710 	case RK3288_PCLK_I2C3:
711 	case RK3288_PCLK_I2C4:
712 	case RK3288_PCLK_I2C5:
713 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10));
714 		mux = (reg >> 15) & 0x1;
715 		/* peri_pclk_div_con */
716 		div_con = (reg >> 12) & 0x3;
717 		/* peri_aclk_div_con */
718 		aclk_div_con = reg & 0xf;
719 		if (mux == 1)
720 			idx = RK3288_PLL_GPLL;
721 		else
722 			idx = RK3288_PLL_CPLL;
723 		return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >>
724 		    div_con;
725 	default:
726 		break;
727 	}
728 
729 	return rkclock_get_frequency(sc, idx);
730 }
731 
732 int
733 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
734 {
735 	struct rkclock_softc *sc = cookie;
736 	uint32_t idx = cells[0];
737 	int error;
738 
739 	switch (idx) {
740 	case RK3288_PLL_APLL:
741 		return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq);
742 	case RK3288_ARMCLK:
743 		idx = RK3288_PLL_APLL;
744 		error = rk3288_set_frequency(sc, &idx, freq);
745 		if (error == 0) {
746 			HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0),
747 			    ((1 << 15) | (0x1f << 8)) << 16);
748 		}
749 		return error;
750 	default:
751 		break;
752 	}
753 
754 	return rkclock_set_frequency(sc, idx, freq);
755 }
756 
757 void
758 rk3288_enable(void *cookie, uint32_t *cells, int on)
759 {
760 	uint32_t idx = cells[0];
761 
762 	switch (idx) {
763 	case RK3288_CLK_SDMMC:
764 	case RK3288_CLK_TSADC:
765 	case RK3288_CLK_UART0:
766 	case RK3288_CLK_UART1:
767 	case RK3288_CLK_UART2:
768 	case RK3288_CLK_UART3:
769 	case RK3288_CLK_UART4:
770 	case RK3288_CLK_MAC_RX:
771 	case RK3288_CLK_MAC_TX:
772 	case RK3288_CLK_SDMMC_DRV:
773 	case RK3288_CLK_SDMMC_SAMPLE:
774 	case RK3288_CLK_MAC:
775 	case RK3288_ACLK_GMAC:
776 	case RK3288_PCLK_GMAC:
777 	case RK3288_PCLK_I2C0:
778 	case RK3288_PCLK_I2C1:
779 	case RK3288_PCLK_I2C2:
780 	case RK3288_PCLK_I2C3:
781 	case RK3288_PCLK_I2C4:
782 	case RK3288_PCLK_I2C5:
783 	case RK3288_PCLK_TSADC:
784 	case RK3288_HCLK_HOST0:
785 	case RK3288_HCLK_SDMMC:
786 		/* Enabled by default. */
787 		break;
788 	default:
789 		printf("%s: 0x%08x\n", __func__, idx);
790 		break;
791 	}
792 }
793 
794 void
795 rk3288_reset(void *cookie, uint32_t *cells, int on)
796 {
797 	struct rkclock_softc *sc = cookie;
798 	uint32_t idx = cells[0];
799 	uint32_t mask = (1 << (idx % 16));
800 
801 	HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16),
802 	    mask << 16 | (on ? mask : 0));
803 }
804 
805 /*
806  * Rockchip RK3328
807  */
808 
809 struct rkclock rk3328_clocks[] = {
810 	{
811 		RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38),
812 		SEL(15, 14), DIV(13, 0),
813 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M }
814 	},
815 	{
816 		RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30),
817 		SEL(9, 8), DIV(7, 0),
818 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
819 		  RK3328_USB480M }
820 	},
821 	{
822 		RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31),
823 		SEL(9, 8), DIV(7, 0),
824 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
825 		  RK3328_USB480M }
826 	},
827 	{
828 		RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32),
829 		SEL(9, 8), DIV(7, 0),
830 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
831 		  RK3328_USB480M }
832 	},
833 	{
834 		RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22),
835 		0, DIV(9, 0),
836 		{ RK3328_CLK_24M }
837 	},
838 	{
839 		RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14),
840 		SEL(9, 8), 0,
841 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
842 	},
843 	{
844 		RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16),
845 		SEL(9, 8), 0,
846 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
847 	},
848 	{
849 		RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18),
850 		SEL(9, 8), 0,
851 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
852 	},
853 	{
854 		RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52),
855 		SEL(7, 6), DIV(5, 0),
856 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M }
857 	},
858 	{
859 		RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34),
860 		SEL(7, 7), DIV(6, 0),
861 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
862 	},
863 	{
864 		RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34),
865 		SEL(15, 15), DIV(14, 8),
866 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
867 	},
868 	{
869 		RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35),
870 		SEL(7, 7), DIV(6, 0),
871 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
872 	},
873 	{
874 		RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35),
875 		SEL(15, 15), DIV(14, 8),
876 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
877 	},
878 	{
879 		RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
880 		SEL(15, 14), DIV(12, 8),
881 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
882 		FIXED_PARENT | SET_PARENT
883 	},
884 	{
885 		RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
886 		SEL(15, 14), DIV(12, 8),
887 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
888 		  RK3328_USB480M }
889 	},
890 	{
891 		RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
892 		SEL(7, 6), DIV(4, 0),
893 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
894 		  RK3328_USB480M }
895 	},
896 	{
897 		RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
898 		SEL(15, 14), DIV(12, 8),
899 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
900 		  RK3328_USB480M }
901 	},
902 	{
903 		RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
904 		SEL(15, 14), DIV(12, 8),
905 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
906 		  RK3328_USB480M }
907 	},
908 	{
909 		RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
910 		SEL(15, 15), DIV(12, 8),
911 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
912 	},
913 	{
914 		RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
915 		SEL(7, 7), DIV(4, 0),
916 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
917 	},
918 	{
919 		RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
920 		SEL(1, 1), 0,
921 		{ RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
922 	},
923 	{
924 		RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
925 		SEL(7, 6), DIV(4, 0),
926 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
927 		  RK3328_USB480M }
928 	},
929 	{
930 		RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
931 		SEL(15, 14), DIV(12, 8),
932 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
933 		  RK3328_USB480M }
934 	},
935 	{
936 		RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
937 		SEL(14, 13), DIV(12, 8),
938 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
939 	},
940 	{
941 		RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
942 		SEL(7, 6), DIV(4, 0),
943 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
944 	},
945 	{
946 		RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
947 		SEL(7, 6), DIV(4, 0),
948 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
949 		  RK3328_USB480M }
950 	},
951 	{
952 		RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
953 		SEL(7, 6), DIV(4, 0),
954 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
955 		  RK3328_USB480M }
956 	},
957 	{
958 		RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
959 		SEL(7, 6), DIV(4, 0),
960 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
961 		  RK3328_USB480M }
962 	},
963 	{
964 		RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
965 		SEL(7, 6), DIV(4, 0),
966 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
967 		  RK3328_USB480M }
968 	},
969 	{
970 		RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
971 		0, DIV(14, 12),
972 		{ RK3328_ACLK_BUS_PRE }
973 	},
974 	{
975 		RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
976 		0, DIV(9, 8),
977 		{ RK3328_ACLK_BUS_PRE }
978 	},
979 	{
980 		RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
981 		0, DIV(6, 4),
982 		{ RK3328_ACLK_PERI_PRE }
983 	},
984 	{
985 		RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
986 		0, DIV(1, 0),
987 		{ RK3328_ACLK_PERI_PRE }
988 	},
989 	{
990 		RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
991 		0, DIV(12, 8),
992 		{ RK3328_XIN24M }
993 	},
994 	{
995 		/* Sentinel */
996 	}
997 };
998 
999 void
1000 rk3328_init(struct rkclock_softc *sc)
1001 {
1002 	int i;
1003 
1004 	/* The code below assumes all clocks are enabled.  Check this!. */
1005 	for (i = 0; i <= 28; i++) {
1006 		if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1007 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1008 			    HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1009 		}
1010 	}
1011 
1012 	sc->sc_clocks = rk3328_clocks;
1013 }
1014 
1015 uint32_t
1016 rk3328_armclk_parent(uint32_t mux)
1017 {
1018 	switch (mux) {
1019 	case 0:
1020 		return RK3328_PLL_APLL;
1021 	case 1:
1022 		return RK3328_PLL_GPLL;
1023 	case 2:
1024 		return RK3328_PLL_DPLL;
1025 	case 3:
1026 		return RK3328_PLL_NPLL;
1027 	}
1028 
1029 	return 0;
1030 }
1031 
1032 uint32_t
1033 rk3328_get_armclk(struct rkclock_softc *sc)
1034 {
1035 	uint32_t reg, mux, div_con;
1036 	uint32_t idx;
1037 
1038 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1039 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1040 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1041 	div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1042 	    RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1043 	idx = rk3328_armclk_parent(mux);
1044 
1045 	return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1046 }
1047 
1048 int
1049 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1050 {
1051 	uint32_t reg, mux;
1052 	uint32_t old_freq, div;
1053 	uint32_t idx;
1054 
1055 	old_freq = rk3328_get_armclk(sc);
1056 	if (freq == old_freq)
1057 		return 0;
1058 
1059 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1060 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1061 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1062 
1063 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1064 	div = 1;
1065 	while (freq / (div + 1) > 300000000)
1066 		div++;
1067 	/* and make sure we use an odd divider. */
1068 	if ((div % 2) == 0)
1069 		div++;
1070 
1071 	/* When ramping up, set clock dividers first. */
1072 	if (freq > old_freq) {
1073 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1074 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1075 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1076 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1077 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1078 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1079 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1080 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1081 	}
1082 
1083 	/* We always use NPLL and force the switch below if needed. */
1084 	idx = RK3328_PLL_NPLL;
1085 	rk3328_set_frequency(sc, &idx, freq);
1086 
1087 	/* When ramping down, set clock dividers last. */
1088 	if (freq < old_freq || mux != 3) {
1089 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1090 		    RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1091 		    3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1092 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1093 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1094 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1095 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1096 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1097 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1098 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1099 	}
1100 
1101 	return 0;
1102 }
1103 
1104 uint32_t
1105 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1106 {
1107 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1108 	uint32_t dsmpd, fracdiv;
1109 	uint64_t frac = 0;
1110 	uint32_t reg;
1111 
1112 	reg = HREAD4(sc, base + 0x0000);
1113 	postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1114 	    RK3328_CRU_PLL_POSTDIV1_SHIFT;
1115 	fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1116 	    RK3328_CRU_PLL_FBDIV_SHIFT;
1117 	reg = HREAD4(sc, base + 0x0004);
1118 	dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1119 	postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1120 	    RK3328_CRU_PLL_POSTDIV2_SHIFT;
1121 	refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1122 	    RK3328_CRU_PLL_REFDIV_SHIFT;
1123 	reg = HREAD4(sc, base + 0x0008);
1124 	fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1125 	    RK3328_CRU_PLL_FRACDIV_SHIFT;
1126 
1127 	if (dsmpd == 0)
1128 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1129 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1130 }
1131 
1132 int
1133 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1134 {
1135 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1136 	int mode_shift = -1;
1137 
1138 	switch (base) {
1139 	case RK3328_CRU_APLL_CON(0):
1140 		mode_shift = 0;
1141 		break;
1142 	case RK3328_CRU_DPLL_CON(0):
1143 		mode_shift = 4;
1144 		break;
1145 	case RK3328_CRU_CPLL_CON(0):
1146 		mode_shift = 8;
1147 		break;
1148 	case RK3328_CRU_GPLL_CON(0):
1149 		mode_shift = 12;
1150 		break;
1151 	case RK3328_CRU_NPLL_CON(0):
1152 		mode_shift = 1;
1153 		break;
1154 	}
1155 	KASSERT(mode_shift != -1);
1156 
1157 	/*
1158 	 * It is not clear whether all combinations of the clock
1159 	 * dividers result in a stable clock.  Therefore this function
1160 	 * only supports a limited set of PLL clock rates.  For now
1161 	 * this set covers all the CPU frequencies supported by the
1162 	 * Linux kernel.
1163 	 */
1164 	switch (freq) {
1165 	case 1800000000U:
1166 	case 1704000000U:
1167 	case 1608000000U:
1168 	case 1512000000U:
1169 	case 1488000000U:
1170 	case 1416000000U:
1171 	case 1392000000U:
1172 	case 1296000000U:
1173 	case 1200000000U:
1174 	case 1104000000U:
1175 		postdiv1 = postdiv2 = refdiv = 1;
1176 		break;
1177 	case 1008000000U:
1178 	case 912000000U:
1179 	case 816000000U:
1180 	case 696000000U:
1181 		postdiv1 = 2; postdiv2 = refdiv = 1;
1182 		break;
1183 	case 600000000U:
1184 		postdiv1 = 3; postdiv2 = refdiv = 1;
1185 		break;
1186 	case 408000000U:
1187 	case 312000000U:
1188 		postdiv1 = postdiv2 = 2; refdiv = 1;
1189 		break;
1190 	case 216000000U:
1191 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1192 		break;
1193 	case 96000000U:
1194 		postdiv1 = postdiv2 = 4; refdiv = 1;
1195 		break;
1196 	default:
1197 		printf("%s: %u Hz\n", __func__, freq);
1198 		return -1;
1199 	}
1200 
1201 	/* Calculate feedback divider. */
1202 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1203 
1204 	/*
1205 	 * Select slow mode to guarantee a stable clock while we're
1206 	 * adjusting the PLL.
1207 	 */
1208 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1209 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1210 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1211 
1212 	/* Set PLL rate. */
1213 	HWRITE4(sc, base + 0x0000,
1214 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1215 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1216 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1217 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1218 	HWRITE4(sc, base + 0x0004,
1219 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1220 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1221 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1222 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1223 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1224 
1225 	/* Wait for PLL to stabilize. */
1226 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1227 		delay(10);
1228 
1229 	/* Switch back to normal mode. */
1230 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1231 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1232 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1233 
1234 	return 0;
1235 }
1236 
1237 int
1238 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1239 {
1240 	uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
1241 	int mode_shift = -1;
1242 	uint32_t reg;
1243 
1244 	switch (base) {
1245 	case RK3328_CRU_APLL_CON(0):
1246 		mode_shift = 0;
1247 		break;
1248 	case RK3328_CRU_DPLL_CON(0):
1249 		mode_shift = 4;
1250 		break;
1251 	case RK3328_CRU_CPLL_CON(0):
1252 		mode_shift = 8;
1253 		break;
1254 	case RK3328_CRU_GPLL_CON(0):
1255 		mode_shift = 12;
1256 		break;
1257 	case RK3328_CRU_NPLL_CON(0):
1258 		mode_shift = 1;
1259 		break;
1260 	}
1261 	KASSERT(mode_shift != -1);
1262 
1263 	/*
1264 	 * It is not clear whether all combinations of the clock
1265 	 * dividers result in a stable clock.  Therefore this function
1266 	 * only supports a limited set of PLL clock rates.  This set
1267 	 * set covers all the fractional PLL frequencies supported by
1268 	 * the Linux kernel.
1269 	 */
1270 	switch (freq) {
1271 	case 1016064000U:
1272 		postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
1273 		break;
1274 	case 983040000U:
1275 		postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1276 		break;
1277 	case 491520000U:
1278 		postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1279 		break;
1280 	case 61440000U:
1281 		postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
1282 		break;
1283 	case 56448000U:
1284 		postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
1285 		break;
1286 	case 40960000U:
1287 		postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
1288 		break;
1289 	default:
1290 		printf("%s: %u Hz\n", __func__, freq);
1291 		return -1;
1292 	}
1293 
1294 	/* Calculate feedback divider. */
1295 	fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
1296 
1297 	/*
1298 	 * Select slow mode to guarantee a stable clock while we're
1299 	 * adjusting the PLL.
1300 	 */
1301 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1302 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1303 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1304 
1305 	/* Set PLL rate. */
1306 	HWRITE4(sc, base + 0x0000,
1307 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1308 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1309 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1310 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1311 	HWRITE4(sc, base + 0x0004,
1312 	    RK3328_CRU_PLL_DSMPD << 16 |
1313 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1314 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1315 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1316 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1317 	reg = HREAD4(sc, base + 0x0008);
1318 	reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
1319 	reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
1320 	HWRITE4(sc, base + 0x0008, reg);
1321 
1322 	/* Wait for PLL to stabilize. */
1323 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1324 		delay(10);
1325 
1326 	/* Switch back to normal mode. */
1327 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1328 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1329 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1330 
1331 	return 0;
1332 }
1333 
1334 uint32_t
1335 rk3328_get_frequency(void *cookie, uint32_t *cells)
1336 {
1337 	struct rkclock_softc *sc = cookie;
1338 	uint32_t idx = cells[0];
1339 	uint32_t reg;
1340 
1341 	switch (idx) {
1342 	case RK3328_PLL_APLL:
1343 		return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
1344 		break;
1345 	case RK3328_PLL_DPLL:
1346 		return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
1347 		break;
1348 	case RK3328_PLL_CPLL:
1349 		return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
1350 		break;
1351 	case RK3328_PLL_GPLL:
1352 		return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
1353 		break;
1354 	case RK3328_PLL_NPLL:
1355 		return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
1356 		break;
1357 	case RK3328_ARMCLK:
1358 		return rk3328_get_armclk(sc);
1359 	case RK3328_XIN24M:
1360 		return 24000000;
1361 	case RK3328_GMAC_CLKIN:
1362 		return 125000000;
1363 	/*
1364 	 * XXX The HDMIPHY and USB480M clocks are external.  Returning
1365 	 * zero here will cause them to be ignored for reparenting
1366 	 * purposes.
1367 	 */
1368 	case RK3328_HDMIPHY:
1369 		return 0;
1370 	case RK3328_USB480M:
1371 		return 0;
1372 	case RK3328_CLK_MAC2IO:
1373 		reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
1374 		if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
1375 			idx = RK3328_GMAC_CLKIN;
1376 		else
1377 			idx = RK3328_CLK_MAC2IO_SRC;
1378 		return rk3328_get_frequency(sc, &idx);
1379 	default:
1380 		break;
1381 	}
1382 
1383 	return rkclock_get_frequency(sc, idx);
1384 }
1385 
1386 int
1387 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1388 {
1389 	struct rkclock_softc *sc = cookie;
1390 	uint32_t idx = cells[0];
1391 	uint32_t reg, mux;
1392 
1393 	switch (idx) {
1394 	case RK3328_PLL_APLL:
1395 		return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
1396 	case RK3328_PLL_DPLL:
1397 		return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
1398 	case RK3328_PLL_CPLL:
1399 		return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
1400 	case RK3328_PLL_GPLL:
1401 		return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
1402 	case RK3328_PLL_NPLL:
1403 		return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
1404 	case RK3328_ARMCLK:
1405 		return rk3328_set_armclk(sc, freq);
1406 	case RK3328_CLK_UART0:
1407 	case RK3328_CLK_UART1:
1408 	case RK3328_CLK_UART2:
1409 		if (freq == rk3328_get_frequency(sc, &idx))
1410 			return 0;
1411 		break;
1412 	case RK3328_DCLK_LCDC:
1413 		reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
1414 		mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
1415 		    RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
1416 		idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
1417 		return rk3328_set_frequency(sc, &idx, freq);
1418 	default:
1419 		break;
1420 	}
1421 
1422 	return rkclock_set_frequency(sc, idx, freq);
1423 }
1424 
1425 int
1426 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1427 {
1428 	struct rkclock_softc *sc = cookie;
1429 	uint32_t idx = cells[0];
1430 	uint32_t parent;
1431 
1432 	if (pcells[0] == sc->sc_phandle)
1433 		parent = pcells[1];
1434 	else {
1435 		char name[32];
1436 		int node;
1437 
1438 		node = OF_getnodebyphandle(pcells[0]);
1439 		if (node == 0)
1440 			return -1;
1441 		name[0] = 0;
1442 		OF_getprop(node, "clock-output-names", name, sizeof(name));
1443 		name[sizeof(name) - 1] = 0;
1444 		if (strcmp(name, "xin24m") == 0)
1445 			parent = RK3328_XIN24M;
1446 		else if (strcmp(name, "gmac_clkin") == 0)
1447 			parent = RK3328_GMAC_CLKIN;
1448 		else
1449 			return -1;
1450 	}
1451 
1452 	switch (idx) {
1453 	case RK3328_CLK_MAC2IO:
1454 		if (parent == RK3328_GMAC_CLKIN) {
1455 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1456 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
1457 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
1458 		} else {
1459 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
1460 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
1461 		}
1462 		return 0;
1463 	case RK3328_CLK_MAC2IO_EXT:
1464 		if (parent == RK3328_GMAC_CLKIN) {
1465 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1466 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
1467 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
1468 		} else {
1469 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
1470 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
1471 		}
1472 		return 0;
1473 	}
1474 
1475 	return rkclock_set_parent(sc, idx, parent);
1476 }
1477 
1478 void
1479 rk3328_enable(void *cookie, uint32_t *cells, int on)
1480 {
1481 	uint32_t idx = cells[0];
1482 
1483 	/*
1484 	 * All clocks are enabled by default, so there is nothing for
1485 	 * us to do until we start disabling clocks.
1486 	 */
1487 	if (!on)
1488 		printf("%s: 0x%08x\n", __func__, idx);
1489 }
1490 
1491 void
1492 rk3328_reset(void *cookie, uint32_t *cells, int on)
1493 {
1494 	struct rkclock_softc *sc = cookie;
1495 	uint32_t idx = cells[0];
1496 	uint32_t mask = (1 << (idx % 16));
1497 
1498 	HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
1499 	    mask << 16 | (on ? mask : 0));
1500 }
1501 
1502 /*
1503  * Rockchip RK3399
1504  */
1505 
1506 struct rkclock rk3399_clocks[] = {
1507 	{
1508 		RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
1509 		SEL(7, 7), DIV(6, 0),
1510 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1511 	},
1512 	{
1513 		RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
1514 		SEL(7, 7), DIV(6, 0),
1515 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1516 	},
1517 	{
1518 		RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
1519 		SEL(7, 7), DIV(6, 0),
1520 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1521 	},
1522 	{
1523 		RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
1524 		SEL(15, 15), DIV(14, 8),
1525 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1526 	},
1527 	{
1528 		RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
1529 		SEL(15, 15), DIV(14, 8),
1530 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1531 	},
1532 	{
1533 		RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
1534 		SEL(15, 15), DIV(14, 8),
1535 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1536 	},
1537 	{
1538 		RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
1539 		SEL(10, 8), DIV(6, 0),
1540 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1541 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
1542 		  RK3399_XIN24M }
1543 	},
1544 	{
1545 		RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
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_TSADC, RK3399_CRU_CLKSEL_CON(27),
1553 		SEL(15, 15), DIV(9, 0),
1554 		{ RK3399_XIN24M, RK3399_CLK_32K }
1555 	},
1556 	{
1557 		RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
1558 		SEL(9, 8), 0,
1559 		{ 0, 0, RK3399_XIN24M }
1560 	},
1561 	{
1562 		RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
1563 		SEL(9, 8), 0,
1564 		{ 0, 0, RK3399_XIN24M }
1565 	},
1566 	{
1567 		RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
1568 		SEL(9, 8), 0,
1569 		{ 0, 0, RK3399_XIN24M }
1570 	},
1571 	{
1572 		RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
1573 		SEL(9, 8), 0,
1574 		{ 0, 0, RK3399_XIN24M }
1575 	},
1576 	{
1577 		RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
1578 		SEL(15, 14), DIV(12, 8),
1579 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
1580 	},
1581 	{
1582 		RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1583 		SEL(7, 7), DIV(4, 0),
1584 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1585 	},
1586 	{
1587 		RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1588 		SEL(7, 7), DIV(4, 0),
1589 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1590 	},
1591 	{
1592 		RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
1593 		SEL(7, 6), DIV(4, 0),
1594 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1595 	},
1596 	{
1597 		RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
1598 		SEL(7, 6), DIV(4, 0),
1599 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
1600 		  RK3399_PLL_VPLL }
1601 	},
1602 	{
1603 		RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
1604 		SEL(15, 14), DIV(12, 8),
1605 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
1606 	},
1607 	{
1608 		RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
1609 		SEL(15, 15), DIV(12, 8),
1610 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1611 	},
1612 	{
1613 		RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1614 		0, DIV(14, 12),
1615 		{ RK3399_ACLK_PERIPH }
1616 	},
1617 	{
1618 		RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1619 		0, DIV(14, 12),
1620 		{ RK3399_ACLK_PERILP0 }
1621 	},
1622 	{
1623 		RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1624 		0, DIV(10, 8),
1625 		{ RK3399_HCLK_PERILP1 }
1626 	},
1627 	{
1628 		RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
1629 		SEL(15, 15), DIV(12, 8),
1630 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1631 	},
1632 	{
1633 		RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
1634 		0, DIV(9, 8),
1635 		{ RK3399_ACLK_PERIPH }
1636 	},
1637 	{
1638 		RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
1639 		0, DIV(9, 8),
1640 		{ RK3399_ACLK_PERILP0 }
1641 	},
1642 	{
1643 		RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
1644 		SEL(7, 7), DIV(4, 0),
1645 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1646 	},
1647 	{
1648 		RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
1649 		SEL(15, 15), DIV(12, 8),
1650 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
1651 	},
1652 	{
1653 		/* Sentinel */
1654 	}
1655 };
1656 
1657 /* Some of our parent clocks live in the PMUCRU. */
1658 struct rkclock_softc *rk3399_pmucru_sc;
1659 
1660 void
1661 rk3399_init(struct rkclock_softc *sc)
1662 {
1663 	int i;
1664 
1665 	/* PMUCRU instance should attach before us. */
1666 	KASSERT(rk3399_pmucru_sc != NULL);
1667 
1668 	/*
1669 	 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
1670 	 * module is buggy and sets the parent of the clock for the
1671 	 * "big" cluster to LPLL.  Undo that mistake here such that
1672 	 * the clocks of both clusters are independent.
1673 	 */
1674 	HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
1675 	    RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
1676 	    RK3399_CRU_CORE_PLL_SEL_BPLL);
1677 
1678 	/* The code below assumes all clocks are enabled.  Check this!. */
1679 	for (i = 0; i <= 34; i++) {
1680 		if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
1681 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1682 			    HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
1683 		}
1684 	}
1685 
1686 	sc->sc_clocks = rk3399_clocks;
1687 }
1688 
1689 uint32_t
1690 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
1691 {
1692 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1693 	uint32_t pll_work_mode;
1694 	uint32_t reg;
1695 
1696 	reg = HREAD4(sc, base + 0x000c);
1697 	pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
1698 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
1699 		return 24000000;
1700 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
1701 		return 32768;
1702 
1703 	reg = HREAD4(sc, base + 0x0000);
1704 	fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
1705 	    RK3399_CRU_PLL_FBDIV_SHIFT;
1706 	reg = HREAD4(sc, base + 0x0004);
1707 	postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
1708 	    RK3399_CRU_PLL_POSTDIV2_SHIFT;
1709 	postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
1710 	    RK3399_CRU_PLL_POSTDIV1_SHIFT;
1711 	refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
1712 	    RK3399_CRU_PLL_REFDIV_SHIFT;
1713 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
1714 }
1715 
1716 int
1717 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1718 {
1719 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1720 
1721 	/*
1722 	 * It is not clear whether all combinations of the clock
1723 	 * dividers result in a stable clock.  Therefore this function
1724 	 * only supports a limited set of PLL clock rates.  For now
1725 	 * this set covers all the CPU frequencies supported by the
1726 	 * Linux kernel.
1727 	 */
1728 	switch (freq) {
1729 	case 2208000000U:
1730 	case 2184000000U:
1731 	case 2088000000U:
1732 	case 2040000000U:
1733 	case 2016000000U:
1734 	case 1992000000U:
1735 	case 1896000000U:
1736 	case 1800000000U:
1737 	case 1704000000U:
1738 	case 1608000000U:
1739 	case 1512000000U:
1740 	case 1488000000U:
1741 	case 1416000000U:
1742 	case 1200000000U:
1743 		postdiv1 = postdiv2 = refdiv = 1;
1744 		break;
1745 	case 1008000000U:
1746 	case 816000000U:
1747 	case 696000000U:
1748 		postdiv1 = 2; postdiv2 = refdiv = 1;
1749 		break;
1750 	case 676000000U:
1751 		postdiv1 = 2; postdiv2 = 1; refdiv = 3;
1752 		break;
1753 	case 1000000000U:
1754 	case 800000000U:
1755 	case 600000000U:
1756 		postdiv1 = 3; postdiv2 = refdiv = 1;
1757 		break;
1758 	case 594000000U:
1759 		postdiv1 = 4; postdiv2 = refdiv = 1;
1760 		break;
1761 	case 408000000U:
1762 		postdiv1 = postdiv2 = 2; refdiv = 1;
1763 		break;
1764 	case 216000000U:
1765 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1766 		break;
1767 	case 96000000U:
1768 		postdiv1 = postdiv2 = 4; refdiv = 1;
1769 		break;
1770 	default:
1771 		printf("%s: %d Hz\n", __func__, freq);
1772 		return -1;
1773 	}
1774 
1775 	/* Calculate feedback divider. */
1776 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1777 
1778 	/*
1779 	 * Select slow mode to guarantee a stable clock while we're
1780 	 * adjusting the PLL.
1781 	 */
1782 	HWRITE4(sc, base + 0x000c,
1783 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1784 	    RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
1785 
1786 	/* Set PLL rate. */
1787 	HWRITE4(sc, base + 0x0000,
1788 	    RK3399_CRU_PLL_FBDIV_MASK << 16 |
1789 	    fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
1790 	HWRITE4(sc, base + 0x0004,
1791 	    RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
1792 	    postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
1793 	    RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
1794 	    postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
1795 	    RK3399_CRU_PLL_REFDIV_MASK << 16 |
1796 	    refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
1797 
1798 	/* Wait for PLL to stabilize. */
1799 	while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
1800 		delay(10);
1801 
1802 	/* Switch back to normal mode. */
1803 	HWRITE4(sc, base + 0x000c,
1804 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
1805 	    RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
1806 
1807 	return 0;
1808 }
1809 
1810 uint32_t
1811 rk3399_armclk_parent(uint32_t mux)
1812 {
1813 	switch (mux) {
1814 	case 0:
1815 		return RK3399_PLL_ALPLL;
1816 	case 1:
1817 		return RK3399_PLL_ABPLL;
1818 	case 2:
1819 		return RK3399_PLL_DPLL;
1820 	case 3:
1821 		return RK3399_PLL_GPLL;
1822 	}
1823 
1824 	return 0;
1825 }
1826 
1827 uint32_t
1828 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
1829 {
1830 	uint32_t reg, mux, div_con;
1831 	uint32_t idx;
1832 
1833 	reg = HREAD4(sc, clksel);
1834 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1835 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1836 	div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
1837 	    RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
1838 	idx = rk3399_armclk_parent(mux);
1839 
1840 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
1841 }
1842 
1843 int
1844 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
1845 {
1846 	uint32_t reg, mux;
1847 	uint32_t old_freq, div;
1848 	uint32_t idx;
1849 
1850 	old_freq = rk3399_get_armclk(sc, clksel);
1851 	if (freq == old_freq)
1852 		return 0;
1853 
1854 	reg = HREAD4(sc, clksel);
1855 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
1856 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
1857 	idx = rk3399_armclk_parent(mux);
1858 
1859 	/* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
1860 	div = 1;
1861 	while (freq / (div + 1) > 200000000)
1862 		div++;
1863 
1864 	/* When ramping up, set clock dividers first. */
1865 	if (freq > old_freq) {
1866 		HWRITE4(sc, clksel,
1867 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1868 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
1869 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
1870 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
1871 		HWRITE4(sc, clksel + 0x0004,
1872 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
1873 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
1874 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
1875 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
1876 	}
1877 
1878 	rk3399_set_frequency(sc, &idx, freq);
1879 
1880 	/* When ramping down, set clock dividers last. */
1881 	if (freq < old_freq) {
1882 		HWRITE4(sc, clksel,
1883 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1884 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
1885 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
1886 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
1887 		HWRITE4(sc, clksel + 0x0004,
1888 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
1889 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
1890 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
1891 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
1892 	}
1893 
1894 	return 0;
1895 }
1896 
1897 uint32_t
1898 rk3399_get_frequency(void *cookie, uint32_t *cells)
1899 {
1900 	struct rkclock_softc *sc = cookie;
1901 	uint32_t idx = cells[0];
1902 
1903 	switch (idx) {
1904 	case RK3399_PLL_ALPLL:
1905 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
1906 	case RK3399_PLL_ABPLL:
1907 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
1908 	case RK3399_PLL_DPLL:
1909 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
1910 	case RK3399_PLL_CPLL:
1911 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
1912 	case RK3399_PLL_GPLL:
1913 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
1914 	case RK3399_PLL_NPLL:
1915 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
1916 	case RK3399_PLL_VPLL:
1917 		return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
1918 	case RK3399_ARMCLKL:
1919 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
1920 	case RK3399_ARMCLKB:
1921 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
1922 	case RK3399_XIN24M:
1923 		return 24000000;
1924 	case RK3399_CLK_32K:
1925 		return 32768;
1926 	default:
1927 		break;
1928 	}
1929 
1930 	return rkclock_get_frequency(sc, idx);
1931 }
1932 
1933 int
1934 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1935 {
1936 	struct rkclock_softc *sc = cookie;
1937 	uint32_t idx = cells[0];
1938 
1939 	switch (idx) {
1940 	case RK3399_PLL_ALPLL:
1941 		return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
1942 	case RK3399_PLL_ABPLL:
1943 		return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
1944 	case RK3399_PLL_CPLL:
1945 		return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
1946 	case RK3399_PLL_GPLL:
1947 		return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
1948 	case RK3399_PLL_NPLL:
1949 		return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
1950 	case RK3399_ARMCLKL:
1951 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
1952 	case RK3399_ARMCLKB:
1953 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
1954 	default:
1955 		break;
1956 	}
1957 
1958 	return rkclock_set_frequency(sc, idx, freq);
1959 }
1960 
1961 void
1962 rk3399_enable(void *cookie, uint32_t *cells, int on)
1963 {
1964 	uint32_t idx = cells[0];
1965 
1966 	/*
1967 	 * All clocks are enabled by default, so there is nothing for
1968 	 * us to do until we start disabling clocks.
1969 	 */
1970 	if (!on)
1971 		printf("%s: 0x%08x\n", __func__, idx);
1972 }
1973 
1974 void
1975 rk3399_reset(void *cookie, uint32_t *cells, int on)
1976 {
1977 	struct rkclock_softc *sc = cookie;
1978 	uint32_t idx = cells[0];
1979 	uint32_t mask = (1 << (idx % 16));
1980 
1981 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
1982 	    mask << 16 | (on ? mask : 0));
1983 }
1984 
1985 /* PMUCRU */
1986 
1987 struct rkclock rk3399_pmu_clocks[] = {
1988 	{
1989 		RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
1990 		0, DIV(6, 0),
1991 		{ RK3399_PLL_PPLL }
1992 	},
1993 	{
1994 		RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
1995 		0, DIV(6, 0),
1996 		{ RK3399_PLL_PPLL }
1997 	},
1998 	{
1999 		RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
2000 		0, DIV(14, 8),
2001 		{ RK3399_PLL_PPLL }
2002 	},
2003 	{
2004 		/* Sentinel */
2005 	}
2006 };
2007 
2008 void
2009 rk3399_pmu_init(struct rkclock_softc *sc)
2010 {
2011 	sc->sc_clocks = rk3399_pmu_clocks;
2012 	rk3399_pmucru_sc = sc;
2013 }
2014 
2015 uint32_t
2016 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
2017 {
2018 	struct rkclock_softc *sc = cookie;
2019 	uint32_t idx = cells[0];
2020 
2021 	switch (idx) {
2022 	case RK3399_PLL_PPLL:
2023 		return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
2024 	default:
2025 		break;
2026 	}
2027 
2028 	return rkclock_get_frequency(sc, idx);
2029 }
2030 
2031 int
2032 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2033 {
2034 	struct rkclock_softc *sc = cookie;
2035 	uint32_t idx = cells[0];
2036 
2037 	switch (idx) {
2038 	case RK3399_PLL_PPLL:
2039 		return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
2040 		break;
2041 	default:
2042 		break;
2043 	}
2044 
2045 	return rkclock_set_frequency(sc, idx, freq);
2046 }
2047 
2048 void
2049 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
2050 {
2051 	uint32_t idx = cells[0];
2052 
2053 	switch (idx) {
2054 	case RK3399_CLK_I2C0:
2055 	case RK3399_CLK_I2C4:
2056 	case RK3399_CLK_I2C8:
2057 	case RK3399_PCLK_I2C0:
2058 	case RK3399_PCLK_I2C4:
2059 	case RK3399_PCLK_I2C8:
2060 		/* Enabled by default. */
2061 		break;
2062 	default:
2063 		printf("%s: 0x%08x\n", __func__, idx);
2064 		break;
2065 	}
2066 }
2067 
2068 void
2069 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
2070 {
2071 	uint32_t idx = cells[0];
2072 
2073 	printf("%s: 0x%08x\n", __func__, idx);
2074 }
2075