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