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