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