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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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