1 /* $OpenBSD: sxiccmu.c,v 1.32 2023/08/15 08:27:30 miod 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_a23_get_frequency(struct sxiccmu_softc *, uint32_t); 96 int sxiccmu_a23_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 97 uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *, uint32_t); 98 int sxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 99 uint32_t sxiccmu_a80_get_frequency(struct sxiccmu_softc *, uint32_t); 100 int sxiccmu_a80_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 101 uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *, uint32_t); 102 int sxiccmu_h3_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 103 uint32_t sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *, uint32_t); 104 uint32_t sxiccmu_h6_get_frequency(struct sxiccmu_softc *, uint32_t); 105 int sxiccmu_h6_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 106 uint32_t sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *, uint32_t); 107 uint32_t sxiccmu_r40_get_frequency(struct sxiccmu_softc *, uint32_t); 108 int sxiccmu_r40_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 109 uint32_t sxiccmu_v3s_get_frequency(struct sxiccmu_softc *, uint32_t); 110 int sxiccmu_v3s_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 111 uint32_t sxiccmu_nop_get_frequency(struct sxiccmu_softc *, uint32_t); 112 int sxiccmu_nop_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); 113 114 int 115 sxiccmu_match(struct device *parent, void *match, void *aux) 116 { 117 struct fdt_attach_args *faa = aux; 118 int node = faa->fa_node; 119 120 if (node == OF_finddevice("/clocks")) { 121 node = OF_parent(node); 122 123 return (OF_is_compatible(node, "allwinner,sun4i-a10") || 124 OF_is_compatible(node, "allwinner,sun5i-a10s") || 125 OF_is_compatible(node, "allwinner,sun5i-r8") || 126 OF_is_compatible(node, "allwinner,sun7i-a20") || 127 OF_is_compatible(node, "allwinner,sun8i-a23") || 128 OF_is_compatible(node, "allwinner,sun8i-a33") || 129 OF_is_compatible(node, "allwinner,sun8i-h3") || 130 OF_is_compatible(node, "allwinner,sun8i-v3s") || 131 OF_is_compatible(node, "allwinner,sun9i-a80") || 132 OF_is_compatible(node, "allwinner,sun50i-a64") || 133 OF_is_compatible(node, "allwinner,sun50i-h5")); 134 } 135 136 return (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") || 137 OF_is_compatible(node, "allwinner,sun7i-a20-ccu") || 138 OF_is_compatible(node, "allwinner,sun8i-a23-ccu") || 139 OF_is_compatible(node, "allwinner,sun8i-a23-prcm") || 140 OF_is_compatible(node, "allwinner,sun8i-a33-ccu") || 141 OF_is_compatible(node, "allwinner,sun8i-h3-ccu") || 142 OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") || 143 OF_is_compatible(node, "allwinner,sun8i-r40-ccu") || 144 OF_is_compatible(node, "allwinner,sun8i-v3s-ccu") || 145 OF_is_compatible(node, "allwinner,sun9i-a80-ccu") || 146 OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks") || 147 OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk") || 148 OF_is_compatible(node, "allwinner,sun50i-a64-ccu") || 149 OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu") || 150 OF_is_compatible(node, "allwinner,sun50i-h5-ccu") || 151 OF_is_compatible(node, "allwinner,sun50i-h6-ccu") || 152 OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu")); 153 } 154 155 void 156 sxiccmu_attach(struct device *parent, struct device *self, void *aux) 157 { 158 struct sxiccmu_softc *sc = (struct sxiccmu_softc *)self; 159 struct fdt_attach_args *faa = aux; 160 int node = faa->fa_node; 161 162 sc->sc_node = faa->fa_node; 163 sc->sc_iot = faa->fa_iot; 164 if (faa->fa_nreg > 0 && bus_space_map(sc->sc_iot, 165 faa->fa_reg[0].addr, faa->fa_reg[0].size, 0, &sc->sc_ioh)) 166 panic("%s: bus_space_map failed!", __func__); 167 168 /* On the R40, the GMAC needs to poke at one of our registers. */ 169 if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) { 170 bus_space_handle_t ioh; 171 172 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 173 R40_GMAC_CLK_REG, 4, &ioh); 174 regmap_register(faa->fa_node, sc->sc_iot, ioh, 4); 175 } 176 177 printf("\n"); 178 179 if (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") || 180 OF_is_compatible(node, "allwinner,sun7i-a20-ccu")) { 181 KASSERT(faa->fa_nreg > 0); 182 sc->sc_gates = sun4i_a10_gates; 183 sc->sc_ngates = nitems(sun4i_a10_gates); 184 sc->sc_resets = sun4i_a10_resets; 185 sc->sc_nresets = nitems(sun4i_a10_resets); 186 sc->sc_get_frequency = sxiccmu_a10_get_frequency; 187 sc->sc_set_frequency = sxiccmu_a10_set_frequency; 188 } else if (OF_is_compatible(node, "allwinner,sun8i-a23-ccu") || 189 OF_is_compatible(node, "allwinner,sun8i-a33-ccu")) { 190 KASSERT(faa->fa_nreg > 0); 191 sc->sc_gates = sun8i_a23_gates; 192 sc->sc_ngates = nitems(sun8i_a23_gates); 193 sc->sc_resets = sun8i_a23_resets; 194 sc->sc_nresets = nitems(sun8i_a23_resets); 195 sc->sc_get_frequency = sxiccmu_a23_get_frequency; 196 sc->sc_set_frequency = sxiccmu_a23_set_frequency; 197 } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu") || 198 OF_is_compatible(node, "allwinner,sun50i-h5-ccu")) { 199 KASSERT(faa->fa_nreg > 0); 200 sc->sc_gates = sun8i_h3_gates; 201 sc->sc_ngates = nitems(sun8i_h3_gates); 202 sc->sc_resets = sun8i_h3_resets; 203 sc->sc_nresets = nitems(sun8i_h3_resets); 204 sc->sc_get_frequency = sxiccmu_h3_get_frequency; 205 sc->sc_set_frequency = sxiccmu_h3_set_frequency; 206 } else if (OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") || 207 OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu")) { 208 KASSERT(faa->fa_nreg > 0); 209 sc->sc_gates = sun8i_h3_r_gates; 210 sc->sc_ngates = nitems(sun8i_h3_r_gates); 211 sc->sc_resets = sun8i_h3_r_resets; 212 sc->sc_nresets = nitems(sun8i_h3_r_resets); 213 sc->sc_get_frequency = sxiccmu_h3_r_get_frequency; 214 sc->sc_set_frequency = sxiccmu_nop_set_frequency; 215 } else if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) { 216 KASSERT(faa->fa_nreg > 0); 217 sc->sc_gates = sun8i_r40_gates; 218 sc->sc_ngates = nitems(sun8i_r40_gates); 219 sc->sc_resets = sun8i_r40_resets; 220 sc->sc_nresets = nitems(sun8i_r40_resets); 221 sc->sc_get_frequency = sxiccmu_r40_get_frequency; 222 sc->sc_set_frequency = sxiccmu_r40_set_frequency; 223 } else if (OF_is_compatible(node, "allwinner,sun8i-v3s-ccu")) { 224 KASSERT(faa->fa_nreg > 0); 225 sc->sc_gates = sun8i_v3s_gates; 226 sc->sc_ngates = nitems(sun8i_v3s_gates); 227 sc->sc_resets = sun8i_v3s_resets; 228 sc->sc_nresets = nitems(sun8i_v3s_resets); 229 sc->sc_get_frequency = sxiccmu_v3s_get_frequency; 230 sc->sc_set_frequency = sxiccmu_v3s_set_frequency; 231 } else if (OF_is_compatible(node, "allwinner,sun9i-a80-ccu")) { 232 KASSERT(faa->fa_nreg > 0); 233 sc->sc_gates = sun9i_a80_gates; 234 sc->sc_ngates = nitems(sun9i_a80_gates); 235 sc->sc_resets = sun9i_a80_resets; 236 sc->sc_nresets = nitems(sun9i_a80_resets); 237 sc->sc_get_frequency = sxiccmu_a80_get_frequency; 238 sc->sc_set_frequency = sxiccmu_a80_set_frequency; 239 } else if (OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks")) { 240 KASSERT(faa->fa_nreg > 0); 241 sc->sc_gates = sun9i_a80_usb_gates; 242 sc->sc_ngates = nitems(sun9i_a80_usb_gates); 243 sc->sc_resets = sun9i_a80_usb_resets; 244 sc->sc_nresets = nitems(sun9i_a80_usb_resets); 245 sc->sc_get_frequency = sxiccmu_nop_get_frequency; 246 sc->sc_set_frequency = sxiccmu_nop_set_frequency; 247 } else if (OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk")) { 248 KASSERT(faa->fa_nreg > 0); 249 sc->sc_gates = sun9i_a80_mmc_gates; 250 sc->sc_ngates = nitems(sun9i_a80_mmc_gates); 251 sc->sc_resets = sun9i_a80_mmc_resets; 252 sc->sc_nresets = nitems(sun9i_a80_mmc_resets); 253 sc->sc_get_frequency = sxiccmu_nop_get_frequency; 254 sc->sc_set_frequency = sxiccmu_nop_set_frequency; 255 } else if (OF_is_compatible(node, "allwinner,sun50i-a64-ccu")) { 256 KASSERT(faa->fa_nreg > 0); 257 sc->sc_gates = sun50i_a64_gates; 258 sc->sc_ngates = nitems(sun50i_a64_gates); 259 sc->sc_resets = sun50i_a64_resets; 260 sc->sc_nresets = nitems(sun50i_a64_resets); 261 sc->sc_get_frequency = sxiccmu_a64_get_frequency; 262 sc->sc_set_frequency = sxiccmu_a64_set_frequency; 263 } else if (OF_is_compatible(node, "allwinner,sun50i-h6-ccu")) { 264 KASSERT(faa->fa_nreg > 0); 265 sc->sc_gates = sun50i_h6_gates; 266 sc->sc_ngates = nitems(sun50i_h6_gates); 267 sc->sc_resets = sun50i_h6_resets; 268 sc->sc_nresets = nitems(sun50i_h6_resets); 269 sc->sc_get_frequency = sxiccmu_h6_get_frequency; 270 sc->sc_set_frequency = sxiccmu_h6_set_frequency; 271 } else if (OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu")) { 272 KASSERT(faa->fa_nreg > 0); 273 sc->sc_gates = sun50i_h6_r_gates; 274 sc->sc_ngates = nitems(sun50i_h6_r_gates); 275 sc->sc_resets = sun50i_h6_r_resets; 276 sc->sc_nresets = nitems(sun50i_h6_r_resets); 277 sc->sc_get_frequency = sxiccmu_h6_r_get_frequency; 278 sc->sc_set_frequency = sxiccmu_nop_set_frequency; 279 } else { 280 for (node = OF_child(node); node; node = OF_peer(node)) 281 sxiccmu_attach_clock(sc, node, faa->fa_nreg); 282 } 283 284 if (sc->sc_gates) { 285 sc->sc_cd.cd_node = sc->sc_node; 286 sc->sc_cd.cd_cookie = sc; 287 sc->sc_cd.cd_get_frequency = sxiccmu_ccu_get_frequency; 288 sc->sc_cd.cd_set_frequency = sxiccmu_ccu_set_frequency; 289 sc->sc_cd.cd_enable = sxiccmu_ccu_enable; 290 clock_register(&sc->sc_cd); 291 } 292 293 if (sc->sc_resets) { 294 sc->sc_rd.rd_node = sc->sc_node; 295 sc->sc_rd.rd_cookie = sc; 296 sc->sc_rd.rd_reset = sxiccmu_ccu_reset; 297 reset_register(&sc->sc_rd); 298 } 299 } 300 301 /* 302 * Classic device trees for the Allwinner SoCs have basically a clock 303 * node per register of the clock control unit. Attaching a separate 304 * driver to each of them would be crazy, so we handle them here. 305 */ 306 307 struct sxiccmu_clock { 308 int sc_node; 309 bus_space_tag_t sc_iot; 310 bus_space_handle_t sc_ioh; 311 312 struct clock_device sc_cd; 313 struct reset_device sc_rd; 314 }; 315 316 struct sxiccmu_device { 317 const char *compat; 318 uint32_t (*get_frequency)(void *, uint32_t *); 319 int (*set_frequency)(void *, uint32_t *, uint32_t); 320 void (*enable)(void *, uint32_t *, int); 321 void (*reset)(void *, uint32_t *, int); 322 bus_size_t offset; 323 }; 324 325 uint32_t sxiccmu_gen_get_frequency(void *, uint32_t *); 326 uint32_t sxiccmu_osc_get_frequency(void *, uint32_t *); 327 uint32_t sxiccmu_pll6_get_frequency(void *, uint32_t *); 328 void sxiccmu_pll6_enable(void *, uint32_t *, int); 329 uint32_t sxiccmu_apb1_get_frequency(void *, uint32_t *); 330 uint32_t sxiccmu_cpus_get_frequency(void *, uint32_t *); 331 uint32_t sxiccmu_apbs_get_frequency(void *, uint32_t *); 332 int sxiccmu_gmac_set_frequency(void *, uint32_t *, uint32_t); 333 int sxiccmu_mmc_set_frequency(void *, uint32_t *, uint32_t); 334 void sxiccmu_mmc_enable(void *, uint32_t *, int); 335 void sxiccmu_gate_enable(void *, uint32_t *, int); 336 void sxiccmu_reset(void *, uint32_t *, int); 337 338 const struct sxiccmu_device sxiccmu_devices[] = { 339 { 340 .compat = "allwinner,sun4i-a10-osc-clk", 341 .get_frequency = sxiccmu_osc_get_frequency, 342 }, 343 { 344 .compat = "allwinner,sun4i-a10-pll6-clk", 345 .get_frequency = sxiccmu_pll6_get_frequency, 346 .enable = sxiccmu_pll6_enable 347 }, 348 { 349 .compat = "allwinner,sun4i-a10-apb1-clk", 350 .get_frequency = sxiccmu_apb1_get_frequency, 351 }, 352 { 353 .compat = "allwinner,sun4i-a10-ahb-gates-clk", 354 .get_frequency = sxiccmu_gen_get_frequency, 355 .enable = sxiccmu_gate_enable 356 }, 357 { 358 .compat = "allwinner,sun4i-a10-apb0-gates-clk", 359 .get_frequency = sxiccmu_gen_get_frequency, 360 .enable = sxiccmu_gate_enable 361 }, 362 { 363 .compat = "allwinner,sun4i-a10-apb1-gates-clk", 364 .get_frequency = sxiccmu_gen_get_frequency, 365 .enable = sxiccmu_gate_enable 366 }, 367 { 368 .compat = "allwinner,sun4i-a10-mmc-clk", 369 .set_frequency = sxiccmu_mmc_set_frequency, 370 .enable = sxiccmu_mmc_enable 371 }, 372 { 373 .compat = "allwinner,sun4i-a10-usb-clk", 374 .get_frequency = sxiccmu_gen_get_frequency, 375 .enable = sxiccmu_gate_enable, 376 .reset = sxiccmu_reset 377 }, 378 { 379 .compat = "allwinner,sun5i-a10s-ahb-gates-clk", 380 .get_frequency = sxiccmu_gen_get_frequency, 381 .enable = sxiccmu_gate_enable 382 }, 383 { 384 .compat = "allwinner,sun5i-a10s-apb0-gates-clk", 385 .get_frequency = sxiccmu_gen_get_frequency, 386 .enable = sxiccmu_gate_enable 387 }, 388 { 389 .compat = "allwinner,sun5i-a10s-apb1-gates-clk", 390 .get_frequency = sxiccmu_gen_get_frequency, 391 .enable = sxiccmu_gate_enable 392 }, 393 { 394 .compat = "allwinner,sun5i-a13-ahb-gates-clk", 395 .get_frequency = sxiccmu_gen_get_frequency, 396 .enable = sxiccmu_gate_enable 397 }, 398 { 399 .compat = "allwinner,sun5i-a13-apb0-gates-clk", 400 .get_frequency = sxiccmu_gen_get_frequency, 401 .enable = sxiccmu_gate_enable 402 }, 403 { 404 .compat = "allwinner,sun5i-a13-apb1-gates-clk", 405 .get_frequency = sxiccmu_gen_get_frequency, 406 .enable = sxiccmu_gate_enable 407 }, 408 { 409 .compat = "allwinner,sun5i-a13-usb-clk", 410 .get_frequency = sxiccmu_gen_get_frequency, 411 .enable = sxiccmu_gate_enable, 412 .reset = sxiccmu_reset 413 }, 414 { 415 .compat = "allwinner,sun6i-a31-ahb1-reset", 416 .reset = sxiccmu_reset 417 }, 418 { 419 .compat = "allwinner,sun6i-a31-clock-reset", 420 .reset = sxiccmu_reset, 421 .offset = 0x00b0 422 }, 423 { 424 .compat = "allwinner,sun7i-a20-ahb-gates-clk", 425 .get_frequency = sxiccmu_gen_get_frequency, 426 .enable = sxiccmu_gate_enable 427 }, 428 { 429 .compat = "allwinner,sun7i-a20-apb0-gates-clk", 430 .get_frequency = sxiccmu_gen_get_frequency, 431 .enable = sxiccmu_gate_enable 432 }, 433 { 434 .compat = "allwinner,sun7i-a20-apb1-gates-clk", 435 .get_frequency = sxiccmu_gen_get_frequency, 436 .enable = sxiccmu_gate_enable 437 }, 438 { 439 .compat = "allwinner,sun7i-a20-gmac-clk", 440 .set_frequency = sxiccmu_gmac_set_frequency 441 }, 442 { 443 .compat = "allwinner,sun8i-a23-apb0-clk", 444 .get_frequency = sxiccmu_apbs_get_frequency, 445 .offset = 0x000c 446 }, 447 { 448 .compat = "allwinner,sun8i-a23-ahb1-gates-clk", 449 .get_frequency = sxiccmu_gen_get_frequency, 450 .enable = sxiccmu_gate_enable 451 }, 452 { 453 .compat = "allwinner,sun8i-a23-apb0-gates-clk", 454 .get_frequency = sxiccmu_gen_get_frequency, 455 .enable = sxiccmu_gate_enable, 456 .offset = 0x0028 457 }, 458 { 459 .compat = "allwinner,sun8i-a23-apb1-gates-clk", 460 .get_frequency = sxiccmu_gen_get_frequency, 461 .enable = sxiccmu_gate_enable 462 }, 463 { 464 .compat = "allwinner,sun8i-a23-apb2-gates-clk", 465 .get_frequency = sxiccmu_gen_get_frequency, 466 .enable = sxiccmu_gate_enable 467 }, 468 { 469 .compat = "allwinner,sun8i-a23-usb-clk", 470 .get_frequency = sxiccmu_gen_get_frequency, 471 .enable = sxiccmu_gate_enable, 472 .reset = sxiccmu_reset 473 }, 474 { 475 .compat = "allwinner,sun8i-h3-apb0-gates-clk", 476 .get_frequency = sxiccmu_gen_get_frequency, 477 .enable = sxiccmu_gate_enable 478 }, 479 { 480 .compat = "allwinner,sun9i-a80-apb1-clk", 481 .get_frequency = sxiccmu_apb1_get_frequency, 482 }, 483 { 484 .compat = "allwinner,sun9i-a80-ahb0-gates-clk", 485 .get_frequency = sxiccmu_gen_get_frequency, 486 .enable = sxiccmu_gate_enable 487 }, 488 { 489 .compat = "allwinner,sun9i-a80-ahb1-gates-clk", 490 .get_frequency = sxiccmu_gen_get_frequency, 491 .enable = sxiccmu_gate_enable 492 }, 493 { 494 .compat = "allwinner,sun9i-a80-ahb2-gates-clk", 495 .get_frequency = sxiccmu_gen_get_frequency, 496 .enable = sxiccmu_gate_enable 497 }, 498 { 499 .compat = "allwinner,sun9i-a80-apb0-gates-clk", 500 .get_frequency = sxiccmu_gen_get_frequency, 501 .enable = sxiccmu_gate_enable 502 }, 503 { 504 .compat = "allwinner,sun9i-a80-apb1-gates-clk", 505 .get_frequency = sxiccmu_gen_get_frequency, 506 .enable = sxiccmu_gate_enable 507 }, 508 { 509 .compat = "allwinner,sun9i-a80-apbs-gates-clk", 510 .get_frequency = sxiccmu_gen_get_frequency, 511 .enable = sxiccmu_gate_enable 512 }, 513 { 514 .compat = "allwinner,sun9i-a80-cpus-clk", 515 .get_frequency = sxiccmu_cpus_get_frequency 516 }, 517 { 518 .compat = "allwinner,sun9i-a80-mmc-clk", 519 .set_frequency = sxiccmu_mmc_set_frequency, 520 .enable = sxiccmu_mmc_enable 521 }, 522 { 523 .compat = "allwinner,sun9i-a80-usb-mod-clk", 524 .get_frequency = sxiccmu_gen_get_frequency, 525 .enable = sxiccmu_gate_enable, 526 .reset = sxiccmu_reset 527 }, 528 { 529 .compat = "allwinner,sun9i-a80-usb-phy-clk", 530 .get_frequency = sxiccmu_gen_get_frequency, 531 .enable = sxiccmu_gate_enable, 532 .reset = sxiccmu_reset 533 }, 534 }; 535 536 void 537 sxiccmu_attach_clock(struct sxiccmu_softc *sc, int node, int nreg) 538 { 539 struct sxiccmu_clock *clock; 540 uint32_t reg[2]; 541 int i, error = ENODEV; 542 543 for (i = 0; i < nitems(sxiccmu_devices); i++) 544 if (OF_is_compatible(node, sxiccmu_devices[i].compat)) 545 break; 546 if (i == nitems(sxiccmu_devices)) 547 return; 548 549 clock = malloc(sizeof(*clock), M_DEVBUF, M_WAITOK); 550 clock->sc_node = node; 551 552 clock->sc_iot = sc->sc_iot; 553 if (OF_getpropintarray(node, "reg", reg, sizeof(reg)) == sizeof(reg)) { 554 error = bus_space_map(clock->sc_iot, reg[0], reg[1], 0, 555 &clock->sc_ioh); 556 } else if (nreg > 0) { 557 error = bus_space_subregion(clock->sc_iot, sc->sc_ioh, 558 sxiccmu_devices[i].offset, 4, &clock->sc_ioh); 559 } 560 if (error) { 561 printf("%s: can't map registers", sc->sc_dev.dv_xname); 562 free(clock, M_DEVBUF, sizeof(*clock)); 563 return; 564 } 565 566 clock->sc_cd.cd_node = node; 567 clock->sc_cd.cd_cookie = clock; 568 clock->sc_cd.cd_get_frequency = sxiccmu_devices[i].get_frequency; 569 clock->sc_cd.cd_set_frequency = sxiccmu_devices[i].set_frequency; 570 clock->sc_cd.cd_enable = sxiccmu_devices[i].enable; 571 clock_register(&clock->sc_cd); 572 573 if (sxiccmu_devices[i].reset) { 574 clock->sc_rd.rd_node = node; 575 clock->sc_rd.rd_cookie = clock; 576 clock->sc_rd.rd_reset = sxiccmu_devices[i].reset; 577 reset_register(&clock->sc_rd); 578 } 579 } 580 581 /* 582 * A "generic" function that simply gets the clock frequency from the 583 * parent clock. Useful for clock gating devices that don't scale 584 * their clocks. 585 */ 586 uint32_t 587 sxiccmu_gen_get_frequency(void *cookie, uint32_t *cells) 588 { 589 struct sxiccmu_clock *sc = cookie; 590 591 return clock_get_frequency(sc->sc_node, NULL); 592 } 593 594 uint32_t 595 sxiccmu_osc_get_frequency(void *cookie, uint32_t *cells) 596 { 597 struct sxiccmu_clock *sc = cookie; 598 599 return OF_getpropint(sc->sc_node, "clock-frequency", 24000000); 600 } 601 602 #define CCU_PLL6_ENABLE (1U << 31) 603 #define CCU_PLL6_BYPASS_EN (1U << 30) 604 #define CCU_PLL6_SATA_CLK_EN (1U << 14) 605 #define CCU_PLL6_FACTOR_N(x) (((x) >> 8) & 0x1f) 606 #define CCU_PLL6_FACTOR_N_MASK (0x1f << 8) 607 #define CCU_PLL6_FACTOR_N_SHIFT 8 608 #define CCU_PLL6_FACTOR_K(x) (((x) >> 4) & 0x3) 609 #define CCU_PLL6_FACTOR_K_MASK (0x3 << 4) 610 #define CCU_PLL6_FACTOR_K_SHIFT 4 611 #define CCU_PLL6_FACTOR_M(x) (((x) >> 0) & 0x3) 612 #define CCU_PLL6_FACTOR_M_MASK (0x3 << 0) 613 #define CCU_PLL6_FACTOR_M_SHIFT 0 614 615 uint32_t 616 sxiccmu_pll6_get_frequency(void *cookie, uint32_t *cells) 617 { 618 struct sxiccmu_clock *sc = cookie; 619 uint32_t reg, k, m, n, freq; 620 uint32_t idx = cells[0]; 621 622 /* XXX Assume bypass is disabled. */ 623 reg = SXIREAD4(sc, 0); 624 k = CCU_PLL6_FACTOR_K(reg) + 1; 625 m = CCU_PLL6_FACTOR_M(reg) + 1; 626 n = CCU_PLL6_FACTOR_N(reg); 627 628 freq = clock_get_frequency_idx(sc->sc_node, 0); 629 switch (idx) { 630 case 0: 631 return (freq * n * k) / m / 6; /* pll6_sata */ 632 case 1: 633 return (freq * n * k) / 2; /* pll6_other */ 634 case 2: 635 return (freq * n * k); /* pll6 */ 636 case 3: 637 return (freq * n * k) / 4; /* pll6_div_4 */ 638 } 639 640 return 0; 641 } 642 643 void 644 sxiccmu_pll6_enable(void *cookie, uint32_t *cells, int on) 645 { 646 struct sxiccmu_clock *sc = cookie; 647 uint32_t idx = cells[0]; 648 uint32_t reg; 649 650 /* 651 * Since this clock has several outputs, we never turn it off. 652 */ 653 654 reg = SXIREAD4(sc, 0); 655 switch (idx) { 656 case 0: /* pll6_sata */ 657 if (on) 658 reg |= CCU_PLL6_SATA_CLK_EN; 659 else 660 reg &= ~CCU_PLL6_SATA_CLK_EN; 661 /* FALLTHROUGH */ 662 case 1: /* pll6_other */ 663 case 2: /* pll6 */ 664 case 3: /* pll6_div_4 */ 665 if (on) 666 reg |= CCU_PLL6_ENABLE; 667 } 668 SXIWRITE4(sc, 0, reg); 669 } 670 671 #define CCU_APB1_CLK_RAT_N(x) (((x) >> 16) & 0x3) 672 #define CCU_APB1_CLK_RAT_M(x) (((x) >> 0) & 0x1f) 673 #define CCU_APB1_CLK_SRC_SEL(x) (((x) >> 24) & 0x3) 674 675 uint32_t 676 sxiccmu_apb1_get_frequency(void *cookie, uint32_t *cells) 677 { 678 struct sxiccmu_clock *sc = cookie; 679 uint32_t reg, m, n, freq; 680 int idx; 681 682 reg = SXIREAD4(sc, 0); 683 m = CCU_APB1_CLK_RAT_M(reg); 684 n = CCU_APB1_CLK_RAT_N(reg); 685 idx = CCU_APB1_CLK_SRC_SEL(reg); 686 687 freq = clock_get_frequency_idx(sc->sc_node, idx); 688 return freq / (1 << n) / (m + 1); 689 } 690 691 #define CCU_CPUS_CLK_SRC_SEL(x) (((x) >> 16) & 0x3) 692 #define CCU_CPUS_POST_DIV(x) (((x) >> 8) & 0x1f) 693 #define CCU_CPUS_CLK_RATIO(x) (((x) >> 0) & 0x3) 694 695 uint32_t 696 sxiccmu_cpus_get_frequency(void *cookie, uint32_t *cells) 697 { 698 struct sxiccmu_clock *sc = cookie; 699 uint32_t reg, post_div, clk_ratio, freq; 700 int idx; 701 702 reg = SXIREAD4(sc, 0); 703 idx = CCU_CPUS_CLK_SRC_SEL(reg); 704 post_div = (idx == 2 ? CCU_CPUS_POST_DIV(reg): 0); 705 clk_ratio = CCU_CPUS_CLK_RATIO(reg); 706 707 freq = clock_get_frequency_idx(sc->sc_node, idx); 708 return freq / (clk_ratio + 1) / (post_div + 1); 709 } 710 711 #define CCU_APBS_CLK_RATIO(x) (((x) >> 0) & 0x3) 712 713 uint32_t 714 sxiccmu_apbs_get_frequency(void *cookie, uint32_t *cells) 715 { 716 struct sxiccmu_clock *sc = cookie; 717 uint32_t reg, freq; 718 719 reg = SXIREAD4(sc, 0); 720 freq = clock_get_frequency(sc->sc_node, NULL); 721 return freq / (CCU_APBS_CLK_RATIO(reg) + 1); 722 } 723 724 #define CCU_GMAC_CLK_PIT (1 << 2) 725 #define CCU_GMAC_CLK_TCS (3 << 0) 726 #define CCU_GMAC_CLK_TCS_MII 0 727 #define CCU_GMAC_CLK_TCS_EXT_125 1 728 #define CCU_GMAC_CLK_TCS_INT_RGMII 2 729 730 int 731 sxiccmu_gmac_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 732 { 733 struct sxiccmu_clock *sc = cookie; 734 735 switch (freq) { 736 case 25000000: /* MMI, 25 MHz */ 737 SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS, 738 CCU_GMAC_CLK_TCS_MII); 739 break; 740 case 125000000: /* RGMII, 125 MHz */ 741 SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS, 742 CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS_INT_RGMII); 743 break; 744 default: 745 return -1; 746 } 747 748 return 0; 749 } 750 751 #define CCU_SDx_SCLK_GATING (1U << 31) 752 #define CCU_SDx_CLK_SRC_SEL_OSC24M (0 << 24) 753 #define CCU_SDx_CLK_SRC_SEL_PLL6 (1 << 24) 754 #define CCU_SDx_CLK_SRC_SEL_PLL5 (2 << 24) 755 #define CCU_SDx_CLK_SRC_SEL_MASK (3 << 24) 756 #define CCU_SDx_CLK_DIV_RATIO_N_MASK (3 << 16) 757 #define CCU_SDx_CLK_DIV_RATIO_N_SHIFT 16 758 #define CCU_SDx_CLK_DIV_RATIO_M_MASK (7 << 0) 759 #define CCU_SDx_CLK_DIV_RATIO_M_SHIFT 0 760 761 int 762 sxiccmu_mmc_do_set_frequency(struct sxiccmu_clock *sc, uint32_t freq, 763 uint32_t parent_freq) 764 { 765 uint32_t reg, m, n; 766 uint32_t clk_src; 767 768 switch (freq) { 769 case 400000: 770 n = 2, m = 15; 771 clk_src = CCU_SDx_CLK_SRC_SEL_OSC24M; 772 break; 773 case 20000000: 774 case 25000000: 775 case 26000000: 776 case 50000000: 777 case 52000000: 778 n = 0, m = 0; 779 clk_src = CCU_SDx_CLK_SRC_SEL_PLL6; 780 while ((parent_freq / (1 << n) / 16) > freq) 781 n++; 782 while ((parent_freq / (1 << n) / (m + 1)) > freq) 783 m++; 784 break; 785 default: 786 return -1; 787 } 788 789 reg = SXIREAD4(sc, 0); 790 reg &= ~CCU_SDx_CLK_SRC_SEL_MASK; 791 reg |= clk_src; 792 reg &= ~CCU_SDx_CLK_DIV_RATIO_N_MASK; 793 reg |= n << CCU_SDx_CLK_DIV_RATIO_N_SHIFT; 794 reg &= ~CCU_SDx_CLK_DIV_RATIO_M_MASK; 795 reg |= m << CCU_SDx_CLK_DIV_RATIO_M_SHIFT; 796 SXIWRITE4(sc, 0, reg); 797 798 return 0; 799 } 800 801 int 802 sxiccmu_mmc_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 803 { 804 struct sxiccmu_clock *sc = cookie; 805 uint32_t parent_freq; 806 807 if (cells[0] != 0) 808 return -1; 809 810 parent_freq = clock_get_frequency_idx(sc->sc_node, 1); 811 return sxiccmu_mmc_do_set_frequency(sc, freq, parent_freq); 812 } 813 814 void 815 sxiccmu_mmc_enable(void *cookie, uint32_t *cells, int on) 816 { 817 struct sxiccmu_clock *sc = cookie; 818 819 if (cells[0] != 0) 820 return; 821 822 if (on) 823 SXISET4(sc, 0, CCU_SDx_SCLK_GATING); 824 else 825 SXICLR4(sc, 0, CCU_SDx_SCLK_GATING); 826 } 827 828 void 829 sxiccmu_gate_enable(void *cookie, uint32_t *cells, int on) 830 { 831 struct sxiccmu_clock *sc = cookie; 832 int reg = cells[0] / 32; 833 int bit = cells[0] % 32; 834 835 if (on) { 836 clock_enable(sc->sc_node, NULL); 837 SXISET4(sc, reg * 4, (1U << bit)); 838 } else { 839 SXICLR4(sc, reg * 4, (1U << bit)); 840 clock_disable(sc->sc_node, NULL); 841 } 842 } 843 844 void 845 sxiccmu_reset(void *cookie, uint32_t *cells, int assert) 846 { 847 struct sxiccmu_clock *sc = cookie; 848 int reg = cells[0] / 32; 849 int bit = cells[0] % 32; 850 851 if (assert) 852 SXICLR4(sc, reg * 4, (1U << bit)); 853 else 854 SXISET4(sc, reg * 4, (1U << bit)); 855 } 856 857 /* 858 * Newer device trees, such as those for the Allwinner H3/A64 have 859 * most of the clock nodes replaced with a single clock control unit 860 * node. 861 */ 862 863 uint32_t 864 sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells) 865 { 866 struct sxiccmu_softc *sc = cookie; 867 uint32_t idx = cells[0]; 868 uint32_t parent; 869 870 if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) { 871 parent = sc->sc_gates[idx].parent; 872 return sxiccmu_ccu_get_frequency(sc, &parent); 873 } 874 875 return sc->sc_get_frequency(sc, idx); 876 } 877 878 /* Allwinner A10/A20 */ 879 #define A10_PLL1_CFG_REG 0x0000 880 #define A10_PLL1_OUT_EXT_DIVP_MASK (0x3 << 16) 881 #define A10_PLL1_OUT_EXT_DIVP_SHIFT 16 882 #define A10_PLL1_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3) 883 #define A10_PLL1_FACTOR_N(x) (((x) >> 8) & 0x1f) 884 #define A10_PLL1_FACTOR_N_MASK (0x1f << 8) 885 #define A10_PLL1_FACTOR_N_SHIFT 8 886 #define A10_PLL1_FACTOR_K(x) (((x) >> 4) & 0x3) 887 #define A10_PLL1_FACTOR_K_MASK (0x3 << 4) 888 #define A10_PLL1_FACTOR_K_SHIFT 4 889 #define A10_PLL1_FACTOR_M(x) (((x) >> 0) & 0x3) 890 #define A10_PLL1_FACTOR_M_MASK (0x3 << 0) 891 #define A10_PLL1_FACTOR_M_SHIFT 0 892 #define A10_CPU_AHB_APB0_CFG_REG 0x0054 893 #define A10_CPU_CLK_SRC_SEL (0x3 << 16) 894 #define A10_CPU_CLK_SRC_SEL_LOSC (0x0 << 16) 895 #define A10_CPU_CLK_SRC_SEL_OSC24M (0x1 << 16) 896 #define A10_CPU_CLK_SRC_SEL_PLL1 (0x2 << 16) 897 #define A10_CPU_CLK_SRC_SEL_200MHZ (0x3 << 16) 898 #define A10_AHB_CLK_DIV_RATIO(x) (((x) >> 8) & 0x3) 899 #define A10_AXI_CLK_DIV_RATIO(x) (((x) >> 0) & 0x3) 900 901 uint32_t 902 sxiccmu_a10_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 903 { 904 uint32_t parent; 905 uint32_t reg, div; 906 uint32_t k, m, n, p; 907 908 switch (idx) { 909 case A10_CLK_LOSC: 910 return clock_get_frequency(sc->sc_node, "losc"); 911 case A10_CLK_HOSC: 912 return clock_get_frequency(sc->sc_node, "hosc"); 913 case A10_CLK_PLL_CORE: 914 reg = SXIREAD4(sc, A10_PLL1_CFG_REG); 915 k = A10_PLL1_FACTOR_K(reg) + 1; 916 m = A10_PLL1_FACTOR_M(reg) + 1; 917 n = A10_PLL1_FACTOR_N(reg); 918 p = 1 << A10_PLL1_OUT_EXT_DIVP(reg); 919 return (24000000 * n * k) / (m * p); 920 case A10_CLK_PLL_PERIPH_BASE: 921 /* Not hardcoded, but recommended. */ 922 return 600000000; 923 case A10_CLK_PLL_PERIPH: 924 return sxiccmu_a10_get_frequency(sc, A10_CLK_PLL_PERIPH_BASE) * 2; 925 case A10_CLK_CPU: 926 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 927 switch (reg & A10_CPU_CLK_SRC_SEL) { 928 case A10_CPU_CLK_SRC_SEL_LOSC: 929 parent = A10_CLK_LOSC; 930 break; 931 case A10_CPU_CLK_SRC_SEL_OSC24M: 932 parent = A10_CLK_HOSC; 933 break; 934 case A10_CPU_CLK_SRC_SEL_PLL1: 935 parent = A10_CLK_PLL_CORE; 936 break; 937 case A10_CPU_CLK_SRC_SEL_200MHZ: 938 return 200000000; 939 } 940 return sxiccmu_ccu_get_frequency(sc, &parent); 941 case A10_CLK_AXI: 942 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 943 div = 1 << A10_AXI_CLK_DIV_RATIO(reg); 944 parent = A10_CLK_CPU; 945 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 946 case A10_CLK_AHB: 947 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 948 div = 1 << A10_AHB_CLK_DIV_RATIO(reg); 949 parent = A10_CLK_AXI; 950 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 951 case A10_CLK_APB1: 952 /* XXX Controlled by a MUX. */ 953 return 24000000; 954 } 955 956 printf("%s: 0x%08x\n", __func__, idx); 957 return 0; 958 } 959 960 /* Allwinner A23/A64/H3/H5/R40 */ 961 #define CCU_AHB1_APB1_CFG_REG 0x0054 962 #define CCU_AHB1_CLK_SRC_SEL (3 << 12) 963 #define CCU_AHB1_CLK_SRC_SEL_LOSC (0 << 12) 964 #define CCU_AHB1_CLK_SRC_SEL_OSC24M (1 << 12) 965 #define CCU_AHB1_CLK_SRC_SEL_AXI (2 << 12) 966 #define CCU_AHB1_CLK_SRC_SEL_PERIPH0 (3 << 12) 967 #define CCU_AHB1_PRE_DIV(x) ((((x) >> 6) & 3) + 1) 968 #define CCU_AHB1_CLK_DIV_RATIO(x) (1 << (((x) >> 4) & 3)) 969 #define CCU_AHB2_CFG_REG 0x005c 970 #define CCU_AHB2_CLK_CFG (3 << 0) 971 972 uint32_t 973 sxiccmu_a23_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 974 { 975 uint32_t parent; 976 uint32_t reg, div; 977 978 switch (idx) { 979 case A23_CLK_LOSC: 980 return clock_get_frequency(sc->sc_node, "losc"); 981 case A23_CLK_HOSC: 982 return clock_get_frequency(sc->sc_node, "hosc"); 983 case A23_CLK_PLL_PERIPH: 984 /* Not hardcoded, but recommended. */ 985 return 600000000; 986 case A23_CLK_APB2: 987 /* XXX Controlled by a MUX. */ 988 return 24000000; 989 case A23_CLK_AHB1: 990 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 991 div = CCU_AHB1_CLK_DIV_RATIO(reg); 992 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 993 case CCU_AHB1_CLK_SRC_SEL_LOSC: 994 parent = A23_CLK_LOSC; 995 break; 996 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 997 parent = A23_CLK_HOSC; 998 break; 999 case CCU_AHB1_CLK_SRC_SEL_AXI: 1000 parent = A23_CLK_AXI; 1001 break; 1002 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1003 parent = A23_CLK_PLL_PERIPH; 1004 div *= CCU_AHB1_PRE_DIV(reg); 1005 break; 1006 default: 1007 return 0; 1008 } 1009 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1010 } 1011 1012 printf("%s: 0x%08x\n", __func__, idx); 1013 return 0; 1014 } 1015 1016 #define A64_PLL_CPUX_CTRL_REG 0x0000 1017 #define A64_PLL_CPUX_LOCK (1 << 28) 1018 #define A64_PLL_CPUX_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3) 1019 #define A64_PLL_CPUX_OUT_EXT_DIVP_MASK (0x3 << 16) 1020 #define A64_PLL_CPUX_FACTOR_N(x) (((x) >> 8) & 0x1f) 1021 #define A64_PLL_CPUX_FACTOR_N_MASK (0x1f << 8) 1022 #define A64_PLL_CPUX_FACTOR_N_SHIFT 8 1023 #define A64_PLL_CPUX_FACTOR_K(x) (((x) >> 4) & 0x3) 1024 #define A64_PLL_CPUX_FACTOR_K_MASK (0x3 << 4) 1025 #define A64_PLL_CPUX_FACTOR_K_SHIFT 4 1026 #define A64_PLL_CPUX_FACTOR_M(x) (((x) >> 0) & 0x3) 1027 #define A64_PLL_CPUX_FACTOR_M_MASK (0x3 << 0) 1028 #define A64_CPUX_AXI_CFG_REG 0x0050 1029 #define A64_CPUX_CLK_SRC_SEL (0x3 << 16) 1030 #define A64_CPUX_CLK_SRC_SEL_LOSC (0x0 << 16) 1031 #define A64_CPUX_CLK_SRC_SEL_OSC24M (0x1 << 16) 1032 #define A64_CPUX_CLK_SRC_SEL_PLL_CPUX (0x2 << 16) 1033 1034 uint32_t 1035 sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1036 { 1037 uint32_t parent; 1038 uint32_t reg, div; 1039 uint32_t k, m, n, p; 1040 1041 switch (idx) { 1042 case A64_CLK_PLL_CPUX: 1043 reg = SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG); 1044 k = A64_PLL_CPUX_FACTOR_K(reg) + 1; 1045 m = A64_PLL_CPUX_FACTOR_M(reg) + 1; 1046 n = A64_PLL_CPUX_FACTOR_N(reg) + 1; 1047 p = 1 << A64_PLL_CPUX_OUT_EXT_DIVP(reg); 1048 return (24000000 * n * k) / (m * p); 1049 case A64_CLK_CPUX: 1050 reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG); 1051 switch (reg & A64_CPUX_CLK_SRC_SEL) { 1052 case A64_CPUX_CLK_SRC_SEL_LOSC: 1053 parent = A64_CLK_LOSC; 1054 break; 1055 case A64_CPUX_CLK_SRC_SEL_OSC24M: 1056 parent = A64_CLK_HOSC; 1057 break; 1058 case A64_CPUX_CLK_SRC_SEL_PLL_CPUX: 1059 parent = A64_CLK_PLL_CPUX; 1060 break; 1061 default: 1062 return 0; 1063 } 1064 return sxiccmu_ccu_get_frequency(sc, &parent); 1065 case A64_CLK_LOSC: 1066 return clock_get_frequency(sc->sc_node, "losc"); 1067 case A64_CLK_HOSC: 1068 return clock_get_frequency(sc->sc_node, "hosc"); 1069 case A64_CLK_PLL_PERIPH0: 1070 /* Not hardcoded, but recommended. */ 1071 return 600000000; 1072 case A64_CLK_PLL_PERIPH0_2X: 1073 return sxiccmu_a64_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2; 1074 case A64_CLK_APB2: 1075 /* XXX Controlled by a MUX. */ 1076 return 24000000; 1077 case A64_CLK_AHB1: 1078 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1079 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1080 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1081 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1082 parent = A64_CLK_LOSC; 1083 break; 1084 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1085 parent = A64_CLK_HOSC; 1086 break; 1087 case CCU_AHB1_CLK_SRC_SEL_AXI: 1088 parent = A64_CLK_AXI; 1089 break; 1090 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1091 parent = A64_CLK_PLL_PERIPH0; 1092 div *= CCU_AHB1_PRE_DIV(reg); 1093 break; 1094 default: 1095 return 0; 1096 } 1097 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1098 case A64_CLK_AHB2: 1099 reg = SXIREAD4(sc, CCU_AHB2_CFG_REG); 1100 switch (reg & CCU_AHB2_CLK_CFG) { 1101 case 0: 1102 parent = A64_CLK_AHB1; 1103 div = 1; 1104 break; 1105 case 1: 1106 parent = A64_CLK_PLL_PERIPH0; 1107 div = 2; 1108 break; 1109 default: 1110 return 0; 1111 } 1112 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1113 } 1114 1115 printf("%s: 0x%08x\n", __func__, idx); 1116 return 0; 1117 } 1118 1119 #define A80_AHB1_CLK_CFG_REG 0x0064 1120 #define A80_AHB1_SRC_CLK_SELECT (3 << 24) 1121 #define A80_AHB1_SRC_CLK_SELECT_GTBUS (0 << 24) 1122 #define A80_AHB1_SRC_CLK_SELECT_PERIPH0 (1 << 24) 1123 #define A80_AHB1_CLK_DIV_RATIO(x) (1 << ((x) & 0x3)) 1124 1125 uint32_t 1126 sxiccmu_a80_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1127 { 1128 uint32_t parent; 1129 uint32_t reg, div; 1130 1131 switch (idx) { 1132 case A80_CLK_PLL_PERIPH0: 1133 /* Not hardcoded, but recommended. */ 1134 return 960000000; 1135 case A80_CLK_AHB1: 1136 reg = SXIREAD4(sc, A80_AHB1_CLK_CFG_REG); 1137 div = A80_AHB1_CLK_DIV_RATIO(reg); 1138 switch (reg & A80_AHB1_SRC_CLK_SELECT) { 1139 case A80_AHB1_SRC_CLK_SELECT_GTBUS: 1140 parent = A80_CLK_GTBUS; 1141 break; 1142 case A80_AHB1_SRC_CLK_SELECT_PERIPH0: 1143 parent = A80_CLK_PLL_PERIPH0; 1144 break; 1145 default: 1146 parent = A80_CLK_PLL_PERIPH1; 1147 break; 1148 } 1149 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1150 case A80_CLK_APB1: 1151 /* XXX Controlled by a MUX. */ 1152 return 24000000; 1153 } 1154 1155 printf("%s: 0x%08x\n", __func__, idx); 1156 return 0; 1157 } 1158 1159 /* Allwinner H3/H5 */ 1160 #define H3_PLL_CPUX_CTRL_REG 0x0000 1161 #define H3_PLL_CPUX_ENABLE (1U << 31) 1162 #define H3_PLL_CPUX_LOCK (1 << 28) 1163 #define H3_PLL_CPUX_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3) 1164 #define H3_PLL_CPUX_OUT_EXT_DIVP_MASK (0x3 << 16) 1165 #define H3_PLL_CPUX_OUT_EXT_DIVP_SHIFT 16 1166 #define H3_PLL_CPUX_FACTOR_N(x) (((x) >> 8) & 0x1f) 1167 #define H3_PLL_CPUX_FACTOR_N_MASK (0x1f << 8) 1168 #define H3_PLL_CPUX_FACTOR_N_SHIFT 8 1169 #define H3_PLL_CPUX_FACTOR_K(x) (((x) >> 4) & 0x3) 1170 #define H3_PLL_CPUX_FACTOR_K_MASK (0x3 << 4) 1171 #define H3_PLL_CPUX_FACTOR_K_SHIFT 4 1172 #define H3_PLL_CPUX_FACTOR_M(x) (((x) >> 0) & 0x3) 1173 #define H3_PLL_CPUX_FACTOR_M_MASK (0x3 << 0) 1174 #define H3_PLL_CPUX_FACTOR_M_SHIFT 0 1175 #define H3_CPUX_AXI_CFG_REG 0x0050 1176 #define H3_CPUX_CLK_SRC_SEL (0x3 << 16) 1177 #define H3_CPUX_CLK_SRC_SEL_LOSC (0x0 << 16) 1178 #define H3_CPUX_CLK_SRC_SEL_OSC24M (0x1 << 16) 1179 #define H3_CPUX_CLK_SRC_SEL_PLL_CPUX (0x2 << 16) 1180 #define H3_PLL_STABLE_TIME_REG1 0x0204 1181 #define H3_PLL_STABLE_TIME_REG1_TIME(x) (((x) >> 0) & 0xffff) 1182 1183 uint32_t 1184 sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1185 { 1186 uint32_t parent; 1187 uint32_t reg, div; 1188 uint32_t k, m, n, p; 1189 1190 switch (idx) { 1191 case H3_CLK_LOSC: 1192 return clock_get_frequency(sc->sc_node, "losc"); 1193 case H3_CLK_HOSC: 1194 return clock_get_frequency(sc->sc_node, "hosc"); 1195 case H3_CLK_PLL_CPUX: 1196 reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG); 1197 k = H3_PLL_CPUX_FACTOR_K(reg) + 1; 1198 m = H3_PLL_CPUX_FACTOR_M(reg) + 1; 1199 n = H3_PLL_CPUX_FACTOR_N(reg) + 1; 1200 p = 1 << H3_PLL_CPUX_OUT_EXT_DIVP(reg); 1201 return (24000000 * n * k) / (m * p); 1202 case H3_CLK_PLL_PERIPH0: 1203 /* Not hardcoded, but recommended. */ 1204 return 600000000; 1205 case H3_CLK_CPUX: 1206 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1207 switch (reg & H3_CPUX_CLK_SRC_SEL) { 1208 case H3_CPUX_CLK_SRC_SEL_LOSC: 1209 parent = H3_CLK_LOSC; 1210 break; 1211 case H3_CPUX_CLK_SRC_SEL_OSC24M: 1212 parent = H3_CLK_HOSC; 1213 break; 1214 case H3_CPUX_CLK_SRC_SEL_PLL_CPUX: 1215 parent = H3_CLK_PLL_CPUX; 1216 break; 1217 default: 1218 return 0; 1219 } 1220 return sxiccmu_ccu_get_frequency(sc, &parent); 1221 case H3_CLK_APB2: 1222 /* XXX Controlled by a MUX. */ 1223 return 24000000; 1224 case H3_CLK_AHB1: 1225 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1226 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1227 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1228 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1229 parent = H3_CLK_LOSC; 1230 break; 1231 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1232 parent = H3_CLK_HOSC; 1233 break; 1234 case CCU_AHB1_CLK_SRC_SEL_AXI: 1235 parent = H3_CLK_AXI; 1236 break; 1237 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1238 parent = H3_CLK_PLL_PERIPH0; 1239 div *= CCU_AHB1_PRE_DIV(reg); 1240 break; 1241 default: 1242 return 0; 1243 } 1244 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1245 case H3_CLK_AHB2: 1246 reg = SXIREAD4(sc, CCU_AHB2_CFG_REG); 1247 switch (reg & CCU_AHB2_CLK_CFG) { 1248 case 0: 1249 parent = H3_CLK_AHB1; 1250 div = 1; 1251 break; 1252 case 1: 1253 parent = H3_CLK_PLL_PERIPH0; 1254 div = 2; 1255 break; 1256 default: 1257 return 0; 1258 } 1259 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1260 } 1261 1262 printf("%s: 0x%08x\n", __func__, idx); 1263 return 0; 1264 } 1265 1266 #define H3_AHB0_CLK_REG 0x0000 1267 #define H3_AHB0_CLK_SRC_SEL (0x3 << 16) 1268 #define H3_AHB0_CLK_SRC_SEL_OSC32K (0x0 << 16) 1269 #define H3_AHB0_CLK_SRC_SEL_OSC24M (0x1 << 16) 1270 #define H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0 (0x2 << 16) 1271 #define H3_AHB0_CLK_SRC_SEL_IOSC (0x3 << 16) 1272 #define H3_AHB0_CLK_PRE_DIV(x) ((((x) >> 8) & 0x1f) + 1) 1273 #define H3_AHB0_CLK_RATIO(x) (1 << (((x) >> 4) & 3)) 1274 #define H3_APB0_CFG_REG 0x000c 1275 #define H3_APB0_CLK_RATIO(x) (1 << ((x) & 1)) 1276 1277 uint32_t 1278 sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1279 { 1280 uint32_t parent; 1281 uint32_t reg, div; 1282 uint32_t freq; 1283 1284 switch (idx) { 1285 case H3_R_CLK_AHB0: 1286 reg = SXIREAD4(sc, H3_AHB0_CLK_REG); 1287 switch (reg & H3_AHB0_CLK_SRC_SEL) { 1288 case H3_AHB0_CLK_SRC_SEL_OSC32K: 1289 freq = clock_get_frequency(sc->sc_node, "losc"); 1290 break; 1291 case H3_AHB0_CLK_SRC_SEL_OSC24M: 1292 freq = clock_get_frequency(sc->sc_node, "hosc"); 1293 break; 1294 case H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0: 1295 freq = clock_get_frequency(sc->sc_node, "pll-periph"); 1296 break; 1297 case H3_AHB0_CLK_SRC_SEL_IOSC: 1298 freq = clock_get_frequency(sc->sc_node, "iosc"); 1299 break; 1300 } 1301 div = H3_AHB0_CLK_PRE_DIV(reg) * H3_AHB0_CLK_RATIO(reg); 1302 return freq / div; 1303 case H3_R_CLK_APB0: 1304 reg = SXIREAD4(sc, H3_APB0_CFG_REG); 1305 div = H3_APB0_CLK_RATIO(reg); 1306 parent = H3_R_CLK_AHB0; 1307 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1308 } 1309 1310 printf("%s: 0x%08x\n", __func__, idx); 1311 return 0; 1312 } 1313 1314 /* Allwinner H6 */ 1315 #define H6_AHB3_CFG_REG 0x051c 1316 #define H6_AHB3_CLK_FACTOR_N(x) (((x) >> 8) & 0x3) 1317 #define H6_AHB3_CLK_FACTOR_M(x) (((x) >> 0) & 0x3) 1318 1319 uint32_t 1320 sxiccmu_h6_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1321 { 1322 uint32_t reg, m, n; 1323 uint32_t freq; 1324 1325 switch (idx) { 1326 case H6_CLK_PLL_PERIPH0: 1327 /* Not hardcoded, but recommended. */ 1328 return 600000000; 1329 case H6_CLK_PLL_PERIPH0_2X: 1330 return sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0) * 2; 1331 case H6_CLK_AHB3: 1332 reg = SXIREAD4(sc, H6_AHB3_CFG_REG); 1333 /* assume PLL_PERIPH0 source */ 1334 freq = sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0); 1335 m = H6_AHB3_CLK_FACTOR_M(reg) + 1; 1336 n = 1 << H6_AHB3_CLK_FACTOR_N(reg); 1337 return freq / (m * n); 1338 case H6_CLK_APB2: 1339 /* XXX Controlled by a MUX. */ 1340 return 24000000; 1341 break; 1342 } 1343 1344 printf("%s: 0x%08x\n", __func__, idx); 1345 return 0; 1346 } 1347 1348 uint32_t 1349 sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1350 { 1351 switch (idx) { 1352 case H6_R_CLK_APB2: 1353 /* XXX Controlled by a MUX. */ 1354 return 24000000; 1355 break; 1356 } 1357 1358 printf("%s: 0x%08x\n", __func__, idx); 1359 return 0; 1360 } 1361 1362 uint32_t 1363 sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1364 { 1365 uint32_t parent; 1366 uint32_t reg, div; 1367 1368 switch (idx) { 1369 case R40_CLK_LOSC: 1370 return clock_get_frequency(sc->sc_node, "losc"); 1371 case R40_CLK_HOSC: 1372 return clock_get_frequency(sc->sc_node, "hosc"); 1373 case R40_CLK_PLL_PERIPH0: 1374 /* Not hardcoded, but recommended. */ 1375 return 600000000; 1376 case R40_CLK_PLL_PERIPH0_2X: 1377 return sxiccmu_r40_get_frequency(sc, R40_CLK_PLL_PERIPH0) * 2; 1378 case R40_CLK_AHB1: 1379 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1380 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1381 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1382 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1383 parent = R40_CLK_LOSC; 1384 break; 1385 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1386 parent = R40_CLK_HOSC; 1387 break; 1388 case CCU_AHB1_CLK_SRC_SEL_AXI: 1389 parent = R40_CLK_AXI; 1390 break; 1391 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1392 parent = R40_CLK_PLL_PERIPH0; 1393 div *= CCU_AHB1_PRE_DIV(reg); 1394 break; 1395 } 1396 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1397 case R40_CLK_APB2: 1398 /* XXX Controlled by a MUX. */ 1399 return 24000000; 1400 } 1401 1402 printf("%s: 0x%08x\n", __func__, idx); 1403 return 0; 1404 } 1405 1406 uint32_t 1407 sxiccmu_v3s_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1408 { 1409 uint32_t parent; 1410 uint32_t reg, div; 1411 1412 switch (idx) { 1413 case V3S_CLK_LOSC: 1414 return clock_get_frequency(sc->sc_node, "losc"); 1415 case V3S_CLK_HOSC: 1416 return clock_get_frequency(sc->sc_node, "hosc"); 1417 case V3S_CLK_PLL_PERIPH0: 1418 /* Not hardcoded, but recommended. */ 1419 return 600000000; 1420 case V3S_CLK_APB2: 1421 /* XXX Controlled by a MUX. */ 1422 return 24000000; 1423 case V3S_CLK_AHB1: 1424 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1425 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1426 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1427 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1428 parent = V3S_CLK_LOSC; 1429 break; 1430 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1431 parent = V3S_CLK_HOSC; 1432 break; 1433 case CCU_AHB1_CLK_SRC_SEL_AXI: 1434 parent = V3S_CLK_AXI; 1435 break; 1436 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1437 parent = V3S_CLK_PLL_PERIPH0; 1438 div *= CCU_AHB1_PRE_DIV(reg); 1439 break; 1440 default: 1441 return 0; 1442 } 1443 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1444 case V3S_CLK_AHB2: 1445 reg = SXIREAD4(sc, CCU_AHB2_CFG_REG); 1446 switch (reg & CCU_AHB2_CLK_CFG) { 1447 case 0: 1448 parent = V3S_CLK_AHB1; 1449 div = 1; 1450 break; 1451 case 1: 1452 parent = V3S_CLK_PLL_PERIPH0; 1453 div = 2; 1454 break; 1455 default: 1456 return 0; 1457 } 1458 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1459 } 1460 1461 printf("%s: 0x%08x\n", __func__, idx); 1462 return 0; 1463 } 1464 1465 uint32_t 1466 sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1467 { 1468 printf("%s: 0x%08x\n", __func__, idx); 1469 return 0; 1470 } 1471 1472 int 1473 sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 1474 { 1475 struct sxiccmu_softc *sc = cookie; 1476 uint32_t idx = cells[0]; 1477 1478 return sc->sc_set_frequency(sc, idx, freq); 1479 } 1480 1481 int 1482 sxiccmu_a10_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1483 { 1484 struct sxiccmu_clock clock; 1485 uint32_t parent, parent_freq; 1486 uint32_t reg; 1487 int k, n; 1488 int error; 1489 1490 switch (idx) { 1491 case A10_CLK_PLL_CORE: 1492 k = 1; n = 32; 1493 while (k <= 4 && (24000000 * n * k) < freq) 1494 k++; 1495 while (n >= 1 && (24000000 * n * k) > freq) 1496 n--; 1497 1498 reg = SXIREAD4(sc, A10_PLL1_CFG_REG); 1499 reg &= ~A10_PLL1_OUT_EXT_DIVP_MASK; 1500 reg &= ~A10_PLL1_FACTOR_N_MASK; 1501 reg &= ~A10_PLL1_FACTOR_K_MASK; 1502 reg &= ~A10_PLL1_FACTOR_M_MASK; 1503 reg |= (n << A10_PLL1_FACTOR_N_SHIFT); 1504 reg |= ((k - 1) << A10_PLL1_FACTOR_K_SHIFT); 1505 SXIWRITE4(sc, A10_PLL1_CFG_REG, reg); 1506 1507 /* No need to wait PLL to lock? */ 1508 1509 return 0; 1510 case A10_CLK_CPU: 1511 /* Switch to 24 MHz clock. */ 1512 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 1513 reg &= ~A10_CPU_CLK_SRC_SEL; 1514 reg |= A10_CPU_CLK_SRC_SEL_OSC24M; 1515 SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg); 1516 1517 error = sxiccmu_a10_set_frequency(sc, A10_CLK_PLL_CORE, freq); 1518 1519 /* Switch back to PLL. */ 1520 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 1521 reg &= ~A10_CPU_CLK_SRC_SEL; 1522 reg |= A10_CPU_CLK_SRC_SEL_PLL1; 1523 SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg); 1524 return error; 1525 case A10_CLK_MMC0: 1526 case A10_CLK_MMC1: 1527 case A10_CLK_MMC2: 1528 case A10_CLK_MMC3: 1529 clock.sc_iot = sc->sc_iot; 1530 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1531 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1532 parent = A10_CLK_PLL_PERIPH; 1533 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1534 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1535 } 1536 1537 printf("%s: 0x%08x\n", __func__, idx); 1538 return -1; 1539 } 1540 1541 int 1542 sxiccmu_a23_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1543 { 1544 struct sxiccmu_clock clock; 1545 uint32_t parent, parent_freq; 1546 1547 switch (idx) { 1548 case A23_CLK_MMC0: 1549 case A23_CLK_MMC1: 1550 case A23_CLK_MMC2: 1551 clock.sc_iot = sc->sc_iot; 1552 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1553 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1554 parent = A23_CLK_PLL_PERIPH; 1555 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1556 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1557 } 1558 1559 printf("%s: 0x%08x\n", __func__, idx); 1560 return -1; 1561 } 1562 1563 int 1564 sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1565 { 1566 struct sxiccmu_clock clock; 1567 uint32_t parent, parent_freq; 1568 uint32_t reg; 1569 int k, n; 1570 int error; 1571 1572 switch (idx) { 1573 case A64_CLK_PLL_CPUX: 1574 k = 1; n = 32; 1575 while (k <= 4 && (24000000 * n * k) < freq) 1576 k++; 1577 while (n >= 1 && (24000000 * n * k) > freq) 1578 n--; 1579 1580 reg = SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG); 1581 reg &= ~A64_PLL_CPUX_OUT_EXT_DIVP_MASK; 1582 reg &= ~A64_PLL_CPUX_FACTOR_N_MASK; 1583 reg &= ~A64_PLL_CPUX_FACTOR_K_MASK; 1584 reg &= ~A64_PLL_CPUX_FACTOR_M_MASK; 1585 reg |= ((n - 1) << A64_PLL_CPUX_FACTOR_N_SHIFT); 1586 reg |= ((k - 1) << A64_PLL_CPUX_FACTOR_K_SHIFT); 1587 SXIWRITE4(sc, A64_PLL_CPUX_CTRL_REG, reg); 1588 1589 /* Wait for PLL to lock. */ 1590 while ((SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG) & 1591 A64_PLL_CPUX_LOCK) == 0) { 1592 delay(200); 1593 } 1594 1595 return 0; 1596 case A64_CLK_CPUX: 1597 /* Switch to 24 MHz clock. */ 1598 reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG); 1599 reg &= ~A64_CPUX_CLK_SRC_SEL; 1600 reg |= A64_CPUX_CLK_SRC_SEL_OSC24M; 1601 SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg); 1602 1603 error = sxiccmu_a64_set_frequency(sc, A64_CLK_PLL_CPUX, freq); 1604 1605 /* Switch back to PLL. */ 1606 reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG); 1607 reg &= ~A64_CPUX_CLK_SRC_SEL; 1608 reg |= A64_CPUX_CLK_SRC_SEL_PLL_CPUX; 1609 SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg); 1610 return error; 1611 case A64_CLK_MMC0: 1612 case A64_CLK_MMC1: 1613 case A64_CLK_MMC2: 1614 clock.sc_iot = sc->sc_iot; 1615 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1616 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1617 parent = A64_CLK_PLL_PERIPH0_2X; 1618 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1619 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1620 } 1621 1622 printf("%s: 0x%08x\n", __func__, idx); 1623 return -1; 1624 } 1625 1626 int 1627 sxiccmu_a80_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1628 { 1629 struct sxiccmu_clock clock; 1630 uint32_t parent, parent_freq; 1631 1632 switch (idx) { 1633 case A80_CLK_MMC0: 1634 case A80_CLK_MMC1: 1635 case A80_CLK_MMC2: 1636 clock.sc_iot = sc->sc_iot; 1637 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1638 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1639 parent = A80_CLK_PLL_PERIPH0; 1640 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1641 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1642 } 1643 1644 printf("%s: 0x%08x\n", __func__, idx); 1645 return -1; 1646 } 1647 1648 int 1649 sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1650 { 1651 struct sxiccmu_clock clock; 1652 uint32_t parent, parent_freq; 1653 uint32_t reg, lock_time; 1654 int k, n; 1655 int error; 1656 1657 switch (idx) { 1658 case H3_CLK_PLL_CPUX: 1659 k = 1; n = 32; 1660 while (k <= 4 && (24000000 * n * k) < freq) 1661 k++; 1662 while (n >= 1 && (24000000 * n * k) > freq) 1663 n--; 1664 1665 /* Gate the PLL first */ 1666 reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG); 1667 reg &= ~H3_PLL_CPUX_ENABLE; 1668 SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg); 1669 1670 /* Set factors and external divider. */ 1671 reg &= ~H3_PLL_CPUX_OUT_EXT_DIVP_MASK; 1672 reg &= ~H3_PLL_CPUX_FACTOR_N_MASK; 1673 reg &= ~H3_PLL_CPUX_FACTOR_K_MASK; 1674 reg &= ~H3_PLL_CPUX_FACTOR_M_MASK; 1675 reg |= ((n - 1) << H3_PLL_CPUX_FACTOR_N_SHIFT); 1676 reg |= ((k - 1) << H3_PLL_CPUX_FACTOR_K_SHIFT); 1677 SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg); 1678 1679 /* Ungate the PLL */ 1680 reg |= H3_PLL_CPUX_ENABLE; 1681 SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg); 1682 1683 /* Wait for PLL to lock. (LOCK flag is unreliable) */ 1684 lock_time = SXIREAD4(sc, H3_PLL_STABLE_TIME_REG1); 1685 delay(H3_PLL_STABLE_TIME_REG1_TIME(lock_time)); 1686 1687 return 0; 1688 case H3_CLK_CPUX: 1689 /* Switch to 24 MHz clock. */ 1690 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1691 reg &= ~H3_CPUX_CLK_SRC_SEL; 1692 reg |= H3_CPUX_CLK_SRC_SEL_OSC24M; 1693 SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg); 1694 /* Must wait at least 8 cycles of the current clock. */ 1695 delay(1); 1696 1697 error = sxiccmu_h3_set_frequency(sc, H3_CLK_PLL_CPUX, freq); 1698 1699 /* Switch back to PLL. */ 1700 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1701 reg &= ~H3_CPUX_CLK_SRC_SEL; 1702 reg |= H3_CPUX_CLK_SRC_SEL_PLL_CPUX; 1703 SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg); 1704 /* Must wait at least 8 cycles of the current clock. */ 1705 delay(1); 1706 return error; 1707 case H3_CLK_MMC0: 1708 case H3_CLK_MMC1: 1709 case H3_CLK_MMC2: 1710 clock.sc_iot = sc->sc_iot; 1711 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1712 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1713 parent = H3_CLK_PLL_PERIPH0; 1714 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1715 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1716 } 1717 1718 printf("%s: 0x%08x\n", __func__, idx); 1719 return -1; 1720 } 1721 1722 #define H6_SMHC0_CLK_REG 0x0830 1723 #define H6_SMHC1_CLK_REG 0x0834 1724 #define H6_SMHC2_CLK_REG 0x0838 1725 #define H6_SMHC_CLK_SRC_SEL (0x3 << 24) 1726 #define H6_SMHC_CLK_SRC_SEL_OSC24M (0x0 << 24) 1727 #define H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X (0x1 << 24) 1728 #define H6_SMHC_FACTOR_N_MASK (0x3 << 8) 1729 #define H6_SMHC_FACTOR_N_SHIFT 8 1730 #define H6_SMHC_FACTOR_M_MASK (0xf << 0) 1731 #define H6_SMHC_FACTOR_M_SHIFT 0 1732 1733 int 1734 sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset, 1735 uint32_t freq) 1736 { 1737 uint32_t parent_freq; 1738 uint32_t reg, m, n; 1739 uint32_t clk_src; 1740 1741 switch (freq) { 1742 case 400000: 1743 n = 2, m = 15; 1744 clk_src = H6_SMHC_CLK_SRC_SEL_OSC24M; 1745 break; 1746 case 20000000: 1747 case 25000000: 1748 case 26000000: 1749 case 50000000: 1750 case 52000000: 1751 n = 0, m = 0; 1752 clk_src = H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X; 1753 parent_freq = 1754 sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0_2X); 1755 while ((parent_freq / (1 << n) / 16) > freq) 1756 n++; 1757 while ((parent_freq / (1 << n) / (m + 1)) > freq) 1758 m++; 1759 break; 1760 default: 1761 return -1; 1762 } 1763 1764 reg = SXIREAD4(sc, offset); 1765 reg &= ~H6_SMHC_CLK_SRC_SEL; 1766 reg |= clk_src; 1767 reg &= ~H6_SMHC_FACTOR_N_MASK; 1768 reg |= n << H6_SMHC_FACTOR_N_SHIFT; 1769 reg &= ~H6_SMHC_FACTOR_M_MASK; 1770 reg |= m << H6_SMHC_FACTOR_M_SHIFT; 1771 SXIWRITE4(sc, offset, reg); 1772 1773 return 0; 1774 } 1775 1776 int 1777 sxiccmu_h6_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1778 { 1779 switch (idx) { 1780 case H6_CLK_MMC0: 1781 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG, freq); 1782 case H6_CLK_MMC1: 1783 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG, freq); 1784 case H6_CLK_MMC2: 1785 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG, freq); 1786 } 1787 1788 printf("%s: 0x%08x\n", __func__, idx); 1789 return -1; 1790 } 1791 1792 int 1793 sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1794 { 1795 struct sxiccmu_clock clock; 1796 uint32_t parent, parent_freq; 1797 1798 switch (idx) { 1799 case R40_CLK_MMC0: 1800 case R40_CLK_MMC1: 1801 case R40_CLK_MMC2: 1802 case R40_CLK_MMC3: 1803 clock.sc_iot = sc->sc_iot; 1804 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1805 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1806 parent = R40_CLK_PLL_PERIPH0_2X; 1807 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1808 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1809 } 1810 1811 printf("%s: 0x%08x\n", __func__, idx); 1812 return -1; 1813 } 1814 1815 int 1816 sxiccmu_v3s_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1817 { 1818 struct sxiccmu_clock clock; 1819 uint32_t parent, parent_freq; 1820 1821 switch (idx) { 1822 case V3S_CLK_MMC0: 1823 case V3S_CLK_MMC1: 1824 case V3S_CLK_MMC2: 1825 clock.sc_iot = sc->sc_iot; 1826 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1827 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1828 parent = V3S_CLK_PLL_PERIPH0; 1829 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1830 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1831 } 1832 1833 printf("%s: 0x%08x\n", __func__, idx); 1834 return -1; 1835 } 1836 1837 int 1838 sxiccmu_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1839 { 1840 printf("%s: 0x%08x\n", __func__, idx); 1841 return -1; 1842 } 1843 1844 void 1845 sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on) 1846 { 1847 struct sxiccmu_softc *sc = cookie; 1848 uint32_t idx = cells[0]; 1849 int reg, bit; 1850 1851 clock_enable_all(sc->sc_node); 1852 1853 if (idx >= sc->sc_ngates || 1854 (sc->sc_gates[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) { 1855 printf("%s: 0x%08x\n", __func__, cells[0]); 1856 return; 1857 } 1858 1859 /* If the clock can't be gated, simply return. */ 1860 if (sc->sc_gates[idx].reg == 0xffff && sc->sc_gates[idx].bit == 0xff) 1861 return; 1862 1863 reg = sc->sc_gates[idx].reg; 1864 bit = sc->sc_gates[idx].bit; 1865 1866 if (on) 1867 SXISET4(sc, reg, (1U << bit)); 1868 else 1869 SXICLR4(sc, reg, (1U << bit)); 1870 } 1871 1872 void 1873 sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert) 1874 { 1875 struct sxiccmu_softc *sc = cookie; 1876 uint32_t idx = cells[0]; 1877 int reg, bit; 1878 1879 reset_deassert_all(sc->sc_node); 1880 1881 if (idx >= sc->sc_nresets || 1882 (sc->sc_resets[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) { 1883 printf("%s: 0x%08x\n", __func__, cells[0]); 1884 return; 1885 } 1886 1887 reg = sc->sc_resets[idx].reg; 1888 bit = sc->sc_resets[idx].bit; 1889 1890 if (assert) 1891 SXICLR4(sc, reg, (1U << bit)); 1892 else 1893 SXISET4(sc, reg, (1U << bit)); 1894 } 1895