xref: /openbsd/sys/dev/fdt/rkclock.c (revision 4bdff4be)
1 /*	$OpenBSD: rkclock.c,v 1.84 2023/11/26 13:47:45 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 #define RK3568_PMUCRU_GATE_CON(i)	(0x0180 + (i) * 4)
190 
191 /* RK3588 registers */
192 #define RK3588_CRU_AUPLL_CON(i)		(0x00180 + (i) * 4)
193 #define RK3588_CRU_CPLL_CON(i)		(0x001a0 + (i) * 4)
194 #define RK3588_CRU_GPLL_CON(i)		(0x001c0 + (i) * 4)
195 #define RK3588_CRU_NPLL_CON(i)		(0x001e0 + (i) * 4)
196 #define  RK3588_CRU_PLL_M_MASK			(0x3ff << 0)
197 #define  RK3588_CRU_PLL_M_SHIFT			0
198 #define  RK3588_CRU_PLL_RESETB			(1 << 13)
199 #define  RK3588_CRU_PLL_S_MASK			(0x7 << 6)
200 #define  RK3588_CRU_PLL_S_SHIFT			6
201 #define  RK3588_CRU_PLL_P_MASK			(0x3f << 0)
202 #define  RK3588_CRU_PLL_P_SHIFT			0
203 #define  RK3588_CRU_PLL_K_MASK			(0xffff << 0)
204 #define  RK3588_CRU_PLL_K_SHIFT			0
205 #define  RK3588_CRU_PLL_PLL_LOCK		(1 << 15)
206 #define RK3588_CRU_MODE_CON		0x00280
207 #define  RK3588_CRU_MODE_MASK			0x3
208 #define  RK3588_CRU_MODE_SLOW			0x0
209 #define  RK3588_CRU_MODE_NORMAL			0x1
210 
211 #define RK3588_CRU_CLKSEL_CON(i)	(0x00300 + (i) * 4)
212 #define RK3588_CRU_GATE_CON(i)		(0x00800 + (i) * 4)
213 #define RK3588_CRU_SOFTRST_CON(i)	(0x00a00 + (i) * 4)
214 
215 #define RK3588_PHPTOPCRU_PPLL_CON(i)	(0x08200 + (i) * 4)
216 #define RK3588_PHPTOPCRU_SOFTRST_CON(i)	(0x08a00 + (i) * 4)
217 #define RK3588_PMUCRU_CLKSEL_CON(i)	(0x30300 + (i) * 4)
218 
219 #include "rkclock_clocks.h"
220 
221 struct rkclock {
222 	uint16_t idx;
223 	uint32_t reg;
224 	uint16_t sel_mask;
225 	uint16_t div_mask;
226 	uint16_t parents[8];
227 	uint32_t flags;
228 };
229 
230 #define SEL(l, f)	(((1 << (l - f + 1)) - 1) << f)
231 #define DIV(l, f)	SEL(l, f)
232 
233 #define FIXED_PARENT	(1 << 0)
234 #define SET_PARENT	(1 << 1)
235 
236 #define HREAD4(sc, reg)							\
237 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
238 #define HWRITE4(sc, reg, val)						\
239 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
240 #define HSET4(sc, reg, bits)						\
241 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
242 #define HCLR4(sc, reg, bits)						\
243 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
244 
245 struct rkclock_softc {
246 	struct device		sc_dev;
247 	bus_space_tag_t		sc_iot;
248 	bus_space_handle_t	sc_ioh;
249 	struct regmap		*sc_grf;
250 
251 	uint32_t		sc_phandle;
252 	const struct rkclock	*sc_clocks;
253 
254 	struct clock_device	sc_cd;
255 	struct reset_device	sc_rd;
256 };
257 
258 int rkclock_match(struct device *, void *, void *);
259 void rkclock_attach(struct device *, struct device *, void *);
260 
261 const struct cfattach	rkclock_ca = {
262 	sizeof (struct rkclock_softc), rkclock_match, rkclock_attach
263 };
264 
265 struct cfdriver rkclock_cd = {
266 	NULL, "rkclock", DV_DULL
267 };
268 
269 void	rk3288_init(struct rkclock_softc *);
270 uint32_t rk3288_get_frequency(void *, uint32_t *);
271 int	rk3288_set_frequency(void *, uint32_t *, uint32_t);
272 void	rk3288_enable(void *, uint32_t *, int);
273 void	rk3288_reset(void *, uint32_t *, int);
274 
275 void	rk3308_init(struct rkclock_softc *);
276 uint32_t rk3308_get_frequency(void *, uint32_t *);
277 int	rk3308_set_frequency(void *, uint32_t *, uint32_t);
278 int	rk3308_set_parent(void *, uint32_t *, uint32_t *);
279 void	rk3308_enable(void *, uint32_t *, int);
280 void	rk3308_reset(void *, uint32_t *, int);
281 
282 void	rk3328_init(struct rkclock_softc *);
283 uint32_t rk3328_get_frequency(void *, uint32_t *);
284 int	rk3328_set_frequency(void *, uint32_t *, uint32_t);
285 int	rk3328_set_parent(void *, uint32_t *, uint32_t *);
286 void	rk3328_enable(void *, uint32_t *, int);
287 void	rk3328_reset(void *, uint32_t *, int);
288 
289 void	rk3399_init(struct rkclock_softc *);
290 uint32_t rk3399_get_frequency(void *, uint32_t *);
291 int	rk3399_set_frequency(void *, uint32_t *, uint32_t);
292 int	rk3399_set_parent(void *, uint32_t *, uint32_t *);
293 void	rk3399_enable(void *, uint32_t *, int);
294 void	rk3399_reset(void *, uint32_t *, int);
295 
296 void	rk3399_pmu_init(struct rkclock_softc *);
297 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *);
298 int	rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t);
299 void	rk3399_pmu_enable(void *, uint32_t *, int);
300 void	rk3399_pmu_reset(void *, uint32_t *, int);
301 
302 void	rk3568_init(struct rkclock_softc *);
303 uint32_t rk3568_get_frequency(void *, uint32_t *);
304 int	rk3568_set_frequency(void *, uint32_t *, uint32_t);
305 int	rk3568_set_parent(void *, uint32_t *, uint32_t *);
306 void	rk3568_enable(void *, uint32_t *, int);
307 void	rk3568_reset(void *, uint32_t *, int);
308 
309 void	rk3568_pmu_init(struct rkclock_softc *);
310 uint32_t rk3568_pmu_get_frequency(void *, uint32_t *);
311 int	rk3568_pmu_set_frequency(void *, uint32_t *, uint32_t);
312 void	rk3568_pmu_enable(void *, uint32_t *, int);
313 void	rk3568_pmu_reset(void *, uint32_t *, int);
314 
315 void	rk3588_init(struct rkclock_softc *);
316 uint32_t rk3588_get_frequency(void *, uint32_t *);
317 int	rk3588_set_frequency(void *, uint32_t *, uint32_t);
318 void	rk3588_enable(void *, uint32_t *, int);
319 void	rk3588_reset(void *, uint32_t *, int);
320 
321 struct rkclock_compat {
322 	const char *compat;
323 	const char *name;
324 	int	assign;
325 	void	(*init)(struct rkclock_softc *);
326 	void	(*enable)(void *, uint32_t *, int);
327 	uint32_t (*get_frequency)(void *, uint32_t *);
328 	int	(*set_frequency)(void *, uint32_t *, uint32_t);
329 	int	(*set_parent)(void *, uint32_t *, uint32_t *);
330 	void	(*reset)(void *, uint32_t *, int);
331 };
332 
333 const struct rkclock_compat rkclock_compat[] = {
334 	{
335 		"rockchip,rk3288-cru", NULL, 0, rk3288_init,
336 		rk3288_enable, rk3288_get_frequency,
337 		rk3288_set_frequency, NULL,
338 		rk3288_reset
339 	},
340 	{
341 		"rockchip,rk3308-cru", NULL, 1, rk3308_init,
342 		rk3308_enable, rk3308_get_frequency,
343 		rk3308_set_frequency, rk3308_set_parent,
344 		rk3308_reset
345 	},
346 	{
347 		"rockchip,rk3328-cru", NULL, 1, rk3328_init,
348 		rk3328_enable, rk3328_get_frequency,
349 		rk3328_set_frequency, rk3328_set_parent,
350 		rk3328_reset
351 	},
352 	{
353 		"rockchip,rk3399-cru", NULL, 1, rk3399_init,
354 		rk3399_enable, rk3399_get_frequency,
355 		rk3399_set_frequency, rk3399_set_parent,
356 		rk3399_reset
357 	},
358 	{
359 		"rockchip,rk3399-pmucru", NULL, 1, rk3399_pmu_init,
360 		rk3399_pmu_enable, rk3399_pmu_get_frequency,
361 		rk3399_pmu_set_frequency, NULL,
362 		rk3399_pmu_reset
363 	},
364 	{
365 		"rockchip,rk3568-cru", "CRU", 1, rk3568_init,
366 		rk3568_enable, rk3568_get_frequency,
367 		rk3568_set_frequency, rk3568_set_parent,
368 		rk3568_reset
369 	},
370 	{
371 		"rockchip,rk3568-pmucru", "PMUCRU", 1, rk3568_pmu_init,
372 		rk3568_pmu_enable, rk3568_pmu_get_frequency,
373 		rk3568_pmu_set_frequency, NULL,
374 		rk3568_pmu_reset
375 	},
376 	{
377 		"rockchip,rk3588-cru", NULL, 1, rk3588_init,
378 		rk3588_enable, rk3588_get_frequency,
379 		rk3588_set_frequency, NULL,
380 		rk3588_reset
381 	},
382 };
383 
384 int
385 rkclock_match(struct device *parent, void *match, void *aux)
386 {
387 	struct fdt_attach_args *faa = aux;
388 	int i;
389 
390 	for (i = 0; i < nitems(rkclock_compat); i++) {
391 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat))
392 			return 10;
393 	}
394 
395 	return 0;
396 }
397 
398 void
399 rkclock_attach(struct device *parent, struct device *self, void *aux)
400 {
401 	struct rkclock_softc *sc = (struct rkclock_softc *)self;
402 	struct fdt_attach_args *faa = aux;
403 	uint32_t grf;
404 	int i;
405 
406 	if (faa->fa_nreg < 1) {
407 		printf(": no registers\n");
408 		return;
409 	}
410 
411 	sc->sc_iot = faa->fa_iot;
412 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
413 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
414 		printf(": can't map registers\n");
415 		return;
416 	}
417 
418 	grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
419 	sc->sc_grf = regmap_byphandle(grf);
420 
421 	sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0);
422 
423 	for (i = 0; i < nitems(rkclock_compat); i++) {
424 		if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) {
425 			break;
426 		}
427 	}
428 	KASSERT(i < nitems(rkclock_compat));
429 
430 	if (rkclock_compat[i].name != NULL)
431 		printf(": %s", rkclock_compat[i].name);
432 
433 	printf("\n");
434 
435 	if (rkclock_compat[i].init)
436 		rkclock_compat[i].init(sc);
437 
438 	sc->sc_cd.cd_node = faa->fa_node;
439 	sc->sc_cd.cd_cookie = sc;
440 	sc->sc_cd.cd_enable = rkclock_compat[i].enable;
441 	sc->sc_cd.cd_get_frequency = rkclock_compat[i].get_frequency;
442 	sc->sc_cd.cd_set_frequency = rkclock_compat[i].set_frequency;
443 	sc->sc_cd.cd_set_parent = rkclock_compat[i].set_parent;
444 	clock_register(&sc->sc_cd);
445 
446 	sc->sc_rd.rd_node = faa->fa_node;
447 	sc->sc_rd.rd_cookie = sc;
448 	sc->sc_rd.rd_reset = rkclock_compat[i].reset;
449 	reset_register(&sc->sc_rd);
450 
451 	if (rkclock_compat[i].assign)
452 		clock_set_assigned(faa->fa_node);
453 }
454 
455 const struct rkclock *
456 rkclock_lookup(struct rkclock_softc *sc, uint32_t idx)
457 {
458 	const struct rkclock *clk;
459 
460 	for (clk = sc->sc_clocks; clk->idx; clk++) {
461 		if (clk->idx == idx)
462 			return clk;
463 	}
464 
465 	return NULL;
466 }
467 
468 uint32_t
469 rkclock_external_frequency(const char *name)
470 {
471 	char buf[64] = {};
472 	int len, node;
473 
474 	/*
475 	 * Hunt through the device tree to find a fixed-rate clock
476 	 * that has the requested clock output signal name.  This may
477 	 * be too simple.
478 	 */
479 	node = OF_peer(0);
480 	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
481 		len = OF_getproplen(node, "clock-output-names");
482 		if (len <= 0 || len > sizeof(buf))
483 			continue;
484 		OF_getprop(node, "clock-output-names", buf, sizeof(buf));
485 		if (strcmp(buf, name) != 0)
486 			continue;
487 		if (OF_is_compatible(node, "fixed-clock"))
488 			return OF_getpropint(node, "clock-frequency", 0);
489 	}
490 
491 	return 0;
492 }
493 
494 uint32_t
495 rkclock_div_con(struct rkclock_softc *sc, const struct rkclock *clk,
496     uint32_t mux, uint32_t freq)
497 {
498 	uint32_t parent_freq, div, div_con, max_div_con;
499 	uint32_t idx = clk->parents[mux];
500 
501 	/* Derive maximum value from mask. */
502 	max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1);
503 
504 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
505 	div = (parent_freq + freq - 1) / freq;
506 	div_con = (div > 0 ? div - 1 : 0);
507 	return (div_con < max_div_con) ? div_con : max_div_con;
508 }
509 
510 uint32_t
511 rkclock_freq(struct rkclock_softc *sc, const struct rkclock *clk,
512     uint32_t mux, uint32_t freq)
513 {
514 	uint32_t parent_freq, div_con;
515 	uint32_t idx = clk->parents[mux];
516 
517 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
518 	div_con = rkclock_div_con(sc, clk, mux, freq);
519 	return parent_freq / (div_con + 1);
520 }
521 
522 uint32_t
523 rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx)
524 {
525 	const struct rkclock *clk;
526 	uint32_t reg, mux, div_con;
527 	int shift;
528 
529 	clk = rkclock_lookup(sc, idx);
530 	if (clk == NULL) {
531 		printf("%s(%s, %u)\n", __func__, sc->sc_dev.dv_xname, idx);
532 		return 0;
533 	}
534 
535 	reg = HREAD4(sc, clk->reg);
536 	shift = ffs(clk->sel_mask) - 1;
537 	if (shift == -1)
538 		mux = 0;
539 	else
540 		mux = (reg & clk->sel_mask) >> shift;
541 	shift = ffs(clk->div_mask) - 1;
542 	if (shift == -1)
543 		div_con = 0;
544 	else
545 		div_con = (reg & clk->div_mask) >> shift;
546 
547 	if (clk->parents[mux] == 0) {
548 		printf("%s: parent 0x%08x\n", __func__, idx);
549 		return 0;
550 	}
551 	idx = clk->parents[mux];
552 	return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1);
553 }
554 
555 int
556 rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq)
557 {
558 	const struct rkclock *clk;
559 	uint32_t reg, mux, div_con;
560 	uint32_t best_freq, best_mux, f;
561 	uint32_t parent;
562 	int sel_shift, div_shift, i;
563 
564 	clk = rkclock_lookup(sc, idx);
565 	if (clk == NULL) {
566 		printf("%s(%s, %u, %u)\n", __func__, sc->sc_dev.dv_xname,
567 		    idx, freq);
568 		return -1;
569 	}
570 
571 	reg = HREAD4(sc, clk->reg);
572 	sel_shift = ffs(clk->sel_mask) - 1;
573 	if (sel_shift == -1)
574 		mux = sel_shift = 0;
575 	else
576 		mux = (reg & clk->sel_mask) >> sel_shift;
577 
578 	if (clk->parents[mux] == 0) {
579 		printf("%s(%s, %u, %u) parent\n", __func__,
580 		    sc->sc_dev.dv_xname, idx, freq);
581 		return 0;
582 	}
583 
584 	if (clk->flags & SET_PARENT) {
585 		parent = clk->parents[mux];
586 		sc->sc_cd.cd_set_frequency(sc, &parent, freq);
587 		if (clk->div_mask == 0)
588 			return 0;
589 	}
590 
591 	/*
592 	 * If there is no divider, pick the parent with the frequency
593 	 * closest to the target frequency.
594 	 */
595 	if (clk->div_mask == 0) {
596 		/*
597 		 * Start out with the current parent.  This prevents
598 		 * unnecessary switching to a different parent.
599 		 */
600 		parent = clk->parents[mux];
601 		best_freq = sc->sc_cd.cd_get_frequency(sc, &parent);
602 		best_mux = mux;
603 
604 		for (i = 0; i < nitems(clk->parents); i++) {
605 			if (clk->parents[i] == 0)
606 				continue;
607 			parent = clk->parents[i];
608 			f = sc->sc_cd.cd_get_frequency(sc, &parent);
609 			if ((best_freq > freq && f < best_freq) ||
610 			    (f > best_freq && f <= freq)) {
611 				best_freq = f;
612 				best_mux = i;
613 			}
614 		}
615 
616 		HWRITE4(sc, clk->reg,
617 		    clk->sel_mask << 16 | best_mux << sel_shift);
618 		return 0;
619 	}
620 
621 	/*
622 	 * Start out with the current parent.  This prevents
623 	 * unnecessary switching to a different parent.
624 	 */
625 	best_freq = rkclock_freq(sc, clk, mux, freq);
626 	best_mux = mux;
627 
628 	/*
629 	 * Find the parent that allows configuration of a frequency
630 	 * closest to the target frequency.
631 	 */
632 	if ((clk->flags & FIXED_PARENT) == 0) {
633 		for (i = 0; i < nitems(clk->parents); i++) {
634 			if (clk->parents[i] == 0)
635 				continue;
636 			f = rkclock_freq(sc, clk, i, freq);
637 			if ((best_freq > freq && f < best_freq) ||
638 			    (f > best_freq && f <= freq)) {
639 				best_freq = f;
640 				best_mux = i;
641 			}
642 		}
643 	}
644 
645 	div_con = rkclock_div_con(sc, clk, best_mux, freq);
646 	div_shift = ffs(clk->div_mask) - 1;
647 	HWRITE4(sc, clk->reg,
648 	    clk->sel_mask << 16 | best_mux << sel_shift |
649 	    clk->div_mask << 16 | div_con << div_shift);
650 	return 0;
651 }
652 
653 int
654 rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent)
655 {
656 	const struct rkclock *clk;
657 	uint32_t mux;
658 	int shift;
659 
660 	clk = rkclock_lookup(sc, idx);
661 	if (clk == NULL || clk->sel_mask == 0) {
662 		printf("%s: 0x%08x\n", __func__, idx);
663 		return -1;
664 	}
665 
666 	for (mux = 0; mux < nitems(clk->parents); mux++) {
667 		if (clk->parents[mux] == parent)
668 			break;
669 	}
670 	if (mux == nitems(clk->parents) || parent == 0) {
671 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent);
672 		return -1;
673 	}
674 
675 	shift = ffs(clk->sel_mask) - 1;
676 	HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift);
677 	return 0;
678 }
679 
680 /*
681  * Rockchip RK3288
682  */
683 
684 const struct rkclock rk3288_clocks[] = {
685 	{
686 		RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11),
687 		SEL(7, 6), DIV(5, 0),
688 		{ RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M }
689 	}
690 };
691 
692 void
693 rk3288_init(struct rkclock_softc *sc)
694 {
695 	int node;
696 
697 	/*
698 	 * Since the hardware comes up with a really conservative CPU
699 	 * clock frequency, and U-Boot doesn't set it to a more
700 	 * reasonable default, try to do so here.  These defaults were
701 	 * chosen assuming that the CPU voltage is at least 1.1 V.
702 	 * Only do this on the Tinker-RK3288 for now where this is
703 	 * likely to be true given the default voltages for the
704 	 * regulators on that board.
705 	 */
706 	node = OF_finddevice("/");
707 	if (OF_is_compatible(node, "rockchip,rk3288-tinker")) {
708 		uint32_t idx;
709 
710 		/* Run at 1.2 GHz. */
711 		idx = RK3288_ARMCLK;
712 		rk3288_set_frequency(sc, &idx, 1200000000);
713 	}
714 
715 	sc->sc_clocks = rk3288_clocks;
716 }
717 
718 uint32_t
719 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
720 {
721 	uint32_t clkod, clkr, clkf;
722 	uint32_t reg;
723 
724 	reg = HREAD4(sc, base);
725 	clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >>
726 	    RK3288_CRU_PLL_CLKOD_SHIFT;
727 	clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >>
728 	    RK3288_CRU_PLL_CLKR_SHIFT;
729 	reg = HREAD4(sc, base + 4);
730 	clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >>
731 	    RK3288_CRU_PLL_CLKF_SHIFT;
732 	return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
733 }
734 
735 int
736 rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
737 {
738 	int shift = 4 * (base / RK3288_CRU_CPLL_CON(0));
739 	uint32_t no, nr, nf;
740 
741 	/*
742 	 * It is not clear whether all combinations of the clock
743 	 * dividers result in a stable clock.  Therefore this function
744 	 * only supports a limited set of PLL clock rates.  For now
745 	 * this set covers all the CPU frequencies supported by the
746 	 * Linux kernel.
747 	 */
748 	switch (freq) {
749 	case 1800000000:
750 	case 1704000000:
751 	case 1608000000:
752 	case 1512000000:
753 	case 1488000000:
754 	case 1416000000:
755 	case 1200000000:
756 		nr = no = 1;
757 		break;
758 	case 1008000000:
759 	case 816000000:
760 	case 696000000:
761 	case 600000000:
762 		nr = 1; no = 2;
763 		break;
764 	case 408000000:
765 	case 312000000:
766 		nr = 1; no = 4;
767 		break;
768 	case 216000000:
769 	case 126000000:
770 		nr = 1; no = 8;
771 		break;
772 	default:
773 		printf("%s: %u Hz\n", __func__, freq);
774 		return -1;
775 	}
776 
777 	/* Calculate feedback divider. */
778 	nf = freq * nr * no / 24000000;
779 
780 	/*
781 	 * Select slow mode to guarantee a stable clock while we're
782 	 * adjusting the PLL.
783 	 */
784 	HWRITE4(sc, RK3288_CRU_MODE_CON,
785 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
786 	     RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift);
787 
788 	/* Assert reset. */
789 	HWRITE4(sc, base + 0x000c,
790 	    RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET);
791 
792 	/* Set PLL rate. */
793 	HWRITE4(sc, base + 0x0000,
794 	    RK3288_CRU_PLL_CLKR_MASK << 16 |
795 	    (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT |
796 	    RK3288_CRU_PLL_CLKOD_MASK << 16 |
797 	    (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT);
798 	HWRITE4(sc, base + 0x0004,
799 	    RK3288_CRU_PLL_CLKF_MASK << 16 |
800 	    (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT);
801 
802 	/* Deassert reset and wait. */
803 	HWRITE4(sc, base + 0x000c,
804 	    RK3288_CRU_PLL_RESET << 16);
805 	delay((nr * 500 / 24) + 1);
806 
807 	/* Switch back to normal mode. */
808 	HWRITE4(sc, RK3288_CRU_MODE_CON,
809 	    (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
810 	     RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift);
811 
812 	return 0;
813 }
814 
815 uint32_t
816 rk3288_get_frequency(void *cookie, uint32_t *cells)
817 {
818 	struct rkclock_softc *sc = cookie;
819 	uint32_t idx = cells[0];
820 	uint32_t reg, mux, div_con, aclk_div_con;
821 
822 	switch (idx) {
823 	case RK3288_PLL_APLL:
824 		return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0));
825 	case RK3288_PLL_CPLL:
826 		return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
827 	case RK3288_PLL_GPLL:
828 		return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
829 	case RK3288_PLL_NPLL:
830 		return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0));
831 	case RK3288_ARMCLK:
832 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
833 		mux = (reg >> 15) & 0x1;
834 		div_con = (reg >> 8) & 0x1f;
835 		idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL;
836 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
837 	case RK3288_XIN24M:
838 		return 24000000;
839 	case RK3288_CLK_UART0:
840 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
841 		mux = (reg >> 8) & 0x3;
842 		div_con = reg & 0x7f;
843 		if (mux == 2)
844 			return 24000000 / (div_con + 1);
845 		break;
846 	case RK3288_CLK_UART1:
847 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
848 		mux = (reg >> 8) & 0x3;
849 		div_con = reg & 0x7f;
850 		if (mux == 2)
851 			return 24000000 / (div_con + 1);
852 		break;
853 	case RK3288_CLK_UART2:
854 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
855 		mux = (reg >> 8) & 0x3;
856 		div_con = reg & 0x7f;
857 		if (mux == 2)
858 			return 24000000 / (div_con + 1);
859 		break;
860 	case RK3288_CLK_UART3:
861 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
862 		mux = (reg >> 8) & 0x3;
863 		div_con = reg & 0x7f;
864 		if (mux == 2)
865 			return 24000000 / (div_con + 1);
866 		break;
867 	case RK3288_CLK_UART4:
868 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
869 		mux = (reg >> 8) & 0x3;
870 		div_con = reg & 0x7f;
871 		if (mux == 2)
872 			return 24000000 / (div_con + 1);
873 		break;
874 	case RK3288_CLK_MAC:
875 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21));
876 		if (reg & 0x10)
877 			return 125000000;
878 		mux = (reg >> 0) & 0x3;
879 		div_con = (reg >> 8) & 0x1f;
880 		switch (mux) {
881 		case 0:
882 			idx = RK3288_PLL_NPLL;
883 			break;
884 		case 1:
885 			idx = RK3288_PLL_CPLL;
886 			break;
887 		case 2:
888 			idx = RK3288_PLL_GPLL;
889 			break;
890 		default:
891 			return 0;
892 		}
893 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
894 	case RK3288_PCLK_I2C0:
895 	case RK3288_PCLK_I2C2:
896 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1));
897 		mux = (reg >> 15) & 0x1;
898 		/* pd_bus_pclk_div_con */
899 		div_con = (reg >> 12) & 0x7;
900 		if (mux == 1)
901 			idx = RK3288_PLL_GPLL;
902 		else
903 			idx = RK3288_PLL_CPLL;
904 		return rk3288_get_frequency(sc, &idx) / (div_con + 1);
905 	case RK3288_PCLK_I2C1:
906 	case RK3288_PCLK_I2C3:
907 	case RK3288_PCLK_I2C4:
908 	case RK3288_PCLK_I2C5:
909 		reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10));
910 		mux = (reg >> 15) & 0x1;
911 		/* peri_pclk_div_con */
912 		div_con = (reg >> 12) & 0x3;
913 		/* peri_aclk_div_con */
914 		aclk_div_con = reg & 0xf;
915 		if (mux == 1)
916 			idx = RK3288_PLL_GPLL;
917 		else
918 			idx = RK3288_PLL_CPLL;
919 		return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >>
920 		    div_con;
921 	default:
922 		break;
923 	}
924 
925 	return rkclock_get_frequency(sc, idx);
926 }
927 
928 int
929 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
930 {
931 	struct rkclock_softc *sc = cookie;
932 	uint32_t idx = cells[0];
933 	int error;
934 
935 	switch (idx) {
936 	case RK3288_PLL_APLL:
937 		return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq);
938 	case RK3288_ARMCLK:
939 		idx = RK3288_PLL_APLL;
940 		error = rk3288_set_frequency(sc, &idx, freq);
941 		if (error == 0) {
942 			HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0),
943 			    ((1 << 15) | (0x1f << 8)) << 16);
944 		}
945 		return error;
946 	default:
947 		break;
948 	}
949 
950 	return rkclock_set_frequency(sc, idx, freq);
951 }
952 
953 void
954 rk3288_enable(void *cookie, uint32_t *cells, int on)
955 {
956 	uint32_t idx = cells[0];
957 
958 	switch (idx) {
959 	case RK3288_CLK_SDMMC:
960 	case RK3288_CLK_TSADC:
961 	case RK3288_CLK_UART0:
962 	case RK3288_CLK_UART1:
963 	case RK3288_CLK_UART2:
964 	case RK3288_CLK_UART3:
965 	case RK3288_CLK_UART4:
966 	case RK3288_CLK_MAC_RX:
967 	case RK3288_CLK_MAC_TX:
968 	case RK3288_CLK_SDMMC_DRV:
969 	case RK3288_CLK_SDMMC_SAMPLE:
970 	case RK3288_CLK_MAC:
971 	case RK3288_ACLK_GMAC:
972 	case RK3288_PCLK_GMAC:
973 	case RK3288_PCLK_I2C0:
974 	case RK3288_PCLK_I2C1:
975 	case RK3288_PCLK_I2C2:
976 	case RK3288_PCLK_I2C3:
977 	case RK3288_PCLK_I2C4:
978 	case RK3288_PCLK_I2C5:
979 	case RK3288_PCLK_TSADC:
980 	case RK3288_HCLK_HOST0:
981 	case RK3288_HCLK_SDMMC:
982 		/* Enabled by default. */
983 		break;
984 	default:
985 		printf("%s: 0x%08x\n", __func__, idx);
986 		break;
987 	}
988 }
989 
990 void
991 rk3288_reset(void *cookie, uint32_t *cells, int on)
992 {
993 	struct rkclock_softc *sc = cookie;
994 	uint32_t idx = cells[0];
995 	uint32_t mask = (1 << (idx % 16));
996 
997 	HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16),
998 	    mask << 16 | (on ? mask : 0));
999 }
1000 
1001 /*
1002  * Rockchip RK3308
1003  */
1004 
1005 const struct rkclock rk3308_clocks[] = {
1006 	{
1007 		RK3308_CLK_RTC32K, RK3308_CRU_CLKSEL_CON(2),
1008 		SEL(10, 9), 0,
1009 		{ RK3308_PLL_VPLL0, RK3308_PLL_VPLL1 }
1010 	},
1011 	{
1012 		RK3308_CLK_UART0, RK3308_CRU_CLKSEL_CON(10),
1013 		SEL(15, 13), DIV(4, 0),
1014 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1015 		  RK3308_USB480M, RK3308_XIN24M }
1016 	},
1017 	{
1018 		RK3308_CLK_UART1, RK3308_CRU_CLKSEL_CON(13),
1019 		SEL(15, 13), DIV(4, 0),
1020 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1021 		  RK3308_USB480M, RK3308_XIN24M }
1022 	},
1023 	{
1024 		RK3308_CLK_UART2, RK3308_CRU_CLKSEL_CON(16),
1025 		SEL(15, 13), DIV(4, 0),
1026 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1027 		  RK3308_USB480M, RK3308_XIN24M }
1028 	},
1029 	{
1030 		RK3308_CLK_UART3, RK3308_CRU_CLKSEL_CON(19),
1031 		SEL(15, 13), DIV(4, 0),
1032 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1033 		  RK3308_USB480M, RK3308_XIN24M }
1034 	},
1035 	{
1036 		RK3308_CLK_UART4, RK3308_CRU_CLKSEL_CON(22),
1037 		SEL(15, 13), DIV(4, 0),
1038 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1039 		  RK3308_USB480M, RK3308_XIN24M }
1040 	},
1041 	{
1042 		RK3308_CLK_PWM0, RK3308_CRU_CLKSEL_CON(29),
1043 		SEL(15, 14), DIV(6, 0),
1044 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
1045 	},
1046 	{
1047 		RK3308_CLK_TSADC, RK3308_CRU_CLKSEL_CON(33),
1048 		0, DIV(10, 0),
1049 		{ RK3308_XIN24M }
1050 	},
1051 	{
1052 		RK3308_CLK_SARADC, RK3308_CRU_CLKSEL_CON(34),
1053 		0, DIV(10, 0),
1054 		{ RK3308_XIN24M }
1055 	},
1056 	{
1057 		RK3308_CLK_CRYPTO, RK3308_CRU_CLKSEL_CON(7),
1058 		SEL(7, 6), DIV(4, 0),
1059 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1060 	},
1061 	{
1062 		RK3308_CLK_CRYPTO_APK, RK3308_CRU_CLKSEL_CON(7),
1063 		SEL(15, 14), DIV(12, 8),
1064 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1065 	},
1066 	{
1067 		RK3308_CLK_SDMMC, RK3308_CRU_CLKSEL_CON(39),
1068 		SEL(9, 8), DIV(7, 0),
1069 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1070 		  RK3308_XIN24M }
1071 	},
1072 	{
1073 		RK3308_CLK_SDIO, RK3308_CRU_CLKSEL_CON(40),
1074 		SEL(9, 8), DIV(7, 0),
1075 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1076 		  RK3308_XIN24M }
1077 	},
1078 	{
1079 		RK3308_CLK_EMMC, RK3308_CRU_CLKSEL_CON(41),
1080 		SEL(9, 8), DIV(7, 0),
1081 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1082 		  RK3308_XIN24M }
1083 	},
1084 	{
1085 		RK3308_CLK_MAC_SRC, RK3308_CRU_CLKSEL_CON(43),
1086 		SEL(7, 6), DIV(4, 0),
1087 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1088 	},
1089 	{
1090 		RK3308_CLK_MAC, RK3308_CRU_CLKSEL_CON(43),
1091 		SEL(14, 13), 0,
1092 		{ RK3308_CLK_MAC_SRC, 0 },
1093 		SET_PARENT
1094 	},
1095 	{
1096 		RK3308_ACLK_PERI_SRC, RK3308_CRU_CLKSEL_CON(36),
1097 		SEL(7, 6), 0,
1098 		{ RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1099 	},
1100 	{
1101 		RK3308_PCLK_PERI, RK3308_CRU_CLKSEL_CON(37),
1102 		0, DIV(12, 8),
1103 		{ RK3308_ACLK_PERI_SRC }
1104 	},
1105 	{
1106 		RK3308_PCLK_MAC, 0, 0, 0,
1107 		{ RK3308_PCLK_PERI }
1108 	},
1109 
1110 	{
1111 		/* Sentinel */
1112 	}
1113 };
1114 
1115 void
1116 rk3308_init(struct rkclock_softc *sc)
1117 {
1118 	int i;
1119 
1120 	/* The code below assumes all clocks are enabled.  Check this!. */
1121 	for (i = 0; i <= 14; i++) {
1122 		if (HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)) != 0x00000000) {
1123 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1124 			    HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)));
1125 		}
1126 	}
1127 	sc->sc_clocks = rk3308_clocks;
1128 }
1129 
1130 uint32_t
1131 rk3308_armclk_parent(uint32_t mux)
1132 {
1133 	switch (mux) {
1134 	case 0:
1135 		return RK3308_PLL_APLL;
1136 	case 1:
1137 		return RK3308_PLL_VPLL0;
1138 	case 2:
1139 		return RK3308_PLL_VPLL1;
1140 	}
1141 
1142 	return 0;
1143 }
1144 
1145 uint32_t
1146 rk3308_get_armclk(struct rkclock_softc *sc)
1147 {
1148 	uint32_t reg, mux, div_con;
1149 	uint32_t idx;
1150 
1151 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1152 	mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1153 	    RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1154 	div_con = (reg & RK3308_CRU_CLK_CORE_DIV_CON_MASK) >>
1155 	    RK3308_CRU_CLK_CORE_DIV_CON_SHIFT;
1156 	idx = rk3308_armclk_parent(mux);
1157 
1158 	return rk3308_get_frequency(sc, &idx) / (div_con + 1);
1159 }
1160 
1161 int
1162 rk3308_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1163 {
1164 	uint32_t reg, mux;
1165 	uint32_t old_freq, div;
1166 	uint32_t idx;
1167 
1168 	old_freq = rk3308_get_armclk(sc);
1169 	if (freq == old_freq)
1170 		return 0;
1171 
1172 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1173 	mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1174 	    RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1175 
1176 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1177 	div = 1;
1178 	while (freq / (div + 1) > 300000000)
1179 		div++;
1180 	/* and make sure we use an odd divider. */
1181 	if ((div % 2) == 0)
1182 		div++;
1183 
1184 	/* When ramping up, set clock dividers first. */
1185 	if (freq > old_freq) {
1186 		HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1187 		    RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1188 		    0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1189 		    RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1190 		    1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1191 		    RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1192 		    div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1193 	}
1194 
1195 	/* We always use VPLL1 and force the switch below if needed. */
1196 	idx = RK3308_PLL_VPLL1;
1197 	rk3308_set_frequency(sc, &idx, freq);
1198 
1199 	/* When ramping down, set clock dividers last. */
1200 	if (freq < old_freq || mux != 2) {
1201 		HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1202 		    RK3308_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1203 		    2 << RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT |
1204 		    RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1205 		    0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1206 		    RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1207 		    1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1208 		    RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1209 		    div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1210 	}
1211 
1212 	return 0;
1213 }
1214 
1215 uint32_t
1216 rk3308_get_pll(struct rkclock_softc *sc, bus_size_t base)
1217 {
1218 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1219 	uint32_t dsmpd, fracdiv;
1220 	uint64_t frac = 0;
1221 	uint32_t reg;
1222 
1223 	reg = HREAD4(sc, base + 0x0000);
1224 	postdiv1 = (reg & RK3308_CRU_PLL_POSTDIV1_MASK) >>
1225 	    RK3308_CRU_PLL_POSTDIV1_SHIFT;
1226 	fbdiv = (reg & RK3308_CRU_PLL_FBDIV_MASK) >>
1227 	    RK3308_CRU_PLL_FBDIV_SHIFT;
1228 	reg = HREAD4(sc, base + 0x0004);
1229 	dsmpd = (reg & RK3308_CRU_PLL_DSMPD);
1230 	postdiv2 = (reg & RK3308_CRU_PLL_POSTDIV2_MASK) >>
1231 	    RK3308_CRU_PLL_POSTDIV2_SHIFT;
1232 	refdiv = (reg & RK3308_CRU_PLL_REFDIV_MASK) >>
1233 	    RK3308_CRU_PLL_REFDIV_SHIFT;
1234 	reg = HREAD4(sc, base + 0x0008);
1235 	fracdiv = (reg & RK3308_CRU_PLL_FRACDIV_MASK) >>
1236 	    RK3308_CRU_PLL_FRACDIV_SHIFT;
1237 
1238 	if (dsmpd == 0)
1239 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1240 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1241 }
1242 
1243 int
1244 rk3308_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1245 {
1246 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1247 	int mode_shift = -1;
1248 
1249 	switch (base) {
1250 	case RK3308_CRU_APLL_CON(0):
1251 		mode_shift = 0;
1252 		break;
1253 	case RK3308_CRU_DPLL_CON(0):
1254 		mode_shift = 2;
1255 		break;
1256 	case RK3308_CRU_VPLL0_CON(0):
1257 		mode_shift = 4;
1258 		break;
1259 	case RK3308_CRU_VPLL1_CON(0):
1260 		mode_shift = 6;
1261 		break;
1262 	}
1263 	KASSERT(mode_shift != -1);
1264 
1265 	/*
1266 	 * It is not clear whether all combinations of the clock
1267 	 * dividers result in a stable clock.  Therefore this function
1268 	 * only supports a limited set of PLL clock rates.  For now
1269 	 * this set covers all the CPU frequencies supported by the
1270 	 * Linux kernel.
1271 	 */
1272 	switch (freq) {
1273 	case 1608000000U:
1274 	case 1584000000U:
1275 	case 1560000000U:
1276 	case 1536000000U:
1277 	case 1512000000U:
1278 	case 1488000000U:
1279 	case 1464000000U:
1280 	case 1440000000U:
1281 	case 1416000000U:
1282 	case 1392000000U:
1283 	case 1368000000U:
1284 	case 1344000000U:
1285 	case 1320000000U:
1286 	case 1296000000U:
1287 	case 1272000000U:
1288 	case 1248000000U:
1289 	case 1200000000U:
1290 	case 1104000000U:
1291 		postdiv1 = postdiv2 = refdiv = 1;
1292 		break;
1293 	case 1188000000U:
1294 		refdiv = 2; postdiv1 = postdiv2 = 1;
1295 		break;
1296 	case 1100000000U:
1297 		refdiv = 12; postdiv1 = postdiv2 = 1;
1298 		break;
1299 	case 1000000000U:
1300 		refdiv = 6; postdiv1 = postdiv2 = 1;
1301 		break;
1302 	case 1008000000U:
1303 	case 984000000U:
1304 	case 960000000U:
1305 	case 936000000U:
1306 	case 912000000U:
1307 	case 888000000U:
1308 	case 864000000U:
1309 	case 840000000U:
1310 	case 816000000U:
1311 	case 696000000U:
1312 	case 624000000U:
1313 		postdiv1 = 2; postdiv2 = refdiv = 1;
1314 		break;
1315 	case 900000000U:
1316 		refdiv = 4; postdiv1 = 2; postdiv2 = 1;
1317 		break;
1318 	case 800000000U:
1319 	case 700000000U:
1320 	case 500000000U:
1321 		refdiv = 6; postdiv1 = 2; postdiv2 = 1;
1322 		break;
1323 	case 600000000U:
1324 	case 504000000U:
1325 		postdiv1 = 3; postdiv2 = refdiv = 1;
1326 		break;
1327 	case 594000000U:
1328 		refdiv = 2; postdiv1 = 2; postdiv2 = 1;
1329 		break;
1330 	case 408000000U:
1331 	case 312000000U:
1332 		postdiv1 = postdiv2 = 2; refdiv = 1;
1333 		break;
1334 	case 216000000U:
1335 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1336 		break;
1337 	case 96000000U:
1338 		postdiv1 = postdiv2 = 4; refdiv = 1;
1339 		break;
1340 	default:
1341 		printf("%s: %u Hz\n", __func__, freq);
1342 		return -1;
1343 	}
1344 
1345 	/* Calculate feedback divider. */
1346 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1347 
1348 	/*
1349 	 * Select slow mode to guarantee a stable clock while we're
1350 	 * adjusting the PLL.
1351 	 */
1352 	HWRITE4(sc, RK3308_CRU_CRU_MODE,
1353 	   (RK3308_CRU_CRU_MODE_MASK << 16 |
1354 	   RK3308_CRU_CRU_MODE_SLOW) << mode_shift);
1355 
1356 	/* Set PLL rate. */
1357 	HWRITE4(sc, base + 0x0000,
1358 	    RK3308_CRU_PLL_POSTDIV1_MASK << 16 |
1359 	    postdiv1 << RK3308_CRU_PLL_POSTDIV1_SHIFT |
1360 	    RK3308_CRU_PLL_FBDIV_MASK << 16 |
1361 	    fbdiv << RK3308_CRU_PLL_FBDIV_SHIFT);
1362 	HWRITE4(sc, base + 0x0004,
1363 	    RK3308_CRU_PLL_DSMPD << 16 | RK3308_CRU_PLL_DSMPD |
1364 	    RK3308_CRU_PLL_POSTDIV2_MASK << 16 |
1365 	    postdiv2 << RK3308_CRU_PLL_POSTDIV2_SHIFT |
1366 	    RK3308_CRU_PLL_REFDIV_MASK << 16 |
1367 	    refdiv << RK3308_CRU_PLL_REFDIV_SHIFT);
1368 
1369 	/* Wait for PLL to stabilize. */
1370 	while ((HREAD4(sc, base + 0x0004) & RK3308_CRU_PLL_PLL_LOCK) == 0)
1371 		delay(10);
1372 
1373 	/* Switch back to normal mode. */
1374 	HWRITE4(sc, RK3308_CRU_CRU_MODE,
1375 	   (RK3308_CRU_CRU_MODE_MASK << 16 |
1376 	   RK3308_CRU_CRU_MODE_NORMAL) << mode_shift);
1377 
1378 	return 0;
1379 }
1380 
1381 uint32_t
1382 rk3308_get_rtc32k(struct rkclock_softc *sc)
1383 {
1384 	uint32_t reg, mux, pll, div_con;
1385 
1386 	reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(2));
1387 	mux = (reg & 0x300) >> 8;
1388 	if (mux != 3) {
1389 		printf("%s: RTC32K not using clk_32k_div\n", __func__);
1390 		return 0;
1391 	}
1392 
1393 	if ((reg >> 10) & 1)
1394 		pll = RK3308_PLL_VPLL1;
1395 	else
1396 		pll = RK3308_PLL_VPLL0;
1397 
1398 	div_con = HREAD4(sc, RK3308_CRU_CLKSEL_CON(4)) & 0xffff;
1399 	return rk3308_get_frequency(sc, &pll) / (div_con + 1);
1400 }
1401 
1402 int
1403 rk3308_set_rtc32k(struct rkclock_softc *sc, uint32_t freq)
1404 {
1405 	const struct rkclock *clk;
1406 	uint32_t vpll0_freq, vpll1_freq, mux, div_con;
1407 
1408 	clk = rkclock_lookup(sc, RK3308_CLK_RTC32K);
1409 	vpll0_freq = rkclock_freq(sc, clk, 0, freq);
1410 	vpll1_freq = rkclock_freq(sc, clk, 1, freq);
1411 	mux = 0;
1412 	freq = vpll0_freq;
1413 
1414 	if ((vpll1_freq > vpll0_freq && vpll1_freq <= freq) ||
1415 	    (vpll1_freq < vpll0_freq && vpll1_freq >= freq)) {
1416 		mux = 1;
1417 		freq = vpll1_freq;
1418 	}
1419 
1420 	div_con = rkclock_div_con(sc, clk, mux, freq);
1421 	HWRITE4(sc, RK3308_CRU_CLKSEL_CON(2), 1 << 26 | (mux << 10));
1422 	HWRITE4(sc, RK3308_CRU_CLKSEL_CON(4), 0xffff0000 | div_con);
1423 	return 0;
1424 }
1425 
1426 uint32_t
1427 rk3308_get_frequency(void *cookie, uint32_t *cells)
1428 {
1429 	struct rkclock_softc *sc = cookie;
1430 	uint32_t idx = cells[0];
1431 
1432 	switch (idx) {
1433 	case RK3308_PLL_APLL:
1434 		return rk3308_get_pll(sc, RK3308_CRU_APLL_CON(0));
1435 	case RK3308_PLL_DPLL:
1436 		return rk3308_get_pll(sc, RK3308_CRU_DPLL_CON(0));
1437 	case RK3308_PLL_VPLL0:
1438 		return rk3308_get_pll(sc, RK3308_CRU_VPLL0_CON(0));
1439 	case RK3308_PLL_VPLL1:
1440 		return rk3308_get_pll(sc, RK3308_CRU_VPLL1_CON(0));
1441 	case RK3308_ARMCLK:
1442 		return rk3308_get_armclk(sc);
1443 	case RK3308_XIN24M:
1444 		return 24000000;
1445 	case RK3308_CLK_RTC32K:
1446 		return rk3308_get_rtc32k(sc);
1447 
1448 	/*
1449 	 * XXX The USB480M clock is external.  Returning zero here will cause
1450 	 * it to be ignored for reparenting purposes.
1451 	 */
1452 	case RK3308_USB480M:
1453 		return 0;
1454 	default:
1455 		break;
1456 	}
1457 
1458 	return rkclock_get_frequency(sc, idx);
1459 }
1460 
1461 int
1462 rk3308_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1463 {
1464 	struct rkclock_softc *sc = cookie;
1465 	uint32_t idx = cells[0];
1466 
1467 	switch (idx) {
1468 	case RK3308_PLL_APLL:
1469 		return rk3308_set_pll(sc, RK3308_CRU_APLL_CON(0), freq);
1470 	case RK3308_PLL_DPLL:
1471 		return rk3308_set_pll(sc, RK3308_CRU_DPLL_CON(0), freq);
1472 	case RK3308_PLL_VPLL0:
1473 		return rk3308_set_pll(sc, RK3308_CRU_VPLL0_CON(0), freq);
1474 	case RK3308_PLL_VPLL1:
1475 		return rk3308_set_pll(sc, RK3308_CRU_VPLL1_CON(0), freq);
1476 	case RK3308_ARMCLK:
1477 		return rk3308_set_armclk(sc, freq);
1478 	case RK3308_CLK_RTC32K:
1479 		return rk3308_set_rtc32k(sc, freq);
1480 	default:
1481 		break;
1482 	}
1483 
1484 	return rkclock_set_frequency(sc, idx, freq);
1485 }
1486 
1487 
1488 int
1489 rk3308_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1490 {
1491 	struct rkclock_softc *sc = cookie;
1492 
1493 	if (pcells[0] != sc->sc_phandle)
1494 		return -1;
1495 
1496 	return rkclock_set_parent(sc, cells[0], pcells[1]);
1497 }
1498 
1499 void
1500 rk3308_enable(void *cookie, uint32_t *cells, int on)
1501 {
1502 	uint32_t idx = cells[0];
1503 
1504 	/*
1505 	 * All clocks are enabled by default, so there is nothing for
1506 	 * us to do until we start disabling clocks.
1507 	 */
1508 	if (!on)
1509 		printf("%s: 0x%08x\n", __func__, idx);
1510 }
1511 
1512 void
1513 rk3308_reset(void *cookie, uint32_t *cells, int on)
1514 {
1515 	struct rkclock_softc *sc = cookie;
1516 	uint32_t idx = cells[0];
1517 	uint32_t mask = (1 << (idx % 16));
1518 
1519 	HWRITE4(sc, RK3308_CRU_SOFTRST_CON(idx / 16),
1520 	    mask << 16 | (on ? mask : 0));
1521 }
1522 
1523 
1524 /*
1525  * Rockchip RK3328
1526  */
1527 
1528 const struct rkclock rk3328_clocks[] = {
1529 	{
1530 		RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38),
1531 		SEL(15, 14), DIV(13, 0),
1532 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M }
1533 	},
1534 	{
1535 		RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30),
1536 		SEL(9, 8), DIV(7, 0),
1537 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1538 		  RK3328_USB480M }
1539 	},
1540 	{
1541 		RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31),
1542 		SEL(9, 8), DIV(7, 0),
1543 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1544 		  RK3328_USB480M }
1545 	},
1546 	{
1547 		RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32),
1548 		SEL(9, 8), DIV(7, 0),
1549 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1550 		  RK3328_USB480M }
1551 	},
1552 	{
1553 		RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22),
1554 		0, DIV(9, 0),
1555 		{ RK3328_CLK_24M }
1556 	},
1557 	{
1558 		RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14),
1559 		SEL(9, 8), 0,
1560 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1561 	},
1562 	{
1563 		RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16),
1564 		SEL(9, 8), 0,
1565 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1566 	},
1567 	{
1568 		RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18),
1569 		SEL(9, 8), 0,
1570 		{ 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1571 	},
1572 	{
1573 		RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52),
1574 		SEL(7, 6), DIV(5, 0),
1575 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M }
1576 	},
1577 	{
1578 		RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34),
1579 		SEL(7, 7), DIV(6, 0),
1580 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1581 	},
1582 	{
1583 		RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34),
1584 		SEL(15, 15), DIV(14, 8),
1585 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1586 	},
1587 	{
1588 		RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35),
1589 		SEL(7, 7), DIV(6, 0),
1590 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1591 	},
1592 	{
1593 		RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35),
1594 		SEL(15, 15), DIV(14, 8),
1595 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1596 	},
1597 	{
1598 		RK3328_CLK_CRYPTO, RK3328_CRU_CLKSEL_CON(20),
1599 		SEL(7, 7), DIV(4, 0),
1600 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1601 	},
1602 	{
1603 		RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
1604 		SEL(15, 14), DIV(12, 8),
1605 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
1606 		FIXED_PARENT | SET_PARENT
1607 	},
1608 	{
1609 		RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
1610 		SEL(15, 14), DIV(12, 8),
1611 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1612 		  RK3328_USB480M }
1613 	},
1614 	{
1615 		RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
1616 		SEL(7, 6), DIV(4, 0),
1617 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1618 		  RK3328_USB480M }
1619 	},
1620 	{
1621 		RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
1622 		SEL(15, 14), DIV(12, 8),
1623 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1624 		  RK3328_USB480M }
1625 	},
1626 	{
1627 		RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
1628 		SEL(15, 14), DIV(12, 8),
1629 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1630 		  RK3328_USB480M }
1631 	},
1632 	{
1633 		RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
1634 		SEL(15, 15), DIV(12, 8),
1635 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1636 	},
1637 	{
1638 		RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
1639 		SEL(7, 7), DIV(4, 0),
1640 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1641 	},
1642 	{
1643 		RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
1644 		SEL(1, 1), 0,
1645 		{ RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
1646 	},
1647 	{
1648 		RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
1649 		SEL(7, 6), DIV(4, 0),
1650 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1651 		  RK3328_USB480M }
1652 	},
1653 	{
1654 		RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
1655 		SEL(15, 14), DIV(12, 8),
1656 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1657 		  RK3328_USB480M }
1658 	},
1659 	{
1660 		RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
1661 		SEL(14, 13), DIV(12, 8),
1662 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1663 	},
1664 	{
1665 		RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
1666 		SEL(7, 6), DIV(4, 0),
1667 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1668 	},
1669 	{
1670 		RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
1671 		SEL(7, 6), DIV(4, 0),
1672 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1673 		  RK3328_USB480M }
1674 	},
1675 	{
1676 		RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
1677 		SEL(7, 6), DIV(4, 0),
1678 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1679 		  RK3328_USB480M }
1680 	},
1681 	{
1682 		RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
1683 		SEL(7, 6), DIV(4, 0),
1684 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1685 		  RK3328_USB480M }
1686 	},
1687 	{
1688 		RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
1689 		SEL(7, 6), DIV(4, 0),
1690 		{ RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1691 		  RK3328_USB480M }
1692 	},
1693 	{
1694 		RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1695 		0, DIV(14, 12),
1696 		{ RK3328_ACLK_BUS_PRE }
1697 	},
1698 	{
1699 		RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1700 		0, DIV(9, 8),
1701 		{ RK3328_ACLK_BUS_PRE }
1702 	},
1703 	{
1704 		RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1705 		0, DIV(6, 4),
1706 		{ RK3328_ACLK_PERI_PRE }
1707 	},
1708 	{
1709 		RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1710 		0, DIV(1, 0),
1711 		{ RK3328_ACLK_PERI_PRE }
1712 	},
1713 	{
1714 		RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
1715 		0, DIV(12, 8),
1716 		{ RK3328_XIN24M }
1717 	},
1718 	{
1719 		/* Sentinel */
1720 	}
1721 };
1722 
1723 void
1724 rk3328_init(struct rkclock_softc *sc)
1725 {
1726 	int i;
1727 
1728 	/* The code below assumes all clocks are enabled.  Check this!. */
1729 	for (i = 0; i <= 28; i++) {
1730 		if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1731 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1732 			    HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1733 		}
1734 	}
1735 
1736 	sc->sc_clocks = rk3328_clocks;
1737 }
1738 
1739 uint32_t
1740 rk3328_armclk_parent(uint32_t mux)
1741 {
1742 	switch (mux) {
1743 	case 0:
1744 		return RK3328_PLL_APLL;
1745 	case 1:
1746 		return RK3328_PLL_GPLL;
1747 	case 2:
1748 		return RK3328_PLL_DPLL;
1749 	case 3:
1750 		return RK3328_PLL_NPLL;
1751 	}
1752 
1753 	return 0;
1754 }
1755 
1756 uint32_t
1757 rk3328_get_armclk(struct rkclock_softc *sc)
1758 {
1759 	uint32_t reg, mux, div_con;
1760 	uint32_t idx;
1761 
1762 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1763 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1764 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1765 	div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1766 	    RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1767 	idx = rk3328_armclk_parent(mux);
1768 
1769 	return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1770 }
1771 
1772 int
1773 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1774 {
1775 	uint32_t reg, mux;
1776 	uint32_t old_freq, div;
1777 	uint32_t idx;
1778 
1779 	old_freq = rk3328_get_armclk(sc);
1780 	if (freq == old_freq)
1781 		return 0;
1782 
1783 	reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1784 	mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1785 	    RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1786 
1787 	/* Keep the pclk_dbg clock at or below 300 MHz. */
1788 	div = 1;
1789 	while (freq / (div + 1) > 300000000)
1790 		div++;
1791 	/* and make sure we use an odd divider. */
1792 	if ((div % 2) == 0)
1793 		div++;
1794 
1795 	/* When ramping up, set clock dividers first. */
1796 	if (freq > old_freq) {
1797 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1798 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1799 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1800 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1801 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1802 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1803 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1804 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1805 	}
1806 
1807 	/* We always use NPLL and force the switch below if needed. */
1808 	idx = RK3328_PLL_NPLL;
1809 	rk3328_set_frequency(sc, &idx, freq);
1810 
1811 	/* When ramping down, set clock dividers last. */
1812 	if (freq < old_freq || mux != 3) {
1813 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1814 		    RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1815 		    3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1816 		    RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1817 		    0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1818 		HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1819 		    RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1820 		    1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1821 		    RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1822 		    div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1823 	}
1824 
1825 	return 0;
1826 }
1827 
1828 uint32_t
1829 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1830 {
1831 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1832 	uint32_t dsmpd, fracdiv;
1833 	uint64_t frac = 0;
1834 	uint32_t reg;
1835 
1836 	reg = HREAD4(sc, base + 0x0000);
1837 	postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1838 	    RK3328_CRU_PLL_POSTDIV1_SHIFT;
1839 	fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1840 	    RK3328_CRU_PLL_FBDIV_SHIFT;
1841 	reg = HREAD4(sc, base + 0x0004);
1842 	dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1843 	postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1844 	    RK3328_CRU_PLL_POSTDIV2_SHIFT;
1845 	refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1846 	    RK3328_CRU_PLL_REFDIV_SHIFT;
1847 	reg = HREAD4(sc, base + 0x0008);
1848 	fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1849 	    RK3328_CRU_PLL_FRACDIV_SHIFT;
1850 
1851 	if (dsmpd == 0)
1852 		frac = (24000000ULL * fracdiv / refdiv) >> 24;
1853 	return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1854 }
1855 
1856 int
1857 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1858 {
1859 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1860 	int mode_shift = -1;
1861 
1862 	switch (base) {
1863 	case RK3328_CRU_APLL_CON(0):
1864 		mode_shift = 0;
1865 		break;
1866 	case RK3328_CRU_DPLL_CON(0):
1867 		mode_shift = 4;
1868 		break;
1869 	case RK3328_CRU_CPLL_CON(0):
1870 		mode_shift = 8;
1871 		break;
1872 	case RK3328_CRU_GPLL_CON(0):
1873 		mode_shift = 12;
1874 		break;
1875 	case RK3328_CRU_NPLL_CON(0):
1876 		mode_shift = 1;
1877 		break;
1878 	}
1879 	KASSERT(mode_shift != -1);
1880 
1881 	/*
1882 	 * It is not clear whether all combinations of the clock
1883 	 * dividers result in a stable clock.  Therefore this function
1884 	 * only supports a limited set of PLL clock rates.  For now
1885 	 * this set covers all the CPU frequencies supported by the
1886 	 * Linux kernel.
1887 	 */
1888 	switch (freq) {
1889 	case 1800000000U:
1890 	case 1704000000U:
1891 	case 1608000000U:
1892 	case 1512000000U:
1893 	case 1488000000U:
1894 	case 1416000000U:
1895 	case 1392000000U:
1896 	case 1296000000U:
1897 	case 1200000000U:
1898 	case 1104000000U:
1899 		postdiv1 = postdiv2 = refdiv = 1;
1900 		break;
1901 	case 1008000000U:
1902 	case 912000000U:
1903 	case 816000000U:
1904 	case 696000000U:
1905 		postdiv1 = 2; postdiv2 = refdiv = 1;
1906 		break;
1907 	case 600000000U:
1908 		postdiv1 = 3; postdiv2 = refdiv = 1;
1909 		break;
1910 	case 408000000U:
1911 	case 312000000U:
1912 		postdiv1 = postdiv2 = 2; refdiv = 1;
1913 		break;
1914 	case 216000000U:
1915 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1916 		break;
1917 	case 96000000U:
1918 		postdiv1 = postdiv2 = 4; refdiv = 1;
1919 		break;
1920 	default:
1921 		printf("%s: %u Hz\n", __func__, freq);
1922 		return -1;
1923 	}
1924 
1925 	/* Calculate feedback divider. */
1926 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1927 
1928 	/*
1929 	 * Select slow mode to guarantee a stable clock while we're
1930 	 * adjusting the PLL.
1931 	 */
1932 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1933 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1934 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1935 
1936 	/* Set PLL rate. */
1937 	HWRITE4(sc, base + 0x0000,
1938 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1939 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1940 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
1941 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1942 	HWRITE4(sc, base + 0x0004,
1943 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1944 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1945 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1946 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
1947 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1948 
1949 	/* Wait for PLL to stabilize. */
1950 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1951 		delay(10);
1952 
1953 	/* Switch back to normal mode. */
1954 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
1955 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
1956 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1957 
1958 	return 0;
1959 }
1960 
1961 int
1962 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1963 {
1964 	uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
1965 	int mode_shift = -1;
1966 	uint32_t reg;
1967 
1968 	switch (base) {
1969 	case RK3328_CRU_APLL_CON(0):
1970 		mode_shift = 0;
1971 		break;
1972 	case RK3328_CRU_DPLL_CON(0):
1973 		mode_shift = 4;
1974 		break;
1975 	case RK3328_CRU_CPLL_CON(0):
1976 		mode_shift = 8;
1977 		break;
1978 	case RK3328_CRU_GPLL_CON(0):
1979 		mode_shift = 12;
1980 		break;
1981 	case RK3328_CRU_NPLL_CON(0):
1982 		mode_shift = 1;
1983 		break;
1984 	}
1985 	KASSERT(mode_shift != -1);
1986 
1987 	/*
1988 	 * It is not clear whether all combinations of the clock
1989 	 * dividers result in a stable clock.  Therefore this function
1990 	 * only supports a limited set of PLL clock rates.  This set
1991 	 * set covers all the fractional PLL frequencies supported by
1992 	 * the Linux kernel.
1993 	 */
1994 	switch (freq) {
1995 	case 1016064000U:
1996 		postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
1997 		break;
1998 	case 983040000U:
1999 		postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
2000 		break;
2001 	case 491520000U:
2002 		postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
2003 		break;
2004 	case 61440000U:
2005 		postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
2006 		break;
2007 	case 56448000U:
2008 		postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
2009 		break;
2010 	case 40960000U:
2011 		postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
2012 		break;
2013 	default:
2014 		printf("%s: %u Hz\n", __func__, freq);
2015 		return -1;
2016 	}
2017 
2018 	/* Calculate feedback divider. */
2019 	fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
2020 
2021 	/*
2022 	 * Select slow mode to guarantee a stable clock while we're
2023 	 * adjusting the PLL.
2024 	 */
2025 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
2026 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
2027 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
2028 
2029 	/* Set PLL rate. */
2030 	HWRITE4(sc, base + 0x0000,
2031 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
2032 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
2033 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
2034 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
2035 	HWRITE4(sc, base + 0x0004,
2036 	    RK3328_CRU_PLL_DSMPD << 16 |
2037 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
2038 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
2039 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
2040 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
2041 	reg = HREAD4(sc, base + 0x0008);
2042 	reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
2043 	reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
2044 	HWRITE4(sc, base + 0x0008, reg);
2045 
2046 	/* Wait for PLL to stabilize. */
2047 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
2048 		delay(10);
2049 
2050 	/* Switch back to normal mode. */
2051 	HWRITE4(sc, RK3328_CRU_CRU_MODE,
2052 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
2053 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
2054 
2055 	return 0;
2056 }
2057 
2058 uint32_t
2059 rk3328_get_frequency(void *cookie, uint32_t *cells)
2060 {
2061 	struct rkclock_softc *sc = cookie;
2062 	uint32_t idx = cells[0];
2063 	uint32_t reg;
2064 
2065 	switch (idx) {
2066 	case RK3328_PLL_APLL:
2067 		return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
2068 	case RK3328_PLL_DPLL:
2069 		return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
2070 	case RK3328_PLL_CPLL:
2071 		return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
2072 	case RK3328_PLL_GPLL:
2073 		return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
2074 	case RK3328_PLL_NPLL:
2075 		return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
2076 	case RK3328_ARMCLK:
2077 		return rk3328_get_armclk(sc);
2078 	case RK3328_XIN24M:
2079 		return 24000000;
2080 	case RK3328_GMAC_CLKIN:
2081 		return 125000000;
2082 	/*
2083 	 * XXX The HDMIPHY and USB480M clocks are external.  Returning
2084 	 * zero here will cause them to be ignored for reparenting
2085 	 * purposes.
2086 	 */
2087 	case RK3328_HDMIPHY:
2088 		return 0;
2089 	case RK3328_USB480M:
2090 		return 0;
2091 	case RK3328_CLK_MAC2IO:
2092 		reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
2093 		if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
2094 			idx = RK3328_GMAC_CLKIN;
2095 		else
2096 			idx = RK3328_CLK_MAC2IO_SRC;
2097 		return rk3328_get_frequency(sc, &idx);
2098 	default:
2099 		break;
2100 	}
2101 
2102 	return rkclock_get_frequency(sc, idx);
2103 }
2104 
2105 int
2106 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2107 {
2108 	struct rkclock_softc *sc = cookie;
2109 	uint32_t idx = cells[0];
2110 	uint32_t reg, mux;
2111 
2112 	switch (idx) {
2113 	case RK3328_PLL_APLL:
2114 		return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
2115 	case RK3328_PLL_DPLL:
2116 		return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
2117 	case RK3328_PLL_CPLL:
2118 		return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
2119 	case RK3328_PLL_GPLL:
2120 		return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
2121 	case RK3328_PLL_NPLL:
2122 		return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
2123 	case RK3328_ARMCLK:
2124 		return rk3328_set_armclk(sc, freq);
2125 	case RK3328_CLK_UART0:
2126 	case RK3328_CLK_UART1:
2127 	case RK3328_CLK_UART2:
2128 		if (freq == rk3328_get_frequency(sc, &idx))
2129 			return 0;
2130 		break;
2131 	case RK3328_DCLK_LCDC:
2132 		reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
2133 		mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
2134 		    RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
2135 		idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
2136 		return rk3328_set_frequency(sc, &idx, freq);
2137 	case RK3328_HCLK_CRYPTO_SLV:
2138 		idx = RK3328_HCLK_BUS_PRE;
2139 		return rk3328_set_frequency(sc, &idx, freq);
2140 	default:
2141 		break;
2142 	}
2143 
2144 	return rkclock_set_frequency(sc, idx, freq);
2145 }
2146 
2147 int
2148 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
2149 {
2150 	struct rkclock_softc *sc = cookie;
2151 	uint32_t idx = cells[0];
2152 	uint32_t parent;
2153 
2154 	if (pcells[0] == sc->sc_phandle)
2155 		parent = pcells[1];
2156 	else {
2157 		char name[32];
2158 		int node;
2159 
2160 		node = OF_getnodebyphandle(pcells[0]);
2161 		if (node == 0)
2162 			return -1;
2163 		name[0] = 0;
2164 		OF_getprop(node, "clock-output-names", name, sizeof(name));
2165 		name[sizeof(name) - 1] = 0;
2166 		if (strcmp(name, "xin24m") == 0)
2167 			parent = RK3328_XIN24M;
2168 		else if (strcmp(name, "gmac_clkin") == 0)
2169 			parent = RK3328_GMAC_CLKIN;
2170 		else
2171 			return -1;
2172 	}
2173 
2174 	switch (idx) {
2175 	case RK3328_CLK_MAC2IO:
2176 		if (parent == RK3328_GMAC_CLKIN) {
2177 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2178 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
2179 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
2180 		} else {
2181 			regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2182 			    RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
2183 		}
2184 		return 0;
2185 	case RK3328_CLK_MAC2IO_EXT:
2186 		if (parent == RK3328_GMAC_CLKIN) {
2187 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2188 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
2189 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
2190 		} else {
2191 			regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2192 			    RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
2193 		}
2194 		return 0;
2195 	}
2196 
2197 	return rkclock_set_parent(sc, idx, parent);
2198 }
2199 
2200 void
2201 rk3328_enable(void *cookie, uint32_t *cells, int on)
2202 {
2203 	uint32_t idx = cells[0];
2204 
2205 	/*
2206 	 * All clocks are enabled by default, so there is nothing for
2207 	 * us to do until we start disabling clocks.
2208 	 */
2209 	if (!on)
2210 		printf("%s: 0x%08x\n", __func__, idx);
2211 }
2212 
2213 void
2214 rk3328_reset(void *cookie, uint32_t *cells, int on)
2215 {
2216 	struct rkclock_softc *sc = cookie;
2217 	uint32_t idx = cells[0];
2218 	uint32_t mask = (1 << (idx % 16));
2219 
2220 	HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
2221 	    mask << 16 | (on ? mask : 0));
2222 }
2223 
2224 /*
2225  * Rockchip RK3399
2226  */
2227 
2228 const struct rkclock rk3399_clocks[] = {
2229 	{
2230 		RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
2231 		SEL(7, 7), DIV(6, 0),
2232 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2233 	},
2234 	{
2235 		RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
2236 		SEL(7, 7), DIV(6, 0),
2237 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2238 	},
2239 	{
2240 		RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
2241 		SEL(7, 7), DIV(6, 0),
2242 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2243 	},
2244 	{
2245 		RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
2246 		SEL(15, 15), DIV(14, 8),
2247 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2248 	},
2249 	{
2250 		RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
2251 		SEL(15, 15), DIV(14, 8),
2252 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2253 	},
2254 	{
2255 		RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
2256 		SEL(15, 15), DIV(14, 8),
2257 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2258 	},
2259 	{
2260 		RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
2261 		SEL(10, 8), DIV(6, 0),
2262 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2263 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2264 		  RK3399_XIN24M }
2265 	},
2266 	{
2267 		RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
2268 		SEL(10, 8), DIV(6, 0),
2269 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2270 		  /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2271 		  RK3399_XIN24M }
2272 	},
2273 	{
2274 		RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22),
2275 		SEL(10, 8), DIV(6, 0),
2276 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2277 		  /* RK3399_USB_480M */ 0, RK3399_XIN24M }
2278 	},
2279 	{
2280 		RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27),
2281 		SEL(15, 15), DIV(9, 0),
2282 		{ RK3399_XIN24M, RK3399_CLK_32K }
2283 	},
2284 	{
2285 		RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
2286 		SEL(9, 8), 0,
2287 		{ 0, 0, RK3399_XIN24M }
2288 	},
2289 	{
2290 		RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
2291 		SEL(9, 8), 0,
2292 		{ 0, 0, RK3399_XIN24M }
2293 	},
2294 	{
2295 		RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
2296 		SEL(9, 8), 0,
2297 		{ 0, 0, RK3399_XIN24M }
2298 	},
2299 	{
2300 		RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
2301 		SEL(9, 8), 0,
2302 		{ 0, 0, RK3399_XIN24M }
2303 	},
2304 	{
2305 		RK3399_CLK_I2S0_8CH, RK3399_CRU_CLKSEL_CON(28),
2306 		SEL(9, 8), 0,
2307 		{ RK3399_CLK_I2S0_DIV, RK3399_CLK_I2S0_FRAC, 0, RK3399_XIN12M },
2308 		SET_PARENT
2309 	},
2310 	{
2311 		RK3399_CLK_I2S1_8CH, RK3399_CRU_CLKSEL_CON(29),
2312 		SEL(9, 8), 0,
2313 		{ RK3399_CLK_I2S1_DIV, RK3399_CLK_I2S1_FRAC, 0, RK3399_XIN12M },
2314 		SET_PARENT
2315 	},
2316 	{
2317 		RK3399_CLK_I2S2_8CH, RK3399_CRU_CLKSEL_CON(30),
2318 		SEL(9, 8), 0,
2319 		{ RK3399_CLK_I2S2_DIV, RK3399_CLK_I2S2_FRAC, 0, RK3399_XIN12M },
2320 		SET_PARENT
2321 	},
2322 	{
2323 		RK3399_CLK_I2S_8CH_OUT, RK3399_CRU_CLKSEL_CON(31),
2324 		SEL(2, 2), 0,
2325 		{ RK3399_CLK_I2SOUT_SRC, RK3399_XIN12M },
2326 		SET_PARENT
2327 	},
2328 	{
2329 		RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
2330 		SEL(15, 14), DIV(12, 8),
2331 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
2332 	},
2333 	{
2334 		RK3399_CLK_UPHY0_TCPDCORE, RK3399_CRU_CLKSEL_CON(64),
2335 		SEL(7, 6), DIV(4, 0),
2336 		{ RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL,
2337 		  RK3399_PLL_GPLL }
2338 	},
2339 	{
2340 		RK3399_CLK_UPHY1_TCPDCORE, RK3399_CRU_CLKSEL_CON(65),
2341 		SEL(7, 6), DIV(4, 0),
2342 		{ RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL,
2343 		  RK3399_PLL_GPLL }
2344 	},
2345 	{
2346 		RK3399_CLK_PCIEPHY_REF, RK3399_CRU_CLKSEL_CON(18),
2347 		SEL(10, 10), 0,
2348 		{ RK3399_XIN24M, RK3399_CLK_PCIEPHY_REF100M },
2349 		SET_PARENT
2350 	},
2351 	{
2352 		RK3399_CLK_PCIEPHY_REF100M, RK3399_CRU_CLKSEL_CON(18),
2353 		0, DIV(15, 11),
2354 		{ RK3399_PLL_NPLL }
2355 	},
2356 	{
2357 		RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49),
2358 		SEL(11, 11), 0,
2359 		{ RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC },
2360 		SET_PARENT
2361 	},
2362 	{
2363 		RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50),
2364 		SEL(11, 11), 0,
2365 		{ RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC },
2366 		SET_PARENT
2367 	},
2368 	{
2369 		RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49),
2370 		SEL(9, 8), DIV(7, 0),
2371 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2372 	},
2373 	{
2374 		RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50),
2375 		SEL(9, 8), DIV(7, 0),
2376 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2377 	},
2378 	{
2379 		RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2380 		SEL(7, 7), DIV(4, 0),
2381 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2382 	},
2383 	{
2384 		RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2385 		SEL(7, 7), DIV(4, 0),
2386 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2387 	},
2388 	{
2389 		RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
2390 		SEL(7, 6), DIV(4, 0),
2391 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2392 	},
2393 	{
2394 		RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
2395 		SEL(7, 6), DIV(4, 0),
2396 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2397 		  RK3399_PLL_VPLL }
2398 	},
2399 	{
2400 		RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2401 		SEL(7, 6), DIV(4, 0),
2402 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2403 		  RK3399_PLL_NPLL }
2404 	},
2405 	{
2406 		RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2407 		SEL(7, 6), DIV(4, 0),
2408 		{ RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2409 		  RK3399_PLL_NPLL }
2410 	},
2411 	{
2412 		RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
2413 		SEL(15, 14), DIV(12, 8),
2414 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2415 	},
2416 	{
2417 		RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
2418 		SEL(15, 15), DIV(12, 8),
2419 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2420 	},
2421 	{
2422 		RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2423 		0, DIV(14, 12),
2424 		{ RK3399_ACLK_PERIPH }
2425 	},
2426 	{
2427 		RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2428 		0, DIV(14, 12),
2429 		{ RK3399_ACLK_PERILP0 }
2430 	},
2431 	{
2432 		RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2433 		0, DIV(10, 8),
2434 		{ RK3399_HCLK_PERILP1 }
2435 	},
2436 	{
2437 		RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
2438 		SEL(15, 15), DIV(12, 8),
2439 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2440 	},
2441 	{
2442 		RK3399_PCLK_WDT, RK3399_CRU_CLKSEL_CON(57),
2443 		0, DIV(4, 0),
2444 		{ RK3399_PLL_GPLL }
2445 	},
2446 	{
2447 		RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2448 		0, DIV(9, 8),
2449 		{ RK3399_ACLK_PERIPH }
2450 	},
2451 	{
2452 		RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2453 		0, DIV(9, 8),
2454 		{ RK3399_ACLK_PERILP0 }
2455 	},
2456 	{
2457 		RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2458 		SEL(7, 7), DIV(4, 0),
2459 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2460 	},
2461 	{
2462 		RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
2463 		SEL(15, 15), DIV(12, 8),
2464 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2465 	},
2466 	{
2467 		RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2468 		0, DIV(12, 8),
2469 		{ RK3399_ACLK_VOP0 }
2470 	},
2471 	{
2472 		RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2473 		0, DIV(12, 8),
2474 		{ RK3399_ACLK_VOP1 }
2475 	},
2476 	{
2477 		RK3399_CLK_I2S0_DIV, RK3399_CRU_CLKSEL_CON(28),
2478 		SEL(7, 7), DIV(6, 0),
2479 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2480 	},
2481 	{
2482 		RK3399_CLK_I2S1_DIV, RK3399_CRU_CLKSEL_CON(29),
2483 		SEL(7, 7), DIV(6, 0),
2484 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2485 	},
2486 	{
2487 		RK3399_CLK_I2S2_DIV, RK3399_CRU_CLKSEL_CON(30),
2488 		SEL(7, 7), DIV(6, 0),
2489 		{ RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2490 	},
2491 	{
2492 		RK3399_CLK_I2SOUT_SRC, RK3399_CRU_CLKSEL_CON(31),
2493 		SEL(1, 0), 0,
2494 		{ RK3399_CLK_I2S0_8CH, RK3399_CLK_I2S1_8CH,
2495 		  RK3399_CLK_I2S2_8CH },
2496 		SET_PARENT
2497 	},
2498 	{
2499 		/* Sentinel */
2500 	}
2501 };
2502 
2503 /* Some of our parent clocks live in the PMUCRU. */
2504 struct rkclock_softc *rk3399_pmucru_sc;
2505 
2506 void
2507 rk3399_init(struct rkclock_softc *sc)
2508 {
2509 	int i;
2510 
2511 	/* PMUCRU instance should attach before us. */
2512 	KASSERT(rk3399_pmucru_sc != NULL);
2513 
2514 	/*
2515 	 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
2516 	 * module is buggy and sets the parent of the clock for the
2517 	 * "big" cluster to LPLL.  Undo that mistake here such that
2518 	 * the clocks of both clusters are independent.
2519 	 */
2520 	HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
2521 	    RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
2522 	    RK3399_CRU_CORE_PLL_SEL_BPLL);
2523 
2524 	/* The code below assumes all clocks are enabled.  Check this!. */
2525 	for (i = 0; i <= 34; i++) {
2526 		if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
2527 			printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
2528 			    HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
2529 		}
2530 	}
2531 
2532 	sc->sc_clocks = rk3399_clocks;
2533 }
2534 
2535 uint32_t
2536 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
2537 {
2538 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2539 	uint32_t pll_work_mode;
2540 	uint32_t reg;
2541 
2542 	reg = HREAD4(sc, base + 0x000c);
2543 	pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
2544 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
2545 		return 24000000;
2546 	if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
2547 		return 32768;
2548 
2549 	reg = HREAD4(sc, base + 0x0000);
2550 	fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
2551 	    RK3399_CRU_PLL_FBDIV_SHIFT;
2552 	reg = HREAD4(sc, base + 0x0004);
2553 	postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
2554 	    RK3399_CRU_PLL_POSTDIV2_SHIFT;
2555 	postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
2556 	    RK3399_CRU_PLL_POSTDIV1_SHIFT;
2557 	refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
2558 	    RK3399_CRU_PLL_REFDIV_SHIFT;
2559 	return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
2560 }
2561 
2562 int
2563 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
2564 {
2565 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2566 
2567 	/*
2568 	 * It is not clear whether all combinations of the clock
2569 	 * dividers result in a stable clock.  Therefore this function
2570 	 * only supports a limited set of PLL clock rates.  For now
2571 	 * this set covers all the CPU frequencies supported by the
2572 	 * Linux kernel.
2573 	 */
2574 	switch (freq) {
2575 	case 2208000000U:
2576 	case 2184000000U:
2577 	case 2088000000U:
2578 	case 2040000000U:
2579 	case 2016000000U:
2580 	case 1992000000U:
2581 	case 1896000000U:
2582 	case 1800000000U:
2583 	case 1704000000U:
2584 	case 1608000000U:
2585 	case 1512000000U:
2586 	case 1488000000U:
2587 	case 1416000000U:
2588 	case 1200000000U:
2589 		postdiv1 = postdiv2 = refdiv = 1;
2590 		break;
2591 	case 1008000000U:
2592 	case 816000000U:
2593 	case 696000000U:
2594 		postdiv1 = 2; postdiv2 = refdiv = 1;
2595 		break;
2596 	case 676000000U:
2597 		postdiv1 = 2; postdiv2 = 1; refdiv = 3;
2598 		break;
2599 	case 1000000000U:
2600 	case 800000000U:
2601 	case 600000000U:
2602 		postdiv1 = 3; postdiv2 = refdiv = 1;
2603 		break;
2604 	case 594000000U:
2605 		postdiv1 = 4; postdiv2 = refdiv = 1;
2606 		break;
2607 	case 408000000U:
2608 		postdiv1 = postdiv2 = 2; refdiv = 1;
2609 		break;
2610 	case 297000000U:
2611 	case 216000000U:
2612 		postdiv1 = 4; postdiv2 = 2; refdiv = 1;
2613 		break;
2614 	case 148500000U:
2615 	case 96000000U:
2616 		postdiv1 = postdiv2 = 4; refdiv = 1;
2617 		break;
2618 	case 74250000U:
2619 		postdiv1 = postdiv2 = 4; refdiv = 2;
2620 		break;
2621 	case 65000000U:
2622 	case 54000000U:
2623 	case 27000000U:
2624 		postdiv1 = 6; postdiv2 = 4; refdiv = 1;
2625 		break;
2626 	default:
2627 		printf("%s: %d Hz\n", __func__, freq);
2628 		return -1;
2629 	}
2630 
2631 	/* Calculate feedback divider. */
2632 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
2633 
2634 	/*
2635 	 * Select slow mode to guarantee a stable clock while we're
2636 	 * adjusting the PLL.
2637 	 */
2638 	HWRITE4(sc, base + 0x000c,
2639 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2640 	    RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
2641 
2642 	/* Set PLL rate. */
2643 	HWRITE4(sc, base + 0x0000,
2644 	    RK3399_CRU_PLL_FBDIV_MASK << 16 |
2645 	    fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
2646 	HWRITE4(sc, base + 0x0004,
2647 	    RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
2648 	    postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
2649 	    RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
2650 	    postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
2651 	    RK3399_CRU_PLL_REFDIV_MASK << 16 |
2652 	    refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
2653 
2654 	/* Wait for PLL to stabilize. */
2655 	while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
2656 		delay(10);
2657 
2658 	/* Switch back to normal mode. */
2659 	HWRITE4(sc, base + 0x000c,
2660 	    RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2661 	    RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
2662 
2663 	return 0;
2664 }
2665 
2666 uint32_t
2667 rk3399_armclk_parent(uint32_t mux)
2668 {
2669 	switch (mux) {
2670 	case 0:
2671 		return RK3399_PLL_ALPLL;
2672 	case 1:
2673 		return RK3399_PLL_ABPLL;
2674 	case 2:
2675 		return RK3399_PLL_DPLL;
2676 	case 3:
2677 		return RK3399_PLL_GPLL;
2678 	}
2679 
2680 	return 0;
2681 }
2682 
2683 uint32_t
2684 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
2685 {
2686 	uint32_t reg, mux, div_con;
2687 	uint32_t idx;
2688 
2689 	reg = HREAD4(sc, clksel);
2690 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2691 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
2692 	div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
2693 	    RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
2694 	idx = rk3399_armclk_parent(mux);
2695 
2696 	return rk3399_get_frequency(sc, &idx) / (div_con + 1);
2697 }
2698 
2699 int
2700 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
2701 {
2702 	uint32_t reg, mux;
2703 	uint32_t old_freq, div;
2704 	uint32_t idx;
2705 
2706 	old_freq = rk3399_get_armclk(sc, clksel);
2707 	if (freq == old_freq)
2708 		return 0;
2709 
2710 	reg = HREAD4(sc, clksel);
2711 	mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2712 	    RK3399_CRU_CORE_PLL_SEL_SHIFT;
2713 	idx = rk3399_armclk_parent(mux);
2714 
2715 	/* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
2716 	div = 1;
2717 	while (freq / (div + 1) > 200000000)
2718 		div++;
2719 
2720 	/* When ramping up, set clock dividers first. */
2721 	if (freq > old_freq) {
2722 		HWRITE4(sc, clksel,
2723 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2724 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2725 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2726 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2727 		HWRITE4(sc, clksel + 0x0004,
2728 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2729 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2730 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2731 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2732 	}
2733 
2734 	rk3399_set_frequency(sc, &idx, freq);
2735 
2736 	/* When ramping down, set clock dividers last. */
2737 	if (freq < old_freq) {
2738 		HWRITE4(sc, clksel,
2739 		    RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2740 		    0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2741 		    RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2742 		    1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2743 		HWRITE4(sc, clksel + 0x0004,
2744 		    RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2745 		    div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2746 		    RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2747 		    div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2748 	}
2749 
2750 	return 0;
2751 }
2752 
2753 uint32_t
2754 rk3399_get_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base)
2755 {
2756 	uint32_t parent_freq, frac;
2757 	uint16_t n, d;
2758 
2759 	frac = HREAD4(sc, base);
2760 	n = frac >> 16;
2761 	d = frac & 0xffff;
2762 	if (n == 0 || d == 0)
2763 		n = d = 1;
2764 	parent_freq = sc->sc_cd.cd_get_frequency(sc, &parent);
2765 	return ((uint64_t)parent_freq * n) / d;
2766 }
2767 
2768 int
2769 rk3399_set_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base,
2770     uint32_t freq)
2771 {
2772 	uint32_t n, d;
2773 	uint32_t p0, p1, p2;
2774 	uint32_t q0, q1, q2;
2775 	uint32_t a, tmp;
2776 
2777 	n = freq;
2778 	d = sc->sc_cd.cd_get_frequency(sc, &parent);
2779 
2780 	/*
2781 	 * The denominator needs to be at least 20 times the numerator
2782 	 * for a stable clock.
2783 	 */
2784 	if (n == 0 || d == 0 || d < 20 * n)
2785 		return -1;
2786 
2787 	/*
2788 	 * This is a simplified implementation of the algorithm to
2789 	 * calculate the best rational approximation using continued
2790 	 * fractions.
2791 	 */
2792 
2793 	p0 = q1 = 0;
2794 	p1 = q0 = 1;
2795 
2796 	while (d != 0) {
2797 		/*
2798 		 * Calculate next coefficient in the continued
2799 		 * fraction and keep track of the remainder.
2800 		 */
2801 		tmp = d;
2802 		a = n / d;
2803 		d = n % d;
2804 		n = tmp;
2805 
2806 		/*
2807 		 * Calculate next approximation in the series based on
2808 		 * the current coefficient.
2809 		 */
2810 		p2 = p0 + a * p1;
2811 		q2 = q0 + a * q1;
2812 
2813 		/*
2814 		 * Terminate if we reached the maximum allowed
2815 		 * denominator.
2816 		 */
2817 		if (q2 > 0xffff)
2818 			break;
2819 
2820 		p0 = p1; p1 = p2;
2821 		q0 = q1; q1 = q2;
2822 	}
2823 
2824 	HWRITE4(sc, base, p1 << 16 | q1);
2825 	return 0;
2826 }
2827 
2828 uint32_t
2829 rk3399_get_frequency(void *cookie, uint32_t *cells)
2830 {
2831 	struct rkclock_softc *sc = cookie;
2832 	uint32_t idx = cells[0];
2833 
2834 	switch (idx) {
2835 	case RK3399_PLL_ALPLL:
2836 		return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
2837 	case RK3399_PLL_ABPLL:
2838 		return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
2839 	case RK3399_PLL_DPLL:
2840 		return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
2841 	case RK3399_PLL_CPLL:
2842 		return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
2843 	case RK3399_PLL_GPLL:
2844 		return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
2845 	case RK3399_PLL_NPLL:
2846 		return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
2847 	case RK3399_PLL_VPLL:
2848 		return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
2849 	case RK3399_ARMCLKL:
2850 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
2851 	case RK3399_ARMCLKB:
2852 		return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
2853 	case RK3399_XIN24M:
2854 		return 24000000;
2855 	case RK3399_CLK_32K:
2856 		return 32768;
2857 	case RK3399_XIN12M:
2858 		return 12000000;
2859 	case RK3399_CLK_I2S0_FRAC:
2860 		return rk3399_get_frac(sc, RK3399_CLK_I2S0_DIV,
2861 		    RK3399_CRU_CLKSEL_CON(96));
2862 	case RK3399_CLK_I2S1_FRAC:
2863 		return rk3399_get_frac(sc, RK3399_CLK_I2S1_DIV,
2864 		    RK3399_CRU_CLKSEL_CON(97));
2865 	case RK3399_CLK_I2S2_FRAC:
2866 		return rk3399_get_frac(sc, RK3399_CLK_I2S2_DIV,
2867 		    RK3399_CRU_CLKSEL_CON(98));
2868 	default:
2869 		break;
2870 	}
2871 
2872 	return rkclock_get_frequency(sc, idx);
2873 }
2874 
2875 int
2876 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2877 {
2878 	struct rkclock_softc *sc = cookie;
2879 	uint32_t idx = cells[0];
2880 
2881 	switch (idx) {
2882 	case RK3399_PLL_ALPLL:
2883 		return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
2884 	case RK3399_PLL_ABPLL:
2885 		return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
2886 	case RK3399_PLL_CPLL:
2887 		return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
2888 	case RK3399_PLL_GPLL:
2889 		return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
2890 	case RK3399_PLL_NPLL:
2891 		return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
2892 	case RK3399_PLL_VPLL:
2893 		return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq);
2894 	case RK3399_ARMCLKL:
2895 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
2896 	case RK3399_ARMCLKB:
2897 		return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
2898 	case RK3399_CLK_I2S0_8CH:
2899 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S0_FRAC);
2900 		return rkclock_set_frequency(sc, idx, freq);
2901 	case RK3399_CLK_I2S1_8CH:
2902 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S1_FRAC);
2903 		return rkclock_set_frequency(sc, idx, freq);
2904 	case RK3399_CLK_I2S2_8CH:
2905 		rkclock_set_parent(sc, idx, RK3399_CLK_I2S2_FRAC);
2906 		return rkclock_set_frequency(sc, idx, freq);
2907 	case RK3399_XIN12M:
2908 		if (freq / (1000 * 1000) != 12)
2909 			return -1;
2910 		return 0;
2911 	case RK3399_CLK_I2S0_FRAC:
2912 		return rk3399_set_frac(sc, RK3399_CLK_I2S0_DIV,
2913 		    RK3399_CRU_CLKSEL_CON(96), freq);
2914 	case RK3399_CLK_I2S1_FRAC:
2915 		return rk3399_set_frac(sc, RK3399_CLK_I2S1_DIV,
2916 		    RK3399_CRU_CLKSEL_CON(97), freq);
2917 	case RK3399_CLK_I2S2_FRAC:
2918 		return rk3399_set_frac(sc, RK3399_CLK_I2S2_DIV,
2919 		    RK3399_CRU_CLKSEL_CON(98), freq);
2920 	default:
2921 		break;
2922 	}
2923 
2924 	return rkclock_set_frequency(sc, idx, freq);
2925 }
2926 
2927 
2928 int
2929 rk3399_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
2930 {
2931 	struct rkclock_softc *sc = cookie;
2932 
2933 	if (pcells[0] != sc->sc_phandle)
2934 		return -1;
2935 
2936 	return rkclock_set_parent(sc, cells[0], pcells[1]);
2937 }
2938 
2939 void
2940 rk3399_enable(void *cookie, uint32_t *cells, int on)
2941 {
2942 	struct rkclock_softc *sc = cookie;
2943 	uint32_t idx = cells[0];
2944 
2945 	/*
2946 	 * All clocks are enabled upon hardware reset, but on some boards the
2947 	 * firmware will disable some of them.  Handle those here.
2948 	 */
2949 	if (!on) {
2950 		printf("%s: 0x%08x\n", __func__, idx);
2951 		return;
2952 	}
2953 
2954 	switch (idx) {
2955 	case RK3399_CLK_USB2PHY0_REF:
2956 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (5 << 0) << 16);
2957 		break;
2958 	case RK3399_CLK_USB2PHY1_REF:
2959 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (6 << 0) << 16);
2960 		break;
2961 	case RK3399_CLK_UPHY0_TCPDPHY_REF:
2962 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (4 << 0) << 16);
2963 		break;
2964 	case RK3399_CLK_UPHY0_TCPDCORE:
2965 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (5 << 0) << 16);
2966 		break;
2967 	case RK3399_CLK_UPHY1_TCPDPHY_REF:
2968 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (6 << 0) << 16);
2969 		break;
2970 	case RK3399_CLK_UPHY1_TCPDCORE:
2971 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (7 << 0) << 16);
2972 		break;
2973 	case RK3399_ACLK_GMAC:
2974 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 0) << 16);
2975 		break;
2976 	case RK3399_PCLK_GMAC:
2977 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 2) << 16);
2978 		break;
2979 	case RK3399_CLK_MAC:
2980 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 5) << 16);
2981 		break;
2982 	case RK3399_CLK_MAC_RX:
2983 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 8) << 16);
2984 		break;
2985 	case RK3399_CLK_MAC_TX:
2986 		HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 9) << 16);
2987 		break;
2988 	}
2989 }
2990 
2991 void
2992 rk3399_reset(void *cookie, uint32_t *cells, int on)
2993 {
2994 	struct rkclock_softc *sc = cookie;
2995 	uint32_t idx = cells[0];
2996 	uint32_t mask = (1 << (idx % 16));
2997 
2998 	HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
2999 	    mask << 16 | (on ? mask : 0));
3000 }
3001 
3002 /* PMUCRU */
3003 
3004 const struct rkclock rk3399_pmu_clocks[] = {
3005 	{
3006 		RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
3007 		0, DIV(6, 0),
3008 		{ RK3399_PLL_PPLL }
3009 	},
3010 	{
3011 		RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
3012 		0, DIV(6, 0),
3013 		{ RK3399_PLL_PPLL }
3014 	},
3015 	{
3016 		RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
3017 		0, DIV(14, 8),
3018 		{ RK3399_PLL_PPLL }
3019 	},
3020 	{
3021 		RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0),
3022 		0, DIV(6, 0),
3023 		{ RK3399_PLL_PPLL }
3024 	},
3025 	{
3026 		/* Sentinel */
3027 	}
3028 };
3029 
3030 void
3031 rk3399_pmu_init(struct rkclock_softc *sc)
3032 {
3033 	sc->sc_clocks = rk3399_pmu_clocks;
3034 	rk3399_pmucru_sc = sc;
3035 }
3036 
3037 uint32_t
3038 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
3039 {
3040 	struct rkclock_softc *sc = cookie;
3041 	uint32_t idx = cells[0];
3042 
3043 	switch (idx) {
3044 	case RK3399_PLL_PPLL:
3045 		return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
3046 	default:
3047 		break;
3048 	}
3049 
3050 	return rkclock_get_frequency(sc, idx);
3051 }
3052 
3053 int
3054 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3055 {
3056 	struct rkclock_softc *sc = cookie;
3057 	uint32_t idx = cells[0];
3058 
3059 	switch (idx) {
3060 	case RK3399_PLL_PPLL:
3061 		return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
3062 	default:
3063 		break;
3064 	}
3065 
3066 	return rkclock_set_frequency(sc, idx, freq);
3067 }
3068 
3069 void
3070 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
3071 {
3072 	uint32_t idx = cells[0];
3073 
3074 	switch (idx) {
3075 	case RK3399_CLK_I2C0:
3076 	case RK3399_CLK_I2C4:
3077 	case RK3399_CLK_I2C8:
3078 	case RK3399_PCLK_I2C0:
3079 	case RK3399_PCLK_I2C4:
3080 	case RK3399_PCLK_I2C8:
3081 	case RK3399_PCLK_RKPWM:
3082 		/* Enabled by default. */
3083 		break;
3084 	default:
3085 		printf("%s: 0x%08x\n", __func__, idx);
3086 		break;
3087 	}
3088 }
3089 
3090 void
3091 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
3092 {
3093 	uint32_t idx = cells[0];
3094 
3095 	printf("%s: 0x%08x\n", __func__, idx);
3096 }
3097 
3098 /*
3099  * Rockchip RK3568
3100  */
3101 
3102 const struct rkclock rk3568_clocks[] = {
3103 	{
3104 		RK3568_BCLK_EMMC, RK3568_CRU_CLKSEL_CON(28),
3105 		SEL(9, 8), 0,
3106 		{ RK3568_GPLL_200M, RK3568_GPLL_150M, RK3568_CPLL_125M }
3107 	},
3108 	{
3109 		RK3568_CCLK_EMMC, RK3568_CRU_CLKSEL_CON(28),
3110 		SEL(14, 12), 0,
3111 		{ RK3568_XIN24M, RK3568_GPLL_200M, RK3568_GPLL_150M,
3112 		  RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_375K }
3113 	},
3114 	{
3115 		RK3568_TCLK_EMMC, 0, 0, 0,
3116 		{ RK3568_XIN24M }
3117 	},
3118 
3119 	{
3120 		RK3568_ACLK_PHP, RK3568_CRU_CLKSEL_CON(30),
3121 		SEL(1, 0), 0,
3122 		{ RK3568_GPLL_300M, RK3568_GPLL_200M,
3123 		  RK3568_GPLL_100M, RK3568_XIN24M }
3124 	},
3125 	{
3126 		RK3568_PCLK_PHP, RK3568_CRU_CLKSEL_CON(30),
3127 		0, DIV(7, 4),
3128 		{ RK3568_ACLK_PHP }
3129 	},
3130 	{
3131 		RK3568_CLK_SDMMC0, RK3568_CRU_CLKSEL_CON(30),
3132 		SEL(10, 8), 0,
3133 		{ RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3134 		  RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3135 	},
3136 	{
3137 		RK3568_CLK_SDMMC1, RK3568_CRU_CLKSEL_CON(30),
3138 		SEL(14, 12), 0,
3139 		{ RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3140 		  RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3141 	},
3142 	{
3143 		RK3568_CLK_SDMMC2, RK3568_CRU_CLKSEL_CON(32),
3144 		SEL(10, 8), 0,
3145 		{ RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3146 		  RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3147 	},
3148 	{
3149 		RK3568_ACLK_GMAC0, 0, 0, 0,
3150 		{ RK3568_ACLK_PHP }
3151 	},
3152 	{
3153 		RK3568_PCLK_GMAC0, 0, 0, 0,
3154 		{ RK3568_PCLK_PHP }
3155 	},
3156 	{
3157 		RK3568_CLK_MAC0_2TOP, RK3568_CRU_CLKSEL_CON(31),
3158 		SEL(9, 8), 0,
3159 		{ RK3568_CPLL_125M, RK3568_CPLL_50M,
3160 		  RK3568_CPLL_25M, RK3568_XIN24M }
3161 	},
3162 	{
3163 		RK3568_CLK_MAC0_REFOUT, 0, 0, 0,
3164 		{ RK3568_CLK_MAC0_2TOP }
3165 	},
3166 	{
3167 		RK3568_CLK_GMAC0_PTP_REF, RK3568_CRU_CLKSEL_CON(31),
3168 		SEL(13, 12), 0,
3169 		{ RK3568_CPLL_62P5M, RK3568_GPLL_100M,
3170 		  RK3568_CPLL_50M, RK3568_XIN24M }
3171 	},
3172 	{
3173 		RK3568_ACLK_USB, RK3568_CRU_CLKSEL_CON(32),
3174 		SEL(1, 0), 0,
3175 		{ RK3568_GPLL_300M, RK3568_GPLL_200M,
3176 		  RK3568_GPLL_100M, RK3568_XIN24M }
3177 	},
3178 	{
3179 		RK3568_PCLK_USB, RK3568_CRU_CLKSEL_CON(32),
3180 		0, DIV(7, 4),
3181 		{ RK3568_ACLK_USB }
3182 	},
3183 	{
3184 		RK3568_ACLK_GMAC1, 0, 0, 0,
3185 		{ RK3568_ACLK_USB }
3186 	},
3187 	{
3188 		RK3568_PCLK_GMAC1, 0, 0, 0,
3189 		{ RK3568_PCLK_USB }
3190 	},
3191 	{
3192 		RK3568_CLK_MAC1_2TOP, RK3568_CRU_CLKSEL_CON(33),
3193 		SEL(9, 8), 0,
3194 		{ RK3568_CPLL_125M, RK3568_CPLL_50M,
3195 		  RK3568_CPLL_25M, RK3568_XIN24M }
3196 	},
3197 	{
3198 		RK3568_CLK_MAC1_REFOUT, 0, 0, 0,
3199 		{ RK3568_CLK_MAC1_2TOP }
3200 	},
3201 	{
3202 		RK3568_CLK_GMAC1_PTP_REF, RK3568_CRU_CLKSEL_CON(33),
3203 		SEL(13, 12), 0,
3204 		{ RK3568_CPLL_62P5M, RK3568_GPLL_100M,
3205 		  RK3568_CPLL_50M, RK3568_XIN24M }
3206 	},
3207 	{
3208 		RK3568_CLK_TSADC_TSEN, RK3568_CRU_CLKSEL_CON(51),
3209 		SEL(5, 4), DIV(2, 0),
3210 		{ RK3568_XIN24M, RK3568_GPLL_100M, RK3568_CPLL_100M }
3211 	},
3212 	{
3213 		RK3568_CLK_TSADC, RK3568_CRU_CLKSEL_CON(51),
3214 		0, DIV(14, 8),
3215 		{ RK3568_CLK_TSADC_TSEN }
3216 	},
3217 	{
3218 		RK3568_SCLK_UART1, RK3568_CRU_CLKSEL_CON(52),
3219 		SEL(13, 12), 0,
3220 		{ 0, 0, RK3568_XIN24M }
3221 	},
3222 	{
3223 		RK3568_SCLK_UART2, RK3568_CRU_CLKSEL_CON(54),
3224 		SEL(13, 12), 0,
3225 		{ 0, 0, RK3568_XIN24M }
3226 	},
3227 	{
3228 		RK3568_SCLK_UART3, RK3568_CRU_CLKSEL_CON(56),
3229 		SEL(13, 12), 0,
3230 		{ 0, 0, RK3568_XIN24M }
3231 	},
3232 	{
3233 		RK3568_SCLK_UART4, RK3568_CRU_CLKSEL_CON(58),
3234 		SEL(13, 12), 0,
3235 		{ 0, 0, RK3568_XIN24M }
3236 	},
3237 	{
3238 		RK3568_SCLK_UART5, RK3568_CRU_CLKSEL_CON(60),
3239 		SEL(13, 12), 0,
3240 		{ 0, 0, RK3568_XIN24M }
3241 	},
3242 	{
3243 		RK3568_SCLK_UART6, RK3568_CRU_CLKSEL_CON(62),
3244 		SEL(13, 12), 0,
3245 		{ 0, 0, RK3568_XIN24M }
3246 	},
3247 	{
3248 		RK3568_SCLK_UART7, RK3568_CRU_CLKSEL_CON(64),
3249 		SEL(13, 12), 0,
3250 		{ 0, 0, RK3568_XIN24M }
3251 	},
3252 	{
3253 		RK3568_SCLK_UART8, RK3568_CRU_CLKSEL_CON(66),
3254 		SEL(13, 12), 0,
3255 		{ 0, 0, RK3568_XIN24M }
3256 	},
3257 	{
3258 		RK3568_SCLK_UART9, RK3568_CRU_CLKSEL_CON(68),
3259 		SEL(13, 12), 0,
3260 		{ 0, 0, RK3568_XIN24M }
3261 	},
3262 	{
3263 		RK3568_CLK_I2C, RK3568_CRU_CLKSEL_CON(71),
3264 		SEL(9, 8), 0,
3265 		{ 0, 0, RK3568_XIN24M }
3266 	},
3267 	{
3268 		RK3568_CLK_I2C1, 0, 0, 0,
3269 		{ RK3568_CLK_I2C }
3270 	},
3271 	{
3272 		RK3568_CLK_I2C2, 0, 0, 0,
3273 		{ RK3568_CLK_I2C }
3274 	},
3275 	{
3276 		RK3568_CLK_I2C3, 0, 0, 0,
3277 		{ RK3568_CLK_I2C }
3278 	},
3279 	{
3280 		RK3568_CLK_I2C4, 0, 0, 0,
3281 		{ RK3568_CLK_I2C }
3282 	},
3283 	{
3284 		RK3568_CLK_I2C5, 0, 0, 0,
3285 		{ RK3568_CLK_I2C }
3286 	},
3287 	{
3288 		RK3568_SCLK_GMAC0, RK3568_CRU_CLKSEL_CON(31),
3289 		SEL(2, 2), 0,
3290 		{ RK3568_CLK_MAC0_2TOP, RK3568_GMAC0_CLKIN }
3291 	},
3292 	{
3293 		RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(31),
3294 		SEL(5, 4), 0,
3295 		{ RK3568_SCLK_GMAC0, RK3568_SCLK_GMAC0,
3296 		  RK3568_SCLK_GMAC0_DIV_50, RK3568_SCLK_GMAC0_DIV_5 }
3297 	},
3298 	{
3299 		RK3568_SCLK_GMAC0_RMII_SPEED, RK3568_CRU_CLKSEL_CON(31),
3300 		SEL(3, 3), 0,
3301 		{ RK3568_SCLK_GMAC0_DIV_20, RK3568_SCLK_GMAC0_DIV_2 }
3302 	},
3303 	{
3304 		RK3568_SCLK_GMAC0_RX_TX, RK3568_CRU_CLKSEL_CON(31),
3305 		SEL(1, 0), 0,
3306 		{ RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_SCLK_GMAC0_RMII_SPEED }
3307 	},
3308 	{
3309 		RK3568_SCLK_GMAC1, RK3568_CRU_CLKSEL_CON(33),
3310 		SEL(2, 2), 0,
3311 		{ RK3568_CLK_MAC1_2TOP, RK3568_GMAC1_CLKIN }
3312 	},
3313 	{
3314 		RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(33),
3315 		SEL(5, 4), 0,
3316 		{ RK3568_SCLK_GMAC1, RK3568_SCLK_GMAC1,
3317 		  RK3568_SCLK_GMAC1_DIV_50, RK3568_SCLK_GMAC1_DIV_5 }
3318 	},
3319 	{
3320 		RK3568_SCLK_GMAC1_RMII_SPEED, RK3568_CRU_CLKSEL_CON(33),
3321 		SEL(3, 3), 0,
3322 		{ RK3568_SCLK_GMAC1_DIV_20, RK3568_SCLK_GMAC1_DIV_2 }
3323 	},
3324 	{
3325 		RK3568_SCLK_GMAC1_RX_TX, RK3568_CRU_CLKSEL_CON(33),
3326 		SEL(1, 0), 0,
3327 		{ RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_SCLK_GMAC1_RMII_SPEED }
3328 	},
3329 	{
3330 		RK3568_CPLL_125M, RK3568_CRU_CLKSEL_CON(80),
3331 		0, DIV(4, 0),
3332 		{ RK3568_PLL_CPLL }
3333 	},
3334 	{
3335 		RK3568_CPLL_62P5M, RK3568_CRU_CLKSEL_CON(80),
3336 		0, DIV(12, 8),
3337 		{ RK3568_PLL_CPLL }
3338 	},
3339 	{
3340 		RK3568_CPLL_50M, RK3568_CRU_CLKSEL_CON(81),
3341 		0, DIV(4, 0),
3342 		{ RK3568_PLL_CPLL }
3343 	},
3344 	{
3345 		RK3568_CPLL_25M, RK3568_CRU_CLKSEL_CON(81),
3346 		0, DIV(13, 8),
3347 		{ RK3568_PLL_CPLL }
3348 	},
3349 	{
3350 		RK3568_CPLL_100M, RK3568_CRU_CLKSEL_CON(82),
3351 		0, DIV(4, 0),
3352 		{ RK3568_PLL_CPLL }
3353 	},
3354 	{
3355 		RK3568_GPLL_400M, RK3568_CRU_CLKSEL_CON(75),
3356 		0, DIV(4, 0),
3357 		{ RK3568_PLL_GPLL }
3358 	},
3359 	{
3360 		RK3568_GPLL_300M, RK3568_CRU_CLKSEL_CON(75),
3361 		0, DIV(12, 8),
3362 		{ RK3568_PLL_GPLL }
3363 	},
3364 	{
3365 		RK3568_GPLL_200M, RK3568_CRU_CLKSEL_CON(76),
3366 		0, DIV(4, 0),
3367 		{ RK3568_PLL_GPLL }
3368 	},
3369 	{
3370 		RK3568_GPLL_150M, RK3568_CRU_CLKSEL_CON(76),
3371 		0, DIV(12, 5),
3372 		{ RK3568_PLL_GPLL }
3373 	},
3374 	{
3375 		RK3568_GPLL_100M, RK3568_CRU_CLKSEL_CON(77),
3376 		0, DIV(4, 0),
3377 		{ RK3568_PLL_GPLL }
3378 	},
3379 	{
3380 		RK3568_CLK_OSC0_DIV_750K, RK3568_CRU_CLKSEL_CON(82),
3381 		0, DIV(13, 8),
3382 		{ RK3568_XIN24M }
3383 	},
3384 	{
3385 		/* Sentinel */
3386 	}
3387 };
3388 
3389 void
3390 rk3568_init(struct rkclock_softc *sc)
3391 {
3392 	int i;
3393 
3394 	/* The code below assumes all clocks are enabled.  Check this!. */
3395 	for (i = 0; i <= 35; i++) {
3396 		if (HREAD4(sc, RK3568_CRU_GATE_CON(i)) != 0x00000000) {
3397 			printf("CRU_GATE_CON%d: 0x%08x\n", i,
3398 			    HREAD4(sc, RK3568_CRU_GATE_CON(i)));
3399 		}
3400 	}
3401 
3402 	sc->sc_clocks = rk3568_clocks;
3403 }
3404 
3405 int
3406 rk3568_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
3407 {
3408 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
3409 	int mode_shift = -1;
3410 
3411 	switch (base) {
3412 	case RK3568_CRU_APLL_CON(0):
3413 		mode_shift = 0;
3414 		break;
3415 	case RK3568_CRU_DPLL_CON(0):
3416 		mode_shift = 2;
3417 		break;
3418 	case RK3568_CRU_CPLL_CON(0):
3419 		mode_shift = 4;
3420 		break;
3421 	case RK3568_CRU_GPLL_CON(0):
3422 		mode_shift = 6;
3423 		break;
3424 	case RK3568_CRU_NPLL_CON(0):
3425 		mode_shift = 10;
3426 		break;
3427 	case RK3568_CRU_VPLL_CON(0):
3428 		mode_shift = 12;
3429 		break;
3430 	}
3431 	KASSERT(mode_shift != -1);
3432 
3433 	/*
3434 	 * It is not clear whether all combinations of the clock
3435 	 * dividers result in a stable clock.  Therefore this function
3436 	 * only supports a limited set of PLL clock rates.
3437 	 */
3438 	switch (freq) {
3439 	case 1200000000U:
3440 		postdiv1 = 2; postdiv2 = refdiv = 1;
3441 		break;
3442 	default:
3443 		printf("%s: %u Hz\n", __func__, freq);
3444 		return -1;
3445 	}
3446 
3447 	/* Calculate feedback divider. */
3448 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
3449 
3450 	/*
3451 	 * Select slow mode to guarantee a stable clock while we're
3452 	 * adjusting the PLL.
3453 	 */
3454 	HWRITE4(sc, RK3568_CRU_MODE_CON,
3455 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
3456 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
3457 
3458 	/* Set PLL rate. */
3459 	HWRITE4(sc, base + 0x0000,
3460 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
3461 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
3462 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
3463 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
3464 	HWRITE4(sc, base + 0x0004,
3465 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
3466 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
3467 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
3468 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
3469 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
3470 
3471 	/* Wait for PLL to stabilize. */
3472 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
3473 		delay(10);
3474 
3475 	/* Switch back to normal mode. */
3476 	HWRITE4(sc, RK3568_CRU_MODE_CON,
3477 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
3478 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
3479 
3480 	return 0;
3481 }
3482 
3483 uint32_t
3484 rk3568_get_frequency(void *cookie, uint32_t *cells)
3485 {
3486 	struct rkclock_softc *sc = cookie;
3487 	uint32_t idx = cells[0];
3488 
3489 	switch (idx) {
3490 	case RK3568_PLL_APLL:
3491 		return rk3328_get_pll(sc, RK3568_CRU_APLL_CON(0));
3492 	case RK3568_PLL_DPLL:
3493 		return rk3328_get_pll(sc, RK3568_CRU_DPLL_CON(0));
3494 	case RK3568_PLL_CPLL:
3495 		return rk3328_get_pll(sc, RK3568_CRU_CPLL_CON(0));
3496 	case RK3568_PLL_GPLL:
3497 		return rk3328_get_pll(sc, RK3568_CRU_GPLL_CON(0));
3498 	case RK3568_PLL_NPLL:
3499 		return rk3328_get_pll(sc, RK3568_CRU_NPLL_CON(0));
3500 	case RK3568_PLL_VPLL:
3501 		return rk3328_get_pll(sc, RK3568_CRU_VPLL_CON(0));
3502 	case RK3568_SCLK_GMAC0_DIV_50:
3503 		idx = RK3568_SCLK_GMAC0;
3504 		return rk3568_get_frequency(sc, &idx) / 50;
3505 	case RK3568_SCLK_GMAC0_DIV_5:
3506 		idx = RK3568_SCLK_GMAC0;
3507 		return rk3568_get_frequency(sc, &idx) / 5;
3508 	case RK3568_SCLK_GMAC0_DIV_20:
3509 		idx = RK3568_SCLK_GMAC0;
3510 		return rk3568_get_frequency(sc, &idx) / 20;
3511 	case RK3568_SCLK_GMAC0_DIV_2:
3512 		idx = RK3568_SCLK_GMAC0;
3513 		return rk3568_get_frequency(sc, &idx) / 2;
3514 	case RK3568_SCLK_GMAC1_DIV_50:
3515 		idx = RK3568_SCLK_GMAC1;
3516 		return rk3568_get_frequency(sc, &idx) / 50;
3517 	case RK3568_SCLK_GMAC1_DIV_5:
3518 		idx = RK3568_SCLK_GMAC1;
3519 		return rk3568_get_frequency(sc, &idx) / 5;
3520 	case RK3568_SCLK_GMAC1_DIV_20:
3521 		idx = RK3568_SCLK_GMAC1;
3522 		return rk3568_get_frequency(sc, &idx) / 20;
3523 	case RK3568_SCLK_GMAC1_DIV_2:
3524 		idx = RK3568_SCLK_GMAC1;
3525 		return rk3568_get_frequency(sc, &idx) / 2;
3526 	case RK3568_CLK_OSC0_DIV_375K:
3527 		idx = RK3568_CLK_OSC0_DIV_750K;
3528 		return rk3568_get_frequency(sc, &idx) / 2;
3529 	case RK3568_GMAC0_CLKIN:
3530 		return rkclock_external_frequency("gmac0_clkin");
3531 	case RK3568_GMAC1_CLKIN:
3532 		return rkclock_external_frequency("gmac1_clkin");
3533 	case RK3568_XIN24M:
3534 		return 24000000;
3535 	default:
3536 		break;
3537 	}
3538 
3539 	return rkclock_get_frequency(sc, idx);
3540 }
3541 
3542 int
3543 rk3568_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3544 {
3545 	struct rkclock_softc *sc = cookie;
3546 	uint32_t idx = cells[0];
3547 
3548 	switch (idx) {
3549 	case RK3568_PLL_GPLL:
3550 		return rk3568_set_pll(sc, RK3568_CRU_GPLL_CON(0), freq);
3551 	default:
3552 		break;
3553 	}
3554 
3555 	return rkclock_set_frequency(sc, idx, freq);
3556 }
3557 
3558 int
3559 rk3568_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
3560 {
3561 	struct rkclock_softc *sc = cookie;
3562 	char buf[64] = {};
3563 	int len, node;
3564 
3565 	if (pcells[0] != sc->sc_phandle) {
3566 		node = OF_getnodebyphandle(pcells[0]);
3567 		if (node == 0)
3568 			return -1;
3569 		len = OF_getproplen(node, "clock-output-names");
3570 		if (len <= 0 || len > sizeof(buf))
3571 			return -1;
3572 		OF_getprop(node, "clock-output-names", buf, sizeof(buf));
3573 
3574 		if (strcmp(buf, "gmac0_clkin") == 0) {
3575 			return rkclock_set_parent(sc, cells[0],
3576 			    RK3568_GMAC0_CLKIN);
3577 		}
3578 		if (strcmp(buf, "gmac1_clkin") == 0) {
3579 			return rkclock_set_parent(sc, cells[0],
3580 			    RK3568_GMAC1_CLKIN);
3581 		}
3582 
3583 		printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], pcells[0]);
3584 		return -1;
3585 	}
3586 
3587 	return rkclock_set_parent(sc, cells[0], pcells[1]);
3588 }
3589 
3590 void
3591 rk3568_enable(void *cookie, uint32_t *cells, int on)
3592 {
3593 	uint32_t idx = cells[0];
3594 
3595 	/* All clocks are enabled upon hardware reset. */
3596 	if (!on) {
3597 		printf("%s: 0x%08x\n", __func__, idx);
3598 		return;
3599 	}
3600 }
3601 
3602 void
3603 rk3568_reset(void *cookie, uint32_t *cells, int on)
3604 {
3605 	struct rkclock_softc *sc = cookie;
3606 	uint32_t idx = cells[0];
3607 	uint32_t mask = (1 << (idx % 16));
3608 
3609 	HWRITE4(sc, RK3568_CRU_SOFTRST_CON(idx / 16),
3610 	    mask << 16 | (on ? mask : 0));
3611 }
3612 
3613 /* PMUCRU */
3614 
3615 const struct rkclock rk3568_pmu_clocks[] = {
3616 	{
3617 		RK3568_CLK_RTC_32K, RK3568_PMUCRU_CLKSEL_CON(0),
3618 		SEL(7, 6), 0,
3619 		{ 0, RK3568_XIN32K, RK3568_CLK_RTC32K_FRAC },
3620 		SET_PARENT
3621 	},
3622 	{
3623 		RK3568_CLK_I2C0, RK3568_PMUCRU_CLKSEL_CON(3),
3624 		0, DIV(15, 7),
3625 		{ RK3568_CLK_PDPMU }
3626 	},
3627 	{
3628 		RK3568_SCLK_UART0, RK3568_PMUCRU_CLKSEL_CON(4),
3629 		SEL(11, 10), 0,
3630 		{ 0, 0, RK3568_XIN24M }
3631 	},
3632 	{
3633 		RK3568_CLK_PCIEPHY0_OSC0, 0, 0, 0,
3634 		{ RK3568_XIN24M }
3635 	},
3636 	{
3637 		RK3568_CLK_PCIEPHY0_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3638 		0, DIV(2, 0),
3639 		{ RK3568_PPLL_PH0 }
3640 	},
3641 	{
3642 		RK3568_CLK_PCIEPHY0_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3643 		SEL(3, 3), 0,
3644 		{ RK3568_CLK_PCIEPHY0_OSC0, RK3568_CLK_PCIEPHY0_DIV },
3645 		SET_PARENT
3646 	},
3647 	{
3648 		RK3568_CLK_PCIEPHY1_OSC0, 0, 0, 0,
3649 		{ RK3568_XIN24M }
3650 	},
3651 	{
3652 		RK3568_CLK_PCIEPHY1_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3653 		0, DIV(6, 4),
3654 		{ RK3568_PPLL_PH0 }
3655 	},
3656 	{
3657 		RK3568_CLK_PCIEPHY1_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3658 		SEL(7, 7), 0,
3659 		{ RK3568_CLK_PCIEPHY1_OSC0, RK3568_CLK_PCIEPHY1_DIV },
3660 		SET_PARENT
3661 	},
3662 	{
3663 		RK3568_CLK_PCIEPHY2_OSC0, 0, 0, 0,
3664 		{ RK3568_XIN24M }
3665 	},
3666 	{
3667 		RK3568_CLK_PCIEPHY2_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3668 		0, DIV(10, 8),
3669 		{ RK3568_PPLL_PH0 }
3670 	},
3671 	{
3672 		RK3568_CLK_PCIEPHY2_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3673 		SEL(11, 11), 0,
3674 		{ RK3568_CLK_PCIEPHY2_OSC0, RK3568_CLK_PCIEPHY2_DIV },
3675 		SET_PARENT
3676 	},
3677 	{
3678 		RK3568_CLK_PDPMU, RK3568_PMUCRU_CLKSEL_CON(2),
3679 		SEL(15, 15), 0,
3680 		{ RK3568_PLL_PPLL, 0 }
3681 	},
3682 	{
3683 		/* Sentinel */
3684 	}
3685 };
3686 
3687 void
3688 rk3568_pmu_init(struct rkclock_softc *sc)
3689 {
3690 	int i;
3691 
3692 	/* The code below assumes all clocks are enabled.  Check this!. */
3693 	for (i = 0; i <= 2; i++) {
3694 		if (HREAD4(sc, RK3568_PMUCRU_GATE_CON(i)) != 0x00000000) {
3695 			printf("CRU_GATE_CON%d: 0x%08x\n", i,
3696 			    HREAD4(sc, RK3568_CRU_GATE_CON(i)));
3697 		}
3698 	}
3699 
3700 	sc->sc_clocks = rk3568_pmu_clocks;
3701 }
3702 
3703 int
3704 rk3568_pmu_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
3705 {
3706 	uint32_t fbdiv, postdiv1, postdiv2, refdiv;
3707 	int mode_shift = -1;
3708 
3709 	switch (base) {
3710 	case RK3568_PMUCRU_PPLL_CON(0):
3711 		mode_shift = 0;
3712 		break;
3713 	case RK3568_PMUCRU_HPLL_CON(0):
3714 		mode_shift = 2;
3715 		break;
3716 	}
3717 	KASSERT(mode_shift != -1);
3718 
3719 	/*
3720 	 * It is not clear whether all combinations of the clock
3721 	 * dividers result in a stable clock.  Therefore this function
3722 	 * only supports a limited set of PLL clock rates.
3723 	 */
3724 	switch (freq) {
3725 	case 200000000U:
3726 		postdiv1 = 3; postdiv2 = 4; refdiv = 1;
3727 		break;
3728 	default:
3729 		printf("%s: %u Hz\n", __func__, freq);
3730 		return -1;
3731 	}
3732 
3733 	/* Calculate feedback divider. */
3734 	fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
3735 
3736 	/*
3737 	 * Select slow mode to guarantee a stable clock while we're
3738 	 * adjusting the PLL.
3739 	 */
3740 	HWRITE4(sc, RK3568_PMUCRU_MODE_CON,
3741 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
3742 	   RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
3743 
3744 	/* Set PLL rate. */
3745 	HWRITE4(sc, base + 0x0000,
3746 	    RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
3747 	    postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
3748 	    RK3328_CRU_PLL_FBDIV_MASK << 16 |
3749 	    fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
3750 	HWRITE4(sc, base + 0x0004,
3751 	    RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
3752 	    RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
3753 	    postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
3754 	    RK3328_CRU_PLL_REFDIV_MASK << 16 |
3755 	    refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
3756 
3757 	/* Wait for PLL to stabilize. */
3758 	while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
3759 		delay(10);
3760 
3761 	/* Switch back to normal mode. */
3762 	HWRITE4(sc, RK3568_PMUCRU_MODE_CON,
3763 	   (RK3328_CRU_CRU_MODE_MASK << 16 |
3764 	   RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
3765 
3766 	return 0;
3767 }
3768 
3769 uint32_t
3770 rk3568_pmu_get_frequency(void *cookie, uint32_t *cells)
3771 {
3772 	struct rkclock_softc *sc = cookie;
3773 	uint32_t idx = cells[0];
3774 
3775 	switch (idx) {
3776 	case RK3568_PLL_PPLL:
3777 		return rk3328_get_pll(sc, RK3568_PMUCRU_PPLL_CON(0));
3778 	case RK3568_PLL_HPLL:
3779 		return rk3328_get_pll(sc, RK3568_PMUCRU_HPLL_CON(0));
3780 	case RK3568_CLK_RTC32K_FRAC:
3781 		return rk3399_get_frac(sc, RK3568_XIN24M,
3782 		    RK3568_PMUCRU_CLKSEL_CON(1));
3783 	case RK3568_PPLL_PH0:
3784 		idx = RK3568_PLL_PPLL;
3785 		return rk3568_get_frequency(sc, &idx) / 2;
3786 	case RK3568_XIN32K:
3787 		return 32768;
3788 	case RK3568_XIN24M:
3789 		return 24000000;
3790 	default:
3791 		break;
3792 	}
3793 
3794 	return rkclock_get_frequency(sc, idx);
3795 }
3796 
3797 int
3798 rk3568_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3799 {
3800 	struct rkclock_softc *sc = cookie;
3801 	uint32_t idx = cells[0];
3802 
3803 	switch (idx) {
3804 	case RK3568_PLL_PPLL:
3805 		return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_PPLL_CON(0), freq);
3806 	case RK3568_PLL_HPLL:
3807 		return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_HPLL_CON(0), freq);
3808 	case RK3568_CLK_RTC32K_FRAC:
3809 		return rk3399_set_frac(sc, RK3568_XIN24M,
3810 		    RK3568_PMUCRU_CLKSEL_CON(1), freq);
3811 	default:
3812 		break;
3813 	}
3814 
3815 	return rkclock_set_frequency(sc, idx, freq);
3816 }
3817 
3818 void
3819 rk3568_pmu_enable(void *cookie, uint32_t *cells, int on)
3820 {
3821 	uint32_t idx = cells[0];
3822 
3823 	switch (idx) {
3824 	case RK3568_CLK_USBPHY0_REF:
3825 	case RK3568_CLK_USBPHY1_REF:
3826 	case RK3568_CLK_PCIEPHY0_REF:
3827 	case RK3568_CLK_PCIEPHY1_REF:
3828 	case RK3568_CLK_PCIEPHY2_REF:
3829 	case RK3568_CLK_PCIE30PHY_REF_M:
3830 	case RK3568_CLK_PCIE30PHY_REF_N:
3831 	case RK3568_CLK_I2C0:
3832 	case RK3568_SCLK_UART0:
3833 	case RK3568_PCLK_I2C0:
3834 		/* Enabled by default. */
3835 		break;
3836 	default:
3837 		printf("%s: 0x%08x\n", __func__, idx);
3838 		break;
3839 	}
3840 }
3841 
3842 void
3843 rk3568_pmu_reset(void *cookie, uint32_t *cells, int on)
3844 {
3845 	uint32_t idx = cells[0];
3846 
3847 	printf("%s: 0x%08x\n", __func__, idx);
3848 }
3849 
3850 /*
3851  * Rockchip RK3588
3852  */
3853 
3854 const struct rkclock rk3588_clocks[] = {
3855 	{
3856 		RK3588_ACLK_BUS_ROOT, RK3588_CRU_CLKSEL_CON(38),
3857 		SEL(5, 5), DIV(4, 0),
3858 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3859 	},
3860 	{
3861 		RK3588_CLK_I2C1, RK3588_CRU_CLKSEL_CON(38),
3862 		SEL(6, 6), 0,
3863 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3864 	},
3865 	{
3866 		RK3588_CLK_I2C2, RK3588_CRU_CLKSEL_CON(38),
3867 		SEL(7, 7), 0,
3868 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3869 	},
3870 	{
3871 		RK3588_CLK_I2C3, RK3588_CRU_CLKSEL_CON(38),
3872 		SEL(8, 8), 0,
3873 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3874 	},
3875 	{
3876 		RK3588_CLK_I2C4, RK3588_CRU_CLKSEL_CON(38),
3877 		SEL(9, 9), 0,
3878 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3879 	},
3880 	{
3881 		RK3588_CLK_I2C5, RK3588_CRU_CLKSEL_CON(38),
3882 		SEL(10, 10), 0,
3883 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3884 	},
3885 	{
3886 		RK3588_CLK_I2C6, RK3588_CRU_CLKSEL_CON(38),
3887 		SEL(11, 11), 0,
3888 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3889 	},
3890 	{
3891 		RK3588_CLK_I2C7, RK3588_CRU_CLKSEL_CON(38),
3892 		SEL(12, 12), 0,
3893 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3894 	},
3895 	{
3896 		RK3588_CLK_I2C8, RK3588_CRU_CLKSEL_CON(38),
3897 		SEL(13, 13), 0,
3898 		{ RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
3899 	},
3900 	{
3901 		RK3588_CLK_UART1_SRC, RK3588_CRU_CLKSEL_CON(41),
3902 		SEL(14, 14), DIV(13, 9),
3903 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3904 	},
3905 	{
3906 		RK3588_CLK_UART1, RK3588_CRU_CLKSEL_CON(43),
3907 		SEL(1, 0), 0,
3908 		{ RK3588_CLK_UART1_SRC, RK3588_CLK_UART1_FRAC, RK3588_XIN24M }
3909 	},
3910 	{
3911 		RK3588_SCLK_UART1, 0, 0, 0,
3912 		{ RK3588_CLK_UART1 }
3913 	},
3914 	{
3915 		RK3588_CLK_UART2_SRC, RK3588_CRU_CLKSEL_CON(43),
3916 		SEL(7, 7), DIV(6, 2),
3917 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3918 	},
3919 	{
3920 		RK3588_CLK_UART2, RK3588_CRU_CLKSEL_CON(45),
3921 		SEL(1, 0), 0,
3922 		{ RK3588_CLK_UART2_SRC, RK3588_CLK_UART2_FRAC, RK3588_XIN24M }
3923 	},
3924 	{
3925 		RK3588_SCLK_UART2, 0, 0, 0,
3926 		{ RK3588_CLK_UART2 }
3927 	},
3928 	{
3929 		RK3588_CLK_UART3_SRC, RK3588_CRU_CLKSEL_CON(45),
3930 		SEL(7, 7), DIV(6, 2),
3931 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3932 	},
3933 	{
3934 		RK3588_CLK_UART3, RK3588_CRU_CLKSEL_CON(47),
3935 		SEL(1, 0), 0,
3936 		{ RK3588_CLK_UART3_SRC, RK3588_CLK_UART3_FRAC, RK3588_XIN24M }
3937 	},
3938 	{
3939 		RK3588_SCLK_UART3, 0, 0, 0,
3940 		{ RK3588_CLK_UART3 }
3941 	},
3942 	{
3943 		RK3588_CLK_UART4_SRC, RK3588_CRU_CLKSEL_CON(47),
3944 		SEL(7, 7), DIV(6, 2),
3945 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3946 	},
3947 	{
3948 		RK3588_CLK_UART4, RK3588_CRU_CLKSEL_CON(49),
3949 		SEL(1, 0), 0,
3950 		{ RK3588_CLK_UART4_SRC, RK3588_CLK_UART4_FRAC, RK3588_XIN24M }
3951 	},
3952 	{
3953 		RK3588_SCLK_UART4, 0, 0, 0,
3954 		{ RK3588_CLK_UART4 }
3955 	},
3956 	{
3957 		RK3588_CLK_UART5_SRC, RK3588_CRU_CLKSEL_CON(49),
3958 		SEL(7, 7), DIV(6, 2),
3959 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3960 	},
3961 	{
3962 		RK3588_CLK_UART5, RK3588_CRU_CLKSEL_CON(51),
3963 		SEL(1, 0), 0,
3964 		{ RK3588_CLK_UART5_SRC, RK3588_CLK_UART5_FRAC, RK3588_XIN24M }
3965 	},
3966 	{
3967 		RK3588_SCLK_UART5, 0, 0, 0,
3968 		{ RK3588_CLK_UART5 }
3969 	},
3970 	{
3971 		RK3588_CLK_UART6_SRC, RK3588_CRU_CLKSEL_CON(51),
3972 		SEL(7, 7), DIV(6, 2),
3973 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3974 	},
3975 	{
3976 		RK3588_CLK_UART6, RK3588_CRU_CLKSEL_CON(53),
3977 		SEL(1, 0), 0,
3978 		{ RK3588_CLK_UART6_SRC, RK3588_CLK_UART6_FRAC, RK3588_XIN24M }
3979 	},
3980 	{
3981 		RK3588_SCLK_UART6, 0, 0, 0,
3982 		{ RK3588_CLK_UART6 }
3983 	},
3984 	{
3985 		RK3588_CLK_UART7_SRC, RK3588_CRU_CLKSEL_CON(53),
3986 		SEL(7, 7), DIV(6, 2),
3987 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
3988 	},
3989 	{
3990 		RK3588_CLK_UART7, RK3588_CRU_CLKSEL_CON(55),
3991 		SEL(1, 0), 0,
3992 		{ RK3588_CLK_UART7_SRC, RK3588_CLK_UART7_FRAC, RK3588_XIN24M }
3993 	},
3994 	{
3995 		RK3588_SCLK_UART7, 0, 0, 0,
3996 		{ RK3588_CLK_UART7 }
3997 	},
3998 	{
3999 		RK3588_CLK_UART8_SRC, RK3588_CRU_CLKSEL_CON(55),
4000 		SEL(7, 7), DIV(6, 2),
4001 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4002 	},
4003 	{
4004 		RK3588_CLK_UART8, RK3588_CRU_CLKSEL_CON(57),
4005 		SEL(1, 0), 0,
4006 		{ RK3588_CLK_UART8_SRC, RK3588_CLK_UART8_FRAC, RK3588_XIN24M }
4007 	},
4008 	{
4009 		RK3588_SCLK_UART8, 0, 0, 0,
4010 		{ RK3588_CLK_UART8 }
4011 	},
4012 	{
4013 		RK3588_CLK_UART9_SRC, RK3588_CRU_CLKSEL_CON(57),
4014 		SEL(7, 7), DIV(6, 2),
4015 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4016 	},
4017 	{
4018 		RK3588_CLK_UART9, RK3588_CRU_CLKSEL_CON(59),
4019 		SEL(1, 0), 0,
4020 		{ RK3588_CLK_UART9_SRC, RK3588_CLK_UART9_FRAC, RK3588_XIN24M }
4021 	},
4022 	{
4023 		RK3588_SCLK_UART9, 0, 0, 0,
4024 		{ RK3588_CLK_UART9 }
4025 	},
4026 	{
4027 		RK3588_ACLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165),
4028 		SEL(1, 0), 0,
4029 		{ RK3588_CLK_700M_SRC, RK3588_CLK_400M_SRC,
4030 		  RK3588_CLK_200M_SRC, RK3588_XIN24M }
4031 	},
4032 	{
4033 		RK3588_ACLK_CENTER_LOW_ROOT, RK3588_CRU_CLKSEL_CON(165),
4034 		SEL(3, 2), 0,
4035 		{ RK3588_CLK_500M_SRC, RK3588_CLK_250M_SRC,
4036 		  RK3588_CLK_100M_SRC, RK3588_XIN24M }
4037 	},
4038 	{
4039 		RK3588_HCLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165),
4040 		SEL(5, 4), 0,
4041 		{ RK3588_CLK_400M_SRC, RK3588_CLK_200M_SRC,
4042 		  RK3588_CLK_100M_SRC, RK3588_XIN24M }
4043 	},
4044 	{
4045 		RK3588_CLK_50M_SRC, RK3588_CRU_CLKSEL_CON(0),
4046 		SEL(5, 5), DIV(4, 0),
4047 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4048 	},
4049 	{
4050 		RK3588_CLK_100M_SRC, RK3588_CRU_CLKSEL_CON(0),
4051 		SEL(11, 11), DIV(10, 6),
4052 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4053 	},
4054 	{
4055 		RK3588_CLK_150M_SRC, RK3588_CRU_CLKSEL_CON(1),
4056 		SEL(5, 5), DIV(4, 0),
4057 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4058 	},
4059 	{
4060 		RK3588_CLK_200M_SRC, RK3588_CRU_CLKSEL_CON(1),
4061 		SEL(11, 11), DIV(10, 6),
4062 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4063 	},
4064 	{
4065 		RK3588_CLK_250M_SRC, RK3588_CRU_CLKSEL_CON(2),
4066 		SEL(5, 5), DIV(4, 0),
4067 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4068 	},
4069 	{
4070 		RK3588_CLK_400M_SRC, RK3588_CRU_CLKSEL_CON(3),
4071 		SEL(11, 11), DIV(10, 6),
4072 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4073 	},
4074 	{
4075 		RK3588_CLK_500M_SRC, RK3588_CRU_CLKSEL_CON(4),
4076 		SEL(11, 11), DIV(10, 6),
4077 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4078 	},
4079 	{
4080 		RK3588_CLK_700M_SRC, RK3588_CRU_CLKSEL_CON(6),
4081 		SEL(5, 5), DIV(4, 0),
4082 		{ RK3588_PLL_GPLL, RK3588_PLL_SPLL }
4083 	},
4084 	{
4085 		RK3588_ACLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4086 		SEL(6, 5), 0,
4087 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL }
4088 	},
4089 	{
4090 		RK3588_PCLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4091 		SEL(8, 7), 0,
4092 		{ RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M }
4093 	},
4094 	{
4095 		RK3588_ACLK_LOW_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4096 		SEL(14, 14), DIV(13, 9),
4097 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4098 	},
4099 	{
4100 		RK3588_CLK_GPU_SRC, RK3588_CRU_CLKSEL_CON(158),
4101 		SEL(7, 5), DIV(4, 0),
4102 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL,
4103 		  RK3588_PLL_NPLL, RK3588_PLL_SPLL }
4104 	},
4105 	{
4106 		RK3588_CLK_GPU, 0, 0, 0,
4107 		{ RK3588_CLK_GPU_SRC },
4108 		SET_PARENT
4109 	},
4110 	{
4111 		RK3588_CCLK_SRC_SDIO, RK3588_CRU_CLKSEL_CON(172),
4112 		SEL(9, 8), DIV(7, 2),
4113 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_XIN24M }
4114 	},
4115 	{
4116 		RK3588_ACLK_VOP_ROOT, RK3588_CRU_CLKSEL_CON(110),
4117 		SEL(7, 5), DIV(4, 0),
4118 		{ RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL,
4119 		  RK3588_PLL_NPLL, RK3588_PLL_SPLL }
4120 	},
4121 	{
4122 		RK3588_ACLK_VOP, 0, 0, 0,
4123 		{ RK3588_ACLK_VOP_SUB_SRC },
4124 		SET_PARENT
4125 	},
4126 	{
4127 		RK3588_ACLK_VOP_SUB_SRC, RK3588_CRU_CLKSEL_CON(115),
4128 		SEL(9, 9), 0,
4129 		{ RK3588_ACLK_VOP_ROOT, 0 /* RK3588_ACLK_VOP_DIV2_SRC */ },
4130 		SET_PARENT
4131 	},
4132 	{
4133 		RK3588_CLK_I2C0, RK3588_CRU_CLKSEL_CON(3),
4134 		SEL(6, 6), 0,
4135 		{ RK3588_CLK_PMU1_200M_SRC, RK3588_CLK_PMU1_100M_SRC },
4136 	},
4137 	{
4138 		RK3588_CLK_PMU1_50M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4139 		0, DIV(3, 0),
4140 		{ RK3588_CLK_PMU1_400M_SRC }
4141 	},
4142 	{
4143 		RK3588_CLK_PMU1_100M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4144 		0, DIV(6, 4),
4145 		{ RK3588_CLK_PMU1_400M_SRC }
4146 	},
4147 	{
4148 		RK3588_CLK_PMU1_200M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4149 		0, DIV(9, 7),
4150 		{ RK3588_CLK_PMU1_400M_SRC }
4151 	},
4152 	{
4153 		RK3588_CLK_PMU1_400M_SRC, RK3588_PMUCRU_CLKSEL_CON(1),
4154 		SEL(5, 5), DIV(4, 0),
4155 		{ RK3588_CLK_400M_SRC, RK3588_XIN24M }
4156 	},
4157 	{
4158 		RK3588_PCLK_PMU1_ROOT, RK3588_PMUCRU_CLKSEL_CON(1),
4159 		SEL(9, 8), 0,
4160 		{ RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC,
4161 		  RK3588_XIN24M }
4162 	},
4163 	{
4164 		RK3588_PCLK_PMU0_ROOT, 0, 0, 0,
4165 		{ RK3588_PCLK_PMU1_ROOT },
4166 		SET_PARENT
4167 	},
4168 	{
4169 		RK3588_HCLK_PMU_CM0_ROOT, RK3588_PMUCRU_CLKSEL_CON(1),
4170 		SEL(11, 10), 0,
4171 		{ RK3588_CLK_PMU1_400M_SRC, RK3588_CLK_PMU1_200M_SRC,
4172 		  RK3588_CLK_PMU1_100M_SRC, RK3588_XIN24M }
4173 	},
4174 	{
4175 		RK3588_CLK_PMU1PWM, RK3588_PMUCRU_CLKSEL_CON(2),
4176 		SEL(10, 9), 0,
4177 		{ RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC,
4178 		  RK3588_XIN24M }
4179 	},
4180 	{
4181 		RK3588_CLK_UART0_SRC, RK3588_PMUCRU_CLKSEL_CON(3),
4182 		0, DIV(11, 7),
4183 		{ RK3588_PLL_CPLL }
4184 	},
4185 	{
4186 		RK3588_CLK_UART0, RK3588_PMUCRU_CLKSEL_CON(5),
4187 		SEL(1, 0), 0,
4188 		{ RK3588_CLK_UART0_SRC, RK3588_CLK_UART0_FRAC, RK3588_XIN24M }
4189 	},
4190 	{
4191 		RK3588_SCLK_UART0, 0, 0, 0,
4192 		{ RK3588_CLK_UART0 }
4193 	},
4194 	{
4195 		RK3588_CLK_REF_PIPE_PHY0_OSC_SRC, 0, 0, 0,
4196 		{ RK3588_XIN24M }
4197 	},
4198 	{
4199 		RK3588_CLK_REF_PIPE_PHY1_OSC_SRC, 0, 0, 0,
4200 		{ RK3588_XIN24M }
4201 	},
4202 	{
4203 		RK3588_CLK_REF_PIPE_PHY2_OSC_SRC, 0, 0, 0,
4204 		{ RK3588_XIN24M }
4205 	},
4206 	{
4207 		RK3588_CLK_REF_PIPE_PHY0_PLL_SRC, RK3588_CRU_CLKSEL_CON(176),
4208 		0, DIV(5, 0),
4209 		{ RK3588_PLL_PPLL }
4210 	},
4211 	{
4212 		RK3588_CLK_REF_PIPE_PHY1_PLL_SRC, RK3588_CRU_CLKSEL_CON(176),
4213 		0, DIV(11, 6),
4214 		{ RK3588_PLL_PPLL }
4215 	},
4216 	{
4217 		RK3588_CLK_REF_PIPE_PHY2_PLL_SRC, RK3588_CRU_CLKSEL_CON(177),
4218 		0, DIV(5, 0),
4219 		{ RK3588_PLL_PPLL }
4220 	},
4221 	{
4222 		RK3588_CLK_REF_PIPE_PHY0, RK3588_CRU_CLKSEL_CON(177),
4223 		SEL(6, 6), 0,
4224 		{ RK3588_CLK_REF_PIPE_PHY0_OSC_SRC,
4225 		  RK3588_CLK_REF_PIPE_PHY0_PLL_SRC },
4226 	},
4227 	{
4228 		RK3588_CLK_REF_PIPE_PHY1, RK3588_CRU_CLKSEL_CON(177),
4229 		SEL(7, 7), 0,
4230 		{ RK3588_CLK_REF_PIPE_PHY1_OSC_SRC,
4231 		  RK3588_CLK_REF_PIPE_PHY1_PLL_SRC },
4232 	},
4233 	{
4234 		RK3588_CLK_REF_PIPE_PHY2, RK3588_CRU_CLKSEL_CON(177),
4235 		SEL(8, 8), 0,
4236 		{ RK3588_CLK_REF_PIPE_PHY2_OSC_SRC,
4237 		  RK3588_CLK_REF_PIPE_PHY2_PLL_SRC },
4238 	},
4239 	{
4240 		/* Sentinel */
4241 	}
4242 };
4243 
4244 /* Certain test clocks are disabled. */
4245 const uint32_t rk3588_gates[78] = {
4246 	[2] = 0x00000050,
4247 	[22] = 0x00000200,
4248 	[25] = 0x00000200,
4249 	[29] = 0x00000004,
4250 	[66] = 0x00000004,
4251 };
4252 
4253 void
4254 rk3588_init(struct rkclock_softc *sc)
4255 {
4256 	int i;
4257 
4258 	/* The code below assumes all clocks are enabled.  Check this!. */
4259 	for (i = 0; i < nitems(rk3588_gates); i++) {
4260 		if (HREAD4(sc, RK3588_CRU_GATE_CON(i)) != rk3588_gates[i]) {
4261 			printf("CRU_GATE_CON%d: 0x%08x\n", i,
4262 			    HREAD4(sc, RK3588_CRU_GATE_CON(i)));
4263 		}
4264 	}
4265 
4266 	sc->sc_clocks = rk3588_clocks;
4267 }
4268 
4269 int
4270 rk3588_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
4271 {
4272 	uint32_t p, m, s, k;
4273 	int mode_shift = -1;
4274 
4275 	switch (base) {
4276 	case RK3588_CRU_AUPLL_CON(0):
4277 		mode_shift = 6;
4278 		break;
4279 	case RK3588_CRU_GPLL_CON(0):
4280 		mode_shift = 2;
4281 		break;
4282 	case RK3588_CRU_NPLL_CON(0):
4283 		mode_shift = 0;
4284 		break;
4285 	case RK3588_PHPTOPCRU_PPLL_CON(0):
4286 		mode_shift = 10;
4287 		break;
4288 	}
4289 	KASSERT(mode_shift != -1);
4290 
4291 	/*
4292 	 * It is not clear whether all combinations of the clock
4293 	 * dividers result in a stable clock.  Therefore this function
4294 	 * only supports a limited set of PLL clock rates.
4295 	 */
4296 	switch (freq) {
4297 	case 1188000000U:
4298 		p = 2; m = 198; s = 1; k = 0;
4299 		break;
4300 	case 1100000000U:
4301 		p = 3; m = 550; s = 2; k = 0;
4302 		break;
4303 	case 850000000U:
4304 		p = 3; m = 425; s = 2; k = 0;
4305 		break;
4306 	case 786432000U:
4307 		p = 2; m = 262; s = 2; k = 9437;
4308 		break;
4309 	case 100000000U:
4310 		p = 3; m = 400; s = 5; k = 0;
4311 		break;
4312 	default:
4313 		printf("%s: %u Hz\n", __func__, freq);
4314 		return -1;
4315 	}
4316 
4317 	/*
4318 	 * Select slow mode to guarantee a stable clock while we're
4319 	 * adjusting the PLL.
4320 	 */
4321 	HWRITE4(sc, RK3588_CRU_MODE_CON,
4322 	    (RK3588_CRU_MODE_MASK << 16 |RK3588_CRU_MODE_SLOW) << mode_shift);
4323 
4324 	/* Power down PLL. */
4325 	HWRITE4(sc, base + 0x0004,
4326 	    RK3588_CRU_PLL_RESETB << 16 | RK3588_CRU_PLL_RESETB);
4327 
4328 	/* Set PLL rate. */
4329 	HWRITE4(sc, base + 0x0000,
4330 	    RK3588_CRU_PLL_M_MASK << 16 | m << RK3588_CRU_PLL_M_SHIFT);
4331 	HWRITE4(sc, base + 0x0004,
4332 	    RK3588_CRU_PLL_S_MASK << 16 | s << RK3588_CRU_PLL_S_SHIFT |
4333 	    RK3588_CRU_PLL_P_MASK << 16 | p << RK3588_CRU_PLL_P_SHIFT);
4334 	HWRITE4(sc, base + 0x0008,
4335 	    RK3588_CRU_PLL_K_MASK << 16 | k << RK3588_CRU_PLL_K_SHIFT);
4336 
4337 	/* Power up PLL. */
4338 	HWRITE4(sc, base + 0x0004, RK3588_CRU_PLL_RESETB << 16);
4339 
4340 	/* Wait for PLL to stabilize. */
4341 	while ((HREAD4(sc, base + 0x0018) & RK3588_CRU_PLL_PLL_LOCK) == 0)
4342 		delay(10);
4343 
4344 	/* Switch back to normal mode. */
4345 	HWRITE4(sc, RK3588_CRU_MODE_CON,
4346 	    (RK3588_CRU_MODE_MASK << 16 | RK3588_CRU_MODE_NORMAL) << mode_shift);
4347 
4348 	return 0;
4349 }
4350 
4351 uint32_t
4352 rk3588_get_pll(struct rkclock_softc *sc, bus_size_t base)
4353 {
4354 	uint64_t freq, frac;
4355 	uint32_t k, m, p, s;
4356 	uint32_t reg;
4357 
4358 	reg = HREAD4(sc, base);
4359 	m = (reg & RK3588_CRU_PLL_M_MASK) >> RK3588_CRU_PLL_M_SHIFT;
4360 	reg = HREAD4(sc, base + 4);
4361 	p = (reg & RK3588_CRU_PLL_P_MASK) >> RK3588_CRU_PLL_P_SHIFT;
4362 	s = (reg & RK3588_CRU_PLL_S_MASK) >> RK3588_CRU_PLL_S_SHIFT;
4363 	reg = HREAD4(sc, base + 8);
4364 	k = (reg & RK3588_CRU_PLL_K_MASK) >> RK3588_CRU_PLL_K_SHIFT;
4365 
4366 	freq = (24000000ULL * m) / p;
4367 	if (k) {
4368 		frac = ((24000000ULL * k) / (p * 65535));
4369 		freq += frac;
4370 	}
4371 
4372 	return freq >> s;
4373 }
4374 
4375 uint32_t
4376 rk3588_get_frequency(void *cookie, uint32_t *cells)
4377 {
4378 	struct rkclock_softc *sc = cookie;
4379 	uint32_t idx = cells[0];
4380 	uint32_t freq;
4381 
4382 	switch (idx) {
4383 	case RK3588_PLL_AUPLL:
4384 		return rk3588_get_pll(sc, RK3588_CRU_AUPLL_CON(0));
4385 	case RK3588_PLL_CPLL:
4386 		return rk3588_get_pll(sc, RK3588_CRU_CPLL_CON(0));
4387 	case RK3588_PLL_GPLL:
4388 		return rk3588_get_pll(sc, RK3588_CRU_GPLL_CON(0));
4389 	case RK3588_PLL_NPLL:
4390 		return rk3588_get_pll(sc, RK3588_CRU_NPLL_CON(0));
4391 	case RK3588_PLL_PPLL:
4392 		return rk3588_get_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0));
4393 	case RK3588_PLL_SPLL:
4394 		return rkclock_external_frequency("spll");
4395 	case RK3588_XIN24M:
4396 		return 24000000;
4397 	default:
4398 		break;
4399 	}
4400 
4401 	freq = rkclock_get_frequency(sc, idx);
4402 	return freq;
4403 }
4404 
4405 int
4406 rk3588_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
4407 {
4408 	struct rkclock_softc *sc = cookie;
4409 	uint32_t idx = cells[0];
4410 
4411 	switch (idx) {
4412 	case RK3588_PLL_AUPLL:
4413 		return rk3588_set_pll(sc, RK3588_CRU_AUPLL_CON(0), freq);
4414 	case RK3588_PLL_GPLL:
4415 		return rk3588_set_pll(sc, RK3588_CRU_GPLL_CON(0), freq);
4416 	case RK3588_PLL_NPLL:
4417 		return rk3588_set_pll(sc, RK3588_CRU_NPLL_CON(0), freq);
4418 	case RK3588_PLL_PPLL:
4419 		return rk3588_set_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0), freq);
4420 	default:
4421 		break;
4422 	}
4423 
4424 	return rkclock_set_frequency(sc, idx, freq);
4425 }
4426 
4427 void
4428 rk3588_enable(void *cookie, uint32_t *cells, int on)
4429 {
4430 	uint32_t idx = cells[0];
4431 
4432 	/* All clocks are enabled upon hardware reset. */
4433 	if (!on) {
4434 		printf("%s: 0x%08x\n", __func__, idx);
4435 		return;
4436 	}
4437 }
4438 
4439 void
4440 rk3588_reset(void *cookie, uint32_t *cells, int on)
4441 {
4442 	struct rkclock_softc *sc = cookie;
4443 	uint32_t idx = cells[0];
4444 	uint32_t bit, mask, reg;
4445 
4446 	switch (idx) {
4447 	case RK3588_SRST_PCIE0_POWER_UP:
4448 		reg = RK3588_CRU_SOFTRST_CON(32);
4449 		bit = 13;
4450 		break;
4451 	case RK3588_SRST_PCIE1_POWER_UP:
4452 		reg = RK3588_CRU_SOFTRST_CON(32);
4453 		bit = 14;
4454 		break;
4455 	case RK3588_SRST_PCIE2_POWER_UP:
4456 		reg = RK3588_CRU_SOFTRST_CON(32);
4457 		bit = 15;
4458 		break;
4459 	case RK3588_SRST_PCIE3_POWER_UP:
4460 		reg = RK3588_CRU_SOFTRST_CON(33);
4461 		bit = 0;
4462 		break;
4463 	case RK3588_SRST_PCIE4_POWER_UP:
4464 		reg = RK3588_CRU_SOFTRST_CON(33);
4465 		bit = 1;
4466 		break;
4467 	case RK3588_SRST_P_PCIE0:
4468 		reg = RK3588_CRU_SOFTRST_CON(33);
4469 		bit = 12;
4470 		break;
4471 	case RK3588_SRST_P_PCIE1:
4472 		reg = RK3588_CRU_SOFTRST_CON(33);
4473 		bit = 13;
4474 		break;
4475 	case RK3588_SRST_P_PCIE2:
4476 		reg = RK3588_CRU_SOFTRST_CON(33);
4477 		bit = 14;
4478 		break;
4479 	case RK3588_SRST_P_PCIE3:
4480 		reg = RK3588_CRU_SOFTRST_CON(33);
4481 		bit = 15;
4482 		break;
4483 	case RK3588_SRST_P_PCIE4:
4484 		reg = RK3588_CRU_SOFTRST_CON(34);
4485 		bit = 0;
4486 		break;
4487 	case RK3588_SRST_A_USB3OTG2:
4488 		reg = RK3588_CRU_SOFTRST_CON(35);
4489 		bit = 7;
4490 		break;
4491 	case RK3588_SRST_A_USB3OTG0:
4492 		reg = RK3588_CRU_SOFTRST_CON(42);
4493 		bit = 4;
4494 		break;
4495 	case RK3588_SRST_A_USB3OTG1:
4496 		reg = RK3588_CRU_SOFTRST_CON(42);
4497 		bit = 7;
4498 		break;
4499 	case RK3588_SRST_REF_PIPE_PHY0:
4500 		reg = RK3588_CRU_SOFTRST_CON(77);
4501 		bit = 6;
4502 		break;
4503 	case RK3588_SRST_REF_PIPE_PHY1:
4504 		reg = RK3588_CRU_SOFTRST_CON(77);
4505 		bit = 7;
4506 		break;
4507 	case RK3588_SRST_REF_PIPE_PHY2:
4508 		reg = RK3588_CRU_SOFTRST_CON(77);
4509 		bit = 8;
4510 		break;
4511 	case RK3588_SRST_P_PCIE2_PHY0:
4512 		reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4513 		bit = 5;
4514 		break;
4515 	case RK3588_SRST_P_PCIE2_PHY1:
4516 		reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4517 		bit = 6;
4518 		break;
4519 	case RK3588_SRST_P_PCIE2_PHY2:
4520 		reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4521 		bit = 7;
4522 		break;
4523 	case RK3588_SRST_PCIE30_PHY:
4524 		reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4525 		bit = 10;
4526 		break;
4527 	default:
4528 		printf("%s: 0x%08x\n", __func__, idx);
4529 		return;
4530 	}
4531 
4532 	mask = (1 << bit);
4533 	HWRITE4(sc, reg, mask << 16 | (on ? mask : 0));
4534 }
4535