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