xref: /openbsd/sys/dev/fdt/sxiccmu.c (revision 95c4b0b5)
1 /*	$OpenBSD: sxiccmu.c,v 1.38 2024/03/07 01:04:16 kevlo Exp $	*/
2 /*
3  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
4  * Copyright (c) 2013 Artturi Alm
5  * Copyright (c) 2016,2017 Mark Kettenis <kettenis@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/kernel.h>
23 #include <sys/malloc.h>
24 #include <sys/time.h>
25 #include <sys/device.h>
26 
27 #include <machine/bus.h>
28 #include <machine/fdt.h>
29 #include <machine/intr.h>
30 
31 #include <dev/fdt/sunxireg.h>
32 
33 #include <dev/ofw/openfirm.h>
34 #include <dev/ofw/ofw_clock.h>
35 #include <dev/ofw/ofw_misc.h>
36 #include <dev/ofw/fdt.h>
37 
38 /* R40 */
39 #define R40_GMAC_CLK_REG		0x0164
40 
41 #ifdef DEBUG_CCMU
42 #define DPRINTF(x)	do { printf x; } while (0)
43 #else
44 #define DPRINTF(x)
45 #endif
46 
47 struct sxiccmu_ccu_bit {
48 	uint16_t reg;
49 	uint8_t bit;
50 	uint8_t parent;
51 };
52 
53 #include "sxiccmu_clocks.h"
54 
55 struct sxiccmu_softc {
56 	struct device		sc_dev;
57 	bus_space_tag_t		sc_iot;
58 	bus_space_handle_t	sc_ioh;
59 	int			sc_node;
60 
61 	const struct sxiccmu_ccu_bit *sc_gates;
62 	int			sc_ngates;
63 	struct clock_device	sc_cd;
64 
65 	const struct sxiccmu_ccu_bit *sc_resets;
66 	int			sc_nresets;
67 	struct reset_device	sc_rd;
68 
69 	uint32_t		(*sc_get_frequency)(struct sxiccmu_softc *,
70 				    uint32_t);
71 	int			(*sc_set_frequency)(struct sxiccmu_softc *,
72 				    uint32_t, uint32_t);
73 };
74 
75 int	sxiccmu_match(struct device *, void *, void *);
76 void	sxiccmu_attach(struct device *, struct device *, void *);
77 
78 const struct cfattach	sxiccmu_ca = {
79 	sizeof (struct sxiccmu_softc), sxiccmu_match, sxiccmu_attach
80 };
81 
82 struct cfdriver sxiccmu_cd = {
83 	NULL, "sxiccmu", DV_DULL
84 };
85 
86 void sxiccmu_attach_clock(struct sxiccmu_softc *, int, int);
87 
88 uint32_t sxiccmu_ccu_get_frequency(void *, uint32_t *);
89 int	sxiccmu_ccu_set_frequency(void *, uint32_t *, uint32_t);
90 void	sxiccmu_ccu_enable(void *, uint32_t *, int);
91 void	sxiccmu_ccu_reset(void *, uint32_t *, int);
92 
93 uint32_t sxiccmu_a10_get_frequency(struct sxiccmu_softc *, uint32_t);
94 int	sxiccmu_a10_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
95 uint32_t sxiccmu_a10s_get_frequency(struct sxiccmu_softc *, uint32_t);
96 int	sxiccmu_a10s_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
97 uint32_t sxiccmu_a23_get_frequency(struct sxiccmu_softc *, uint32_t);
98 int	sxiccmu_a23_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
99 uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *, uint32_t);
100 int	sxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
101 uint32_t sxiccmu_a80_get_frequency(struct sxiccmu_softc *, uint32_t);
102 int	sxiccmu_a80_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
103 uint32_t sxiccmu_d1_get_frequency(struct sxiccmu_softc *, uint32_t);
104 int	sxiccmu_d1_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
105 uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *, uint32_t);
106 int	sxiccmu_h3_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
107 uint32_t sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *, uint32_t);
108 uint32_t sxiccmu_h6_get_frequency(struct sxiccmu_softc *, uint32_t);
109 int	sxiccmu_h6_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
110 uint32_t sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *, uint32_t);
111 uint32_t sxiccmu_h616_get_frequency(struct sxiccmu_softc *, uint32_t);
112 int	sxiccmu_h616_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
113 uint32_t sxiccmu_h616_r_get_frequency(struct sxiccmu_softc *, uint32_t);
114 uint32_t sxiccmu_r40_get_frequency(struct sxiccmu_softc *, uint32_t);
115 int	sxiccmu_r40_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
116 uint32_t sxiccmu_v3s_get_frequency(struct sxiccmu_softc *, uint32_t);
117 int	sxiccmu_v3s_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
118 uint32_t sxiccmu_nop_get_frequency(struct sxiccmu_softc *, uint32_t);
119 int	sxiccmu_nop_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
120 
121 int
sxiccmu_match(struct device * parent,void * match,void * aux)122 sxiccmu_match(struct device *parent, void *match, void *aux)
123 {
124 	struct fdt_attach_args *faa = aux;
125 	int node = faa->fa_node;
126 
127 	if (node == OF_finddevice("/clocks")) {
128 		node = OF_parent(node);
129 
130 		return (OF_is_compatible(node, "allwinner,sun4i-a10") ||
131 		    OF_is_compatible(node, "allwinner,sun5i-a10s") ||
132 		    OF_is_compatible(node, "allwinner,sun5i-r8") ||
133 		    OF_is_compatible(node, "allwinner,sun7i-a20") ||
134 		    OF_is_compatible(node, "allwinner,sun8i-a23") ||
135 		    OF_is_compatible(node, "allwinner,sun8i-a33") ||
136 		    OF_is_compatible(node, "allwinner,sun8i-h3") ||
137 		    OF_is_compatible(node, "allwinner,sun8i-v3s") ||
138 		    OF_is_compatible(node, "allwinner,sun9i-a80") ||
139 		    OF_is_compatible(node, "allwinner,sun50i-a64") ||
140 		    OF_is_compatible(node, "allwinner,sun50i-h5"));
141 	}
142 
143 	return (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
144 	    OF_is_compatible(node, "allwinner,sun5i-a10s-ccu") ||
145 	    OF_is_compatible(node, "allwinner,sun5i-a13-ccu") ||
146 	    OF_is_compatible(node, "allwinner,sun7i-a20-ccu") ||
147 	    OF_is_compatible(node, "allwinner,sun8i-a23-ccu") ||
148 	    OF_is_compatible(node, "allwinner,sun8i-a23-prcm") ||
149 	    OF_is_compatible(node, "allwinner,sun8i-a33-ccu") ||
150 	    OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
151 	    OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") ||
152 	    OF_is_compatible(node, "allwinner,sun8i-r40-ccu") ||
153 	    OF_is_compatible(node, "allwinner,sun8i-v3s-ccu") ||
154 	    OF_is_compatible(node, "allwinner,sun9i-a80-ccu") ||
155 	    OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks") ||
156 	    OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk") ||
157 	    OF_is_compatible(node, "allwinner,sun20i-d1-ccu") ||
158 	    OF_is_compatible(node, "allwinner,sun50i-a64-ccu") ||
159 	    OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu") ||
160 	    OF_is_compatible(node, "allwinner,sun50i-h5-ccu") ||
161 	    OF_is_compatible(node, "allwinner,sun50i-h6-ccu") ||
162 	    OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu") ||
163 	    OF_is_compatible(node, "allwinner,sun50i-h616-ccu") ||
164 	    OF_is_compatible(node, "allwinner,sun50i-h616-r-ccu"));
165 }
166 
167 void
sxiccmu_attach(struct device * parent,struct device * self,void * aux)168 sxiccmu_attach(struct device *parent, struct device *self, void *aux)
169 {
170 	struct sxiccmu_softc *sc = (struct sxiccmu_softc *)self;
171 	struct fdt_attach_args *faa = aux;
172 	int node = faa->fa_node;
173 
174 	sc->sc_node = faa->fa_node;
175 	sc->sc_iot = faa->fa_iot;
176 	if (faa->fa_nreg > 0 && bus_space_map(sc->sc_iot,
177 	    faa->fa_reg[0].addr, faa->fa_reg[0].size, 0, &sc->sc_ioh))
178 		panic("%s: bus_space_map failed!", __func__);
179 
180 	/* On the R40, the GMAC needs to poke at one of our registers. */
181 	if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) {
182 		bus_space_handle_t ioh;
183 
184 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
185 		    R40_GMAC_CLK_REG, 4, &ioh);
186 		regmap_register(faa->fa_node, sc->sc_iot, ioh, 4);
187 	}
188 
189 	printf("\n");
190 
191 	if (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
192 	    OF_is_compatible(node, "allwinner,sun7i-a20-ccu")) {
193 		KASSERT(faa->fa_nreg > 0);
194 		sc->sc_gates = sun4i_a10_gates;
195 		sc->sc_ngates = nitems(sun4i_a10_gates);
196 		sc->sc_resets = sun4i_a10_resets;
197 		sc->sc_nresets = nitems(sun4i_a10_resets);
198 		sc->sc_get_frequency = sxiccmu_a10_get_frequency;
199 		sc->sc_set_frequency = sxiccmu_a10_set_frequency;
200 	} else if (OF_is_compatible(node, "allwinner,sun5i-a10s-ccu")) {
201 		KASSERT(faa->fa_nreg > 0);
202 		sc->sc_gates = sun5i_a10s_gates;
203 		sc->sc_ngates = nitems(sun5i_a10s_gates);
204 		sc->sc_resets = sun5i_a10s_resets;
205 		sc->sc_nresets = nitems(sun5i_a10s_resets);
206 		sc->sc_get_frequency = sxiccmu_a10s_get_frequency;
207 		sc->sc_set_frequency = sxiccmu_a10s_set_frequency;
208 	} else if (OF_is_compatible(node, "allwinner,sun8i-a23-ccu") ||
209 	    OF_is_compatible(node, "allwinner,sun8i-a33-ccu")) {
210 		KASSERT(faa->fa_nreg > 0);
211 		sc->sc_gates = sun8i_a23_gates;
212 		sc->sc_ngates = nitems(sun8i_a23_gates);
213 		sc->sc_resets = sun8i_a23_resets;
214 		sc->sc_nresets = nitems(sun8i_a23_resets);
215 		sc->sc_get_frequency = sxiccmu_a23_get_frequency;
216 		sc->sc_set_frequency = sxiccmu_a23_set_frequency;
217 	} else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
218 	    OF_is_compatible(node, "allwinner,sun50i-h5-ccu")) {
219 		KASSERT(faa->fa_nreg > 0);
220 		sc->sc_gates = sun8i_h3_gates;
221 		sc->sc_ngates = nitems(sun8i_h3_gates);
222 		sc->sc_resets = sun8i_h3_resets;
223 		sc->sc_nresets = nitems(sun8i_h3_resets);
224 		sc->sc_get_frequency = sxiccmu_h3_get_frequency;
225 		sc->sc_set_frequency = sxiccmu_h3_set_frequency;
226 	} else if (OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") ||
227 	    OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu")) {
228 		KASSERT(faa->fa_nreg > 0);
229 		sc->sc_gates = sun8i_h3_r_gates;
230 		sc->sc_ngates = nitems(sun8i_h3_r_gates);
231 		sc->sc_resets = sun8i_h3_r_resets;
232 		sc->sc_nresets = nitems(sun8i_h3_r_resets);
233 		sc->sc_get_frequency = sxiccmu_h3_r_get_frequency;
234 		sc->sc_set_frequency = sxiccmu_nop_set_frequency;
235 	} else if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) {
236 		KASSERT(faa->fa_nreg > 0);
237 		sc->sc_gates = sun8i_r40_gates;
238 		sc->sc_ngates = nitems(sun8i_r40_gates);
239 		sc->sc_resets = sun8i_r40_resets;
240 		sc->sc_nresets = nitems(sun8i_r40_resets);
241 		sc->sc_get_frequency = sxiccmu_r40_get_frequency;
242 		sc->sc_set_frequency = sxiccmu_r40_set_frequency;
243 	} else if (OF_is_compatible(node, "allwinner,sun8i-v3s-ccu")) {
244 		KASSERT(faa->fa_nreg > 0);
245 		sc->sc_gates = sun8i_v3s_gates;
246 		sc->sc_ngates = nitems(sun8i_v3s_gates);
247 		sc->sc_resets = sun8i_v3s_resets;
248 		sc->sc_nresets = nitems(sun8i_v3s_resets);
249 		sc->sc_get_frequency = sxiccmu_v3s_get_frequency;
250 		sc->sc_set_frequency = sxiccmu_v3s_set_frequency;
251 	} else if (OF_is_compatible(node, "allwinner,sun9i-a80-ccu")) {
252 		KASSERT(faa->fa_nreg > 0);
253 		sc->sc_gates = sun9i_a80_gates;
254 		sc->sc_ngates = nitems(sun9i_a80_gates);
255 		sc->sc_resets = sun9i_a80_resets;
256 		sc->sc_nresets = nitems(sun9i_a80_resets);
257 		sc->sc_get_frequency = sxiccmu_a80_get_frequency;
258 		sc->sc_set_frequency = sxiccmu_a80_set_frequency;
259 	} else if (OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks")) {
260 		KASSERT(faa->fa_nreg > 0);
261 		sc->sc_gates = sun9i_a80_usb_gates;
262 		sc->sc_ngates = nitems(sun9i_a80_usb_gates);
263 		sc->sc_resets = sun9i_a80_usb_resets;
264 		sc->sc_nresets = nitems(sun9i_a80_usb_resets);
265 		sc->sc_get_frequency = sxiccmu_nop_get_frequency;
266 		sc->sc_set_frequency = sxiccmu_nop_set_frequency;
267 	} else if (OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk")) {
268 		KASSERT(faa->fa_nreg > 0);
269 		sc->sc_gates = sun9i_a80_mmc_gates;
270 		sc->sc_ngates = nitems(sun9i_a80_mmc_gates);
271 		sc->sc_resets = sun9i_a80_mmc_resets;
272 		sc->sc_nresets = nitems(sun9i_a80_mmc_resets);
273 		sc->sc_get_frequency = sxiccmu_nop_get_frequency;
274 		sc->sc_set_frequency = sxiccmu_nop_set_frequency;
275 	} else if (OF_is_compatible(node, "allwinner,sun20i-d1-ccu")) {
276 		KASSERT(faa->fa_nreg > 0);
277 		sc->sc_gates = sun20i_d1_gates;
278 		sc->sc_ngates = nitems(sun20i_d1_gates);
279 		sc->sc_resets = sun20i_d1_resets;
280 		sc->sc_nresets = nitems(sun20i_d1_resets);
281 		sc->sc_get_frequency = sxiccmu_d1_get_frequency;
282 		sc->sc_set_frequency = sxiccmu_d1_set_frequency;
283 	} else if (OF_is_compatible(node, "allwinner,sun50i-a64-ccu")) {
284 		KASSERT(faa->fa_nreg > 0);
285 		sc->sc_gates = sun50i_a64_gates;
286 		sc->sc_ngates = nitems(sun50i_a64_gates);
287 		sc->sc_resets = sun50i_a64_resets;
288 		sc->sc_nresets = nitems(sun50i_a64_resets);
289 		sc->sc_get_frequency = sxiccmu_a64_get_frequency;
290 		sc->sc_set_frequency = sxiccmu_a64_set_frequency;
291 	} else if (OF_is_compatible(node, "allwinner,sun50i-h6-ccu")) {
292 		KASSERT(faa->fa_nreg > 0);
293 		sc->sc_gates = sun50i_h6_gates;
294 		sc->sc_ngates = nitems(sun50i_h6_gates);
295 		sc->sc_resets = sun50i_h6_resets;
296 		sc->sc_nresets = nitems(sun50i_h6_resets);
297 		sc->sc_get_frequency = sxiccmu_h6_get_frequency;
298 		sc->sc_set_frequency = sxiccmu_h6_set_frequency;
299 	} else if (OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu")) {
300 		KASSERT(faa->fa_nreg > 0);
301 		sc->sc_gates = sun50i_h6_r_gates;
302 		sc->sc_ngates = nitems(sun50i_h6_r_gates);
303 		sc->sc_resets = sun50i_h6_r_resets;
304 		sc->sc_nresets = nitems(sun50i_h6_r_resets);
305 		sc->sc_get_frequency = sxiccmu_h6_r_get_frequency;
306 		sc->sc_set_frequency = sxiccmu_nop_set_frequency;
307 	} else if (OF_is_compatible(node, "allwinner,sun50i-h616-ccu")) {
308 		KASSERT(faa->fa_nreg > 0);
309 		sc->sc_gates = sun50i_h616_gates;
310 		sc->sc_ngates = nitems(sun50i_h616_gates);
311 		sc->sc_resets = sun50i_h616_resets;
312 		sc->sc_nresets = nitems(sun50i_h616_resets);
313 		sc->sc_get_frequency = sxiccmu_h616_get_frequency;
314 		sc->sc_set_frequency = sxiccmu_h616_set_frequency;
315 	} else if (OF_is_compatible(node, "allwinner,sun50i-h616-r-ccu")) {
316 		KASSERT(faa->fa_nreg > 0);
317 		sc->sc_gates = sun50i_h616_r_gates;
318 		sc->sc_ngates = nitems(sun50i_h616_r_gates);
319 		sc->sc_resets = sun50i_h616_r_resets;
320 		sc->sc_nresets = nitems(sun50i_h616_r_resets);
321 		sc->sc_get_frequency = sxiccmu_h616_r_get_frequency;
322 		sc->sc_set_frequency = sxiccmu_nop_set_frequency;
323 	} else {
324 		for (node = OF_child(node); node; node = OF_peer(node))
325 			sxiccmu_attach_clock(sc, node, faa->fa_nreg);
326 	}
327 
328 	if (sc->sc_gates) {
329 		sc->sc_cd.cd_node = sc->sc_node;
330 		sc->sc_cd.cd_cookie = sc;
331 		sc->sc_cd.cd_get_frequency = sxiccmu_ccu_get_frequency;
332 		sc->sc_cd.cd_set_frequency = sxiccmu_ccu_set_frequency;
333 		sc->sc_cd.cd_enable = sxiccmu_ccu_enable;
334 		clock_register(&sc->sc_cd);
335 	}
336 
337 	if (sc->sc_resets) {
338 		sc->sc_rd.rd_node = sc->sc_node;
339 		sc->sc_rd.rd_cookie = sc;
340 		sc->sc_rd.rd_reset = sxiccmu_ccu_reset;
341 		reset_register(&sc->sc_rd);
342 	}
343 }
344 
345 /*
346  * Classic device trees for the Allwinner SoCs have basically a clock
347  * node per register of the clock control unit.  Attaching a separate
348  * driver to each of them would be crazy, so we handle them here.
349  */
350 
351 struct sxiccmu_clock {
352 	int sc_node;
353 	bus_space_tag_t sc_iot;
354 	bus_space_handle_t sc_ioh;
355 
356 	struct clock_device sc_cd;
357 	struct reset_device sc_rd;
358 };
359 
360 struct sxiccmu_device {
361 	const char *compat;
362 	uint32_t (*get_frequency)(void *, uint32_t *);
363 	int	(*set_frequency)(void *, uint32_t *, uint32_t);
364 	void	(*enable)(void *, uint32_t *, int);
365 	void	(*reset)(void *, uint32_t *, int);
366 	bus_size_t offset;
367 };
368 
369 uint32_t sxiccmu_gen_get_frequency(void *, uint32_t *);
370 uint32_t sxiccmu_osc_get_frequency(void *, uint32_t *);
371 uint32_t sxiccmu_pll6_get_frequency(void *, uint32_t *);
372 void	sxiccmu_pll6_enable(void *, uint32_t *, int);
373 uint32_t sxiccmu_apb1_get_frequency(void *, uint32_t *);
374 uint32_t sxiccmu_cpus_get_frequency(void *, uint32_t *);
375 uint32_t sxiccmu_apbs_get_frequency(void *, uint32_t *);
376 int	sxiccmu_gmac_set_frequency(void *, uint32_t *, uint32_t);
377 int	sxiccmu_mmc_set_frequency(void *, uint32_t *, uint32_t);
378 void	sxiccmu_mmc_enable(void *, uint32_t *, int);
379 void	sxiccmu_gate_enable(void *, uint32_t *, int);
380 void	sxiccmu_reset(void *, uint32_t *, int);
381 
382 const struct sxiccmu_device sxiccmu_devices[] = {
383 	{
384 		.compat = "allwinner,sun4i-a10-osc-clk",
385 		.get_frequency = sxiccmu_osc_get_frequency,
386 	},
387 	{
388 		.compat = "allwinner,sun4i-a10-pll6-clk",
389 		.get_frequency = sxiccmu_pll6_get_frequency,
390 		.enable = sxiccmu_pll6_enable
391 	},
392 	{
393 		.compat = "allwinner,sun4i-a10-apb1-clk",
394 		.get_frequency = sxiccmu_apb1_get_frequency,
395 	},
396 	{
397 		.compat = "allwinner,sun4i-a10-ahb-gates-clk",
398 		.get_frequency = sxiccmu_gen_get_frequency,
399 		.enable = sxiccmu_gate_enable
400 	},
401 	{
402 		.compat = "allwinner,sun4i-a10-apb0-gates-clk",
403 		.get_frequency = sxiccmu_gen_get_frequency,
404 		.enable = sxiccmu_gate_enable
405 	},
406 	{
407 		.compat = "allwinner,sun4i-a10-apb1-gates-clk",
408 		.get_frequency = sxiccmu_gen_get_frequency,
409 		.enable = sxiccmu_gate_enable
410 	},
411 	{
412 		.compat = "allwinner,sun4i-a10-mmc-clk",
413 		.set_frequency = sxiccmu_mmc_set_frequency,
414 		.enable = sxiccmu_mmc_enable
415 	},
416 	{
417 		.compat = "allwinner,sun4i-a10-usb-clk",
418 		.get_frequency = sxiccmu_gen_get_frequency,
419 		.enable = sxiccmu_gate_enable,
420 		.reset = sxiccmu_reset
421 	},
422 	{
423 		.compat = "allwinner,sun5i-a10s-ahb-gates-clk",
424 		.get_frequency = sxiccmu_gen_get_frequency,
425 		.enable = sxiccmu_gate_enable
426 	},
427 	{
428 		.compat = "allwinner,sun5i-a10s-apb0-gates-clk",
429 		.get_frequency = sxiccmu_gen_get_frequency,
430 		.enable = sxiccmu_gate_enable
431 	},
432 	{
433 		.compat = "allwinner,sun5i-a10s-apb1-gates-clk",
434 		.get_frequency = sxiccmu_gen_get_frequency,
435 		.enable = sxiccmu_gate_enable
436 	},
437 	{
438 		.compat = "allwinner,sun5i-a13-ahb-gates-clk",
439 		.get_frequency = sxiccmu_gen_get_frequency,
440 		.enable = sxiccmu_gate_enable
441 	},
442 	{
443 		.compat = "allwinner,sun5i-a13-apb0-gates-clk",
444 		.get_frequency = sxiccmu_gen_get_frequency,
445 		.enable = sxiccmu_gate_enable
446 	},
447 	{
448 		.compat = "allwinner,sun5i-a13-apb1-gates-clk",
449 		.get_frequency = sxiccmu_gen_get_frequency,
450 		.enable = sxiccmu_gate_enable
451 	},
452 	{
453 		.compat = "allwinner,sun5i-a13-usb-clk",
454 		.get_frequency = sxiccmu_gen_get_frequency,
455 		.enable = sxiccmu_gate_enable,
456 		.reset = sxiccmu_reset
457 	},
458 	{
459 		.compat = "allwinner,sun6i-a31-ahb1-reset",
460 		.reset = sxiccmu_reset
461 	},
462 	{
463 		.compat = "allwinner,sun6i-a31-clock-reset",
464 		.reset = sxiccmu_reset,
465 		.offset = 0x00b0
466 	},
467 	{
468 		.compat = "allwinner,sun7i-a20-ahb-gates-clk",
469 		.get_frequency = sxiccmu_gen_get_frequency,
470 		.enable = sxiccmu_gate_enable
471 	},
472 	{
473 		.compat = "allwinner,sun7i-a20-apb0-gates-clk",
474 		.get_frequency = sxiccmu_gen_get_frequency,
475 		.enable = sxiccmu_gate_enable
476 	},
477 	{
478 		.compat = "allwinner,sun7i-a20-apb1-gates-clk",
479 		.get_frequency = sxiccmu_gen_get_frequency,
480 		.enable = sxiccmu_gate_enable
481 	},
482 	{
483 		.compat = "allwinner,sun7i-a20-gmac-clk",
484 		.set_frequency = sxiccmu_gmac_set_frequency
485 	},
486 	{
487 		.compat = "allwinner,sun8i-a23-apb0-clk",
488 		.get_frequency = sxiccmu_apbs_get_frequency,
489 		.offset = 0x000c
490 	},
491 	{
492 		.compat = "allwinner,sun8i-a23-ahb1-gates-clk",
493 		.get_frequency = sxiccmu_gen_get_frequency,
494 		.enable = sxiccmu_gate_enable
495 	},
496 	{
497 		.compat = "allwinner,sun8i-a23-apb0-gates-clk",
498 		.get_frequency = sxiccmu_gen_get_frequency,
499 		.enable = sxiccmu_gate_enable,
500 		.offset = 0x0028
501 	},
502 	{
503 		.compat = "allwinner,sun8i-a23-apb1-gates-clk",
504 		.get_frequency = sxiccmu_gen_get_frequency,
505 		.enable = sxiccmu_gate_enable
506 	},
507 	{
508 		.compat = "allwinner,sun8i-a23-apb2-gates-clk",
509 		.get_frequency = sxiccmu_gen_get_frequency,
510 		.enable = sxiccmu_gate_enable
511 	},
512 	{
513 		.compat = "allwinner,sun8i-a23-usb-clk",
514 		.get_frequency = sxiccmu_gen_get_frequency,
515 		.enable = sxiccmu_gate_enable,
516 		.reset = sxiccmu_reset
517 	},
518 	{
519 		.compat = "allwinner,sun8i-h3-apb0-gates-clk",
520 		.get_frequency = sxiccmu_gen_get_frequency,
521 		.enable = sxiccmu_gate_enable
522 	},
523 	{
524 		.compat = "allwinner,sun9i-a80-apb1-clk",
525 		.get_frequency = sxiccmu_apb1_get_frequency,
526 	},
527 	{
528 		.compat = "allwinner,sun9i-a80-ahb0-gates-clk",
529 		.get_frequency = sxiccmu_gen_get_frequency,
530 		.enable = sxiccmu_gate_enable
531 	},
532 	{
533 		.compat = "allwinner,sun9i-a80-ahb1-gates-clk",
534 		.get_frequency = sxiccmu_gen_get_frequency,
535 		.enable = sxiccmu_gate_enable
536 	},
537 	{
538 		.compat = "allwinner,sun9i-a80-ahb2-gates-clk",
539 		.get_frequency = sxiccmu_gen_get_frequency,
540 		.enable = sxiccmu_gate_enable
541 	},
542 	{
543 		.compat = "allwinner,sun9i-a80-apb0-gates-clk",
544 		.get_frequency = sxiccmu_gen_get_frequency,
545 		.enable = sxiccmu_gate_enable
546 	},
547 	{
548 		.compat = "allwinner,sun9i-a80-apb1-gates-clk",
549 		.get_frequency = sxiccmu_gen_get_frequency,
550 		.enable = sxiccmu_gate_enable
551 	},
552 	{
553 		.compat = "allwinner,sun9i-a80-apbs-gates-clk",
554 		.get_frequency = sxiccmu_gen_get_frequency,
555 		.enable = sxiccmu_gate_enable
556 	},
557 	{
558 		.compat = "allwinner,sun9i-a80-cpus-clk",
559 		.get_frequency = sxiccmu_cpus_get_frequency
560 	},
561 	{
562 		.compat = "allwinner,sun9i-a80-mmc-clk",
563 		.set_frequency = sxiccmu_mmc_set_frequency,
564 		.enable = sxiccmu_mmc_enable
565 	},
566 	{
567 		.compat = "allwinner,sun9i-a80-usb-mod-clk",
568 		.get_frequency = sxiccmu_gen_get_frequency,
569 		.enable = sxiccmu_gate_enable,
570 		.reset = sxiccmu_reset
571 	},
572 	{
573 		.compat = "allwinner,sun9i-a80-usb-phy-clk",
574 		.get_frequency = sxiccmu_gen_get_frequency,
575 		.enable = sxiccmu_gate_enable,
576 		.reset = sxiccmu_reset
577 	},
578 };
579 
580 void
sxiccmu_attach_clock(struct sxiccmu_softc * sc,int node,int nreg)581 sxiccmu_attach_clock(struct sxiccmu_softc *sc, int node, int nreg)
582 {
583 	struct sxiccmu_clock *clock;
584 	uint32_t reg[2];
585 	int i, error = ENODEV;
586 
587 	for (i = 0; i < nitems(sxiccmu_devices); i++)
588 		if (OF_is_compatible(node, sxiccmu_devices[i].compat))
589 			break;
590 	if (i == nitems(sxiccmu_devices))
591 		return;
592 
593 	clock = malloc(sizeof(*clock), M_DEVBUF, M_WAITOK);
594 	clock->sc_node = node;
595 
596 	clock->sc_iot = sc->sc_iot;
597 	if (OF_getpropintarray(node, "reg", reg, sizeof(reg)) == sizeof(reg)) {
598 		error = bus_space_map(clock->sc_iot, reg[0], reg[1], 0,
599 		    &clock->sc_ioh);
600 	} else if (nreg > 0) {
601 		error = bus_space_subregion(clock->sc_iot, sc->sc_ioh,
602 		    sxiccmu_devices[i].offset, 4, &clock->sc_ioh);
603 	}
604 	if (error) {
605 		printf("%s: can't map registers", sc->sc_dev.dv_xname);
606 		free(clock, M_DEVBUF, sizeof(*clock));
607 		return;
608 	}
609 
610 	clock->sc_cd.cd_node = node;
611 	clock->sc_cd.cd_cookie = clock;
612 	clock->sc_cd.cd_get_frequency = sxiccmu_devices[i].get_frequency;
613 	clock->sc_cd.cd_set_frequency = sxiccmu_devices[i].set_frequency;
614 	clock->sc_cd.cd_enable = sxiccmu_devices[i].enable;
615 	clock_register(&clock->sc_cd);
616 
617 	if (sxiccmu_devices[i].reset) {
618 		clock->sc_rd.rd_node = node;
619 		clock->sc_rd.rd_cookie = clock;
620 		clock->sc_rd.rd_reset = sxiccmu_devices[i].reset;
621 		reset_register(&clock->sc_rd);
622 	}
623 }
624 
625 /*
626  * A "generic" function that simply gets the clock frequency from the
627  * parent clock.  Useful for clock gating devices that don't scale
628  * their clocks.
629  */
630 uint32_t
sxiccmu_gen_get_frequency(void * cookie,uint32_t * cells)631 sxiccmu_gen_get_frequency(void *cookie, uint32_t *cells)
632 {
633 	struct sxiccmu_clock *sc = cookie;
634 
635 	return clock_get_frequency(sc->sc_node, NULL);
636 }
637 
638 uint32_t
sxiccmu_osc_get_frequency(void * cookie,uint32_t * cells)639 sxiccmu_osc_get_frequency(void *cookie, uint32_t *cells)
640 {
641 	struct sxiccmu_clock *sc = cookie;
642 
643 	return OF_getpropint(sc->sc_node, "clock-frequency", 24000000);
644 }
645 
646 #define CCU_PLL6_ENABLE			(1U << 31)
647 #define CCU_PLL6_BYPASS_EN		(1U << 30)
648 #define CCU_PLL6_SATA_CLK_EN		(1U << 14)
649 #define CCU_PLL6_FACTOR_N(x)		(((x) >> 8) & 0x1f)
650 #define CCU_PLL6_FACTOR_N_MASK		(0x1f << 8)
651 #define CCU_PLL6_FACTOR_N_SHIFT		8
652 #define CCU_PLL6_FACTOR_K(x)		(((x) >> 4) & 0x3)
653 #define CCU_PLL6_FACTOR_K_MASK		(0x3 << 4)
654 #define CCU_PLL6_FACTOR_K_SHIFT		4
655 #define CCU_PLL6_FACTOR_M(x)		(((x) >> 0) & 0x3)
656 #define CCU_PLL6_FACTOR_M_MASK		(0x3 << 0)
657 #define CCU_PLL6_FACTOR_M_SHIFT		0
658 
659 uint32_t
sxiccmu_pll6_get_frequency(void * cookie,uint32_t * cells)660 sxiccmu_pll6_get_frequency(void *cookie, uint32_t *cells)
661 {
662 	struct sxiccmu_clock *sc = cookie;
663 	uint32_t reg, k, m, n, freq;
664 	uint32_t idx = cells[0];
665 
666 	/* XXX Assume bypass is disabled. */
667 	reg = SXIREAD4(sc, 0);
668 	k = CCU_PLL6_FACTOR_K(reg) + 1;
669 	m = CCU_PLL6_FACTOR_M(reg) + 1;
670 	n = CCU_PLL6_FACTOR_N(reg);
671 
672 	freq = clock_get_frequency_idx(sc->sc_node, 0);
673 	switch (idx) {
674 	case 0:
675 		return (freq * n * k) / m / 6;		/* pll6_sata */
676 	case 1:
677 		return (freq * n * k) / 2;		/* pll6_other */
678 	case 2:
679 		return (freq * n * k);			/* pll6 */
680 	case 3:
681 		return (freq * n * k) / 4;		/* pll6_div_4 */
682 	}
683 
684 	return 0;
685 }
686 
687 void
sxiccmu_pll6_enable(void * cookie,uint32_t * cells,int on)688 sxiccmu_pll6_enable(void *cookie, uint32_t *cells, int on)
689 {
690 	struct sxiccmu_clock *sc = cookie;
691 	uint32_t idx = cells[0];
692 	uint32_t reg;
693 
694 	/*
695 	 * Since this clock has several outputs, we never turn it off.
696 	 */
697 
698 	reg = SXIREAD4(sc, 0);
699 	switch (idx) {
700 	case 0:			/* pll6_sata */
701 		if (on)
702 			reg |= CCU_PLL6_SATA_CLK_EN;
703 		else
704 			reg &= ~CCU_PLL6_SATA_CLK_EN;
705 		/* FALLTHROUGH */
706 	case 1:			/* pll6_other */
707 	case 2:			/* pll6 */
708 	case 3:			/* pll6_div_4 */
709 		if (on)
710 			reg |= CCU_PLL6_ENABLE;
711 	}
712 	SXIWRITE4(sc, 0, reg);
713 }
714 
715 #define CCU_APB1_CLK_RAT_N(x)		(((x) >> 16) & 0x3)
716 #define CCU_APB1_CLK_RAT_M(x)		(((x) >> 0) & 0x1f)
717 #define CCU_APB1_CLK_SRC_SEL(x)		(((x) >> 24) & 0x3)
718 
719 uint32_t
sxiccmu_apb1_get_frequency(void * cookie,uint32_t * cells)720 sxiccmu_apb1_get_frequency(void *cookie, uint32_t *cells)
721 {
722 	struct sxiccmu_clock *sc = cookie;
723 	uint32_t reg, m, n, freq;
724 	int idx;
725 
726 	reg = SXIREAD4(sc, 0);
727 	m = CCU_APB1_CLK_RAT_M(reg);
728 	n = CCU_APB1_CLK_RAT_N(reg);
729 	idx = CCU_APB1_CLK_SRC_SEL(reg);
730 
731 	freq = clock_get_frequency_idx(sc->sc_node, idx);
732 	return freq / (1 << n) / (m + 1);
733 }
734 
735 #define CCU_CPUS_CLK_SRC_SEL(x)		(((x) >> 16) & 0x3)
736 #define CCU_CPUS_POST_DIV(x)		(((x) >> 8) & 0x1f)
737 #define CCU_CPUS_CLK_RATIO(x)		(((x) >> 0) & 0x3)
738 
739 uint32_t
sxiccmu_cpus_get_frequency(void * cookie,uint32_t * cells)740 sxiccmu_cpus_get_frequency(void *cookie, uint32_t *cells)
741 {
742 	struct sxiccmu_clock *sc = cookie;
743 	uint32_t reg, post_div, clk_ratio, freq;
744 	int idx;
745 
746 	reg = SXIREAD4(sc, 0);
747 	idx = CCU_CPUS_CLK_SRC_SEL(reg);
748 	post_div = (idx == 2 ? CCU_CPUS_POST_DIV(reg): 0);
749 	clk_ratio = CCU_CPUS_CLK_RATIO(reg);
750 
751 	freq = clock_get_frequency_idx(sc->sc_node, idx);
752 	return freq / (clk_ratio + 1) / (post_div + 1);
753 }
754 
755 #define CCU_APBS_CLK_RATIO(x)		(((x) >> 0) & 0x3)
756 
757 uint32_t
sxiccmu_apbs_get_frequency(void * cookie,uint32_t * cells)758 sxiccmu_apbs_get_frequency(void *cookie, uint32_t *cells)
759 {
760 	struct sxiccmu_clock *sc = cookie;
761 	uint32_t reg, freq;
762 
763 	reg = SXIREAD4(sc, 0);
764 	freq = clock_get_frequency(sc->sc_node, NULL);
765 	return freq / (CCU_APBS_CLK_RATIO(reg) + 1);
766 }
767 
768 #define	CCU_GMAC_CLK_PIT		(1 << 2)
769 #define	CCU_GMAC_CLK_TCS		(3 << 0)
770 #define	CCU_GMAC_CLK_TCS_MII		0
771 #define	CCU_GMAC_CLK_TCS_EXT_125	1
772 #define	CCU_GMAC_CLK_TCS_INT_RGMII	2
773 
774 int
sxiccmu_gmac_set_frequency(void * cookie,uint32_t * cells,uint32_t freq)775 sxiccmu_gmac_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
776 {
777 	struct sxiccmu_clock *sc = cookie;
778 
779 	switch (freq) {
780 	case 25000000:		/* MMI, 25 MHz */
781 		SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS,
782 		    CCU_GMAC_CLK_TCS_MII);
783 		break;
784 	case 125000000:		/* RGMII, 125 MHz */
785 		SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS,
786 		    CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS_INT_RGMII);
787 		break;
788 	default:
789 		return -1;
790 	}
791 
792 	return 0;
793 }
794 
795 #define CCU_SDx_SCLK_GATING		(1U << 31)
796 #define CCU_SDx_CLK_SRC_SEL_OSC24M	(0 << 24)
797 #define CCU_SDx_CLK_SRC_SEL_PLL6	(1 << 24)
798 #define CCU_SDx_CLK_SRC_SEL_PLL5	(2 << 24)
799 #define CCU_SDx_CLK_SRC_SEL_MASK	(3 << 24)
800 #define CCU_SDx_CLK_DIV_RATIO_N_MASK	(3 << 16)
801 #define CCU_SDx_CLK_DIV_RATIO_N_SHIFT	16
802 #define CCU_SDx_CLK_DIV_RATIO_M_MASK	(7 << 0)
803 #define CCU_SDx_CLK_DIV_RATIO_M_SHIFT	0
804 
805 int
sxiccmu_mmc_do_set_frequency(struct sxiccmu_clock * sc,uint32_t freq,uint32_t parent_freq)806 sxiccmu_mmc_do_set_frequency(struct sxiccmu_clock *sc, uint32_t freq,
807     uint32_t parent_freq)
808 {
809 	uint32_t reg, m, n;
810 	uint32_t clk_src;
811 
812 	switch (freq) {
813 	case 400000:
814 		n = 2, m = 15;
815 		clk_src = CCU_SDx_CLK_SRC_SEL_OSC24M;
816 		break;
817 	case 20000000:
818 	case 25000000:
819 	case 26000000:
820 	case 50000000:
821 	case 52000000:
822 		n = 0, m = 0;
823 		clk_src = CCU_SDx_CLK_SRC_SEL_PLL6;
824 		while ((parent_freq / (1 << n) / 16) > freq)
825 			n++;
826 		while ((parent_freq / (1 << n) / (m + 1)) > freq)
827 			m++;
828 		break;
829 	default:
830 		return -1;
831 	}
832 
833 	reg = SXIREAD4(sc, 0);
834 	reg &= ~CCU_SDx_CLK_SRC_SEL_MASK;
835 	reg |= clk_src;
836 	reg &= ~CCU_SDx_CLK_DIV_RATIO_N_MASK;
837 	reg |= n << CCU_SDx_CLK_DIV_RATIO_N_SHIFT;
838 	reg &= ~CCU_SDx_CLK_DIV_RATIO_M_MASK;
839 	reg |= m << CCU_SDx_CLK_DIV_RATIO_M_SHIFT;
840 	SXIWRITE4(sc, 0, reg);
841 
842 	return 0;
843 }
844 
845 int
sxiccmu_mmc_set_frequency(void * cookie,uint32_t * cells,uint32_t freq)846 sxiccmu_mmc_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
847 {
848 	struct sxiccmu_clock *sc = cookie;
849 	uint32_t parent_freq;
850 
851 	if (cells[0] != 0)
852 		return -1;
853 
854 	parent_freq = clock_get_frequency_idx(sc->sc_node, 1);
855 	return sxiccmu_mmc_do_set_frequency(sc, freq, parent_freq);
856 }
857 
858 void
sxiccmu_mmc_enable(void * cookie,uint32_t * cells,int on)859 sxiccmu_mmc_enable(void *cookie, uint32_t *cells, int on)
860 {
861 	struct sxiccmu_clock *sc = cookie;
862 
863 	if (cells[0] != 0)
864 		return;
865 
866 	if (on)
867 		SXISET4(sc, 0, CCU_SDx_SCLK_GATING);
868 	else
869 		SXICLR4(sc, 0, CCU_SDx_SCLK_GATING);
870 }
871 
872 void
sxiccmu_gate_enable(void * cookie,uint32_t * cells,int on)873 sxiccmu_gate_enable(void *cookie, uint32_t *cells, int on)
874 {
875 	struct sxiccmu_clock *sc = cookie;
876 	int reg = cells[0] / 32;
877 	int bit = cells[0] % 32;
878 
879 	if (on) {
880 		clock_enable(sc->sc_node, NULL);
881 		SXISET4(sc, reg * 4, (1U << bit));
882 	} else {
883 		SXICLR4(sc, reg * 4, (1U << bit));
884 		clock_disable(sc->sc_node, NULL);
885 	}
886 }
887 
888 void
sxiccmu_reset(void * cookie,uint32_t * cells,int assert)889 sxiccmu_reset(void *cookie, uint32_t *cells, int assert)
890 {
891 	struct sxiccmu_clock *sc = cookie;
892 	int reg = cells[0] / 32;
893 	int bit = cells[0] % 32;
894 
895 	if (assert)
896 		SXICLR4(sc, reg * 4, (1U << bit));
897 	else
898 		SXISET4(sc, reg * 4, (1U << bit));
899 }
900 
901 /*
902  * Newer device trees, such as those for the Allwinner H3/A64 have
903  * most of the clock nodes replaced with a single clock control unit
904  * node.
905  */
906 
907 uint32_t
sxiccmu_ccu_get_frequency(void * cookie,uint32_t * cells)908 sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells)
909 {
910 	struct sxiccmu_softc *sc = cookie;
911 	uint32_t idx = cells[0];
912 	uint32_t parent;
913 
914 	if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
915 		parent = sc->sc_gates[idx].parent;
916 		return sxiccmu_ccu_get_frequency(sc, &parent);
917 	}
918 
919 	return sc->sc_get_frequency(sc, idx);
920 }
921 
922 /* Allwinner A10/A10s/A13/A20 */
923 #define A10_PLL1_CFG_REG		0x0000
924 #define A10_PLL1_OUT_EXT_DIVP_MASK	(0x3 << 16)
925 #define A10_PLL1_OUT_EXT_DIVP_SHIFT	16
926 #define A10_PLL1_OUT_EXT_DIVP(x)	(((x) >> 16) & 0x3)
927 #define A10_PLL1_FACTOR_N(x)		(((x) >> 8) & 0x1f)
928 #define A10_PLL1_FACTOR_N_MASK		(0x1f << 8)
929 #define A10_PLL1_FACTOR_N_SHIFT		8
930 #define A10_PLL1_FACTOR_K(x)		(((x) >> 4) & 0x3)
931 #define A10_PLL1_FACTOR_K_MASK		(0x3 << 4)
932 #define A10_PLL1_FACTOR_K_SHIFT		4
933 #define A10_PLL1_FACTOR_M(x)		(((x) >> 0) & 0x3)
934 #define A10_PLL1_FACTOR_M_MASK		(0x3 << 0)
935 #define A10_PLL1_FACTOR_M_SHIFT		0
936 #define A10_CPU_AHB_APB0_CFG_REG	0x0054
937 #define A10_CPU_CLK_SRC_SEL		(0x3 << 16)
938 #define A10_CPU_CLK_SRC_SEL_LOSC	(0x0 << 16)
939 #define A10_CPU_CLK_SRC_SEL_OSC24M	(0x1 << 16)
940 #define A10_CPU_CLK_SRC_SEL_PLL1	(0x2 << 16)
941 #define A10_CPU_CLK_SRC_SEL_200MHZ	(0x3 << 16)
942 #define A10_AHB_CLK_DIV_RATIO(x)	(((x) >> 8) & 0x3)
943 #define A10_AXI_CLK_DIV_RATIO(x)	(((x) >> 0) & 0x3)
944 
945 uint32_t
sxiccmu_a10_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)946 sxiccmu_a10_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
947 {
948 	uint32_t parent;
949 	uint32_t reg, div;
950 	uint32_t k, m, n, p;
951 
952 	switch (idx) {
953 	case A10_CLK_LOSC:
954 		return clock_get_frequency(sc->sc_node, "losc");
955 	case A10_CLK_HOSC:
956 		return clock_get_frequency(sc->sc_node, "hosc");
957 	case A10_CLK_PLL_CORE:
958 		reg = SXIREAD4(sc, A10_PLL1_CFG_REG);
959 		k = A10_PLL1_FACTOR_K(reg) + 1;
960 		m = A10_PLL1_FACTOR_M(reg) + 1;
961 		n = A10_PLL1_FACTOR_N(reg);
962 		p = 1 << A10_PLL1_OUT_EXT_DIVP(reg);
963 		return (24000000 * n * k) / (m * p);
964 	case A10_CLK_PLL_PERIPH_BASE:
965 		/* Not hardcoded, but recommended. */
966 		return 600000000;
967 	case A10_CLK_PLL_PERIPH:
968 		return sxiccmu_a10_get_frequency(sc, A10_CLK_PLL_PERIPH_BASE) * 2;
969 	case A10_CLK_CPU:
970 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
971 		switch (reg & A10_CPU_CLK_SRC_SEL) {
972 		case A10_CPU_CLK_SRC_SEL_LOSC:
973 			parent = A10_CLK_LOSC;
974 			break;
975 		case A10_CPU_CLK_SRC_SEL_OSC24M:
976 			parent = A10_CLK_HOSC;
977 			break;
978 		case A10_CPU_CLK_SRC_SEL_PLL1:
979 			parent = A10_CLK_PLL_CORE;
980 			break;
981 		case A10_CPU_CLK_SRC_SEL_200MHZ:
982 			return 200000000;
983 		}
984 		return sxiccmu_ccu_get_frequency(sc, &parent);
985 	case A10_CLK_AXI:
986 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
987 		div = 1 << A10_AXI_CLK_DIV_RATIO(reg);
988 		parent = A10_CLK_CPU;
989 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
990 	case A10_CLK_AHB:
991 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
992 		div = 1 << A10_AHB_CLK_DIV_RATIO(reg);
993 		parent = A10_CLK_AXI;
994 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
995 	case A10_CLK_APB1:
996 		/* XXX Controlled by a MUX. */
997 		return 24000000;
998 	}
999 
1000 	printf("%s: 0x%08x\n", __func__, idx);
1001 	return 0;
1002 }
1003 
1004 uint32_t
sxiccmu_a10s_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1005 sxiccmu_a10s_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1006 {
1007 	uint32_t parent;
1008 	uint32_t reg, div;
1009 	uint32_t k, m, n, p;
1010 
1011 	switch (idx) {
1012 	case A10S_CLK_LOSC:
1013 		return clock_get_frequency(sc->sc_node, "losc");
1014 	case A10S_CLK_HOSC:
1015 		return clock_get_frequency(sc->sc_node, "hosc");
1016 	case A10S_CLK_PLL_CORE:
1017 		reg = SXIREAD4(sc, A10_PLL1_CFG_REG);
1018 		k = A10_PLL1_FACTOR_K(reg) + 1;
1019 		m = A10_PLL1_FACTOR_M(reg) + 1;
1020 		n = A10_PLL1_FACTOR_N(reg);
1021 		p = 1 << A10_PLL1_OUT_EXT_DIVP(reg);
1022 		return (24000000 * n * k) / (m * p);
1023 	case A10S_CLK_PLL_PERIPH:
1024 		return 1200000000;
1025 	case A10S_CLK_CPU:
1026 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1027 		switch (reg & A10_CPU_CLK_SRC_SEL) {
1028 		case A10_CPU_CLK_SRC_SEL_LOSC:
1029 			parent = A10S_CLK_LOSC;
1030 			break;
1031 		case A10_CPU_CLK_SRC_SEL_OSC24M:
1032 			parent = A10S_CLK_HOSC;
1033 			break;
1034 		case A10_CPU_CLK_SRC_SEL_PLL1:
1035 			parent = A10S_CLK_PLL_CORE;
1036 			break;
1037 		case A10_CPU_CLK_SRC_SEL_200MHZ:
1038 			return 200000000;
1039 		}
1040 		return sxiccmu_ccu_get_frequency(sc, &parent);
1041 	case A10S_CLK_AXI:
1042 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1043 		div = 1 << A10_AXI_CLK_DIV_RATIO(reg);
1044 		parent = A10S_CLK_CPU;
1045 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1046 	case A10S_CLK_AHB:
1047 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1048 		div = 1 << A10_AHB_CLK_DIV_RATIO(reg);
1049 		parent = A10S_CLK_AXI;
1050 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1051 	case A10S_CLK_APB1:
1052 		/* XXX Controlled by a MUX. */
1053 		return 24000000;
1054 	}
1055 
1056 	printf("%s: 0x%08x\n", __func__, idx);
1057 	return 0;
1058 }
1059 
1060 /* Allwinner A23/A64/H3/H5/R40 */
1061 #define CCU_AHB1_APB1_CFG_REG		0x0054
1062 #define CCU_AHB1_CLK_SRC_SEL		(3 << 12)
1063 #define CCU_AHB1_CLK_SRC_SEL_LOSC	(0 << 12)
1064 #define CCU_AHB1_CLK_SRC_SEL_OSC24M	(1 << 12)
1065 #define CCU_AHB1_CLK_SRC_SEL_AXI	(2 << 12)
1066 #define CCU_AHB1_CLK_SRC_SEL_PERIPH0	(3 << 12)
1067 #define CCU_AHB1_PRE_DIV(x)		((((x) >> 6) & 3) + 1)
1068 #define CCU_AHB1_CLK_DIV_RATIO(x)	(1 << (((x) >> 4) & 3))
1069 #define CCU_AHB2_CFG_REG		0x005c
1070 #define CCU_AHB2_CLK_CFG		(3 << 0)
1071 
1072 uint32_t
sxiccmu_a23_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1073 sxiccmu_a23_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1074 {
1075 	uint32_t parent;
1076 	uint32_t reg, div;
1077 
1078 	switch (idx) {
1079 	case A23_CLK_LOSC:
1080 		return clock_get_frequency(sc->sc_node, "losc");
1081 	case A23_CLK_HOSC:
1082 		return clock_get_frequency(sc->sc_node, "hosc");
1083 	case A23_CLK_PLL_PERIPH:
1084 		/* Not hardcoded, but recommended. */
1085 		return 600000000;
1086 	case A23_CLK_APB2:
1087 		/* XXX Controlled by a MUX. */
1088 		return 24000000;
1089 	case A23_CLK_AHB1:
1090 		reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG);
1091 		div = CCU_AHB1_CLK_DIV_RATIO(reg);
1092 		switch (reg & CCU_AHB1_CLK_SRC_SEL) {
1093 		case CCU_AHB1_CLK_SRC_SEL_LOSC:
1094 			parent = A23_CLK_LOSC;
1095 			break;
1096 		case CCU_AHB1_CLK_SRC_SEL_OSC24M:
1097 			parent = A23_CLK_HOSC;
1098 			break;
1099 		case CCU_AHB1_CLK_SRC_SEL_AXI:
1100 			parent = A23_CLK_AXI;
1101 			break;
1102 		case CCU_AHB1_CLK_SRC_SEL_PERIPH0:
1103 			parent = A23_CLK_PLL_PERIPH;
1104 			div *= CCU_AHB1_PRE_DIV(reg);
1105 			break;
1106 		default:
1107 			return 0;
1108 		}
1109 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1110 	}
1111 
1112 	printf("%s: 0x%08x\n", __func__, idx);
1113 	return 0;
1114 }
1115 
1116 #define A64_PLL_CPUX_CTRL_REG		0x0000
1117 #define A64_PLL_CPUX_LOCK		(1 << 28)
1118 #define A64_PLL_CPUX_OUT_EXT_DIVP(x)	(((x) >> 16) & 0x3)
1119 #define A64_PLL_CPUX_OUT_EXT_DIVP_MASK	(0x3 << 16)
1120 #define A64_PLL_CPUX_FACTOR_N(x)	(((x) >> 8) & 0x1f)
1121 #define A64_PLL_CPUX_FACTOR_N_MASK	(0x1f << 8)
1122 #define A64_PLL_CPUX_FACTOR_N_SHIFT	8
1123 #define A64_PLL_CPUX_FACTOR_K(x)	(((x) >> 4) & 0x3)
1124 #define A64_PLL_CPUX_FACTOR_K_MASK	(0x3 << 4)
1125 #define A64_PLL_CPUX_FACTOR_K_SHIFT	4
1126 #define A64_PLL_CPUX_FACTOR_M(x)	(((x) >> 0) & 0x3)
1127 #define A64_PLL_CPUX_FACTOR_M_MASK	(0x3 << 0)
1128 #define A64_CPUX_AXI_CFG_REG		0x0050
1129 #define A64_CPUX_CLK_SRC_SEL		(0x3 << 16)
1130 #define A64_CPUX_CLK_SRC_SEL_LOSC	(0x0 << 16)
1131 #define A64_CPUX_CLK_SRC_SEL_OSC24M	(0x1 << 16)
1132 #define A64_CPUX_CLK_SRC_SEL_PLL_CPUX	(0x2 << 16)
1133 
1134 uint32_t
sxiccmu_a64_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1135 sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1136 {
1137 	uint32_t parent;
1138 	uint32_t reg, div;
1139 	uint32_t k, m, n, p;
1140 
1141 	switch (idx) {
1142 	case A64_CLK_PLL_CPUX:
1143 		reg = SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG);
1144 		k = A64_PLL_CPUX_FACTOR_K(reg) + 1;
1145 		m = A64_PLL_CPUX_FACTOR_M(reg) + 1;
1146 		n = A64_PLL_CPUX_FACTOR_N(reg) + 1;
1147 		p = 1 << A64_PLL_CPUX_OUT_EXT_DIVP(reg);
1148 		return (24000000 * n * k) / (m * p);
1149 	case A64_CLK_CPUX:
1150 		reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG);
1151 		switch (reg & A64_CPUX_CLK_SRC_SEL) {
1152 		case A64_CPUX_CLK_SRC_SEL_LOSC:
1153 			parent = A64_CLK_LOSC;
1154 			break;
1155 		case A64_CPUX_CLK_SRC_SEL_OSC24M:
1156 			parent = A64_CLK_HOSC;
1157 			break;
1158 		case A64_CPUX_CLK_SRC_SEL_PLL_CPUX:
1159 			parent = A64_CLK_PLL_CPUX;
1160 			break;
1161 		default:
1162 			return 0;
1163 		}
1164 		return sxiccmu_ccu_get_frequency(sc, &parent);
1165 	case A64_CLK_LOSC:
1166 		return clock_get_frequency(sc->sc_node, "losc");
1167 	case A64_CLK_HOSC:
1168 		return clock_get_frequency(sc->sc_node, "hosc");
1169 	case A64_CLK_PLL_PERIPH0:
1170 		/* Not hardcoded, but recommended. */
1171 		return 600000000;
1172 	case A64_CLK_PLL_PERIPH0_2X:
1173 		return sxiccmu_a64_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2;
1174 	case A64_CLK_APB2:
1175 		/* XXX Controlled by a MUX. */
1176 		return 24000000;
1177 	case A64_CLK_AHB1:
1178 		reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG);
1179 		div = CCU_AHB1_CLK_DIV_RATIO(reg);
1180 		switch (reg & CCU_AHB1_CLK_SRC_SEL) {
1181 		case CCU_AHB1_CLK_SRC_SEL_LOSC:
1182 			parent = A64_CLK_LOSC;
1183 			break;
1184 		case CCU_AHB1_CLK_SRC_SEL_OSC24M:
1185 			parent = A64_CLK_HOSC;
1186 			break;
1187 		case CCU_AHB1_CLK_SRC_SEL_AXI:
1188 			parent = A64_CLK_AXI;
1189 			break;
1190 		case CCU_AHB1_CLK_SRC_SEL_PERIPH0:
1191 			parent = A64_CLK_PLL_PERIPH0;
1192 			div *= CCU_AHB1_PRE_DIV(reg);
1193 			break;
1194 		default:
1195 			return 0;
1196 		}
1197 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1198 	case A64_CLK_AHB2:
1199 		reg = SXIREAD4(sc, CCU_AHB2_CFG_REG);
1200 		switch (reg & CCU_AHB2_CLK_CFG) {
1201 		case 0:
1202 			parent = A64_CLK_AHB1;
1203 			div = 1;
1204 			break;
1205 		case 1:
1206 			parent = A64_CLK_PLL_PERIPH0;
1207 			div = 2;
1208 			break;
1209 		default:
1210 			return 0;
1211 		}
1212 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1213 	}
1214 
1215 	printf("%s: 0x%08x\n", __func__, idx);
1216 	return 0;
1217 }
1218 
1219 #define A80_AHB1_CLK_CFG_REG		0x0064
1220 #define A80_AHB1_SRC_CLK_SELECT		(3 << 24)
1221 #define A80_AHB1_SRC_CLK_SELECT_GTBUS	(0 << 24)
1222 #define A80_AHB1_SRC_CLK_SELECT_PERIPH0	(1 << 24)
1223 #define A80_AHB1_CLK_DIV_RATIO(x)	(1 << ((x) & 0x3))
1224 
1225 uint32_t
sxiccmu_a80_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1226 sxiccmu_a80_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1227 {
1228 	uint32_t parent;
1229 	uint32_t reg, div;
1230 
1231 	switch (idx) {
1232 	case A80_CLK_PLL_PERIPH0:
1233 		/* Not hardcoded, but recommended. */
1234 		return 960000000;
1235 	case A80_CLK_AHB1:
1236 		reg = SXIREAD4(sc, A80_AHB1_CLK_CFG_REG);
1237 		div = A80_AHB1_CLK_DIV_RATIO(reg);
1238 		switch (reg & A80_AHB1_SRC_CLK_SELECT) {
1239 		case A80_AHB1_SRC_CLK_SELECT_GTBUS:
1240 			parent = A80_CLK_GTBUS;
1241 			break;
1242 		case A80_AHB1_SRC_CLK_SELECT_PERIPH0:
1243 			parent = A80_CLK_PLL_PERIPH0;
1244 			break;
1245 		default:
1246 			parent = A80_CLK_PLL_PERIPH1;
1247 			break;
1248 		}
1249 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1250 	case A80_CLK_APB1:
1251 		/* XXX Controlled by a MUX. */
1252 		return 24000000;
1253 	}
1254 
1255 	printf("%s: 0x%08x\n", __func__, idx);
1256 	return 0;
1257 }
1258 
1259 /* Allwinner D1 */
1260 #define D1_PLL_CPU_CTRL_REG		0x0000
1261 #define D1_PLL_CPU_FACTOR_M(x)		(((x) >> 0) & 0x3)
1262 #define D1_PLL_CPU_FACTOR_N(x)		(((x) >> 8) & 0xff)
1263 #define D1_RISCV_CLK_REG		0x0d00
1264 #define D1_RISCV_CLK_SEL		(7 << 24)
1265 #define D1_RISCV_CLK_SEL_HOSC		(0 << 24)
1266 #define D1_RISCV_CLK_SEL_PLL_CPU	(5 << 24)
1267 #define D1_RISCV_DIV_CFG_FACTOR_M(x)	(((x) >> 0) & 0x1f)
1268 #define D1_PSI_CLK_REG			0x0510
1269 #define D1_PSI_CLK_FACTOR_N(x)		(((x) >> 8) & 0x3)
1270 #define D1_PSI_CLK_FACTOR_M(x)		(((x) >> 0) & 0x3)
1271 
1272 uint32_t
sxiccmu_d1_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1273 sxiccmu_d1_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1274 {
1275 	uint32_t parent;
1276 	uint32_t reg, freq;
1277 	uint32_t m, n;
1278 
1279 	switch (idx) {
1280 	case D1_CLK_HOSC:
1281 		return clock_get_frequency(sc->sc_node, "hosc");
1282 	case D1_CLK_PLL_CPU:
1283 		reg = SXIREAD4(sc, D1_PLL_CPU_CTRL_REG);
1284 		m = D1_PLL_CPU_FACTOR_M(reg) + 1;
1285 		n = D1_PLL_CPU_FACTOR_N(reg) + 1;
1286 		return (24000000 * n) / m;
1287 	case D1_CLK_PLL_PERIPH0:
1288 		/* Not hardcoded, but recommended. */
1289 		return 600000000;
1290 	case D1_CLK_APB1:
1291 		/* XXX Controlled by a MUX. */
1292 		return 24000000;
1293 	case D1_CLK_RISCV:
1294 		reg = SXIREAD4(sc, D1_RISCV_CLK_REG);
1295 		switch (reg & D1_RISCV_CLK_SEL) {
1296 		case D1_RISCV_CLK_SEL_HOSC:
1297 			parent = D1_CLK_HOSC;
1298 			break;
1299 		case D1_RISCV_CLK_SEL_PLL_CPU:
1300 			parent = D1_CLK_PLL_CPU;
1301 			break;
1302 		default:
1303 			return 0;
1304 		}
1305 		m = D1_RISCV_DIV_CFG_FACTOR_M(reg) + 1;
1306 		return sxiccmu_ccu_get_frequency(sc, &parent) / m;
1307 	case D1_CLK_PSI_AHB:
1308 		reg = SXIREAD4(sc, D1_PSI_CLK_REG);
1309 		/* assume PLL_PERIPH0 source */
1310 		freq = sxiccmu_d1_get_frequency(sc, D1_CLK_PLL_PERIPH0);
1311 		m = D1_PSI_CLK_FACTOR_M(reg) + 1;
1312 		n = 1 << D1_PSI_CLK_FACTOR_N(reg);
1313 		return freq / (m * n);
1314 	}
1315 
1316 	printf("%s: 0x%08x\n", __func__, idx);
1317 	return 0;
1318 }
1319 
1320 /* Allwinner H3/H5 */
1321 #define H3_PLL_CPUX_CTRL_REG		0x0000
1322 #define H3_PLL_CPUX_ENABLE		(1U << 31)
1323 #define H3_PLL_CPUX_LOCK		(1 << 28)
1324 #define H3_PLL_CPUX_OUT_EXT_DIVP(x)	(((x) >> 16) & 0x3)
1325 #define H3_PLL_CPUX_OUT_EXT_DIVP_MASK	(0x3 << 16)
1326 #define H3_PLL_CPUX_OUT_EXT_DIVP_SHIFT	16
1327 #define H3_PLL_CPUX_FACTOR_N(x)		(((x) >> 8) & 0x1f)
1328 #define H3_PLL_CPUX_FACTOR_N_MASK	(0x1f << 8)
1329 #define H3_PLL_CPUX_FACTOR_N_SHIFT	8
1330 #define H3_PLL_CPUX_FACTOR_K(x)		(((x) >> 4) & 0x3)
1331 #define H3_PLL_CPUX_FACTOR_K_MASK	(0x3 << 4)
1332 #define H3_PLL_CPUX_FACTOR_K_SHIFT	4
1333 #define H3_PLL_CPUX_FACTOR_M(x)		(((x) >> 0) & 0x3)
1334 #define H3_PLL_CPUX_FACTOR_M_MASK	(0x3 << 0)
1335 #define H3_PLL_CPUX_FACTOR_M_SHIFT	0
1336 #define H3_CPUX_AXI_CFG_REG		0x0050
1337 #define H3_CPUX_CLK_SRC_SEL		(0x3 << 16)
1338 #define H3_CPUX_CLK_SRC_SEL_LOSC	(0x0 << 16)
1339 #define H3_CPUX_CLK_SRC_SEL_OSC24M	(0x1 << 16)
1340 #define H3_CPUX_CLK_SRC_SEL_PLL_CPUX	(0x2 << 16)
1341 #define H3_PLL_STABLE_TIME_REG1		0x0204
1342 #define H3_PLL_STABLE_TIME_REG1_TIME(x)	(((x) >> 0) & 0xffff)
1343 
1344 uint32_t
sxiccmu_h3_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1345 sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1346 {
1347 	uint32_t parent;
1348 	uint32_t reg, div;
1349 	uint32_t k, m, n, p;
1350 
1351 	switch (idx) {
1352 	case H3_CLK_LOSC:
1353 		return clock_get_frequency(sc->sc_node, "losc");
1354 	case H3_CLK_HOSC:
1355 		return clock_get_frequency(sc->sc_node, "hosc");
1356 	case H3_CLK_PLL_CPUX:
1357 		reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG);
1358 		k = H3_PLL_CPUX_FACTOR_K(reg) + 1;
1359 		m = H3_PLL_CPUX_FACTOR_M(reg) + 1;
1360 		n = H3_PLL_CPUX_FACTOR_N(reg) + 1;
1361 		p = 1 << H3_PLL_CPUX_OUT_EXT_DIVP(reg);
1362 		return (24000000 * n * k) / (m * p);
1363 	case H3_CLK_PLL_PERIPH0:
1364 		/* Not hardcoded, but recommended. */
1365 		return 600000000;
1366 	case H3_CLK_CPUX:
1367 		reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG);
1368 		switch (reg & H3_CPUX_CLK_SRC_SEL) {
1369 		case H3_CPUX_CLK_SRC_SEL_LOSC:
1370 			parent = H3_CLK_LOSC;
1371 			break;
1372 		case H3_CPUX_CLK_SRC_SEL_OSC24M:
1373 			parent = H3_CLK_HOSC;
1374 			break;
1375 		case H3_CPUX_CLK_SRC_SEL_PLL_CPUX:
1376 			parent = H3_CLK_PLL_CPUX;
1377 			break;
1378 		default:
1379 			return 0;
1380 		}
1381 		return sxiccmu_ccu_get_frequency(sc, &parent);
1382 	case H3_CLK_APB2:
1383 		/* XXX Controlled by a MUX. */
1384 		return 24000000;
1385 	case H3_CLK_AHB1:
1386 		reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG);
1387 		div = CCU_AHB1_CLK_DIV_RATIO(reg);
1388 		switch (reg & CCU_AHB1_CLK_SRC_SEL) {
1389 		case CCU_AHB1_CLK_SRC_SEL_LOSC:
1390 			parent = H3_CLK_LOSC;
1391 			break;
1392 		case CCU_AHB1_CLK_SRC_SEL_OSC24M:
1393 			parent = H3_CLK_HOSC;
1394 			break;
1395 		case CCU_AHB1_CLK_SRC_SEL_AXI:
1396 			parent = H3_CLK_AXI;
1397 			break;
1398 		case CCU_AHB1_CLK_SRC_SEL_PERIPH0:
1399 			parent = H3_CLK_PLL_PERIPH0;
1400 			div *= CCU_AHB1_PRE_DIV(reg);
1401 			break;
1402 		default:
1403 			return 0;
1404 		}
1405 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1406 	case H3_CLK_AHB2:
1407 		reg = SXIREAD4(sc, CCU_AHB2_CFG_REG);
1408 		switch (reg & CCU_AHB2_CLK_CFG) {
1409 		case 0:
1410 			parent = H3_CLK_AHB1;
1411 			div = 1;
1412 			break;
1413 		case 1:
1414 			parent = H3_CLK_PLL_PERIPH0;
1415 			div = 2;
1416 			break;
1417 		default:
1418 			return 0;
1419 		}
1420 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1421 	}
1422 
1423 	printf("%s: 0x%08x\n", __func__, idx);
1424 	return 0;
1425 }
1426 
1427 #define H3_AHB0_CLK_REG			0x0000
1428 #define H3_AHB0_CLK_SRC_SEL		(0x3 << 16)
1429 #define H3_AHB0_CLK_SRC_SEL_OSC32K	(0x0 << 16)
1430 #define H3_AHB0_CLK_SRC_SEL_OSC24M	(0x1 << 16)
1431 #define H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0	(0x2 << 16)
1432 #define H3_AHB0_CLK_SRC_SEL_IOSC	(0x3 << 16)
1433 #define H3_AHB0_CLK_PRE_DIV(x)		((((x) >> 8) & 0x1f) + 1)
1434 #define H3_AHB0_CLK_RATIO(x)		(1 << (((x) >> 4) & 3))
1435 #define H3_APB0_CFG_REG			0x000c
1436 #define H3_APB0_CLK_RATIO(x)		(1 << ((x) & 1))
1437 
1438 uint32_t
sxiccmu_h3_r_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1439 sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1440 {
1441 	uint32_t parent;
1442 	uint32_t reg, div;
1443 	uint32_t freq;
1444 
1445 	switch (idx) {
1446 	case H3_R_CLK_AHB0:
1447 		reg = SXIREAD4(sc, H3_AHB0_CLK_REG);
1448 		switch (reg & H3_AHB0_CLK_SRC_SEL) {
1449 		case H3_AHB0_CLK_SRC_SEL_OSC32K:
1450 			freq = clock_get_frequency(sc->sc_node, "losc");
1451 			break;
1452 		case H3_AHB0_CLK_SRC_SEL_OSC24M:
1453 			freq = clock_get_frequency(sc->sc_node, "hosc");
1454 			break;
1455 		case H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0:
1456 			freq = clock_get_frequency(sc->sc_node, "pll-periph");
1457 			break;
1458 		case H3_AHB0_CLK_SRC_SEL_IOSC:
1459 			freq = clock_get_frequency(sc->sc_node, "iosc");
1460 			break;
1461 		}
1462 		div = H3_AHB0_CLK_PRE_DIV(reg) * H3_AHB0_CLK_RATIO(reg);
1463 		return freq / div;
1464 	case H3_R_CLK_APB0:
1465 		reg = SXIREAD4(sc, H3_APB0_CFG_REG);
1466 		div = H3_APB0_CLK_RATIO(reg);
1467 		parent = H3_R_CLK_AHB0;
1468 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1469 	}
1470 
1471 	printf("%s: 0x%08x\n", __func__, idx);
1472 	return 0;
1473 }
1474 
1475 /* Allwinner H6 */
1476 #define H6_AHB3_CFG_REG		0x051c
1477 #define H6_AHB3_CLK_FACTOR_N(x)	(((x) >> 8) & 0x3)
1478 #define H6_AHB3_CLK_FACTOR_M(x)	(((x) >> 0) & 0x3)
1479 
1480 uint32_t
sxiccmu_h6_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1481 sxiccmu_h6_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1482 {
1483 	uint32_t reg, m, n;
1484 	uint32_t freq;
1485 
1486 	switch (idx) {
1487 	case H6_CLK_PLL_PERIPH0:
1488 		/* Not hardcoded, but recommended. */
1489 		return 600000000;
1490 	case H6_CLK_PLL_PERIPH0_2X:
1491 		return sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0) * 2;
1492 	case H6_CLK_AHB3:
1493 		reg = SXIREAD4(sc, H6_AHB3_CFG_REG);
1494 		/* assume PLL_PERIPH0 source */
1495 		freq = sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0);
1496 		m = H6_AHB3_CLK_FACTOR_M(reg) + 1;
1497 		n = 1 << H6_AHB3_CLK_FACTOR_N(reg);
1498 		return freq / (m * n);
1499 	case H6_CLK_APB2:
1500 		/* XXX Controlled by a MUX. */
1501 		return 24000000;
1502 	}
1503 
1504 	printf("%s: 0x%08x\n", __func__, idx);
1505 	return 0;
1506 }
1507 
1508 uint32_t
sxiccmu_h6_r_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1509 sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1510 {
1511 	switch (idx) {
1512 	case H6_R_CLK_APB2:
1513 		/* XXX Controlled by a MUX. */
1514 		return 24000000;
1515 	}
1516 
1517 	printf("%s: 0x%08x\n", __func__, idx);
1518 	return 0;
1519 }
1520 
1521 /* Allwinner H616 */
1522 #define H616_AHB3_CFG_REG		0x051c
1523 #define H616_AHB3_CLK_FACTOR_N(x)	(((x) >> 8) & 0x3)
1524 #define H616_AHB3_CLK_FACTOR_M(x)	(((x) >> 0) & 0x3)
1525 
1526 uint32_t
sxiccmu_h616_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1527 sxiccmu_h616_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1528 {
1529 	uint32_t reg, m, n;
1530 	uint32_t freq;
1531 
1532 	switch (idx) {
1533 	case H616_CLK_PLL_PERIPH0:
1534 		/* Not hardcoded, but recommended. */
1535 		return 600000000;
1536 	case H616_CLK_PLL_PERIPH0_2X:
1537 		return sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0) * 2;
1538 	case H616_CLK_AHB3:
1539 		reg = SXIREAD4(sc, H616_AHB3_CFG_REG);
1540 		/* assume PLL_PERIPH0 source */
1541 		freq = sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0);
1542 		m = H616_AHB3_CLK_FACTOR_M(reg) + 1;
1543 		n = 1 << H616_AHB3_CLK_FACTOR_N(reg);
1544 		return freq / (m * n);
1545 	case H616_CLK_APB2:
1546 		/* XXX Controlled by a MUX. */
1547 		return 24000000;
1548 	}
1549 
1550 	printf("%s: 0x%08x\n", __func__, idx);
1551 	return 0;
1552 }
1553 
1554 uint32_t
sxiccmu_h616_r_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1555 sxiccmu_h616_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1556 {
1557 	switch (idx) {
1558 	case H616_R_CLK_APB2:
1559 		/* XXX Controlled by a MUX. */
1560 		return 24000000;
1561 	}
1562 
1563 	printf("%s: 0x%08x\n", __func__, idx);
1564 	return 0;
1565 }
1566 
1567 uint32_t
sxiccmu_r40_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1568 sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1569 {
1570 	uint32_t parent;
1571 	uint32_t reg, div;
1572 
1573 	switch (idx) {
1574 	case R40_CLK_LOSC:
1575 		return clock_get_frequency(sc->sc_node, "losc");
1576 	case R40_CLK_HOSC:
1577 		return clock_get_frequency(sc->sc_node, "hosc");
1578 	case R40_CLK_PLL_PERIPH0:
1579 		/* Not hardcoded, but recommended. */
1580 		return 600000000;
1581 	case R40_CLK_PLL_PERIPH0_2X:
1582 		return sxiccmu_r40_get_frequency(sc, R40_CLK_PLL_PERIPH0) * 2;
1583 	case R40_CLK_AHB1:
1584 		reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG);
1585 		div = CCU_AHB1_CLK_DIV_RATIO(reg);
1586 		switch (reg & CCU_AHB1_CLK_SRC_SEL) {
1587 		case CCU_AHB1_CLK_SRC_SEL_LOSC:
1588 			parent = R40_CLK_LOSC;
1589 			break;
1590 		case CCU_AHB1_CLK_SRC_SEL_OSC24M:
1591 			parent = R40_CLK_HOSC;
1592 			break;
1593 		case CCU_AHB1_CLK_SRC_SEL_AXI:
1594 			parent = R40_CLK_AXI;
1595 			break;
1596 		case CCU_AHB1_CLK_SRC_SEL_PERIPH0:
1597 			parent = R40_CLK_PLL_PERIPH0;
1598 			div *= CCU_AHB1_PRE_DIV(reg);
1599 			break;
1600 		}
1601 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1602 	case R40_CLK_APB2:
1603 		/* XXX Controlled by a MUX. */
1604 		return 24000000;
1605 	}
1606 
1607 	printf("%s: 0x%08x\n", __func__, idx);
1608 	return 0;
1609 }
1610 
1611 uint32_t
sxiccmu_v3s_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1612 sxiccmu_v3s_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1613 {
1614 	uint32_t parent;
1615 	uint32_t reg, div;
1616 
1617 	switch (idx) {
1618 	case V3S_CLK_LOSC:
1619 		return clock_get_frequency(sc->sc_node, "losc");
1620 	case V3S_CLK_HOSC:
1621 		return clock_get_frequency(sc->sc_node, "hosc");
1622 	case V3S_CLK_PLL_PERIPH0:
1623 		/* Not hardcoded, but recommended. */
1624 		return 600000000;
1625 	case V3S_CLK_APB2:
1626 		/* XXX Controlled by a MUX. */
1627 		return 24000000;
1628 	case V3S_CLK_AHB1:
1629 		reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG);
1630 		div = CCU_AHB1_CLK_DIV_RATIO(reg);
1631 		switch (reg & CCU_AHB1_CLK_SRC_SEL) {
1632 		case CCU_AHB1_CLK_SRC_SEL_LOSC:
1633 			parent = V3S_CLK_LOSC;
1634 			break;
1635 		case CCU_AHB1_CLK_SRC_SEL_OSC24M:
1636 			parent = V3S_CLK_HOSC;
1637 			break;
1638 		case CCU_AHB1_CLK_SRC_SEL_AXI:
1639 			parent = V3S_CLK_AXI;
1640 			break;
1641 		case CCU_AHB1_CLK_SRC_SEL_PERIPH0:
1642 			parent = V3S_CLK_PLL_PERIPH0;
1643 			div *= CCU_AHB1_PRE_DIV(reg);
1644 			break;
1645 		default:
1646 			return 0;
1647 		}
1648 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1649 	case V3S_CLK_AHB2:
1650 		reg = SXIREAD4(sc, CCU_AHB2_CFG_REG);
1651 		switch (reg & CCU_AHB2_CLK_CFG) {
1652 		case 0:
1653 			parent = V3S_CLK_AHB1;
1654 			div = 1;
1655 			break;
1656 		case 1:
1657 			parent = V3S_CLK_PLL_PERIPH0;
1658 			div = 2;
1659 			break;
1660 		default:
1661 			return 0;
1662 		}
1663 		return sxiccmu_ccu_get_frequency(sc, &parent) / div;
1664 	}
1665 
1666 	printf("%s: 0x%08x\n", __func__, idx);
1667 	return 0;
1668 }
1669 
1670 uint32_t
sxiccmu_nop_get_frequency(struct sxiccmu_softc * sc,uint32_t idx)1671 sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
1672 {
1673 	printf("%s: 0x%08x\n", __func__, idx);
1674 	return 0;
1675 }
1676 
1677 int
sxiccmu_ccu_set_frequency(void * cookie,uint32_t * cells,uint32_t freq)1678 sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1679 {
1680 	struct sxiccmu_softc *sc = cookie;
1681 	uint32_t idx = cells[0];
1682 
1683 	return sc->sc_set_frequency(sc, idx, freq);
1684 }
1685 
1686 int
sxiccmu_a10_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1687 sxiccmu_a10_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1688 {
1689 	struct sxiccmu_clock clock;
1690 	uint32_t parent, parent_freq;
1691 	uint32_t reg;
1692 	int k, n;
1693 	int error;
1694 
1695 	switch (idx) {
1696 	case A10_CLK_PLL_CORE:
1697 		k = 1; n = 32;
1698 		while (k <= 4 && (24000000 * n * k) < freq)
1699 			k++;
1700 		while (n >= 1 && (24000000 * n * k) > freq)
1701 			n--;
1702 
1703 		reg = SXIREAD4(sc, A10_PLL1_CFG_REG);
1704 		reg &= ~A10_PLL1_OUT_EXT_DIVP_MASK;
1705 		reg &= ~A10_PLL1_FACTOR_N_MASK;
1706 		reg &= ~A10_PLL1_FACTOR_K_MASK;
1707 		reg &= ~A10_PLL1_FACTOR_M_MASK;
1708 		reg |= (n << A10_PLL1_FACTOR_N_SHIFT);
1709 		reg |= ((k - 1) << A10_PLL1_FACTOR_K_SHIFT);
1710 		SXIWRITE4(sc, A10_PLL1_CFG_REG, reg);
1711 
1712 		/* No need to wait PLL to lock? */
1713 
1714 		return 0;
1715 	case A10_CLK_CPU:
1716 		/* Switch to 24 MHz clock. */
1717 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1718 		reg &= ~A10_CPU_CLK_SRC_SEL;
1719 		reg |= A10_CPU_CLK_SRC_SEL_OSC24M;
1720 		SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg);
1721 
1722 		error = sxiccmu_a10_set_frequency(sc, A10_CLK_PLL_CORE, freq);
1723 
1724 		/* Switch back to PLL. */
1725 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1726 		reg &= ~A10_CPU_CLK_SRC_SEL;
1727 		reg |= A10_CPU_CLK_SRC_SEL_PLL1;
1728 		SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg);
1729 		return error;
1730 	case A10_CLK_MMC0:
1731 	case A10_CLK_MMC1:
1732 	case A10_CLK_MMC2:
1733 	case A10_CLK_MMC3:
1734 		clock.sc_iot = sc->sc_iot;
1735 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
1736 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
1737 		parent = A10_CLK_PLL_PERIPH;
1738 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
1739 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
1740 	}
1741 
1742 	printf("%s: 0x%08x\n", __func__, idx);
1743 	return -1;
1744 }
1745 
1746 int
sxiccmu_a10s_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1747 sxiccmu_a10s_set_frequency(struct sxiccmu_softc *sc, uint32_t idx,
1748     uint32_t freq)
1749 {
1750 	struct sxiccmu_clock clock;
1751 	uint32_t parent, parent_freq;
1752 	uint32_t reg;
1753 	int k, n;
1754 	int error;
1755 
1756 	switch (idx) {
1757 	case A10S_CLK_PLL_CORE:
1758 		k = 1; n = 32;
1759 		while (k <= 4 && (24000000 * n * k) < freq)
1760 			k++;
1761 		while (n >= 1 && (24000000 * n * k) > freq)
1762 			n--;
1763 
1764 		reg = SXIREAD4(sc, A10_PLL1_CFG_REG);
1765 		reg &= ~A10_PLL1_OUT_EXT_DIVP_MASK;
1766 		reg &= ~A10_PLL1_FACTOR_N_MASK;
1767 		reg &= ~A10_PLL1_FACTOR_K_MASK;
1768 		reg &= ~A10_PLL1_FACTOR_M_MASK;
1769 		reg |= (n << A10_PLL1_FACTOR_N_SHIFT);
1770 		reg |= ((k - 1) << A10_PLL1_FACTOR_K_SHIFT);
1771 		SXIWRITE4(sc, A10_PLL1_CFG_REG, reg);
1772 
1773 		/* No need to wait PLL to lock? */
1774 
1775 		return 0;
1776 	case A10S_CLK_CPU:
1777 		/* Switch to 24 MHz clock. */
1778 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1779 		reg &= ~A10_CPU_CLK_SRC_SEL;
1780 		reg |= A10_CPU_CLK_SRC_SEL_OSC24M;
1781 		SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg);
1782 
1783 		error = sxiccmu_a10s_set_frequency(sc, A10S_CLK_PLL_CORE, freq);
1784 
1785 		/* Switch back to PLL. */
1786 		reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG);
1787 		reg &= ~A10_CPU_CLK_SRC_SEL;
1788 		reg |= A10_CPU_CLK_SRC_SEL_PLL1;
1789 		SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg);
1790 		return error;
1791 	case A10S_CLK_MMC0:
1792 	case A10S_CLK_MMC1:
1793 	case A10S_CLK_MMC2:
1794 		clock.sc_iot = sc->sc_iot;
1795 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
1796 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
1797 		parent = A10S_CLK_PLL_PERIPH;
1798 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
1799 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
1800 	}
1801 
1802 	printf("%s: 0x%08x\n", __func__, idx);
1803 	return -1;
1804 }
1805 
1806 int
sxiccmu_a23_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1807 sxiccmu_a23_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1808 {
1809 	struct sxiccmu_clock clock;
1810 	uint32_t parent, parent_freq;
1811 
1812 	switch (idx) {
1813 	case A23_CLK_MMC0:
1814 	case A23_CLK_MMC1:
1815 	case A23_CLK_MMC2:
1816 		clock.sc_iot = sc->sc_iot;
1817 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
1818 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
1819 		parent = A23_CLK_PLL_PERIPH;
1820 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
1821 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
1822 	}
1823 
1824 	printf("%s: 0x%08x\n", __func__, idx);
1825 	return -1;
1826 }
1827 
1828 int
sxiccmu_a64_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1829 sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1830 {
1831 	struct sxiccmu_clock clock;
1832 	uint32_t parent, parent_freq;
1833 	uint32_t reg;
1834 	int k, n;
1835 	int error;
1836 
1837 	switch (idx) {
1838 	case A64_CLK_PLL_CPUX:
1839 		k = 1; n = 32;
1840 		while (k <= 4 && (24000000 * n * k) < freq)
1841 			k++;
1842 		while (n >= 1 && (24000000 * n * k) > freq)
1843 			n--;
1844 
1845 		reg = SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG);
1846 		reg &= ~A64_PLL_CPUX_OUT_EXT_DIVP_MASK;
1847 		reg &= ~A64_PLL_CPUX_FACTOR_N_MASK;
1848 		reg &= ~A64_PLL_CPUX_FACTOR_K_MASK;
1849 		reg &= ~A64_PLL_CPUX_FACTOR_M_MASK;
1850 		reg |= ((n - 1) << A64_PLL_CPUX_FACTOR_N_SHIFT);
1851 		reg |= ((k - 1) << A64_PLL_CPUX_FACTOR_K_SHIFT);
1852 		SXIWRITE4(sc, A64_PLL_CPUX_CTRL_REG, reg);
1853 
1854 		/* Wait for PLL to lock. */
1855 		while ((SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG) &
1856 		    A64_PLL_CPUX_LOCK) == 0) {
1857 			delay(200);
1858 		}
1859 
1860 		return 0;
1861 	case A64_CLK_CPUX:
1862 		/* Switch to 24 MHz clock. */
1863 		reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG);
1864 		reg &= ~A64_CPUX_CLK_SRC_SEL;
1865 		reg |= A64_CPUX_CLK_SRC_SEL_OSC24M;
1866 		SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg);
1867 
1868 		error = sxiccmu_a64_set_frequency(sc, A64_CLK_PLL_CPUX, freq);
1869 
1870 		/* Switch back to PLL. */
1871 		reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG);
1872 		reg &= ~A64_CPUX_CLK_SRC_SEL;
1873 		reg |= A64_CPUX_CLK_SRC_SEL_PLL_CPUX;
1874 		SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg);
1875 		return error;
1876 	case A64_CLK_MMC0:
1877 	case A64_CLK_MMC1:
1878 	case A64_CLK_MMC2:
1879 		clock.sc_iot = sc->sc_iot;
1880 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
1881 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
1882 		parent = A64_CLK_PLL_PERIPH0_2X;
1883 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
1884 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
1885 	}
1886 
1887 	printf("%s: 0x%08x\n", __func__, idx);
1888 	return -1;
1889 }
1890 
1891 int
sxiccmu_a80_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1892 sxiccmu_a80_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1893 {
1894 	struct sxiccmu_clock clock;
1895 	uint32_t parent, parent_freq;
1896 
1897 	switch (idx) {
1898 	case A80_CLK_MMC0:
1899 	case A80_CLK_MMC1:
1900 	case A80_CLK_MMC2:
1901 		clock.sc_iot = sc->sc_iot;
1902 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
1903 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
1904 		parent = A80_CLK_PLL_PERIPH0;
1905 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
1906 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
1907 	}
1908 
1909 	printf("%s: 0x%08x\n", __func__, idx);
1910 	return -1;
1911 }
1912 
1913 #define D1_SMHC0_CLK_REG		0x0830
1914 #define D1_SMHC1_CLK_REG		0x0834
1915 #define D1_SMHC2_CLK_REG		0x0838
1916 #define D1_SMHC_CLK_SRC_SEL			(0x3 << 24)
1917 #define D1_SMHC_CLK_SRC_SEL_HOSC		(0x0 << 24)
1918 #define D1_SMHC_CLK_SRC_SEL_PLL_PERIPH0		(0x1 << 24)
1919 #define D1_SMHC_FACTOR_N_MASK			(0x3 << 8)
1920 #define D1_SMHC_FACTOR_N_SHIFT			8
1921 #define D1_SMHC_FACTOR_M_MASK			(0xf << 0)
1922 #define D1_SMHC_FACTOR_M_SHIFT			0
1923 
1924 int
sxiccmu_d1_mmc_set_frequency(struct sxiccmu_softc * sc,bus_size_t offset,uint32_t freq)1925 sxiccmu_d1_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
1926     uint32_t freq)
1927 {
1928 	uint32_t parent_freq;
1929 	uint32_t reg, m, n;
1930 	uint32_t clk_src;
1931 
1932 	switch (freq) {
1933 	case 400000:
1934 		n = 2, m = 15;
1935 		clk_src = D1_SMHC_CLK_SRC_SEL_HOSC;
1936 		break;
1937 	case 20000000:
1938 	case 25000000:
1939 	case 26000000:
1940 	case 50000000:
1941 	case 52000000:
1942 		n = 0, m = 0;
1943 		clk_src = D1_SMHC_CLK_SRC_SEL_PLL_PERIPH0;
1944 		parent_freq =
1945 		    sxiccmu_d1_get_frequency(sc, D1_CLK_PLL_PERIPH0);
1946 		while ((parent_freq / (1 << n) / 16) > freq)
1947 			n++;
1948 		while ((parent_freq / (1 << n) / (m + 1)) > freq)
1949 			m++;
1950 		break;
1951 	default:
1952 		return -1;
1953 	}
1954 
1955 	reg = SXIREAD4(sc, offset);
1956 	reg &= ~D1_SMHC_CLK_SRC_SEL;
1957 	reg |= clk_src;
1958 	reg &= ~D1_SMHC_FACTOR_N_MASK;
1959 	reg |= n << D1_SMHC_FACTOR_N_SHIFT;
1960 	reg &= ~D1_SMHC_FACTOR_M_MASK;
1961 	reg |= m << D1_SMHC_FACTOR_M_SHIFT;
1962 	SXIWRITE4(sc, offset, reg);
1963 
1964 	return 0;
1965 }
1966 
1967 int
sxiccmu_d1_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1968 sxiccmu_d1_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1969 {
1970 	switch (idx) {
1971 	case D1_CLK_MMC0:
1972 		return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC0_CLK_REG, freq);
1973 	case D1_CLK_MMC1:
1974 		return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC1_CLK_REG, freq);
1975 	case D1_CLK_MMC2:
1976 		return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC2_CLK_REG, freq);
1977 	}
1978 
1979 	printf("%s: 0x%08x\n", __func__, idx);
1980 	return -1;
1981 }
1982 
1983 int
sxiccmu_h3_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)1984 sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
1985 {
1986 	struct sxiccmu_clock clock;
1987 	uint32_t parent, parent_freq;
1988 	uint32_t reg, lock_time;
1989 	int k, n;
1990 	int error;
1991 
1992 	switch (idx) {
1993 	case H3_CLK_PLL_CPUX:
1994 		k = 1; n = 32;
1995 		while (k <= 4 && (24000000 * n * k) < freq)
1996 			k++;
1997 		while (n >= 1 && (24000000 * n * k) > freq)
1998 			n--;
1999 
2000 		/* Gate the PLL first */
2001 		reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG);
2002 		reg &= ~H3_PLL_CPUX_ENABLE;
2003 		SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
2004 
2005 		/* Set factors and external divider. */
2006 		reg &= ~H3_PLL_CPUX_OUT_EXT_DIVP_MASK;
2007 		reg &= ~H3_PLL_CPUX_FACTOR_N_MASK;
2008 		reg &= ~H3_PLL_CPUX_FACTOR_K_MASK;
2009 		reg &= ~H3_PLL_CPUX_FACTOR_M_MASK;
2010 		reg |= ((n - 1) << H3_PLL_CPUX_FACTOR_N_SHIFT);
2011 		reg |= ((k - 1) << H3_PLL_CPUX_FACTOR_K_SHIFT);
2012 		SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
2013 
2014 		/* Ungate the PLL */
2015 		reg |= H3_PLL_CPUX_ENABLE;
2016 		SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg);
2017 
2018 		/* Wait for PLL to lock. (LOCK flag is unreliable) */
2019 		lock_time = SXIREAD4(sc, H3_PLL_STABLE_TIME_REG1);
2020 		delay(H3_PLL_STABLE_TIME_REG1_TIME(lock_time));
2021 
2022 		return 0;
2023 	case H3_CLK_CPUX:
2024 		/* Switch to 24 MHz clock. */
2025 		reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG);
2026 		reg &= ~H3_CPUX_CLK_SRC_SEL;
2027 		reg |= H3_CPUX_CLK_SRC_SEL_OSC24M;
2028 		SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg);
2029 		/* Must wait at least 8 cycles of the current clock. */
2030 		delay(1);
2031 
2032 		error = sxiccmu_h3_set_frequency(sc, H3_CLK_PLL_CPUX, freq);
2033 
2034 		/* Switch back to PLL. */
2035 		reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG);
2036 		reg &= ~H3_CPUX_CLK_SRC_SEL;
2037 		reg |= H3_CPUX_CLK_SRC_SEL_PLL_CPUX;
2038 		SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg);
2039 		/* Must wait at least 8 cycles of the current clock. */
2040 		delay(1);
2041 		return error;
2042 	case H3_CLK_MMC0:
2043 	case H3_CLK_MMC1:
2044 	case H3_CLK_MMC2:
2045 		clock.sc_iot = sc->sc_iot;
2046 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
2047 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
2048 		parent = H3_CLK_PLL_PERIPH0;
2049 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
2050 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
2051 	}
2052 
2053 	printf("%s: 0x%08x\n", __func__, idx);
2054 	return -1;
2055 }
2056 
2057 #define H6_SMHC0_CLK_REG		0x0830
2058 #define H6_SMHC1_CLK_REG		0x0834
2059 #define H6_SMHC2_CLK_REG		0x0838
2060 #define H6_SMHC_CLK_SRC_SEL			(0x3 << 24)
2061 #define H6_SMHC_CLK_SRC_SEL_OSC24M		(0x0 << 24)
2062 #define H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X	(0x1 << 24)
2063 #define H6_SMHC_FACTOR_N_MASK			(0x3 << 8)
2064 #define H6_SMHC_FACTOR_N_SHIFT			8
2065 #define H6_SMHC_FACTOR_M_MASK			(0xf << 0)
2066 #define H6_SMHC_FACTOR_M_SHIFT			0
2067 
2068 int
sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc * sc,bus_size_t offset,uint32_t freq,uint32_t parent_freq)2069 sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
2070     uint32_t freq, uint32_t parent_freq)
2071 {
2072 	uint32_t reg, m, n;
2073 	uint32_t clk_src;
2074 
2075 	switch (freq) {
2076 	case 400000:
2077 		n = 2, m = 15;
2078 		clk_src = H6_SMHC_CLK_SRC_SEL_OSC24M;
2079 		break;
2080 	case 20000000:
2081 	case 25000000:
2082 	case 26000000:
2083 	case 50000000:
2084 	case 52000000:
2085 		n = 0, m = 0;
2086 		clk_src = H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X;
2087 		while ((parent_freq / (1 << n) / 16) > freq)
2088 			n++;
2089 		while ((parent_freq / (1 << n) / (m + 1)) > freq)
2090 			m++;
2091 		break;
2092 	default:
2093 		return -1;
2094 	}
2095 
2096 	reg = SXIREAD4(sc, offset);
2097 	reg &= ~H6_SMHC_CLK_SRC_SEL;
2098 	reg |= clk_src;
2099 	reg &= ~H6_SMHC_FACTOR_N_MASK;
2100 	reg |= n << H6_SMHC_FACTOR_N_SHIFT;
2101 	reg &= ~H6_SMHC_FACTOR_M_MASK;
2102 	reg |= m << H6_SMHC_FACTOR_M_SHIFT;
2103 	SXIWRITE4(sc, offset, reg);
2104 
2105 	return 0;
2106 }
2107 
2108 int
sxiccmu_h6_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)2109 sxiccmu_h6_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
2110 {
2111 	uint32_t parent_freq;
2112 
2113 	parent_freq = sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0_2X);
2114 
2115 	switch (idx) {
2116 	case H6_CLK_MMC0:
2117 		return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG,
2118 						    freq, parent_freq);
2119 	case H6_CLK_MMC1:
2120 		return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG,
2121 						    freq, parent_freq);
2122 	case H6_CLK_MMC2:
2123 		return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG,
2124 						    freq, parent_freq);
2125 	}
2126 
2127 	printf("%s: 0x%08x\n", __func__, idx);
2128 	return -1;
2129 }
2130 
2131 #define H616_SMHC0_CLK_REG		0x0830
2132 #define H616_SMHC1_CLK_REG		0x0834
2133 #define H616_SMHC2_CLK_REG		0x0838
2134 
2135 int
sxiccmu_h616_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)2136 sxiccmu_h616_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
2137 {
2138 	uint32_t parent_freq;
2139 
2140 	parent_freq = sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0_2X);
2141 
2142 	switch (idx) {
2143 	case H616_CLK_MMC0:
2144 		return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC0_CLK_REG,
2145 						    freq, parent_freq);
2146 	case H616_CLK_MMC1:
2147 		return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC1_CLK_REG,
2148 						    freq, parent_freq);
2149 	case H616_CLK_MMC2:
2150 		return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC2_CLK_REG,
2151 						    freq, parent_freq);
2152 	}
2153 
2154 	printf("%s: 0x%08x\n", __func__, idx);
2155 	return -1;
2156 }
2157 
2158 int
sxiccmu_r40_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)2159 sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
2160 {
2161 	struct sxiccmu_clock clock;
2162 	uint32_t parent, parent_freq;
2163 
2164 	switch (idx) {
2165 	case R40_CLK_MMC0:
2166 	case R40_CLK_MMC1:
2167 	case R40_CLK_MMC2:
2168 	case R40_CLK_MMC3:
2169 		clock.sc_iot = sc->sc_iot;
2170 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
2171 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
2172 		parent = R40_CLK_PLL_PERIPH0_2X;
2173 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
2174 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
2175 	}
2176 
2177 	printf("%s: 0x%08x\n", __func__, idx);
2178 	return -1;
2179 }
2180 
2181 int
sxiccmu_v3s_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)2182 sxiccmu_v3s_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
2183 {
2184 	struct sxiccmu_clock clock;
2185 	uint32_t parent, parent_freq;
2186 
2187 	switch (idx) {
2188 	case V3S_CLK_MMC0:
2189 	case V3S_CLK_MMC1:
2190 	case V3S_CLK_MMC2:
2191 		clock.sc_iot = sc->sc_iot;
2192 		bus_space_subregion(sc->sc_iot, sc->sc_ioh,
2193 		    sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
2194 		parent = V3S_CLK_PLL_PERIPH0;
2195 		parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
2196 		return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
2197 	}
2198 
2199 	printf("%s: 0x%08x\n", __func__, idx);
2200 	return -1;
2201 }
2202 
2203 int
sxiccmu_nop_set_frequency(struct sxiccmu_softc * sc,uint32_t idx,uint32_t freq)2204 sxiccmu_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
2205 {
2206 	printf("%s: 0x%08x\n", __func__, idx);
2207 	return -1;
2208 }
2209 
2210 void
sxiccmu_ccu_enable(void * cookie,uint32_t * cells,int on)2211 sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
2212 {
2213 	struct sxiccmu_softc *sc = cookie;
2214 	uint32_t idx = cells[0];
2215 	int reg, bit;
2216 
2217 	clock_enable_all(sc->sc_node);
2218 
2219 	if (idx >= sc->sc_ngates ||
2220 	    (sc->sc_gates[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
2221 		printf("%s: 0x%08x\n", __func__, cells[0]);
2222 		return;
2223 	}
2224 
2225 	/* If the clock can't be gated, simply return. */
2226 	if (sc->sc_gates[idx].reg == 0xffff && sc->sc_gates[idx].bit == 0xff)
2227 		return;
2228 
2229 	reg = sc->sc_gates[idx].reg;
2230 	bit = sc->sc_gates[idx].bit;
2231 
2232 	if (on)
2233 		SXISET4(sc, reg, (1U << bit));
2234 	else
2235 		SXICLR4(sc, reg, (1U << bit));
2236 }
2237 
2238 void
sxiccmu_ccu_reset(void * cookie,uint32_t * cells,int assert)2239 sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert)
2240 {
2241 	struct sxiccmu_softc *sc = cookie;
2242 	uint32_t idx = cells[0];
2243 	int reg, bit;
2244 
2245 	reset_deassert_all(sc->sc_node);
2246 
2247 	if (idx >= sc->sc_nresets ||
2248 	    (sc->sc_resets[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
2249 		printf("%s: 0x%08x\n", __func__, cells[0]);
2250 		return;
2251 	}
2252 
2253 	reg = sc->sc_resets[idx].reg;
2254 	bit = sc->sc_resets[idx].bit;
2255 
2256 	if (assert)
2257 		SXICLR4(sc, reg, (1U << bit));
2258 	else
2259 		SXISET4(sc, reg, (1U << bit));
2260 }
2261