xref: /openbsd/sys/dev/fdt/rkclock.c (revision 097a140d)
1 /*	$OpenBSD: rkclock.c,v 1.55 2021/04/07 16:35:02 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 /* RK3308 registers */
52 #define RK3308_CRU_APLL_CON(i)		(0x0000 + (i) * 4)
53 #define RK3308_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
54 #define RK3308_CRU_VPLL0_CON(i)		(0x0040 + (i) * 4)
55 #define RK3308_CRU_VPLL1_CON(i)		(0x0060 + (i) * 4)
56 #define  RK3308_CRU_PLL_POSTDIV1_MASK		(0x7 << 12)
57 #define  RK3308_CRU_PLL_POSTDIV1_SHIFT		12
58 #define  RK3308_CRU_PLL_FBDIV_MASK		(0xfff << 0)
59 #define  RK3308_CRU_PLL_FBDIV_SHIFT		0
60 #define  RK3308_CRU_PLL_DSMPD			(1 << 12)
61 #define  RK3308_CRU_PLL_PLL_LOCK		(1 << 10)
62 #define  RK3308_CRU_PLL_POSTDIV2_MASK		(0x7 << 6)
63 #define  RK3308_CRU_PLL_POSTDIV2_SHIFT		6
64 #define  RK3308_CRU_PLL_REFDIV_MASK		(0x3f << 0)
65 #define  RK3308_CRU_PLL_REFDIV_SHIFT		0
66 #define  RK3308_CRU_PLL_FRACDIV_MASK		(0xffffff << 0)
67 #define  RK3308_CRU_PLL_FRACDIV_SHIFT		0
68 #define RK3308_CRU_CRU_MODE		0x00a0
69 #define RK3308_CRU_CRU_MODE_MASK	0x3
70 #define RK3308_CRU_CRU_MODE_SLOW	0x0
71 #define RK3308_CRU_CRU_MODE_NORMAL	0x1
72 #define RK3308_CRU_CRU_MODE_DEEP	0x2
73 #define RK3308_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
74 #define  RK3308_CRU_ACLK_CORE_DIV_CON_MASK	(0x07 << 12)
75 #define  RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT	12
76 #define  RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK	(0x0f << 8)
77 #define  RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT  8
78 #define  RK3308_CRU_CORE_CLK_PLL_SEL_MASK	(0x03 << 6)
79 #define  RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT	6
80 #define  RK3308_CRU_CLK_CORE_DIV_CON_MASK	(0x0f << 0)
81 #define  RK3308_CRU_CLK_CORE_DIV_CON_SHIFT	0
82 #define RK3308_CRU_CLKGATE_CON(i)	(0x0300 + (i) * 4)
83 #define RK3308_CRU_SOFTRST_CON(i)	(0x0400 + (i) * 4)
84 
85 /* RK3328 registers */
86 #define RK3328_CRU_APLL_CON(i)		(0x0000 + (i) * 4)
87 #define RK3328_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
88 #define RK3328_CRU_CPLL_CON(i)		(0x0040 + (i) * 4)
89 #define RK3328_CRU_GPLL_CON(i)		(0x0060 + (i) * 4)
90 #define RK3328_CRU_NPLL_CON(i)		(0x00a0 + (i) * 4)
91 #define  RK3328_CRU_PLL_POSTDIV1_MASK		(0x7 << 12)
92 #define  RK3328_CRU_PLL_POSTDIV1_SHIFT		12
93 #define  RK3328_CRU_PLL_FBDIV_MASK		(0xfff << 0)
94 #define  RK3328_CRU_PLL_FBDIV_SHIFT		0
95 #define  RK3328_CRU_PLL_DSMPD			(1 << 12)
96 #define  RK3328_CRU_PLL_PLL_LOCK		(1 << 10)
97 #define  RK3328_CRU_PLL_POSTDIV2_MASK		(0x7 << 6)
98 #define  RK3328_CRU_PLL_POSTDIV2_SHIFT		6
99 #define  RK3328_CRU_PLL_REFDIV_MASK		(0x3f << 0)
100 #define  RK3328_CRU_PLL_REFDIV_SHIFT		0
101 #define  RK3328_CRU_PLL_FRACDIV_MASK		(0xffffff << 0)
102 #define  RK3328_CRU_PLL_FRACDIV_SHIFT		0
103 #define RK3328_CRU_CRU_MODE		0x0080
104 #define  RK3328_CRU_CRU_MODE_MASK		0x1
105 #define  RK3328_CRU_CRU_MODE_SLOW		0x0
106 #define  RK3328_CRU_CRU_MODE_NORMAL		0x1
107 #define RK3328_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
108 #define  RK3328_CRU_CORE_CLK_PLL_SEL_MASK	(0x3 << 6)
109 #define  RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT	6
110 #define  RK3328_CRU_CLK_CORE_DIV_CON_MASK	(0x1f << 0)
111 #define  RK3328_CRU_CLK_CORE_DIV_CON_SHIFT	0
112 #define  RK3328_CRU_ACLK_CORE_DIV_CON_MASK	(0x7 << 4)
113 #define  RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT	4
114 #define  RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK	(0xf << 0)
115 #define  RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT	0
116 #define  RK3328_CRU_VOP_DCLK_SRC_SEL_MASK	(0x1 << 1)
117 #define  RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT	1
118 #define RK3328_CRU_CLKGATE_CON(i)	(0x0200 + (i) * 4)
119 #define RK3328_CRU_SOFTRST_CON(i)	(0x0300 + (i) * 4)
120 
121 #define RK3328_GRF_SOC_CON4		0x0410
122 #define  RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN	(1 << 14)
123 #define RK3328_GRF_MAC_CON1		0x0904
124 #define  RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL	(1 << 10)
125 
126 /* RK3399 registers */
127 #define RK3399_CRU_LPLL_CON(i)		(0x0000 + (i) * 4)
128 #define RK3399_CRU_BPLL_CON(i)		(0x0020 + (i) * 4)
129 #define RK3399_CRU_DPLL_CON(i)		(0x0020 + (i) * 4)
130 #define RK3399_CRU_CPLL_CON(i)		(0x0060 + (i) * 4)
131 #define RK3399_CRU_GPLL_CON(i)		(0x0080 + (i) * 4)
132 #define RK3399_CRU_NPLL_CON(i)		(0x00a0 + (i) * 4)
133 #define RK3399_CRU_VPLL_CON(i)		(0x00c0 + (i) * 4)
134 #define  RK3399_CRU_PLL_FBDIV_MASK		(0xfff << 0)
135 #define  RK3399_CRU_PLL_FBDIV_SHIFT		0
136 #define  RK3399_CRU_PLL_POSTDIV2_MASK		(0x7 << 12)
137 #define  RK3399_CRU_PLL_POSTDIV2_SHIFT		12
138 #define  RK3399_CRU_PLL_POSTDIV1_MASK		(0x7 << 8)
139 #define  RK3399_CRU_PLL_POSTDIV1_SHIFT		8
140 #define  RK3399_CRU_PLL_REFDIV_MASK		(0x3f << 0)
141 #define  RK3399_CRU_PLL_REFDIV_SHIFT		0
142 #define  RK3399_CRU_PLL_PLL_WORK_MODE_MASK	(0x3 << 8)
143 #define  RK3399_CRU_PLL_PLL_WORK_MODE_SLOW	(0x0 << 8)
144 #define  RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL	(0x1 << 8)
145 #define  RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW	(0x2 << 8)
146 #define  RK3399_CRU_PLL_PLL_LOCK		(1U << 31)
147 #define RK3399_CRU_CLKSEL_CON(i)	(0x0100 + (i) * 4)
148 #define  RK3399_CRU_ACLKM_CORE_DIV_CON_MASK	(0x1f << 8)
149 #define  RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT	8
150 #define  RK3399_CRU_CORE_PLL_SEL_MASK		(0x3 << 6)
151 #define  RK3399_CRU_CORE_PLL_SEL_APLL		(0x0 << 6)
152 #define  RK3399_CRU_CORE_PLL_SEL_BPLL		(0x1 << 6)
153 #define  RK3399_CRU_CORE_PLL_SEL_DPLL		(0x2 << 6)
154 #define  RK3399_CRU_CORE_PLL_SEL_GPLL		(0x3 << 6)
155 #define  RK3399_CRU_CORE_PLL_SEL_SHIFT		6
156 #define  RK3399_CRU_CLK_CORE_DIV_CON_MASK	(0x1f << 0)
157 #define  RK3399_CRU_CLK_CORE_DIV_CON_SHIFT	0
158 #define  RK3399_CRU_PCLK_DBG_DIV_CON_MASK	(0x1f << 8)
159 #define  RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT	8
160 #define  RK3399_CRU_ATCLK_CORE_DIV_CON_MASK	(0x1f << 0)
161 #define  RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT	0
162 #define  RK3399_CRU_CLK_SD_PLL_SEL_MASK		(0x7 << 8)
163 #define  RK3399_CRU_CLK_SD_PLL_SEL_SHIFT	8
164 #define  RK3399_CRU_CLK_SD_DIV_CON_MASK		(0x7f << 0)
165 #define  RK3399_CRU_CLK_SD_DIV_CON_SHIFT	0
166 #define RK3399_CRU_CLKGATE_CON(i)	(0x0300 + (i) * 4)
167 #define RK3399_CRU_SOFTRST_CON(i)	(0x0400 + (i) * 4)
168 #define RK3399_CRU_SDMMC_CON(i)		(0x0580 + (i) * 4)
169 
170 #define RK3399_PMUCRU_PPLL_CON(i)	(0x0000 + (i) * 4)
171 #define RK3399_PMUCRU_CLKSEL_CON(i)	(0x0080 + (i) * 4)
172 
173 #include "rkclock_clocks.h"
174 
175 struct rkclock {
176 	uint16_t idx;
177 	uint16_t reg;
178 	uint16_t sel_mask;
179 	uint16_t div_mask;
180 	uint16_t parents[8];
181 	uint32_t flags;
182 };
183 
184 #define SEL(l, f)	(((1 << (l - f + 1)) - 1) << f)
185 #define DIV(l, f)	SEL(l, f)
186 
187 #define FIXED_PARENT	(1 << 0)
188 #define SET_PARENT	(1 << 1)
189 
190 #define HREAD4(sc, reg)							\
191 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
192 #define HWRITE4(sc, reg, val)						\
193 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
194 #define HSET4(sc, reg, bits)						\
195 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
196 #define HCLR4(sc, reg, bits)						\
197 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
198 
199 struct rkclock_softc {
200 	struct device		sc_dev;
201 	bus_space_tag_t		sc_iot;
202 	bus_space_handle_t	sc_ioh;
203 	struct regmap		*sc_grf;
204 
205 	uint32_t		sc_phandle;
206 	struct rkclock		*sc_clocks;
207 
208 	struct clock_device	sc_cd;
209 	struct reset_device	sc_rd;
210 };
211 
212 int rkclock_match(struct device *, void *, void *);
213 void rkclock_attach(struct device *, struct device *, void *);
214 
215 struct cfattach	rkclock_ca = {
216 	sizeof (struct rkclock_softc), rkclock_match, rkclock_attach
217 };
218 
219 struct cfdriver rkclock_cd = {
220 	NULL, "rkclock", DV_DULL
221 };
222 
223 void	rk3288_init(struct rkclock_softc *);
224 uint32_t rk3288_get_frequency(void *, uint32_t *);
225 int	rk3288_set_frequency(void *, uint32_t *, uint32_t);
226 void	rk3288_enable(void *, uint32_t *, int);
227 void	rk3288_reset(void *, uint32_t *, int);
228 
229 void	rk3308_init(struct rkclock_softc *);
230 uint32_t rk3308_get_frequency(void *, uint32_t *);
231 int	rk3308_set_frequency(void *, uint32_t *, uint32_t);
232 int	rk3308_set_parent(void *, uint32_t *, uint32_t *);
233 void	rk3308_enable(void *, uint32_t *, int);
234 void	rk3308_reset(void *, uint32_t *, int);
235 
236 void	rk3328_init(struct rkclock_softc *);
237 uint32_t rk3328_get_frequency(void *, uint32_t *);
238 int	rk3328_set_frequency(void *, uint32_t *, uint32_t);
239 int	rk3328_set_parent(void *, uint32_t *, uint32_t *);
240 void	rk3328_enable(void *, uint32_t *, int);
241 void	rk3328_reset(void *, uint32_t *, int);
242 
243 void	rk3399_init(struct rkclock_softc *);
244 uint32_t rk3399_get_frequency(void *, uint32_t *);
245 int	rk3399_set_frequency(void *, uint32_t *, uint32_t);
246 void	rk3399_enable(void *, uint32_t *, int);
247 void	rk3399_reset(void *, uint32_t *, int);
248 
249 void	rk3399_pmu_init(struct rkclock_softc *);
250 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *);
251 int	rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t);
252 void	rk3399_pmu_enable(void *, uint32_t *, int);
253 void	rk3399_pmu_reset(void *, uint32_t *, int);
254 
255 struct rkclock_compat {
256 	const char *compat;
257 	int	assign;
258 	void	(*init)(struct rkclock_softc *);
259 	void	(*enable)(void *, uint32_t *, int);
260 	uint32_t (*get_frequency)(void *, uint32_t *);
261 	int	(*set_frequency)(void *, uint32_t *, uint32_t);
262 	int	(*set_parent)(void *, uint32_t *, uint32_t *);
263 	void	(*reset)(void *, uint32_t *, int);
264 };
265 
266 struct rkclock_compat rkclock_compat[] = {
267 	{
268 		"rockchip,rk3288-cru", 0, rk3288_init,
269 		rk3288_enable, rk3288_get_frequency,
270 		rk3288_set_frequency, NULL,
271 		rk3288_reset
272 	},
273 	{
274 		"rockchip,rk3308-cru", 1, rk3308_init,
275 		rk3308_enable, rk3308_get_frequency,
276 		rk3308_set_frequency, rk3308_set_parent,
277 		rk3308_reset
278 	},
279 	{
280 		"rockchip,rk3328-cru", 1, rk3328_init,
281 		rk3328_enable, rk3328_get_frequency,
282 		rk3328_set_frequency, rk3328_set_parent,
283 		rk3328_reset
284 	},
285 	{
286 		"rockchip,rk3399-cru", 1, rk3399_init,
287 		rk3399_enable, rk3399_get_frequency,
288 		rk3399_set_frequency, NULL,
289 		rk3399_reset
290 	},
291 	{
292 		"rockchip,rk3399-pmucru", 1, rk3399_pmu_init,
293 		rk3399_pmu_enable, rk3399_pmu_get_frequency,
294 		rk3399_pmu_set_frequency, NULL,
295 		rk3399_pmu_reset
296 	}
297 };
298 
299 int
300 rkclock_match(struct device *parent, void *match, void *aux)
301 {
302 	struct fdt_attach_args *faa = aux;
303 	int i;
304 
305 	for (i = 0; i < nitems(rkclock_compat); i++) {
306 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat))
307 			return 10;
308 	}
309 
310 	return 0;
311 }
312 
313 void
314 rkclock_attach(struct device *parent, struct device *self, void *aux)
315 {
316 	struct rkclock_softc *sc = (struct rkclock_softc *)self;
317 	struct fdt_attach_args *faa = aux;
318 	uint32_t grf;
319 	int i;
320 
321 	if (faa->fa_nreg < 1) {
322 		printf(": no registers\n");
323 		return;
324 	}
325 
326 	sc->sc_iot = faa->fa_iot;
327 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
328 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
329 		printf(": can't map registers\n");
330 		return;
331 	}
332 
333 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
334 	sc->sc_grf = regmap_byphandle(grf);
335 
336 	printf("\n");
337 
338 	sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0);
339 
340 	for (i = 0; i < nitems(rkclock_compat); i++) {
341 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) {
342 			break;
343 		}
344 	}
345 	KASSERT(i < nitems(rkclock_compat));
346 
347 	if (rkclock_compat[i].init)
348 		rkclock_compat[i].init(sc);
349 
350 	sc->sc_cd.cd_node = faa->fa_node;
351 	sc->sc_cd.cd_cookie = sc;
352 	sc->sc_cd.cd_enable = rkclock_compat[i].enable;
353 	sc->sc_cd.cd_get_frequency = rkclock_compat[i].get_frequency;
354 	sc->sc_cd.cd_set_frequency = rkclock_compat[i].set_frequency;
355 	sc->sc_cd.cd_set_parent = rkclock_compat[i].set_parent;
356 	clock_register(&sc->sc_cd);
357 
358 	sc->sc_rd.rd_node = faa->fa_node;
359 	sc->sc_rd.rd_cookie = sc;
360 	sc->sc_rd.rd_reset = rkclock_compat[i].reset;
361 	reset_register(&sc->sc_rd);
362 
363 	if (rkclock_compat[i].assign)
364 		clock_set_assigned(faa->fa_node);
365 }
366 
367 struct rkclock *
368 rkclock_lookup(struct rkclock_softc *sc, uint32_t idx)
369 {
370 	struct rkclock *clk;
371 
372 	for (clk = sc->sc_clocks; clk->idx; clk++) {
373 		if (clk->idx == idx)
374 			return clk;
375 	}
376 
377 	return NULL;
378 }
379 
380 uint32_t
381 rkclock_div_con(struct rkclock_softc *sc, struct rkclock *clk,
382     uint32_t mux, uint32_t freq)
383 {
384 	uint32_t parent_freq, div, div_con, max_div_con;
385 	uint32_t idx = clk->parents[mux];
386 
387 	/* Derive maximum value from mask. */
388 	max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1);
389 
390 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
391 	div = (parent_freq + freq - 1) / freq;
392 	div_con = (div > 0 ? div - 1 : 0);
393 	return (div_con < max_div_con) ? div_con : max_div_con;
394 }
395 
396 uint32_t
397 rkclock_freq(struct rkclock_softc *sc, struct rkclock *clk,
398     uint32_t mux, uint32_t freq)
399 {
400 	uint32_t parent_freq, div_con;
401 	uint32_t idx = clk->parents[mux];
402 
403 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
404 	div_con = rkclock_div_con(sc, clk, mux, freq);
405 	return parent_freq / (div_con + 1);
406 }
407 
408 uint32_t
409 rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx)
410 {
411 	struct rkclock *clk;
412 	uint32_t reg, mux, div_con;
413 	int shift;
414 
415 	clk = rkclock_lookup(sc, idx);
416 	if (clk == NULL) {
417 		printf("%s: 0x%08x\n", __func__, idx);
418 		return 0;
419 	}
420 
421 	reg = HREAD4(sc, clk->reg);
422 	shift = ffs(clk->sel_mask) - 1;
423 	if (shift == -1)
424 		mux = 0;
425 	else
426 		mux = (reg & clk->sel_mask) >> shift;
427 	shift = ffs(clk->div_mask) - 1;
428 	if (shift == -1)
429 		div_con = 0;
430 	else
431 		div_con = (reg & clk->div_mask) >> shift;
432 
433 	if (clk->parents[mux] == 0) {
434 		printf("%s: parent 0x%08x\n", __func__, idx);
435 		return 0;
436 	}
437 	idx = clk->parents[mux];
438 	return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1);
439 }
440 
441 int
442 rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq)
443 {
444 	struct rkclock *clk;
445 	uint32_t reg, mux, div_con;
446 	uint32_t best_freq, best_mux, f;
447 	int sel_shift, div_shift, i;
448 
449 	clk = rkclock_lookup(sc, idx);
450 	if (clk == NULL) {
451 		printf("%s: 0x%08x\n", __func__, idx);
452 		return -1;
453 	}
454 
455 	reg = HREAD4(sc, clk->reg);
456 	sel_shift = ffs(clk->sel_mask) - 1;
457 	if (sel_shift == -1)
458 		mux = sel_shift = 0;
459 	else
460 		mux = (reg & clk->sel_mask) >> sel_shift;
461 
462 	if (clk->parents[mux] == 0) {
463 		printf("%s: parent 0x%08x\n", __func__, idx);
464 		return 0;
465 	}
466 
467 	if (clk->flags & SET_PARENT) {
468 		idx = clk->parents[mux];
469 		sc->sc_cd.cd_set_frequency(sc, &idx, freq);
470 		if (clk->div_mask == 0)
471 			return 0;
472 	}
473 
474 	if (clk->div_mask == 0) {
475 		printf("%s: 0x%08x\n", __func__, idx);
476 		return -1;
477 	}
478 
479 	/*
480 	 * Start out with the current parent.  This prevents
481 	 * unecessary switching to a different parent.
482 	 */
483 	best_freq = rkclock_freq(sc, clk, mux, freq);
484 	best_mux = mux;
485 
486 	/*
487 	 * Find the parent that allows configuration of a frequency
488 	 * closest to the target frequency.
489 	 */
490 	if ((clk->flags & FIXED_PARENT) == 0) {
491 		for (i = 0; i < nitems(clk->parents); i++) {
492 			if (clk->parents[i] == 0)
493 				continue;
494 			f = rkclock_freq(sc, clk, i, freq);
495 			if ((f > best_freq && f <= freq) ||
496 			    (f < best_freq && f >= freq)) {
497 				best_freq = f;
498 				best_mux = i;
499 			}
500 		}
501 	}
502 
503 	div_con = rkclock_div_con(sc, clk, best_mux, freq);
504 	div_shift = ffs(clk->div_mask) - 1;
505 	HWRITE4(sc, clk->reg,
506 	    clk->sel_mask << 16 | best_mux << sel_shift |
507 	    clk->div_mask << 16 | div_con << div_shift);
508 	return 0;
509 }
510 
511 int
512 rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent)
513 {
514 	struct rkclock *clk;
515 	uint32_t mux;
516 	int shift;
517 
518 	clk = rkclock_lookup(sc, idx);
519 	if (clk == NULL || clk->sel_mask == 0) {
520 		printf("%s: 0x%08x\n", __func__, idx);
521 		return -1;
522 	}
523 
524 	for (mux = 0; mux < nitems(clk->parents); mux++) {
525 		if (clk->parents[mux] == parent)
526 			break;
527 	}
528 	if (mux == nitems(clk->parents) || parent == 0) {
529 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent);
530 		return -1;
531 	}
532 
533 	shift = ffs(clk->sel_mask) - 1;
534 	HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift);
535 	return 0;
536 }
537 
538 /*
539  * Rockchip RK3288
540  */
541 
542 struct rkclock rk3288_clocks[] = {
543 	{
544 		RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11),
545 		SEL(7, 6), DIV(5, 0),
546 		{ RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M }
547 	}
548 };
549 
550 void
551 rk3288_init(struct rkclock_softc *sc)
552 {
553 	int node;
554 
555 	/*
556 	 * Since the hardware comes up with a really conservative CPU
557 	 * clock frequency, and U-Boot doesn't set it to a more
558 	 * reasonable default, try to do so here.  These defaults were
559 	 * chosen assuming that the CPU voltage is at least 1.1 V.
560 	 * Only do this on the Tinker-RK3288 for now where this is
561 	 * likely to be true given the default voltages for the
562 	 * regulators on that board.
563 	 */
564 	node = OF_finddevice("/");
565 	if (OF_is_compatible(node, "rockchip,rk3288-tinker")) {
566 		uint32_t idx;
567 
568 		/* Run at 1.2 GHz. */
569 		idx = RK3288_ARMCLK;
570 		rk3288_set_frequency(sc, &idx, 1200000000);
571 	}
572 
573 	sc->sc_clocks = rk3288_clocks;
574 }
575 
576 uint32_t
577 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
578 {
579 	uint32_t clkod, clkr, clkf;
580 	uint32_t reg;
581 
582 	reg = HREAD4(sc, base);
583 	clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >>
584 	    RK3288_CRU_PLL_CLKOD_SHIFT;
585 	clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >>
586 	    RK3288_CRU_PLL_CLKR_SHIFT;
587 	reg = HREAD4(sc, base + 4);
588 	clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >>
589 	    RK3288_CRU_PLL_CLKF_SHIFT;
590 	return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
591 }
592 
593 int
594 rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
595 {
596 	int shift = 4 * (base / RK3288_CRU_CPLL_CON(0));
597 	uint32_t no, nr, nf;
598 
599 	/*
600 	 * It is not clear whether all combinations of the clock
601 	 * dividers result in a stable clock.  Therefore this function
602 	 * only supports a limited set of PLL clock rates.  For now
603 	 * this set covers all the CPU frequencies supported by the
604 	 * Linux kernel.
605 	 */
606 	switch (freq) {
607 	case 1800000000:
608 	case 1704000000:
609 	case 1608000000:
610 	case 1512000000:
611 	case 1488000000:
612 	case 1416000000:
613 	case 1200000000:
614 		nr = no = 1;
615 		break;
616 	case 1008000000:
617 	case 816000000:
618 	case 696000000:
619 	case 600000000:
620 		nr = 1; no = 2;
621 		break;
622 	case 408000000:
623 	case 312000000:
624 		nr = 1; no = 4;
625 		break;
626 	case 216000000:
627 	case 126000000:
628 		nr = 1; no = 8;
629 		break;
630 	default:
631 		printf("%s: %u Hz\n", __func__, freq);
632 		return -1;
633 	}
634 
635 	/* Calculate feedback divider. */
636 	nf = freq * nr * no / 24000000;
637 
638 	/*
639 	 * Select slow mode to guarantee a stable clock while we're
640 	 * adjusting the PLL.
641 	 */
642 	HWRITE4(sc, RK3288_CRU_MODE_CON,
643 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
644 	     RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift);
645 
646 	/* Assert reset. */
647 	HWRITE4(sc, base + 0x000c,
648 	    RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET);
649 
650 	/* Set PLL rate. */
651 	HWRITE4(sc, base + 0x0000,
652 	    RK3288_CRU_PLL_CLKR_MASK << 16 |
653 	    (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT |
654 	    RK3288_CRU_PLL_CLKOD_MASK << 16 |
655 	    (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT);
656 	HWRITE4(sc, base + 0x0004,
657 	    RK3288_CRU_PLL_CLKF_MASK << 16 |
658 	    (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT);
659 
660 	/* Deassert reset and wait. */
661 	HWRITE4(sc, base + 0x000c,
662 	    RK3288_CRU_PLL_RESET << 16);
663 	delay((nr * 500 / 24) + 1);
664 
665 	/* Switch back to normal mode. */
666 	HWRITE4(sc, RK3288_CRU_MODE_CON,
667 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
668 	     RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift);
669 
670 	return 0;
671 }
672 
673 uint32_t
674 rk3288_get_frequency(void *cookie, uint32_t *cells)
675 {
676 	struct rkclock_softc *sc = cookie;
677 	uint32_t idx = cells[0];
678 	uint32_t reg, mux, div_con, aclk_div_con;
679 
680 	switch (idx) {
681 	case RK3288_PLL_APLL:
682 		return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0));
683 	case RK3288_PLL_CPLL:
684 		return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
685 	case RK3288_PLL_GPLL:
686 		return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
687 	case RK3288_PLL_NPLL:
688 		return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0));
689 	case RK3288_ARMCLK:
690 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
691 		mux = (reg >> 15) & 0x1;
692 		div_con = (reg >> 8) & 0x1f;
693 		idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL;
694 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
695 	case RK3288_XIN24M:
696 		return 24000000;
697 	case RK3288_CLK_UART0:
698 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
699 		mux = (reg >> 8) & 0x3;
700 		div_con = reg & 0x7f;
701 		if (mux == 2)
702 			return 24000000 / (div_con + 1);
703 		break;
704 	case RK3288_CLK_UART1:
705 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
706 		mux = (reg >> 8) & 0x3;
707 		div_con = reg & 0x7f;
708 		if (mux == 2)
709 			return 24000000 / (div_con + 1);
710 		break;
711 	case RK3288_CLK_UART2:
712 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
713 		mux = (reg >> 8) & 0x3;
714 		div_con = reg & 0x7f;
715 		if (mux == 2)
716 			return 24000000 / (div_con + 1);
717 		break;
718 	case RK3288_CLK_UART3:
719 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
720 		mux = (reg >> 8) & 0x3;
721 		div_con = reg & 0x7f;
722 		if (mux == 2)
723 			return 24000000 / (div_con + 1);
724 		break;
725 	case RK3288_CLK_UART4:
726 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
727 		mux = (reg >> 8) & 0x3;
728 		div_con = reg & 0x7f;
729 		if (mux == 2)
730 			return 24000000 / (div_con + 1);
731 		break;
732 	case RK3288_CLK_MAC:
733 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21));
734 		if (reg & 0x10)
735 			return 125000000;
736 		mux = (reg >> 0) & 0x3;
737 		div_con = (reg >> 8) & 0x1f;
738 		switch (mux) {
739 		case 0:
740 			idx = RK3288_PLL_NPLL;
741 			break;
742 		case 1:
743 			idx = RK3288_PLL_CPLL;
744 			break;
745 		case 2:
746 			idx = RK3288_PLL_GPLL;
747 			break;
748 		default:
749 			return 0;
750 		}
751 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
752 	case RK3288_PCLK_I2C0:
753 	case RK3288_PCLK_I2C2:
754 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1));
755 		mux = (reg >> 15) & 0x1;
756 		/* pd_bus_pclk_div_con */
757 		div_con = (reg >> 12) & 0x7;
758 		if (mux == 1)
759 			idx = RK3288_PLL_GPLL;
760 		else
761 			idx = RK3288_PLL_CPLL;
762 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
763 	case RK3288_PCLK_I2C1:
764 	case RK3288_PCLK_I2C3:
765 	case RK3288_PCLK_I2C4:
766 	case RK3288_PCLK_I2C5:
767 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10));
768 		mux = (reg >> 15) & 0x1;
769 		/* peri_pclk_div_con */
770 		div_con = (reg >> 12) & 0x3;
771 		/* peri_aclk_div_con */
772 		aclk_div_con = reg & 0xf;
773 		if (mux == 1)
774 			idx = RK3288_PLL_GPLL;
775 		else
776 			idx = RK3288_PLL_CPLL;
777 		return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >>
778 		    div_con;
779 	default:
780 		break;
781 	}
782 
783 	return rkclock_get_frequency(sc, idx);
784 }
785 
786 int
787 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
788 {
789 	struct rkclock_softc *sc = cookie;
790 	uint32_t idx = cells[0];
791 	int error;
792 
793 	switch (idx) {
794 	case RK3288_PLL_APLL:
795 		return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq);
796 	case RK3288_ARMCLK:
797 		idx = RK3288_PLL_APLL;
798 		error = rk3288_set_frequency(sc, &idx, freq);
799 		if (error == 0) {
800 			HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0),
801 			    ((1 << 15) | (0x1f << 8)) << 16);
802 		}
803 		return error;
804 	default:
805 		break;
806 	}
807 
808 	return rkclock_set_frequency(sc, idx, freq);
809 }
810 
811 void
812 rk3288_enable(void *cookie, uint32_t *cells, int on)
813 {
814 	uint32_t idx = cells[0];
815 
816 	switch (idx) {
817 	case RK3288_CLK_SDMMC:
818 	case RK3288_CLK_TSADC:
819 	case RK3288_CLK_UART0:
820 	case RK3288_CLK_UART1:
821 	case RK3288_CLK_UART2:
822 	case RK3288_CLK_UART3:
823 	case RK3288_CLK_UART4:
824 	case RK3288_CLK_MAC_RX:
825 	case RK3288_CLK_MAC_TX:
826 	case RK3288_CLK_SDMMC_DRV:
827 	case RK3288_CLK_SDMMC_SAMPLE:
828 	case RK3288_CLK_MAC:
829 	case RK3288_ACLK_GMAC:
830 	case RK3288_PCLK_GMAC:
831 	case RK3288_PCLK_I2C0:
832 	case RK3288_PCLK_I2C1:
833 	case RK3288_PCLK_I2C2:
834 	case RK3288_PCLK_I2C3:
835 	case RK3288_PCLK_I2C4:
836 	case RK3288_PCLK_I2C5:
837 	case RK3288_PCLK_TSADC:
838 	case RK3288_HCLK_HOST0:
839 	case RK3288_HCLK_SDMMC:
840 		/* Enabled by default. */
841 		break;
842 	default:
843 		printf("%s: 0x%08x\n", __func__, idx);
844 		break;
845 	}
846 }
847 
848 void
849 rk3288_reset(void *cookie, uint32_t *cells, int on)
850 {
851 	struct rkclock_softc *sc = cookie;
852 	uint32_t idx = cells[0];
853 	uint32_t mask = (1 << (idx % 16));
854 
855 	HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16),
856 	    mask << 16 | (on ? mask : 0));
857 }
858 
859 /*
860  * Rockchip RK3308
861  */
862 
863 struct rkclock rk3308_clocks[] = {
864 	{
865 		RK3308_CLK_RTC32K, RK3308_CRU_CLKSEL_CON(2),
866 		SEL(10, 9), 0,
867 		{ RK3308_PLL_VPLL0, RK3308_PLL_VPLL1 }
868 	},
869 	{
870 		RK3308_CLK_UART0, RK3308_CRU_CLKSEL_CON(10),
871 		SEL(15, 13), DIV(4, 0),
872 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
873 		  RK3308_USB480M, RK3308_XIN24M }
874 	},
875 	{
876 		RK3308_CLK_UART1, RK3308_CRU_CLKSEL_CON(13),
877 		SEL(15, 13), DIV(4, 0),
878 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
879 		  RK3308_USB480M, RK3308_XIN24M }
880 	},
881 	{
882 		RK3308_CLK_UART2, RK3308_CRU_CLKSEL_CON(16),
883 		SEL(15, 13), DIV(4, 0),
884 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
885 		  RK3308_USB480M, RK3308_XIN24M }
886 	},
887 	{
888 		RK3308_CLK_UART3, RK3308_CRU_CLKSEL_CON(19),
889 		SEL(15, 13), DIV(4, 0),
890 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
891 		  RK3308_USB480M, RK3308_XIN24M }
892 	},
893 	{
894 		RK3308_CLK_UART4, RK3308_CRU_CLKSEL_CON(22),
895 		SEL(15, 13), DIV(4, 0),
896 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
897 		  RK3308_USB480M, RK3308_XIN24M }
898 	},
899 	{
900 		RK3308_CLK_PWM0, RK3308_CRU_CLKSEL_CON(29),
901 		SEL(15, 14), DIV(6, 0),
902 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
903 	},
904 	{
905 		RK3308_CLK_TSADC, RK3308_CRU_CLKSEL_CON(33),
906 		0, DIV(10, 0),
907 		{ RK3308_XIN24M }
908 	},
909 	{
910 		RK3308_CLK_SARADC, RK3308_CRU_CLKSEL_CON(34),
911 		0, DIV(10, 0),
912 		{ RK3308_XIN24M }
913 	},
914 	{
915 		RK3308_CLK_CRYPTO, RK3308_CRU_CLKSEL_CON(7),
916 		SEL(7, 6), DIV(4, 0),
917 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
918 	},
919 	{
920 		RK3308_CLK_CRYPTO_APK, RK3308_CRU_CLKSEL_CON(7),
921 		SEL(15, 14), DIV(12, 8),
922 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
923 	},
924 	{
925 		RK3308_CLK_SDMMC, RK3308_CRU_CLKSEL_CON(39),
926 		SEL(9, 8), DIV(7, 0),
927 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
928 		  RK3308_XIN24M }
929 	},
930 	{
931 		RK3308_CLK_SDIO, RK3308_CRU_CLKSEL_CON(40),
932 		SEL(9, 8), DIV(7, 0),
933 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
934 		  RK3308_XIN24M }
935 	},
936 	{
937 		RK3308_CLK_EMMC, RK3308_CRU_CLKSEL_CON(41),
938 		SEL(9, 8), DIV(7, 0),
939 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
940 		  RK3308_XIN24M }
941 	},
942 	{
943 		RK3308_CLK_MAC_SRC, RK3308_CRU_CLKSEL_CON(43),
944 		SEL(7, 6), DIV(4, 0),
945 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
946 	},
947 	{
948 		RK3308_CLK_MAC, RK3308_CRU_CLKSEL_CON(43),
949 		SEL(14, 13), 0,
950 		{ RK3308_CLK_MAC_SRC, 0 },
951 		SET_PARENT
952 	},
953 	{
954 		RK3308_ACLK_PERI_SRC, RK3308_CRU_CLKSEL_CON(36),
955 		SEL(7, 6), 0,
956 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
957 	},
958 	{
959 		RK3308_PCLK_PERI, RK3308_CRU_CLKSEL_CON(37),
960 		0, DIV(12, 8),
961 		{ RK3308_ACLK_PERI_SRC }
962 	},
963 	{
964 		RK3308_PCLK_MAC, 0, 0, 0,
965 		{ RK3308_PCLK_PERI }
966 	},
967 
968 	{
969 		/* Sentinel */
970 	}
971 };
972 
973 void
974 rk3308_init(struct rkclock_softc *sc)
975 {
976 	int i;
977 
978 	/* The code below assumes all clocks are enabled.  Check this!. */
979 	for (i = 0; i <= 14; i++) {
980 		if (HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)) != 0x00000000) {
981 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
982 			    HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)));
983 		}
984 	}
985 	sc->sc_clocks = rk3308_clocks;
986 }
987 
988 uint32_t
989 rk3308_armclk_parent(uint32_t mux)
990 {
991 	switch (mux) {
992 	case 0:
993 		return RK3308_PLL_APLL;
994 	case 1:
995 		return RK3308_PLL_VPLL0;
996 	case 2:
997 		return RK3308_PLL_VPLL1;
998 	}
999 
1000 	return 0;
1001 }
1002 
1003 uint32_t
1004 rk3308_get_armclk(struct rkclock_softc *sc)
1005 {
1006 	uint32_t reg, mux, div_con;
1007 	uint32_t idx;
1008 
1009 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1010 	mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1011 	    RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1012 	div_con = (reg & RK3308_CRU_CLK_CORE_DIV_CON_MASK) >>
1013 	    RK3308_CRU_CLK_CORE_DIV_CON_SHIFT;
1014 	idx = rk3308_armclk_parent(mux);
1015 
1016 	return rk3308_get_frequency(sc, &idx) / (div_con + 1);
1017 }
1018 
1019 int
1020 rk3308_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1021 {
1022 	uint32_t reg, mux;
1023 	uint32_t old_freq, div;
1024 	uint32_t idx;
1025 
1026 	old_freq = rk3308_get_armclk(sc);
1027 	if (freq == old_freq)
1028 		return 0;
1029 
1030 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1031 	mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1032 	    RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1033 
1034 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1035 	div = 1;
1036 	while (freq / (div + 1) > 300000000)
1037 		div++;
1038 	/* and make sure we use an odd divider. */
1039 	if ((div % 2) == 0)
1040 		div++;
1041 
1042 	/* When ramping up, set clock dividers first. */
1043 	if (freq > old_freq) {
1044 		HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1045 		    RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1046 		    0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1047 		    RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1048 		    1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1049 		    RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1050 		    div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1051 	}
1052 
1053 	/* We always use VPLL1 and force the switch below if needed. */
1054 	idx = RK3308_PLL_VPLL1;
1055 	rk3308_set_frequency(sc, &idx, freq);
1056 
1057 	/* When ramping down, set clock dividers last. */
1058 	if (freq < old_freq || mux != 2) {
1059 		HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1060 		    RK3308_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1061 		    2 << RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT |
1062 		    RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1063 		    0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1064 		    RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1065 		    1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1066 		    RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1067 		    div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1068 	}
1069 
1070 	return 0;
1071 }
1072 
1073 uint32_t
1074 rk3308_get_pll(struct rkclock_softc *sc, bus_size_t base)
1075 {
1076 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1077 	uint32_t dsmpd, fracdiv;
1078 	uint64_t frac = 0;
1079 	uint32_t reg;
1080 
1081 	reg = HREAD4(sc, base + 0x0000);
1082 	postdiv1 = (reg & RK3308_CRU_PLL_POSTDIV1_MASK) >>
1083 	    RK3308_CRU_PLL_POSTDIV1_SHIFT;
1084 	fbdiv = (reg & RK3308_CRU_PLL_FBDIV_MASK) >>
1085 	    RK3308_CRU_PLL_FBDIV_SHIFT;
1086 	reg = HREAD4(sc, base + 0x0004);
1087 	dsmpd = (reg & RK3308_CRU_PLL_DSMPD);
1088 	postdiv2 = (reg & RK3308_CRU_PLL_POSTDIV2_MASK) >>
1089 	    RK3308_CRU_PLL_POSTDIV2_SHIFT;
1090 	refdiv = (reg & RK3308_CRU_PLL_REFDIV_MASK) >>
1091 	    RK3308_CRU_PLL_REFDIV_SHIFT;
1092 	reg = HREAD4(sc, base + 0x0008);
1093 	fracdiv = (reg & RK3308_CRU_PLL_FRACDIV_MASK) >>
1094 	    RK3308_CRU_PLL_FRACDIV_SHIFT;
1095 
1096 	if (dsmpd == 0)
1097 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1098 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1099 }
1100 
1101 int
1102 rk3308_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1103 {
1104 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1105 	int mode_shift = -1;
1106 
1107 	switch (base) {
1108 	case RK3308_CRU_APLL_CON(0):
1109 		mode_shift = 0;
1110 		break;
1111 	case RK3308_CRU_DPLL_CON(0):
1112 		mode_shift = 2;
1113 		break;
1114 	case RK3308_CRU_VPLL0_CON(0):
1115 		mode_shift = 4;
1116 		break;
1117 	case RK3308_CRU_VPLL1_CON(0):
1118 		mode_shift = 6;
1119 		break;
1120 	}
1121 	KASSERT(mode_shift != -1);
1122 
1123 	/*
1124 	 * It is not clear whether all combinations of the clock
1125 	 * dividers result in a stable clock.  Therefore this function
1126 	 * only supports a limited set of PLL clock rates.  For now
1127 	 * this set covers all the CPU frequencies supported by the
1128 	 * Linux kernel.
1129 	 */
1130 	switch (freq) {
1131 	case 1608000000U:
1132 	case 1584000000U:
1133 	case 1560000000U:
1134 	case 1536000000U:
1135 	case 1512000000U:
1136 	case 1488000000U:
1137 	case 1464000000U:
1138 	case 1440000000U:
1139 	case 1416000000U:
1140 	case 1392000000U:
1141 	case 1368000000U:
1142 	case 1344000000U:
1143 	case 1320000000U:
1144 	case 1296000000U:
1145 	case 1272000000U:
1146 	case 1248000000U:
1147 	case 1200000000U:
1148 	case 1104000000U:
1149 		postdiv1 = postdiv2 = refdiv = 1;
1150 		break;
1151 	case 1188000000U:
1152 		refdiv = 2; postdiv1 = postdiv2 = 1;
1153 		break;
1154 	case 1100000000U:
1155 		refdiv = 12; postdiv1 = postdiv2 = 1;
1156 		break;
1157 	case 1000000000U:
1158 		refdiv = 6; postdiv1 = postdiv2 = 1;
1159 		break;
1160 	case 1008000000U:
1161 	case 984000000U:
1162 	case 960000000U:
1163 	case 936000000U:
1164 	case 912000000U:
1165 	case 888000000U:
1166 	case 864000000U:
1167 	case 840000000U:
1168 	case 816000000U:
1169 	case 696000000U:
1170 	case 624000000U:
1171 		postdiv1 = 2; postdiv2 = refdiv = 1;
1172 		break;
1173 	case 900000000U:
1174 		refdiv = 4; postdiv1 = 2; postdiv2 = 1;
1175 		break;
1176 	case 800000000U:
1177 	case 700000000U:
1178 	case 500000000U:
1179 		refdiv = 6; postdiv1 = 2; postdiv2 = 1;
1180 		break;
1181 	case 600000000U:
1182 	case 504000000U:
1183 		postdiv1 = 3; postdiv2 = refdiv = 1;
1184 		break;
1185 	case 594000000U:
1186 		refdiv = 2; postdiv1 = 2; postdiv2 = 1;
1187 		break;
1188 	case 408000000U:
1189 	case 312000000U:
1190 		postdiv1 = postdiv2 = 2; refdiv = 1;
1191 		break;
1192 	case 216000000U:
1193 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1194 		break;
1195 	case 96000000U:
1196 		postdiv1 = postdiv2 = 4; refdiv = 1;
1197 		break;
1198 	default:
1199 		printf("%s: %u Hz\n", __func__, freq);
1200 		return -1;
1201 	}
1202 
1203 	/* Calculate feedback divider. */
1204 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1205 
1206 	/*
1207 	 * Select slow mode to guarantee a stable clock while we're
1208 	 * adjusting the PLL.
1209 	 */
1210 	HWRITE4(sc, RK3308_CRU_CRU_MODE,
1211 	   (RK3308_CRU_CRU_MODE_MASK << 16 |
1212 	   RK3308_CRU_CRU_MODE_SLOW) << mode_shift);
1213 
1214 	/* Set PLL rate. */
1215 	HWRITE4(sc, base + 0x0000,
1216 	    RK3308_CRU_PLL_POSTDIV1_MASK << 16 |
1217 	    postdiv1 << RK3308_CRU_PLL_POSTDIV1_SHIFT |
1218 	    RK3308_CRU_PLL_FBDIV_MASK << 16 |
1219 	    fbdiv << RK3308_CRU_PLL_FBDIV_SHIFT);
1220 	HWRITE4(sc, base + 0x0004,
1221 	    RK3308_CRU_PLL_DSMPD << 16 | RK3308_CRU_PLL_DSMPD |
1222 	    RK3308_CRU_PLL_POSTDIV2_MASK << 16 |
1223 	    postdiv2 << RK3308_CRU_PLL_POSTDIV2_SHIFT |
1224 	    RK3308_CRU_PLL_REFDIV_MASK << 16 |
1225 	    refdiv << RK3308_CRU_PLL_REFDIV_SHIFT);
1226 
1227 	/* Wait for PLL to stabilize. */
1228 	while ((HREAD4(sc, base + 0x0004) & RK3308_CRU_PLL_PLL_LOCK) == 0)
1229 		delay(10);
1230 
1231 	/* Switch back to normal mode. */
1232 	HWRITE4(sc, RK3308_CRU_CRU_MODE,
1233 	   (RK3308_CRU_CRU_MODE_MASK << 16 |
1234 	   RK3308_CRU_CRU_MODE_NORMAL) << mode_shift);
1235 
1236 	return 0;
1237 }
1238 
1239 uint32_t
1240 rk3308_get_rtc32k(struct rkclock_softc *sc)
1241 {
1242 	uint32_t reg, mux, pll, div_con;
1243 
1244 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(2));
1245 	mux = (reg & 0x30) >> 8;
1246 	if (mux != 3) {
1247 		printf("%s: RTC32K not using clk_32k_div\n", __func__);
1248 		return 0;
1249 	}
1250 
1251 	if ((reg >> 10) & 1)
1252 		pll = RK3308_PLL_VPLL1;
1253 	else
1254 		pll = RK3308_PLL_VPLL0;
1255 
1256 	div_con = HREAD4(sc, RK3308_CRU_CLKSEL_CON(4)) & 0xffff;
1257 	return rk3308_get_frequency(sc, &pll) / (div_con + 1);
1258 }
1259 
1260 int
1261 rk3308_set_rtc32k(struct rkclock_softc *sc, uint32_t freq)
1262 {
1263 	struct rkclock *clk;
1264 	uint32_t vpll0_freq, vpll1_freq, mux, div_con;
1265 
1266 	clk = rkclock_lookup(sc, RK3308_CLK_RTC32K);
1267 	vpll0_freq = rkclock_freq(sc, clk, 0, freq);
1268 	vpll1_freq = rkclock_freq(sc, clk, 1, freq);
1269 	mux = 0;
1270 	freq = vpll0_freq;
1271 
1272 	if ((vpll1_freq > vpll0_freq && vpll1_freq <= freq) ||
1273 	    (vpll1_freq < vpll0_freq && vpll1_freq >= freq)) {
1274 		mux = 1;
1275 		freq = vpll1_freq;
1276 	}
1277 
1278 	div_con = rkclock_div_con(sc, clk, mux, freq);
1279 	HWRITE4(sc, RK3308_CRU_CLKSEL_CON(2), 1 << 26 | (mux << 10));
1280 	HWRITE4(sc, RK3308_CRU_CLKSEL_CON(4), 0xffff0000 | div_con);
1281 	return 0;
1282 }
1283 
1284 uint32_t
1285 rk3308_get_frequency(void *cookie, uint32_t *cells)
1286 {
1287 	struct rkclock_softc *sc = cookie;
1288 	uint32_t idx = cells[0];
1289 
1290 	switch (idx) {
1291 	case RK3308_PLL_APLL:
1292 		return rk3308_get_pll(sc, RK3308_CRU_APLL_CON(0));
1293 	case RK3308_PLL_DPLL:
1294 		return rk3308_get_pll(sc, RK3308_CRU_DPLL_CON(0));
1295 	case RK3308_PLL_VPLL0:
1296 		return rk3308_get_pll(sc, RK3308_CRU_VPLL0_CON(0));
1297 	case RK3308_PLL_VPLL1:
1298 		return rk3308_get_pll(sc, RK3308_CRU_VPLL1_CON(0));
1299 	case RK3308_ARMCLK:
1300 		return rk3308_get_armclk(sc);
1301 	case RK3308_XIN24M:
1302 		return 24000000;
1303 	case RK3308_CLK_RTC32K:
1304 		return rk3308_get_rtc32k(sc);
1305 
1306 	/*
1307 	 * XXX The USB480M clock is external.  Returning zero here will cause
1308 	 * it to be ignored for reparenting purposes.
1309 	 */
1310 	case RK3308_USB480M:
1311 		return 0;
1312 	default:
1313 		break;
1314 	}
1315 
1316 	return rkclock_get_frequency(sc, idx);
1317 }
1318 
1319 int
1320 rk3308_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1321 {
1322 	struct rkclock_softc *sc = cookie;
1323 	uint32_t idx = cells[0];
1324 
1325 	switch (idx) {
1326 	case RK3308_PLL_APLL:
1327 		return rk3308_set_pll(sc, RK3308_CRU_APLL_CON(0), freq);
1328 	case RK3308_PLL_DPLL:
1329 		return rk3308_set_pll(sc, RK3308_CRU_DPLL_CON(0), freq);
1330 	case RK3308_PLL_VPLL0:
1331 		return rk3308_set_pll(sc, RK3308_CRU_VPLL0_CON(0), freq);
1332 	case RK3308_PLL_VPLL1:
1333 		return rk3308_set_pll(sc, RK3308_CRU_VPLL1_CON(0), freq);
1334 	case RK3308_ARMCLK:
1335 		return rk3308_set_armclk(sc, freq);
1336 	case RK3308_CLK_RTC32K:
1337 		return rk3308_set_rtc32k(sc, freq);
1338 	default:
1339 		break;
1340 	}
1341 
1342 	return rkclock_set_frequency(sc, idx, freq);
1343 }
1344 
1345 
1346 int
1347 rk3308_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1348 {
1349 	struct rkclock_softc *sc = cookie;
1350 
1351 	if (pcells[0] != sc->sc_phandle)
1352 		return -1;
1353 
1354 	return rkclock_set_parent(sc, cells[0], pcells[1]);
1355 }
1356 
1357 void
1358 rk3308_enable(void *cookie, uint32_t *cells, int on)
1359 {
1360 	uint32_t idx = cells[0];
1361 
1362 	/*
1363 	 * All clocks are enabled by default, so there is nothing for
1364 	 * us to do until we start disabling clocks.
1365 	 */
1366 	if (!on)
1367 		printf("%s: 0x%08x\n", __func__, idx);
1368 }
1369 
1370 void
1371 rk3308_reset(void *cookie, uint32_t *cells, int on)
1372 {
1373 	struct rkclock_softc *sc = cookie;
1374 	uint32_t idx = cells[0];
1375 	uint32_t mask = (1 << (idx % 16));
1376 
1377 	HWRITE4(sc, RK3308_CRU_SOFTRST_CON(idx / 16),
1378 	    mask << 16 | (on ? mask : 0));
1379 }
1380 
1381 
1382 /*
1383  * Rockchip RK3328
1384  */
1385 
1386 struct rkclock rk3328_clocks[] = {
1387 	{
1388 		RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38),
1389 		SEL(15, 14), DIV(13, 0),
1390 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M }
1391 	},
1392 	{
1393 		RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30),
1394 		SEL(9, 8), DIV(7, 0),
1395 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1396 		  RK3328_USB480M }
1397 	},
1398 	{
1399 		RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31),
1400 		SEL(9, 8), DIV(7, 0),
1401 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1402 		  RK3328_USB480M }
1403 	},
1404 	{
1405 		RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32),
1406 		SEL(9, 8), DIV(7, 0),
1407 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1408 		  RK3328_USB480M }
1409 	},
1410 	{
1411 		RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22),
1412 		0, DIV(9, 0),
1413 		{ RK3328_CLK_24M }
1414 	},
1415 	{
1416 		RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14),
1417 		SEL(9, 8), 0,
1418 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1419 	},
1420 	{
1421 		RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16),
1422 		SEL(9, 8), 0,
1423 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1424 	},
1425 	{
1426 		RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18),
1427 		SEL(9, 8), 0,
1428 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1429 	},
1430 	{
1431 		RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52),
1432 		SEL(7, 6), DIV(5, 0),
1433 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M }
1434 	},
1435 	{
1436 		RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34),
1437 		SEL(7, 7), DIV(6, 0),
1438 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1439 	},
1440 	{
1441 		RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34),
1442 		SEL(15, 15), DIV(14, 8),
1443 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1444 	},
1445 	{
1446 		RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35),
1447 		SEL(7, 7), DIV(6, 0),
1448 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1449 	},
1450 	{
1451 		RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35),
1452 		SEL(15, 15), DIV(14, 8),
1453 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1454 	},
1455 	{
1456 		RK3328_CLK_CRYPTO, RK3328_CRU_CLKSEL_CON(20),
1457 		SEL(7, 7), DIV(4, 0),
1458 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1459 	},
1460 	{
1461 		RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
1462 		SEL(15, 14), DIV(12, 8),
1463 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
1464 		FIXED_PARENT | SET_PARENT
1465 	},
1466 	{
1467 		RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
1468 		SEL(15, 14), DIV(12, 8),
1469 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1470 		  RK3328_USB480M }
1471 	},
1472 	{
1473 		RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
1474 		SEL(7, 6), DIV(4, 0),
1475 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1476 		  RK3328_USB480M }
1477 	},
1478 	{
1479 		RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
1480 		SEL(15, 14), DIV(12, 8),
1481 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1482 		  RK3328_USB480M }
1483 	},
1484 	{
1485 		RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
1486 		SEL(15, 14), DIV(12, 8),
1487 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1488 		  RK3328_USB480M }
1489 	},
1490 	{
1491 		RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
1492 		SEL(15, 15), DIV(12, 8),
1493 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1494 	},
1495 	{
1496 		RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
1497 		SEL(7, 7), DIV(4, 0),
1498 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1499 	},
1500 	{
1501 		RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
1502 		SEL(1, 1), 0,
1503 		{ RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
1504 	},
1505 	{
1506 		RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
1507 		SEL(7, 6), DIV(4, 0),
1508 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1509 		  RK3328_USB480M }
1510 	},
1511 	{
1512 		RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
1513 		SEL(15, 14), DIV(12, 8),
1514 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1515 		  RK3328_USB480M }
1516 	},
1517 	{
1518 		RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
1519 		SEL(14, 13), DIV(12, 8),
1520 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1521 	},
1522 	{
1523 		RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
1524 		SEL(7, 6), DIV(4, 0),
1525 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1526 	},
1527 	{
1528 		RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
1529 		SEL(7, 6), DIV(4, 0),
1530 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1531 		  RK3328_USB480M }
1532 	},
1533 	{
1534 		RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
1535 		SEL(7, 6), DIV(4, 0),
1536 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1537 		  RK3328_USB480M }
1538 	},
1539 	{
1540 		RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
1541 		SEL(7, 6), DIV(4, 0),
1542 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1543 		  RK3328_USB480M }
1544 	},
1545 	{
1546 		RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
1547 		SEL(7, 6), DIV(4, 0),
1548 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1549 		  RK3328_USB480M }
1550 	},
1551 	{
1552 		RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1553 		0, DIV(14, 12),
1554 		{ RK3328_ACLK_BUS_PRE }
1555 	},
1556 	{
1557 		RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1558 		0, DIV(9, 8),
1559 		{ RK3328_ACLK_BUS_PRE }
1560 	},
1561 	{
1562 		RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1563 		0, DIV(6, 4),
1564 		{ RK3328_ACLK_PERI_PRE }
1565 	},
1566 	{
1567 		RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1568 		0, DIV(1, 0),
1569 		{ RK3328_ACLK_PERI_PRE }
1570 	},
1571 	{
1572 		RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
1573 		0, DIV(12, 8),
1574 		{ RK3328_XIN24M }
1575 	},
1576 	{
1577 		/* Sentinel */
1578 	}
1579 };
1580 
1581 void
1582 rk3328_init(struct rkclock_softc *sc)
1583 {
1584 	int i;
1585 
1586 	/* The code below assumes all clocks are enabled.  Check this!. */
1587 	for (i = 0; i <= 28; i++) {
1588 		if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1589 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1590 			    HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1591 		}
1592 	}
1593 
1594 	sc->sc_clocks = rk3328_clocks;
1595 }
1596 
1597 uint32_t
1598 rk3328_armclk_parent(uint32_t mux)
1599 {
1600 	switch (mux) {
1601 	case 0:
1602 		return RK3328_PLL_APLL;
1603 	case 1:
1604 		return RK3328_PLL_GPLL;
1605 	case 2:
1606 		return RK3328_PLL_DPLL;
1607 	case 3:
1608 		return RK3328_PLL_NPLL;
1609 	}
1610 
1611 	return 0;
1612 }
1613 
1614 uint32_t
1615 rk3328_get_armclk(struct rkclock_softc *sc)
1616 {
1617 	uint32_t reg, mux, div_con;
1618 	uint32_t idx;
1619 
1620 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1621 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1622 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1623 	div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1624 	    RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1625 	idx = rk3328_armclk_parent(mux);
1626 
1627 	return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1628 }
1629 
1630 int
1631 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1632 {
1633 	uint32_t reg, mux;
1634 	uint32_t old_freq, div;
1635 	uint32_t idx;
1636 
1637 	old_freq = rk3328_get_armclk(sc);
1638 	if (freq == old_freq)
1639 		return 0;
1640 
1641 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1642 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1643 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1644 
1645 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1646 	div = 1;
1647 	while (freq / (div + 1) > 300000000)
1648 		div++;
1649 	/* and make sure we use an odd divider. */
1650 	if ((div % 2) == 0)
1651 		div++;
1652 
1653 	/* When ramping up, set clock dividers first. */
1654 	if (freq > old_freq) {
1655 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1656 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1657 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1658 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1659 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1660 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1661 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1662 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1663 	}
1664 
1665 	/* We always use NPLL and force the switch below if needed. */
1666 	idx = RK3328_PLL_NPLL;
1667 	rk3328_set_frequency(sc, &idx, freq);
1668 
1669 	/* When ramping down, set clock dividers last. */
1670 	if (freq < old_freq || mux != 3) {
1671 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1672 		    RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1673 		    3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1674 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1675 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1676 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1677 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1678 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1679 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1680 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1681 	}
1682 
1683 	return 0;
1684 }
1685 
1686 uint32_t
1687 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1688 {
1689 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1690 	uint32_t dsmpd, fracdiv;
1691 	uint64_t frac = 0;
1692 	uint32_t reg;
1693 
1694 	reg = HREAD4(sc, base + 0x0000);
1695 	postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1696 	    RK3328_CRU_PLL_POSTDIV1_SHIFT;
1697 	fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1698 	    RK3328_CRU_PLL_FBDIV_SHIFT;
1699 	reg = HREAD4(sc, base + 0x0004);
1700 	dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1701 	postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1702 	    RK3328_CRU_PLL_POSTDIV2_SHIFT;
1703 	refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1704 	    RK3328_CRU_PLL_REFDIV_SHIFT;
1705 	reg = HREAD4(sc, base + 0x0008);
1706 	fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1707 	    RK3328_CRU_PLL_FRACDIV_SHIFT;
1708 
1709 	if (dsmpd == 0)
1710 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1711 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1712 }
1713 
1714 int
1715 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1716 {
1717 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1718 	int mode_shift = -1;
1719 
1720 	switch (base) {
1721 	case RK3328_CRU_APLL_CON(0):
1722 		mode_shift = 0;
1723 		break;
1724 	case RK3328_CRU_DPLL_CON(0):
1725 		mode_shift = 4;
1726 		break;
1727 	case RK3328_CRU_CPLL_CON(0):
1728 		mode_shift = 8;
1729 		break;
1730 	case RK3328_CRU_GPLL_CON(0):
1731 		mode_shift = 12;
1732 		break;
1733 	case RK3328_CRU_NPLL_CON(0):
1734 		mode_shift = 1;
1735 		break;
1736 	}
1737 	KASSERT(mode_shift != -1);
1738 
1739 	/*
1740 	 * It is not clear whether all combinations of the clock
1741 	 * dividers result in a stable clock.  Therefore this function
1742 	 * only supports a limited set of PLL clock rates.  For now
1743 	 * this set covers all the CPU frequencies supported by the
1744 	 * Linux kernel.
1745 	 */
1746 	switch (freq) {
1747 	case 1800000000U:
1748 	case 1704000000U:
1749 	case 1608000000U:
1750 	case 1512000000U:
1751 	case 1488000000U:
1752 	case 1416000000U:
1753 	case 1392000000U:
1754 	case 1296000000U:
1755 	case 1200000000U:
1756 	case 1104000000U:
1757 		postdiv1 = postdiv2 = refdiv = 1;
1758 		break;
1759 	case 1008000000U:
1760 	case 912000000U:
1761 	case 816000000U:
1762 	case 696000000U:
1763 		postdiv1 = 2; postdiv2 = refdiv = 1;
1764 		break;
1765 	case 600000000U:
1766 		postdiv1 = 3; postdiv2 = refdiv = 1;
1767 		break;
1768 	case 408000000U:
1769 	case 312000000U:
1770 		postdiv1 = postdiv2 = 2; refdiv = 1;
1771 		break;
1772 	case 216000000U:
1773 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1774 		break;
1775 	case 96000000U:
1776 		postdiv1 = postdiv2 = 4; refdiv = 1;
1777 		break;
1778 	default:
1779 		printf("%s: %u Hz\n", __func__, freq);
1780 		return -1;
1781 	}
1782 
1783 	/* Calculate feedback divider. */
1784 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1785 
1786 	/*
1787 	 * Select slow mode to guarantee a stable clock while we're
1788 	 * adjusting the PLL.
1789 	 */
1790 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1791 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1792 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1793 
1794 	/* Set PLL rate. */
1795 	HWRITE4(sc, base + 0x0000,
1796 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1797 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1798 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1799 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1800 	HWRITE4(sc, base + 0x0004,
1801 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1802 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1803 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1804 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1805 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1806 
1807 	/* Wait for PLL to stabilize. */
1808 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1809 		delay(10);
1810 
1811 	/* Switch back to normal mode. */
1812 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1813 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1814 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1815 
1816 	return 0;
1817 }
1818 
1819 int
1820 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1821 {
1822 	uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
1823 	int mode_shift = -1;
1824 	uint32_t reg;
1825 
1826 	switch (base) {
1827 	case RK3328_CRU_APLL_CON(0):
1828 		mode_shift = 0;
1829 		break;
1830 	case RK3328_CRU_DPLL_CON(0):
1831 		mode_shift = 4;
1832 		break;
1833 	case RK3328_CRU_CPLL_CON(0):
1834 		mode_shift = 8;
1835 		break;
1836 	case RK3328_CRU_GPLL_CON(0):
1837 		mode_shift = 12;
1838 		break;
1839 	case RK3328_CRU_NPLL_CON(0):
1840 		mode_shift = 1;
1841 		break;
1842 	}
1843 	KASSERT(mode_shift != -1);
1844 
1845 	/*
1846 	 * It is not clear whether all combinations of the clock
1847 	 * dividers result in a stable clock.  Therefore this function
1848 	 * only supports a limited set of PLL clock rates.  This set
1849 	 * set covers all the fractional PLL frequencies supported by
1850 	 * the Linux kernel.
1851 	 */
1852 	switch (freq) {
1853 	case 1016064000U:
1854 		postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
1855 		break;
1856 	case 983040000U:
1857 		postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1858 		break;
1859 	case 491520000U:
1860 		postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
1861 		break;
1862 	case 61440000U:
1863 		postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
1864 		break;
1865 	case 56448000U:
1866 		postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
1867 		break;
1868 	case 40960000U:
1869 		postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
1870 		break;
1871 	default:
1872 		printf("%s: %u Hz\n", __func__, freq);
1873 		return -1;
1874 	}
1875 
1876 	/* Calculate feedback divider. */
1877 	fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
1878 
1879 	/*
1880 	 * Select slow mode to guarantee a stable clock while we're
1881 	 * adjusting the PLL.
1882 	 */
1883 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1884 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1885 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1886 
1887 	/* Set PLL rate. */
1888 	HWRITE4(sc, base + 0x0000,
1889 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1890 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1891 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1892 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1893 	HWRITE4(sc, base + 0x0004,
1894 	    RK3328_CRU_PLL_DSMPD << 16 |
1895 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1896 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1897 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1898 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1899 	reg = HREAD4(sc, base + 0x0008);
1900 	reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
1901 	reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
1902 	HWRITE4(sc, base + 0x0008, reg);
1903 
1904 	/* Wait for PLL to stabilize. */
1905 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1906 		delay(10);
1907 
1908 	/* Switch back to normal mode. */
1909 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1910 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1911 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1912 
1913 	return 0;
1914 }
1915 
1916 uint32_t
1917 rk3328_get_frequency(void *cookie, uint32_t *cells)
1918 {
1919 	struct rkclock_softc *sc = cookie;
1920 	uint32_t idx = cells[0];
1921 	uint32_t reg;
1922 
1923 	switch (idx) {
1924 	case RK3328_PLL_APLL:
1925 		return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
1926 		break;
1927 	case RK3328_PLL_DPLL:
1928 		return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
1929 		break;
1930 	case RK3328_PLL_CPLL:
1931 		return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
1932 		break;
1933 	case RK3328_PLL_GPLL:
1934 		return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
1935 		break;
1936 	case RK3328_PLL_NPLL:
1937 		return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
1938 		break;
1939 	case RK3328_ARMCLK:
1940 		return rk3328_get_armclk(sc);
1941 	case RK3328_XIN24M:
1942 		return 24000000;
1943 	case RK3328_GMAC_CLKIN:
1944 		return 125000000;
1945 	/*
1946 	 * XXX The HDMIPHY and USB480M clocks are external.  Returning
1947 	 * zero here will cause them to be ignored for reparenting
1948 	 * purposes.
1949 	 */
1950 	case RK3328_HDMIPHY:
1951 		return 0;
1952 	case RK3328_USB480M:
1953 		return 0;
1954 	case RK3328_CLK_MAC2IO:
1955 		reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
1956 		if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
1957 			idx = RK3328_GMAC_CLKIN;
1958 		else
1959 			idx = RK3328_CLK_MAC2IO_SRC;
1960 		return rk3328_get_frequency(sc, &idx);
1961 	default:
1962 		break;
1963 	}
1964 
1965 	return rkclock_get_frequency(sc, idx);
1966 }
1967 
1968 int
1969 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1970 {
1971 	struct rkclock_softc *sc = cookie;
1972 	uint32_t idx = cells[0];
1973 	uint32_t reg, mux;
1974 
1975 	switch (idx) {
1976 	case RK3328_PLL_APLL:
1977 		return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
1978 	case RK3328_PLL_DPLL:
1979 		return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
1980 	case RK3328_PLL_CPLL:
1981 		return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
1982 	case RK3328_PLL_GPLL:
1983 		return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
1984 	case RK3328_PLL_NPLL:
1985 		return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
1986 	case RK3328_ARMCLK:
1987 		return rk3328_set_armclk(sc, freq);
1988 	case RK3328_CLK_UART0:
1989 	case RK3328_CLK_UART1:
1990 	case RK3328_CLK_UART2:
1991 		if (freq == rk3328_get_frequency(sc, &idx))
1992 			return 0;
1993 		break;
1994 	case RK3328_DCLK_LCDC:
1995 		reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
1996 		mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
1997 		    RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
1998 		idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
1999 		return rk3328_set_frequency(sc, &idx, freq);
2000 	case RK3328_HCLK_CRYPTO_SLV:
2001 		idx = RK3328_HCLK_BUS_PRE;
2002 		return rk3328_set_frequency(sc, &idx, freq);
2003 	default:
2004 		break;
2005 	}
2006 
2007 	return rkclock_set_frequency(sc, idx, freq);
2008 }
2009 
2010 int
2011 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
2012 {
2013 	struct rkclock_softc *sc = cookie;
2014 	uint32_t idx = cells[0];
2015 	uint32_t parent;
2016 
2017 	if (pcells[0] == sc->sc_phandle)
2018 		parent = pcells[1];
2019 	else {
2020 		char name[32];
2021 		int node;
2022 
2023 		node = OF_getnodebyphandle(pcells[0]);
2024 		if (node == 0)
2025 			return -1;
2026 		name[0] = 0;
2027 		OF_getprop(node, "clock-output-names", name, sizeof(name));
2028 		name[sizeof(name) - 1] = 0;
2029 		if (strcmp(name, "xin24m") == 0)
2030 			parent = RK3328_XIN24M;
2031 		else if (strcmp(name, "gmac_clkin") == 0)
2032 			parent = RK3328_GMAC_CLKIN;
2033 		else
2034 			return -1;
2035 	}
2036 
2037 	switch (idx) {
2038 	case RK3328_CLK_MAC2IO:
2039 		if (parent == RK3328_GMAC_CLKIN) {
2040 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2041 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
2042 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
2043 		} else {
2044 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2045 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
2046 		}
2047 		return 0;
2048 	case RK3328_CLK_MAC2IO_EXT:
2049 		if (parent == RK3328_GMAC_CLKIN) {
2050 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2051 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
2052 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
2053 		} else {
2054 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2055 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
2056 		}
2057 		return 0;
2058 	}
2059 
2060 	return rkclock_set_parent(sc, idx, parent);
2061 }
2062 
2063 void
2064 rk3328_enable(void *cookie, uint32_t *cells, int on)
2065 {
2066 	uint32_t idx = cells[0];
2067 
2068 	/*
2069 	 * All clocks are enabled by default, so there is nothing for
2070 	 * us to do until we start disabling clocks.
2071 	 */
2072 	if (!on)
2073 		printf("%s: 0x%08x\n", __func__, idx);
2074 }
2075 
2076 void
2077 rk3328_reset(void *cookie, uint32_t *cells, int on)
2078 {
2079 	struct rkclock_softc *sc = cookie;
2080 	uint32_t idx = cells[0];
2081 	uint32_t mask = (1 << (idx % 16));
2082 
2083 	HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
2084 	    mask << 16 | (on ? mask : 0));
2085 }
2086 
2087 /*
2088  * Rockchip RK3399
2089  */
2090 
2091 struct rkclock rk3399_clocks[] = {
2092 	{
2093 		RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
2094 		SEL(7, 7), DIV(6, 0),
2095 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2096 	},
2097 	{
2098 		RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
2099 		SEL(7, 7), DIV(6, 0),
2100 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2101 	},
2102 	{
2103 		RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
2104 		SEL(7, 7), DIV(6, 0),
2105 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2106 	},
2107 	{
2108 		RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
2109 		SEL(15, 15), DIV(14, 8),
2110 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2111 	},
2112 	{
2113 		RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
2114 		SEL(15, 15), DIV(14, 8),
2115 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2116 	},
2117 	{
2118 		RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
2119 		SEL(15, 15), DIV(14, 8),
2120 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2121 	},
2122 	{
2123 		RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
2124 		SEL(10, 8), DIV(6, 0),
2125 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2126 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2127 		  RK3399_XIN24M }
2128 	},
2129 	{
2130 		RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
2131 		SEL(10, 8), DIV(6, 0),
2132 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2133 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2134 		  RK3399_XIN24M }
2135 	},
2136 	{
2137 		RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22),
2138 		SEL(10, 8), DIV(6, 0),
2139 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2140 		  /* RK3399_USB_480M */ 0, RK3399_XIN24M }
2141 	},
2142 	{
2143 		RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27),
2144 		SEL(15, 15), DIV(9, 0),
2145 		{ RK3399_XIN24M, RK3399_CLK_32K }
2146 	},
2147 	{
2148 		RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
2149 		SEL(9, 8), 0,
2150 		{ 0, 0, RK3399_XIN24M }
2151 	},
2152 	{
2153 		RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
2154 		SEL(9, 8), 0,
2155 		{ 0, 0, RK3399_XIN24M }
2156 	},
2157 	{
2158 		RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
2159 		SEL(9, 8), 0,
2160 		{ 0, 0, RK3399_XIN24M }
2161 	},
2162 	{
2163 		RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
2164 		SEL(9, 8), 0,
2165 		{ 0, 0, RK3399_XIN24M }
2166 	},
2167 	{
2168 		RK3399_CLK_I2S0_8CH, RK3399_CRU_CLKSEL_CON(28),
2169 		SEL(9, 8), 0,
2170 		{ RK3399_CLK_I2S0_DIV, RK3399_CLK_I2S0_FRAC, 0, RK3399_XIN12M },
2171 		SET_PARENT
2172 	},
2173 	{
2174 		RK3399_CLK_I2S1_8CH, RK3399_CRU_CLKSEL_CON(29),
2175 		SEL(9, 8), 0,
2176 		{ RK3399_CLK_I2S1_DIV, RK3399_CLK_I2S1_FRAC, 0, RK3399_XIN12M },
2177 		SET_PARENT
2178 	},
2179 	{
2180 		RK3399_CLK_I2S2_8CH, RK3399_CRU_CLKSEL_CON(30),
2181 		SEL(9, 8), 0,
2182 		{ RK3399_CLK_I2S2_DIV, RK3399_CLK_I2S2_FRAC, 0, RK3399_XIN12M },
2183 		SET_PARENT
2184 	},
2185 	{
2186 		RK3399_CLK_I2S_8CH_OUT, RK3399_CRU_CLKSEL_CON(31),
2187 		SEL(2, 2), 0,
2188 		{ RK3399_CLK_I2SOUT_SRC, RK3399_XIN12M },
2189 		SET_PARENT
2190 	},
2191 	{
2192 		RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
2193 		SEL(15, 14), DIV(12, 8),
2194 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
2195 	},
2196 	{
2197 		RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49),
2198 		SEL(11, 11), 0,
2199 		{ RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC },
2200 		SET_PARENT
2201 	},
2202 	{
2203 		RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50),
2204 		SEL(11, 11), 0,
2205 		{ RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC },
2206 		SET_PARENT
2207 	},
2208 	{
2209 		RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49),
2210 		SEL(9, 8), DIV(7, 0),
2211 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2212 	},
2213 	{
2214 		RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50),
2215 		SEL(9, 8), DIV(7, 0),
2216 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2217 	},
2218 	{
2219 		RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2220 		SEL(7, 7), DIV(4, 0),
2221 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2222 	},
2223 	{
2224 		RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2225 		SEL(7, 7), DIV(4, 0),
2226 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2227 	},
2228 	{
2229 		RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
2230 		SEL(7, 6), DIV(4, 0),
2231 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2232 	},
2233 	{
2234 		RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
2235 		SEL(7, 6), DIV(4, 0),
2236 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2237 		  RK3399_PLL_VPLL }
2238 	},
2239 	{
2240 		RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2241 		SEL(7, 6), DIV(4, 0),
2242 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2243 		  RK3399_PLL_NPLL }
2244 	},
2245 	{
2246 		RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2247 		SEL(7, 6), DIV(4, 0),
2248 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2249 		  RK3399_PLL_NPLL }
2250 	},
2251 	{
2252 		RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
2253 		SEL(15, 14), DIV(12, 8),
2254 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2255 	},
2256 	{
2257 		RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
2258 		SEL(15, 15), DIV(12, 8),
2259 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2260 	},
2261 	{
2262 		RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2263 		0, DIV(14, 12),
2264 		{ RK3399_ACLK_PERIPH }
2265 	},
2266 	{
2267 		RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2268 		0, DIV(14, 12),
2269 		{ RK3399_ACLK_PERILP0 }
2270 	},
2271 	{
2272 		RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2273 		0, DIV(10, 8),
2274 		{ RK3399_HCLK_PERILP1 }
2275 	},
2276 	{
2277 		RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
2278 		SEL(15, 15), DIV(12, 8),
2279 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2280 	},
2281 	{
2282 		RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2283 		0, DIV(9, 8),
2284 		{ RK3399_ACLK_PERIPH }
2285 	},
2286 	{
2287 		RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2288 		0, DIV(9, 8),
2289 		{ RK3399_ACLK_PERILP0 }
2290 	},
2291 	{
2292 		RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2293 		SEL(7, 7), DIV(4, 0),
2294 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2295 	},
2296 	{
2297 		RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
2298 		SEL(15, 15), DIV(12, 8),
2299 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2300 	},
2301 	{
2302 		RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2303 		0, DIV(12, 8),
2304 		{ RK3399_ACLK_VOP0 }
2305 	},
2306 	{
2307 		RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2308 		0, DIV(12, 8),
2309 		{ RK3399_ACLK_VOP1 }
2310 	},
2311 	{
2312 		RK3399_CLK_I2S0_DIV, RK3399_CRU_CLKSEL_CON(28),
2313 		SEL(7, 7), DIV(6, 0),
2314 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2315 	},
2316 	{
2317 		RK3399_CLK_I2S1_DIV, RK3399_CRU_CLKSEL_CON(29),
2318 		SEL(7, 7), DIV(6, 0),
2319 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2320 	},
2321 	{
2322 		RK3399_CLK_I2S2_DIV, RK3399_CRU_CLKSEL_CON(30),
2323 		SEL(7, 7), DIV(6, 0),
2324 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2325 	},
2326 	{
2327 		RK3399_CLK_I2SOUT_SRC, RK3399_CRU_CLKSEL_CON(31),
2328 		SEL(1, 0), 0,
2329 		{ RK3399_CLK_I2S0_8CH, RK3399_CLK_I2S1_8CH,
2330 		  RK3399_CLK_I2S2_8CH },
2331 		SET_PARENT
2332 	},
2333 	{
2334 		/* Sentinel */
2335 	}
2336 };
2337 
2338 /* Some of our parent clocks live in the PMUCRU. */
2339 struct rkclock_softc *rk3399_pmucru_sc;
2340 
2341 void
2342 rk3399_init(struct rkclock_softc *sc)
2343 {
2344 	int i;
2345 
2346 	/* PMUCRU instance should attach before us. */
2347 	KASSERT(rk3399_pmucru_sc != NULL);
2348 
2349 	/*
2350 	 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
2351 	 * module is buggy and sets the parent of the clock for the
2352 	 * "big" cluster to LPLL.  Undo that mistake here such that
2353 	 * the clocks of both clusters are independent.
2354 	 */
2355 	HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
2356 	    RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
2357 	    RK3399_CRU_CORE_PLL_SEL_BPLL);
2358 
2359 	/* The code below assumes all clocks are enabled.  Check this!. */
2360 	for (i = 0; i <= 34; i++) {
2361 		if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
2362 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
2363 			    HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
2364 		}
2365 	}
2366 
2367 	sc->sc_clocks = rk3399_clocks;
2368 }
2369 
2370 uint32_t
2371 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
2372 {
2373 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2374 	uint32_t pll_work_mode;
2375 	uint32_t reg;
2376 
2377 	reg = HREAD4(sc, base + 0x000c);
2378 	pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
2379 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
2380 		return 24000000;
2381 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
2382 		return 32768;
2383 
2384 	reg = HREAD4(sc, base + 0x0000);
2385 	fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
2386 	    RK3399_CRU_PLL_FBDIV_SHIFT;
2387 	reg = HREAD4(sc, base + 0x0004);
2388 	postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
2389 	    RK3399_CRU_PLL_POSTDIV2_SHIFT;
2390 	postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
2391 	    RK3399_CRU_PLL_POSTDIV1_SHIFT;
2392 	refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
2393 	    RK3399_CRU_PLL_REFDIV_SHIFT;
2394 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
2395 }
2396 
2397 int
2398 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
2399 {
2400 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2401 
2402 	/*
2403 	 * It is not clear whether all combinations of the clock
2404 	 * dividers result in a stable clock.  Therefore this function
2405 	 * only supports a limited set of PLL clock rates.  For now
2406 	 * this set covers all the CPU frequencies supported by the
2407 	 * Linux kernel.
2408 	 */
2409 	switch (freq) {
2410 	case 2208000000U:
2411 	case 2184000000U:
2412 	case 2088000000U:
2413 	case 2040000000U:
2414 	case 2016000000U:
2415 	case 1992000000U:
2416 	case 1896000000U:
2417 	case 1800000000U:
2418 	case 1704000000U:
2419 	case 1608000000U:
2420 	case 1512000000U:
2421 	case 1488000000U:
2422 	case 1416000000U:
2423 	case 1200000000U:
2424 		postdiv1 = postdiv2 = refdiv = 1;
2425 		break;
2426 	case 1008000000U:
2427 	case 816000000U:
2428 	case 696000000U:
2429 		postdiv1 = 2; postdiv2 = refdiv = 1;
2430 		break;
2431 	case 676000000U:
2432 		postdiv1 = 2; postdiv2 = 1; refdiv = 3;
2433 		break;
2434 	case 1000000000U:
2435 	case 800000000U:
2436 	case 600000000U:
2437 		postdiv1 = 3; postdiv2 = refdiv = 1;
2438 		break;
2439 	case 594000000U:
2440 		postdiv1 = 4; postdiv2 = refdiv = 1;
2441 		break;
2442 	case 408000000U:
2443 		postdiv1 = postdiv2 = 2; refdiv = 1;
2444 		break;
2445 	case 297000000U:
2446 	case 216000000U:
2447 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
2448 		break;
2449 	case 148500000U:
2450 	case 96000000U:
2451 		postdiv1 = postdiv2 = 4; refdiv = 1;
2452 		break;
2453 	case 74250000U:
2454 		postdiv1 = postdiv2 = 4; refdiv = 2;
2455 		break;
2456 	case 65000000U:
2457 	case 54000000U:
2458 	case 27000000U:
2459 		postdiv1 = 6; postdiv2 = 4; refdiv = 1;
2460 		break;
2461 	default:
2462 		printf("%s: %d Hz\n", __func__, freq);
2463 		return -1;
2464 	}
2465 
2466 	/* Calculate feedback divider. */
2467 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
2468 
2469 	/*
2470 	 * Select slow mode to guarantee a stable clock while we're
2471 	 * adjusting the PLL.
2472 	 */
2473 	HWRITE4(sc, base + 0x000c,
2474 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2475 	    RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
2476 
2477 	/* Set PLL rate. */
2478 	HWRITE4(sc, base + 0x0000,
2479 	    RK3399_CRU_PLL_FBDIV_MASK << 16 |
2480 	    fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
2481 	HWRITE4(sc, base + 0x0004,
2482 	    RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
2483 	    postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
2484 	    RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
2485 	    postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
2486 	    RK3399_CRU_PLL_REFDIV_MASK << 16 |
2487 	    refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
2488 
2489 	/* Wait for PLL to stabilize. */
2490 	while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
2491 		delay(10);
2492 
2493 	/* Switch back to normal mode. */
2494 	HWRITE4(sc, base + 0x000c,
2495 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2496 	    RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
2497 
2498 	return 0;
2499 }
2500 
2501 uint32_t
2502 rk3399_armclk_parent(uint32_t mux)
2503 {
2504 	switch (mux) {
2505 	case 0:
2506 		return RK3399_PLL_ALPLL;
2507 	case 1:
2508 		return RK3399_PLL_ABPLL;
2509 	case 2:
2510 		return RK3399_PLL_DPLL;
2511 	case 3:
2512 		return RK3399_PLL_GPLL;
2513 	}
2514 
2515 	return 0;
2516 }
2517 
2518 uint32_t
2519 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
2520 {
2521 	uint32_t reg, mux, div_con;
2522 	uint32_t idx;
2523 
2524 	reg = HREAD4(sc, clksel);
2525 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2526 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
2527 	div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
2528 	    RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
2529 	idx = rk3399_armclk_parent(mux);
2530 
2531 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
2532 }
2533 
2534 int
2535 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
2536 {
2537 	uint32_t reg, mux;
2538 	uint32_t old_freq, div;
2539 	uint32_t idx;
2540 
2541 	old_freq = rk3399_get_armclk(sc, clksel);
2542 	if (freq == old_freq)
2543 		return 0;
2544 
2545 	reg = HREAD4(sc, clksel);
2546 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2547 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
2548 	idx = rk3399_armclk_parent(mux);
2549 
2550 	/* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
2551 	div = 1;
2552 	while (freq / (div + 1) > 200000000)
2553 		div++;
2554 
2555 	/* When ramping up, set clock dividers first. */
2556 	if (freq > old_freq) {
2557 		HWRITE4(sc, clksel,
2558 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2559 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2560 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2561 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2562 		HWRITE4(sc, clksel + 0x0004,
2563 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2564 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2565 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2566 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2567 	}
2568 
2569 	rk3399_set_frequency(sc, &idx, freq);
2570 
2571 	/* When ramping down, set clock dividers last. */
2572 	if (freq < old_freq) {
2573 		HWRITE4(sc, clksel,
2574 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2575 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2576 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2577 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2578 		HWRITE4(sc, clksel + 0x0004,
2579 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2580 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2581 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2582 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2583 	}
2584 
2585 	return 0;
2586 }
2587 
2588 uint32_t
2589 rk3399_get_frac(struct rkclock_softc *sc, int parent, bus_size_t base)
2590 {
2591 	uint32_t frac;
2592 	uint16_t n, d;
2593 
2594 	frac = HREAD4(sc, base);
2595 	n = frac >> 16;
2596 	d = frac & 0xffff;
2597 	return ((uint64_t)rkclock_get_frequency(sc, parent) * n) / d;
2598 }
2599 
2600 int
2601 rk3399_set_frac(struct rkclock_softc *sc, int parent, bus_size_t base,
2602     uint32_t freq)
2603 {
2604 	uint32_t n, d;
2605 	uint32_t p0, p1, p2;
2606 	uint32_t q0, q1, q2;
2607 	uint32_t a, tmp;
2608 
2609 	n = freq;
2610 	d = rkclock_get_frequency(sc, parent);
2611 
2612 	/*
2613 	 * The denominator needs to be at least 20 times the numerator
2614 	 * for a stable clock.
2615 	 */
2616 	if (n == 0 || d == 0 || d < 20 * n)
2617 		return -1;
2618 
2619 	/*
2620 	 * This is a simplified implementation of the algorithm to
2621 	 * calculate the best rational approximation using continued
2622 	 * fractions.
2623 	 */
2624 
2625 	p0 = q1 = 0;
2626 	p1 = q0 = 1;
2627 
2628 	while (d != 0) {
2629 		/*
2630 		 * Calculate next coefficient in the continued
2631 		 * fraction and keep track of the remainder.
2632 		 */
2633 		tmp = d;
2634 		a = n / d;
2635 		d = n % d;
2636 		n = tmp;
2637 
2638 		/*
2639 		 * Calculate next approximation in the series based on
2640 		 * the current coefficient.
2641 		 */
2642 		p2 = p0 + a * p1;
2643 		q2 = q0 + a * q1;
2644 
2645 		/*
2646 		 * Terminate if we reached the maximum allowed
2647 		 * denominator.
2648 		 */
2649 		if (q2 > 0xffff)
2650 			break;
2651 
2652 		p0 = p1; p1 = p2;
2653 		q0 = q1; q1 = q2;
2654 	}
2655 
2656 	HWRITE4(sc, base, p1 << 16 | q1);
2657 	return 0;
2658 }
2659 
2660 uint32_t
2661 rk3399_get_frequency(void *cookie, uint32_t *cells)
2662 {
2663 	struct rkclock_softc *sc = cookie;
2664 	uint32_t idx = cells[0];
2665 
2666 	switch (idx) {
2667 	case RK3399_PLL_ALPLL:
2668 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
2669 	case RK3399_PLL_ABPLL:
2670 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
2671 	case RK3399_PLL_DPLL:
2672 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
2673 	case RK3399_PLL_CPLL:
2674 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
2675 	case RK3399_PLL_GPLL:
2676 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
2677 	case RK3399_PLL_NPLL:
2678 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
2679 	case RK3399_PLL_VPLL:
2680 		return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
2681 	case RK3399_ARMCLKL:
2682 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
2683 	case RK3399_ARMCLKB:
2684 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
2685 	case RK3399_XIN24M:
2686 		return 24000000;
2687 	case RK3399_CLK_32K:
2688 		return 32768;
2689 	case RK3399_XIN12M:
2690 		return 12000000;
2691 	case RK3399_CLK_I2S0_FRAC:
2692 		return rk3399_get_frac(sc, RK3399_CLK_I2S0_DIV,
2693 		    RK3399_CRU_CLKSEL_CON(96));
2694 	case RK3399_CLK_I2S1_FRAC:
2695 		return rk3399_get_frac(sc, RK3399_CLK_I2S1_DIV,
2696 		    RK3399_CRU_CLKSEL_CON(97));
2697 	case RK3399_CLK_I2S2_FRAC:
2698 		return rk3399_get_frac(sc, RK3399_CLK_I2S2_DIV,
2699 		    RK3399_CRU_CLKSEL_CON(98));
2700 	default:
2701 		break;
2702 	}
2703 
2704 	return rkclock_get_frequency(sc, idx);
2705 }
2706 
2707 int
2708 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2709 {
2710 	struct rkclock_softc *sc = cookie;
2711 	uint32_t idx = cells[0];
2712 
2713 	switch (idx) {
2714 	case RK3399_PLL_ALPLL:
2715 		return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
2716 	case RK3399_PLL_ABPLL:
2717 		return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
2718 	case RK3399_PLL_CPLL:
2719 		return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
2720 	case RK3399_PLL_GPLL:
2721 		return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
2722 	case RK3399_PLL_NPLL:
2723 		return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
2724 	case RK3399_PLL_VPLL:
2725 		return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq);
2726 	case RK3399_ARMCLKL:
2727 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
2728 	case RK3399_ARMCLKB:
2729 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
2730 	case RK3399_CLK_I2S0_8CH:
2731 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S0_FRAC);
2732 		return rkclock_set_frequency(sc, idx, freq);
2733 	case RK3399_CLK_I2S1_8CH:
2734 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S1_FRAC);
2735 		return rkclock_set_frequency(sc, idx, freq);
2736 	case RK3399_CLK_I2S2_8CH:
2737 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S2_FRAC);
2738 		return rkclock_set_frequency(sc, idx, freq);
2739 	case RK3399_XIN12M:
2740 		if (freq / (1000 * 1000) != 12)
2741 			return -1;
2742 		return 0;
2743 	case RK3399_CLK_I2S0_FRAC:
2744 		return rk3399_set_frac(sc, RK3399_CLK_I2S0_DIV,
2745 		    RK3399_CRU_CLKSEL_CON(96), freq);
2746 	case RK3399_CLK_I2S1_FRAC:
2747 		return rk3399_set_frac(sc, RK3399_CLK_I2S1_DIV,
2748 		    RK3399_CRU_CLKSEL_CON(97), freq);
2749 	case RK3399_CLK_I2S2_FRAC:
2750 		return rk3399_set_frac(sc, RK3399_CLK_I2S2_DIV,
2751 		    RK3399_CRU_CLKSEL_CON(98), freq);
2752 	default:
2753 		break;
2754 	}
2755 
2756 	return rkclock_set_frequency(sc, idx, freq);
2757 }
2758 
2759 void
2760 rk3399_enable(void *cookie, uint32_t *cells, int on)
2761 {
2762 	uint32_t idx = cells[0];
2763 
2764 	/*
2765 	 * All clocks are enabled by default, so there is nothing for
2766 	 * us to do until we start disabling clocks.
2767 	 */
2768 	if (!on)
2769 		printf("%s: 0x%08x\n", __func__, idx);
2770 }
2771 
2772 void
2773 rk3399_reset(void *cookie, uint32_t *cells, int on)
2774 {
2775 	struct rkclock_softc *sc = cookie;
2776 	uint32_t idx = cells[0];
2777 	uint32_t mask = (1 << (idx % 16));
2778 
2779 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
2780 	    mask << 16 | (on ? mask : 0));
2781 }
2782 
2783 /* PMUCRU */
2784 
2785 struct rkclock rk3399_pmu_clocks[] = {
2786 	{
2787 		RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
2788 		0, DIV(6, 0),
2789 		{ RK3399_PLL_PPLL }
2790 	},
2791 	{
2792 		RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
2793 		0, DIV(6, 0),
2794 		{ RK3399_PLL_PPLL }
2795 	},
2796 	{
2797 		RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
2798 		0, DIV(14, 8),
2799 		{ RK3399_PLL_PPLL }
2800 	},
2801 	{
2802 		RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0),
2803 		0, DIV(6, 0),
2804 		{ RK3399_PLL_PPLL }
2805 	},
2806 	{
2807 		/* Sentinel */
2808 	}
2809 };
2810 
2811 void
2812 rk3399_pmu_init(struct rkclock_softc *sc)
2813 {
2814 	sc->sc_clocks = rk3399_pmu_clocks;
2815 	rk3399_pmucru_sc = sc;
2816 }
2817 
2818 uint32_t
2819 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
2820 {
2821 	struct rkclock_softc *sc = cookie;
2822 	uint32_t idx = cells[0];
2823 
2824 	switch (idx) {
2825 	case RK3399_PLL_PPLL:
2826 		return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
2827 	default:
2828 		break;
2829 	}
2830 
2831 	return rkclock_get_frequency(sc, idx);
2832 }
2833 
2834 int
2835 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2836 {
2837 	struct rkclock_softc *sc = cookie;
2838 	uint32_t idx = cells[0];
2839 
2840 	switch (idx) {
2841 	case RK3399_PLL_PPLL:
2842 		return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
2843 		break;
2844 	default:
2845 		break;
2846 	}
2847 
2848 	return rkclock_set_frequency(sc, idx, freq);
2849 }
2850 
2851 void
2852 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
2853 {
2854 	uint32_t idx = cells[0];
2855 
2856 	switch (idx) {
2857 	case RK3399_CLK_I2C0:
2858 	case RK3399_CLK_I2C4:
2859 	case RK3399_CLK_I2C8:
2860 	case RK3399_PCLK_I2C0:
2861 	case RK3399_PCLK_I2C4:
2862 	case RK3399_PCLK_I2C8:
2863 	case RK3399_PCLK_RKPWM:
2864 		/* Enabled by default. */
2865 		break;
2866 	default:
2867 		printf("%s: 0x%08x\n", __func__, idx);
2868 		break;
2869 	}
2870 }
2871 
2872 void
2873 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
2874 {
2875 	uint32_t idx = cells[0];
2876 
2877 	printf("%s: 0x%08x\n", __func__, idx);
2878 }
2879