xref: /openbsd-src/sys/dev/fdt/amlclock.c (revision 09467b48e8bc8b4905716062da846024139afbf2)
1 /*	$OpenBSD: amlclock.c,v 1.11 2020/05/18 10:40:38 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2019 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/device.h>
21 
22 #include <machine/intr.h>
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_clock.h>
28 #include <dev/ofw/ofw_misc.h>
29 #include <dev/ofw/fdt.h>
30 
31 /* Clock IDs */
32 #define G12A_SYS_PLL		0
33 #define G12A_FCLK_DIV2		2
34 #define G12A_FCLK_DIV3		3
35 #define G12A_FCLK_DIV4		4
36 #define G12A_FCLK_DIV5		5
37 #define G12A_FCLK_DIV7		6
38 #define G12A_MPLL1		12
39 #define G12A_MPLL2		13
40 #define G12A_I2C		24
41 #define G12A_SD_EMMC_A		33
42 #define G12A_SD_EMMC_B		34
43 #define G12A_SD_EMMC_C		35
44 #define G12A_SD_EMMC_A_CLK0	60
45 #define G12A_SD_EMMC_B_CLK0	61
46 #define G12A_SD_EMMC_C_CLK0	62
47 #define G12A_USB		47
48 #define G12A_FCLK_DIV2P5	99
49 #define G12A_CPU_CLK		187
50 #define G12A_PCIE_PLL		201
51 #define G12A_TS			212
52 #define G12B_SYS1_PLL		214
53 #define G12B_CPUB_CLK		224
54 
55 /* Registers */
56 #define HHI_PCIE_PLL_CNTL0	0x26
57 #define HHI_PCIE_PLL_CNTL1	0x27
58 #define HHI_PCIE_PLL_CNTL2	0x28
59 #define HHI_PCIE_PLL_CNTL3	0x29
60 #define HHI_PCIE_PLL_CNTL4	0x2a
61 #define HHI_PCIE_PLL_CNTL5	0x2b
62 #define HHI_GCLK_MPEG0		0x50
63 #define HHI_GCLK_MPEG1		0x51
64 #define HHI_MPEG_CLK_CNTL	0x5d
65 #define HHI_TS_CLK_CNTL		0x64
66 #define HHI_SYS_CPU_CLK_CNTL0	0x67
67 #define  HHI_SYS_CPU_CLK_DYN_ENABLE		(1 << 26)
68 #define  HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT(x)	(((x) >> 20) & 0x3f)
69 #define  HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_MASK	(0x3f << 20)
70 #define  HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_SHIFT	20
71 #define  HHI_SYS_CPU_CLK_POSTMUX1		(1 << 18)
72 #define  HHI_SYS_CPU_CLK_PREMUX1(x)		(((x) >> 16) & 0x3)
73 #define  HHI_SYS_CPU_CLK_PREMUX1_MASK		(0x3 << 16)
74 #define  HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV2	(0x1 << 16)
75 #define  HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV3	(0x2 << 16)
76 #define  HHI_SYS_CPU_CLK_FINAL_MUX_SEL		(1 << 11)
77 #define  HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL	(1 << 10)
78 #define  HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT(x)	(((x) >> 4) & 0x3f)
79 #define  HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_MASK	(0x3f << 4)
80 #define  HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_SHIFT	4
81 #define  HHI_SYS_CPU_CLK_POSTMUX0		(1 << 2)
82 #define  HHI_SYS_CPU_CLK_PREMUX0(x)		(((x) >> 0) & 0x3)
83 #define  HHI_SYS_CPU_CLK_PREMUX0_MASK		(0x3 << 0)
84 #define  HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV2	(0x1 << 0)
85 #define  HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV3	(0x2 << 0)
86 #define HHI_SYS_CPUB_CLK_CNTL	0x82
87 #define HHI_NAND_CLK_CNTL	0x97
88 #define HHI_SD_EMMC_CLK_CNTL	0x99
89 #define HHI_SYS_PLL_CNTL0	0xbd
90 #define  HHI_SYS_DPLL_LOCK	(1 << 31)
91 #define  HHI_SYS_DPLL_RESET	(1 << 29)
92 #define  HHI_SYS_DPLL_EN	(1 << 28)
93 #define  HHI_SYS_DPLL_OD(x)	(((x) >> 16) & 0x7)
94 #define  HHI_SYS_DPLL_OD_MASK	(0x7 << 16)
95 #define  HHI_SYS_DPLL_OD_SHIFT	16
96 #define  HHI_SYS_DPLL_N(x)	(((x) >> 10) & 0x1f)
97 #define  HHI_SYS_DPLL_N_MASK	(0x1f << 10)
98 #define  HHI_SYS_DPLL_N_SHIFT	10
99 #define  HHI_SYS_DPLL_M(x)	(((x) >> 0) & 0xff)
100 #define  HHI_SYS_DPLL_M_MASK	(0xff << 0)
101 #define  HHI_SYS_DPLL_M_SHIFT	0
102 #define HHI_SYS1_PLL_CNTL0	0xe0
103 
104 #define HREAD4(sc, reg)							\
105 	(regmap_read_4((sc)->sc_rm, (reg) << 2))
106 #define HWRITE4(sc, reg, val)						\
107 	regmap_write_4((sc)->sc_rm, (reg) << 2, (val))
108 #define HSET4(sc, reg, bits)						\
109 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
110 #define HCLR4(sc, reg, bits)						\
111 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
112 
113 struct amlclock_gate {
114 	uint8_t reg;
115 	uint8_t bit;
116 };
117 
118 struct amlclock_gate aml_g12a_gates[] = {
119 	[G12A_I2C] = { HHI_GCLK_MPEG0, 9 },
120 	[G12A_SD_EMMC_A] = { HHI_GCLK_MPEG0, 24 },
121 	[G12A_SD_EMMC_B] = { HHI_GCLK_MPEG0, 25 },
122 	[G12A_SD_EMMC_C] = { HHI_GCLK_MPEG0, 26 },
123 	[G12A_USB] = { HHI_GCLK_MPEG1, 26 },
124 
125 	[G12A_SD_EMMC_A_CLK0] = { HHI_SD_EMMC_CLK_CNTL, 7 },
126 	[G12A_SD_EMMC_B_CLK0] = { HHI_SD_EMMC_CLK_CNTL, 23 },
127 	[G12A_SD_EMMC_C_CLK0] = { HHI_NAND_CLK_CNTL, 7 },
128 
129 	[G12A_TS] = { HHI_TS_CLK_CNTL, 8 },
130 };
131 
132 struct amlclock_softc {
133 	struct device		sc_dev;
134 	struct regmap		*sc_rm;
135 	int			sc_node;
136 	uint32_t		sc_g12b;
137 
138 	struct amlclock_gate	*sc_gates;
139 	int			sc_ngates;
140 
141 	struct clock_device	sc_cd;
142 	uint32_t		sc_xtal;
143 };
144 
145 int amlclock_match(struct device *, void *, void *);
146 void amlclock_attach(struct device *, struct device *, void *);
147 
148 struct cfattach	amlclock_ca = {
149 	sizeof (struct amlclock_softc), amlclock_match, amlclock_attach
150 };
151 
152 struct cfdriver amlclock_cd = {
153 	NULL, "amlclock", DV_DULL
154 };
155 
156 uint32_t amlclock_get_frequency(void *, uint32_t *);
157 int	amlclock_set_frequency(void *, uint32_t *, uint32_t);
158 void	amlclock_enable(void *, uint32_t *, int);
159 
160 int
161 amlclock_match(struct device *parent, void *match, void *aux)
162 {
163 	struct fdt_attach_args *faa = aux;
164 
165 	return (OF_is_compatible(faa->fa_node, "amlogic,g12a-clkc") ||
166 	    OF_is_compatible(faa->fa_node, "amlogic,g12b-clkc") ||
167 	    OF_is_compatible(faa->fa_node, "amlogic,sm1-clkc"));
168 }
169 
170 void
171 amlclock_attach(struct device *parent, struct device *self, void *aux)
172 {
173 	struct amlclock_softc *sc = (struct amlclock_softc *)self;
174 	struct fdt_attach_args *faa = aux;
175 
176 	sc->sc_rm = regmap_bynode(OF_parent(faa->fa_node));
177 	if (sc->sc_rm == NULL) {
178 		printf(": no registers\n");
179 		return;
180 	}
181 
182 	sc->sc_node = faa->fa_node;
183 	printf("\n");
184 
185 	if (OF_is_compatible(faa->fa_node, "amlogic,g12b-clkc"))
186 		sc->sc_g12b = 1;
187 
188 	sc->sc_gates = aml_g12a_gates;
189 	sc->sc_ngates = nitems(aml_g12a_gates);
190 
191 	sc->sc_xtal = clock_get_frequency(sc->sc_node, "xtal");
192 
193 	sc->sc_cd.cd_node = faa->fa_node;
194 	sc->sc_cd.cd_cookie = sc;
195 	sc->sc_cd.cd_get_frequency = amlclock_get_frequency;
196 	sc->sc_cd.cd_set_frequency = amlclock_set_frequency;
197 	sc->sc_cd.cd_enable = amlclock_enable;
198 	clock_register(&sc->sc_cd);
199 }
200 
201 uint32_t
202 amlclock_get_cpu_freq(struct amlclock_softc *sc, bus_size_t offset)
203 {
204 	uint32_t reg, mux, div;
205 	uint32_t idx;
206 
207 	reg = HREAD4(sc, offset);
208 	if (reg & HHI_SYS_CPU_CLK_FINAL_MUX_SEL) {
209 		if (sc->sc_g12b && offset == HHI_SYS_CPU_CLK_CNTL0)
210 			idx = G12B_SYS1_PLL;
211 		else
212 			idx = G12A_SYS_PLL;
213 		return amlclock_get_frequency(sc, &idx);
214 	}
215 	if (reg & HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL) {
216 		div = (reg & HHI_SYS_CPU_CLK_POSTMUX1) ?
217 		    (HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT(reg) + 1) : 1;
218 		mux = HHI_SYS_CPU_CLK_PREMUX1(reg);
219 	} else {
220 		div = (reg & HHI_SYS_CPU_CLK_POSTMUX0) ?
221 		    (HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT(reg) + 1) : 1;
222 		mux = HHI_SYS_CPU_CLK_PREMUX0(reg);
223 	}
224 	switch (mux) {
225 	case 0:
226 		return sc->sc_xtal / div;
227 	case 1:
228 		idx = G12A_FCLK_DIV2;
229 		break;
230 	case 2:
231 		idx = G12A_FCLK_DIV3;
232 		break;
233 	case 3:
234 		return 0;
235 	}
236 	return amlclock_get_frequency(sc, &idx) / div;
237 }
238 
239 int
240 amlclock_set_cpu_freq(struct amlclock_softc *sc, bus_size_t offset,
241     uint32_t freq)
242 {
243 	uint32_t reg, div;
244 	uint32_t parent_freq;
245 	uint32_t idx;
246 
247 	/*
248 	 * For clock frequencies above 1GHz we have to use
249 	 * SYS_PLL/SYS1_PLL.
250 	 */
251 	reg = HREAD4(sc, offset);
252 	if (freq > 1000000000) {
253 		/*
254 		 * Switch to a fixed clock if we're currently using
255 		 * SYS_PLL/SYS1_PLL.  Doesn't really matter which one.
256 		 */
257 		if (reg & HHI_SYS_CPU_CLK_FINAL_MUX_SEL) {
258 			reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL;
259 			HWRITE4(sc, offset, reg);
260 			delay(100);
261 		}
262 
263 		if (sc->sc_g12b && offset == HHI_SYS_CPU_CLK_CNTL0)
264 			idx = G12B_SYS1_PLL;
265 		else
266 			idx = G12A_SYS_PLL;
267 		amlclock_set_frequency(sc, &idx, freq);
268 
269 		/* Switch to SYS_PLL/SYS1_PLL. */
270 		reg |= HHI_SYS_CPU_CLK_FINAL_MUX_SEL;
271 		HWRITE4(sc, offset, reg);
272 		delay(100);
273 
274 		return 0;
275 	}
276 
277 	/*
278 	 * There are two signal paths for frequencies up to 1GHz.  If
279 	 * we're using one, we can program the dividers for the other
280 	 * one and switch to it.  The pre-divider can be either 2 or 3
281 	 * and can't be bypassed, so take this into account and only
282 	 * allow frequencies that include such a divider.
283 	 */
284 	div = 2;
285 	parent_freq = 2000000000;
286 	while (parent_freq / div > freq)
287 		div++;
288 	while ((div % 2) != 0 && (div % 3) != 0)
289 		div++;
290 	if (div > 32)
291 		return EINVAL;
292 	if ((div % 2) == 0) {
293 		parent_freq /= 2;
294 		div /= 2;
295 	} else {
296 		parent_freq /= 3;
297 		div /= 3;
298 	}
299 
300 	if (reg & HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL) {
301 		/* premux0 */
302 		reg = HREAD4(sc, offset);
303 		reg &= ~HHI_SYS_CPU_CLK_PREMUX0_MASK;
304 		if (parent_freq == 1000000000)
305 			reg |= HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV2;
306 		else
307 			reg |= HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV3;
308 		HWRITE4(sc, offset, reg);
309 		delay(100);
310 
311 		/* mux0 divider */
312 		HSET4(sc, offset, HHI_SYS_CPU_CLK_DYN_ENABLE);
313 		reg = HREAD4(sc, offset);
314 		reg &= ~HHI_SYS_CPU_CLK_DYN_ENABLE;
315 		reg &= ~HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_MASK;
316 		reg |= ((div - 1) << HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_SHIFT);
317 		HWRITE4(sc, offset, reg);
318 
319 		/* postmux0 */
320 		if (div != 1)
321 			HSET4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX0);
322 		else
323 			HCLR4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX0);
324 
325 		/* final_dyn_mux_sel and final_mux_sel */
326 		reg = HREAD4(sc, offset);
327 		reg &= ~HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL;
328 		reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL;
329 		HWRITE4(sc, offset, reg);
330 		delay(100);
331 	} else {
332 		/* premux1 */
333 		reg = HREAD4(sc, offset);
334 		reg &= ~HHI_SYS_CPU_CLK_PREMUX1_MASK;
335 		if (parent_freq == 1000000000)
336 			reg |= HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV2;
337 		else
338 			reg |= HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV3;
339 		HWRITE4(sc, offset, reg);
340 		delay(100);
341 
342 		/* mux1 divider */
343 		HSET4(sc, offset, HHI_SYS_CPU_CLK_DYN_ENABLE);
344 		reg = HREAD4(sc, offset);
345 		reg &= ~HHI_SYS_CPU_CLK_DYN_ENABLE;
346 		reg &= ~HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_MASK;
347 		reg |= ((div - 1) << HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_SHIFT);
348 		HWRITE4(sc, offset, reg);
349 
350 		/* postmux1 */
351 		if (div != 1)
352 			HSET4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX1);
353 		else
354 			HCLR4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX1);
355 
356 		/* final_dyn_mux_sel and final_mux_sel */
357 		reg = HREAD4(sc, offset);
358 		reg |= HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL;
359 		reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL;
360 		HWRITE4(sc, offset, reg);
361 		delay(100);
362 	}
363 
364 	return 0;
365 }
366 
367 int
368 amlclock_set_pll_freq(struct amlclock_softc *sc, bus_size_t offset,
369     uint32_t freq)
370 {
371 	uint32_t reg, div;
372 	uint32_t m, n = 1;
373 	int timo;
374 
375 	/*
376 	 * The multiplier should be between 128 and 255.  If
377 	 * necessary, adjust the divider to achieve this.
378 	 */
379 	div = 1;
380 	while ((div * (uint64_t)freq) / sc->sc_xtal < 128)
381 		div *= 2;
382 	if (div > 128)
383 		return EINVAL;
384 	m = (div * (uint64_t)freq) / sc->sc_xtal;
385 	if (m > 255)
386 		return EINVAL;
387 
388 	HSET4(sc, offset, HHI_SYS_DPLL_RESET);
389 	HCLR4(sc, offset, HHI_SYS_DPLL_EN);
390 
391 	reg = HREAD4(sc, offset);
392 	reg &= ~HHI_SYS_DPLL_OD_MASK;
393 	reg |= ((fls(div) - 1) << HHI_SYS_DPLL_OD_SHIFT);
394 	reg &= ~(HHI_SYS_DPLL_M_MASK | HHI_SYS_DPLL_N_MASK);
395 	reg |= (m << HHI_SYS_DPLL_M_SHIFT);
396 	reg |= (n << HHI_SYS_DPLL_N_SHIFT);
397 	HWRITE4(sc, offset, reg);
398 
399 	HSET4(sc, offset, HHI_SYS_DPLL_RESET);
400 	HSET4(sc, offset, HHI_SYS_DPLL_EN);
401 	HCLR4(sc, offset, HHI_SYS_DPLL_RESET);
402 
403 	for (timo = 24000000; timo > 0; timo--) {
404 		if (HREAD4(sc, offset) & HHI_SYS_DPLL_LOCK)
405 			return 0;
406 	}
407 
408 	return ETIMEDOUT;
409 }
410 
411 uint32_t
412 amlclock_get_frequency(void *cookie, uint32_t *cells)
413 {
414 	struct amlclock_softc *sc = cookie;
415 	uint32_t idx = cells[0];
416 	uint32_t reg, mux, div;
417 	uint32_t m, n;
418 
419 	switch (idx) {
420 	case G12A_SYS_PLL:
421 		reg = HREAD4(sc, HHI_SYS_PLL_CNTL0);
422 		div = 1 << HHI_SYS_DPLL_OD(reg);
423 		m = HHI_SYS_DPLL_M(reg);
424 		n = HHI_SYS_DPLL_N(reg);
425 		return (((uint64_t)sc->sc_xtal * m) / n) / div;
426 	case G12B_SYS1_PLL:
427 		reg = HREAD4(sc, HHI_SYS1_PLL_CNTL0);
428 		div = 1 << HHI_SYS_DPLL_OD(reg);
429 		m = HHI_SYS_DPLL_M(reg);
430 		n = HHI_SYS_DPLL_N(reg);
431 		return (((uint64_t)sc->sc_xtal * m) / n) / div;
432 	case G12A_FCLK_DIV2:
433 		return 1000000000;
434 	case G12A_FCLK_DIV3:
435 		return 666666666;
436 	case G12A_FCLK_DIV4:
437 		return 500000000;
438 	case G12A_FCLK_DIV5:
439 		return 400000000;
440 	case G12A_FCLK_DIV7:
441 		return 285714285;
442 	case G12A_FCLK_DIV2P5:
443 		return 800000000;
444 
445 	case G12A_I2C:
446 		reg = HREAD4(sc, HHI_MPEG_CLK_CNTL);
447 		mux = (reg >> 12) & 0x7;
448 		div = ((reg >> 0) & 0x7f) + 1;
449 		switch (mux) {
450 		case 0:
451 			return sc->sc_xtal / div;
452 		case 2:
453 			idx = G12A_FCLK_DIV7;
454 			break;
455 		case 3:
456 			idx = G12A_MPLL1;
457 			break;
458 		case 4:
459 			idx = G12A_MPLL2;
460 			break;
461 		case 5:
462 			idx = G12A_FCLK_DIV4;
463 			break;
464 		case 6:
465 			idx = G12A_FCLK_DIV3;
466 			break;
467 		case 7:
468 			idx = G12A_FCLK_DIV5;
469 			break;
470 		default:
471 			goto fail;
472 		}
473 		return amlclock_get_frequency(sc, &idx) / div;
474 	case G12A_SD_EMMC_A_CLK0:
475 		reg = HREAD4(sc, HHI_SD_EMMC_CLK_CNTL);
476 		mux = (reg >> 9) & 0x7;
477 		div = ((reg >> 0) & 0x7f) + 1;
478 		switch (mux) {
479 		case 0:
480 			return sc->sc_xtal / div;
481 		case 1:
482 			idx = G12A_FCLK_DIV2;
483 			break;
484 		case 2:
485 			idx = G12A_FCLK_DIV3;
486 			break;
487 		case 3:
488 			idx = G12A_FCLK_DIV5;
489 			break;
490 		case 4:
491 			idx = G12A_FCLK_DIV7;
492 			break;
493 		default:
494 			goto fail;
495 		}
496 		return amlclock_get_frequency(sc, &idx) / div;
497 	case G12A_SD_EMMC_B_CLK0:
498 		reg = HREAD4(sc, HHI_SD_EMMC_CLK_CNTL);
499 		mux = (reg >> 25) & 0x7;
500 		div = ((reg >> 16) & 0x7f) + 1;
501 		switch (mux) {
502 		case 0:
503 			return sc->sc_xtal / div;
504 		case 1:
505 			idx = G12A_FCLK_DIV2;
506 			break;
507 		case 2:
508 			idx = G12A_FCLK_DIV3;
509 			break;
510 		case 3:
511 			idx = G12A_FCLK_DIV5;
512 			break;
513 		case 4:
514 			idx = G12A_FCLK_DIV7;
515 			break;
516 		default:
517 			goto fail;
518 		}
519 		return amlclock_get_frequency(sc, &idx) / div;
520 	case G12A_SD_EMMC_C_CLK0:
521 		reg = HREAD4(sc, HHI_NAND_CLK_CNTL);
522 		mux = (reg >> 9) & 0x7;
523 		div = ((reg >> 0) & 0x7f) + 1;
524 		switch (mux) {
525 		case 0:
526 			return sc->sc_xtal / div;
527 		case 1:
528 			idx = G12A_FCLK_DIV2;
529 			break;
530 		case 2:
531 			idx = G12A_FCLK_DIV3;
532 			break;
533 		case 3:
534 			idx = G12A_FCLK_DIV5;
535 			break;
536 		case 4:
537 			idx = G12A_FCLK_DIV7;
538 			break;
539 		default:
540 			goto fail;
541 		}
542 		return amlclock_get_frequency(sc, &idx) / div;
543 	case G12A_CPU_CLK:
544 		return amlclock_get_cpu_freq(sc, HHI_SYS_CPU_CLK_CNTL0);
545 	case G12B_CPUB_CLK:
546 		return amlclock_get_cpu_freq(sc, HHI_SYS_CPUB_CLK_CNTL);
547 	}
548 
549 fail:
550 	printf("%s: 0x%08x\n", __func__, idx);
551 	return 0;
552 }
553 
554 int
555 amlclock_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
556 {
557 	struct amlclock_softc *sc = cookie;
558 	uint32_t idx = cells[0];
559 
560 	switch (idx) {
561 	case G12A_SYS_PLL:
562 		return amlclock_set_pll_freq(sc, HHI_SYS_PLL_CNTL0, freq);
563 	case G12B_SYS1_PLL:
564 		return amlclock_set_pll_freq(sc, HHI_SYS1_PLL_CNTL0, freq);
565 	case G12A_PCIE_PLL:
566 		/* Fixed at 100 MHz. */
567 		if (freq != 100000000)
568 			return -1;
569 		HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x20090496);
570 		HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x30090496);
571 		HWRITE4(sc, HHI_PCIE_PLL_CNTL1, 0x00000000);
572 		HWRITE4(sc, HHI_PCIE_PLL_CNTL2, 0x00001100);
573 		HWRITE4(sc, HHI_PCIE_PLL_CNTL3, 0x10058e00);
574 		HWRITE4(sc, HHI_PCIE_PLL_CNTL4, 0x000100c0);
575 		HWRITE4(sc, HHI_PCIE_PLL_CNTL5, 0x68000048);
576 		HWRITE4(sc, HHI_PCIE_PLL_CNTL5, 0x68000068);
577 		delay(20);
578 		HWRITE4(sc, HHI_PCIE_PLL_CNTL4, 0x008100c0);
579 		delay(10);
580 		HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x34090496);
581 		HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x14090496);
582 		delay(10);
583 		HWRITE4(sc, HHI_PCIE_PLL_CNTL2, 0x00001000);
584 		return 0;
585 	case G12A_CPU_CLK:
586 		return amlclock_set_cpu_freq(sc, HHI_SYS_CPU_CLK_CNTL0, freq);
587 	case G12B_CPUB_CLK:
588 		return amlclock_set_cpu_freq(sc, HHI_SYS_CPUB_CLK_CNTL, freq);
589 	}
590 
591 	printf("%s: 0x%08x\n", __func__, idx);
592 	return -1;
593 }
594 
595 void
596 amlclock_enable(void *cookie, uint32_t *cells, int on)
597 {
598 	struct amlclock_softc *sc = cookie;
599 	uint32_t idx = cells[0];
600 
601 	if (idx < sc->sc_ngates && sc->sc_gates[idx].reg != 0) {
602 		if (on)
603 			HSET4(sc, sc->sc_gates[idx].reg,
604 			    (1U << sc->sc_gates[idx].bit));
605 		else
606 			HCLR4(sc, sc->sc_gates[idx].reg,
607 			    (1U << sc->sc_gates[idx].bit));
608 		return;
609 	}
610 
611 	switch (idx) {
612 	case G12A_FCLK_DIV2:
613 	case G12A_PCIE_PLL:
614 		/* Already enabled. */
615 		return;
616 	}
617 
618 	printf("%s: 0x%08x\n", __func__, idx);
619 }
620