1 /* $OpenBSD: sxiccmu.c,v 1.26 2019/09/21 15:01:26 kettenis 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 struct sxiccmu_ccu_bit *sc_gates; 62 int sc_ngates; 63 struct clock_device sc_cd; 64 65 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 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 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 uint32_t 1120 sxiccmu_a80_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1121 { 1122 switch (idx) { 1123 case A80_CLK_PLL_PERIPH0: 1124 /* Not hardcoded, but recommended. */ 1125 return 960000000; 1126 case A80_CLK_APB1: 1127 /* XXX Controlled by a MUX. */ 1128 return 24000000; 1129 } 1130 1131 printf("%s: 0x%08x\n", __func__, idx); 1132 return 0; 1133 } 1134 1135 /* Allwinner H3/H5 */ 1136 #define H3_PLL_CPUX_CTRL_REG 0x0000 1137 #define H3_PLL_CPUX_LOCK (1 << 28) 1138 #define H3_PLL_CPUX_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3) 1139 #define H3_PLL_CPUX_OUT_EXT_DIVP_MASK (0x3 << 16) 1140 #define H3_PLL_CPUX_OUT_EXT_DIVP_SHIFT 16 1141 #define H3_PLL_CPUX_FACTOR_N(x) (((x) >> 8) & 0x1f) 1142 #define H3_PLL_CPUX_FACTOR_N_MASK (0x1f << 8) 1143 #define H3_PLL_CPUX_FACTOR_N_SHIFT 8 1144 #define H3_PLL_CPUX_FACTOR_K(x) (((x) >> 4) & 0x3) 1145 #define H3_PLL_CPUX_FACTOR_K_MASK (0x3 << 4) 1146 #define H3_PLL_CPUX_FACTOR_K_SHIFT 4 1147 #define H3_PLL_CPUX_FACTOR_M(x) (((x) >> 0) & 0x3) 1148 #define H3_PLL_CPUX_FACTOR_M_MASK (0x3 << 0) 1149 #define H3_PLL_CPUX_FACTOR_M_SHIFT 0 1150 #define H3_CPUX_AXI_CFG_REG 0x0050 1151 #define H3_CPUX_CLK_SRC_SEL (0x3 << 16) 1152 #define H3_CPUX_CLK_SRC_SEL_LOSC (0x0 << 16) 1153 #define H3_CPUX_CLK_SRC_SEL_OSC24M (0x1 << 16) 1154 #define H3_CPUX_CLK_SRC_SEL_PLL_CPUX (0x2 << 16) 1155 1156 uint32_t 1157 sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1158 { 1159 uint32_t parent; 1160 uint32_t reg, div; 1161 uint32_t k, m, n, p; 1162 1163 switch (idx) { 1164 case H3_CLK_LOSC: 1165 return clock_get_frequency(sc->sc_node, "losc"); 1166 case H3_CLK_HOSC: 1167 return clock_get_frequency(sc->sc_node, "hosc"); 1168 case H3_CLK_PLL_CPUX: 1169 reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG); 1170 k = H3_PLL_CPUX_FACTOR_K(reg) + 1; 1171 m = H3_PLL_CPUX_FACTOR_M(reg) + 1; 1172 n = H3_PLL_CPUX_FACTOR_N(reg) + 1; 1173 p = 1 << H3_PLL_CPUX_OUT_EXT_DIVP(reg); 1174 return (24000000 * n * k) / (m * p); 1175 case H3_CLK_PLL_PERIPH0: 1176 /* Not hardcoded, but recommended. */ 1177 return 600000000; 1178 case H3_CLK_CPUX: 1179 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1180 switch (reg & H3_CPUX_CLK_SRC_SEL) { 1181 case H3_CPUX_CLK_SRC_SEL_LOSC: 1182 parent = H3_CLK_LOSC; 1183 break; 1184 case H3_CPUX_CLK_SRC_SEL_OSC24M: 1185 parent = H3_CLK_HOSC; 1186 break; 1187 case H3_CPUX_CLK_SRC_SEL_PLL_CPUX: 1188 parent = H3_CLK_PLL_CPUX; 1189 break; 1190 default: 1191 return 0; 1192 } 1193 return sxiccmu_ccu_get_frequency(sc, &parent); 1194 case H3_CLK_APB2: 1195 /* XXX Controlled by a MUX. */ 1196 return 24000000; 1197 case H3_CLK_AHB1: 1198 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1199 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1200 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1201 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1202 parent = H3_CLK_LOSC; 1203 break; 1204 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1205 parent = H3_CLK_HOSC; 1206 break; 1207 case CCU_AHB1_CLK_SRC_SEL_AXI: 1208 parent = H3_CLK_AXI; 1209 break; 1210 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1211 parent = H3_CLK_PLL_PERIPH0; 1212 div *= CCU_AHB1_PRE_DIV(reg); 1213 break; 1214 default: 1215 return 0; 1216 } 1217 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1218 case H3_CLK_AHB2: 1219 reg = SXIREAD4(sc, CCU_AHB2_CFG_REG); 1220 switch (reg & CCU_AHB2_CLK_CFG) { 1221 case 0: 1222 parent = H3_CLK_AHB1; 1223 div = 1; 1224 break; 1225 case 1: 1226 parent = H3_CLK_PLL_PERIPH0; 1227 div = 2; 1228 break; 1229 default: 1230 return 0; 1231 } 1232 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1233 } 1234 1235 printf("%s: 0x%08x\n", __func__, idx); 1236 return 0; 1237 } 1238 1239 #define H3_AHB0_CLK_REG 0x0000 1240 #define H3_AHB0_CLK_SRC_SEL (0x3 << 16) 1241 #define H3_AHB0_CLK_SRC_SEL_OSC32K (0x0 << 16) 1242 #define H3_AHB0_CLK_SRC_SEL_OSC24M (0x1 << 16) 1243 #define H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0 (0x2 << 16) 1244 #define H3_AHB0_CLK_SRC_SEL_IOSC (0x3 << 16) 1245 #define H3_AHB0_CLK_PRE_DIV(x) ((((x) >> 8) & 0x1f) + 1) 1246 #define H3_AHB0_CLK_RATIO(x) (1 << (((x) >> 4) & 3)) 1247 #define H3_APB0_CFG_REG 0x000c 1248 #define H3_APB0_CLK_RATIO(x) (1 << ((x) & 1)) 1249 1250 uint32_t 1251 sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1252 { 1253 uint32_t parent; 1254 uint32_t reg, div; 1255 uint32_t freq; 1256 1257 switch (idx) { 1258 case H3_R_CLK_AHB0: 1259 reg = SXIREAD4(sc, H3_AHB0_CLK_REG); 1260 switch (reg & H3_AHB0_CLK_SRC_SEL) { 1261 case H3_AHB0_CLK_SRC_SEL_OSC32K: 1262 freq = clock_get_frequency(sc->sc_node, "losc"); 1263 break; 1264 case H3_AHB0_CLK_SRC_SEL_OSC24M: 1265 freq = clock_get_frequency(sc->sc_node, "hosc"); 1266 break; 1267 case H3_AHB0_CLK_SRC_SEL_PLL_PERIPH0: 1268 freq = clock_get_frequency(sc->sc_node, "pll-periph"); 1269 break; 1270 case H3_AHB0_CLK_SRC_SEL_IOSC: 1271 freq = clock_get_frequency(sc->sc_node, "iosc"); 1272 break; 1273 } 1274 div = H3_AHB0_CLK_PRE_DIV(reg) * H3_AHB0_CLK_RATIO(reg); 1275 return freq / div; 1276 case H3_R_CLK_APB0: 1277 reg = SXIREAD4(sc, H3_APB0_CFG_REG); 1278 div = H3_APB0_CLK_RATIO(reg); 1279 parent = H3_R_CLK_AHB0; 1280 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1281 } 1282 1283 printf("%s: 0x%08x\n", __func__, idx); 1284 return 0; 1285 } 1286 1287 uint32_t 1288 sxiccmu_h6_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1289 { 1290 switch (idx) { 1291 case H6_CLK_PLL_PERIPH0: 1292 /* Not hardcoded, but recommended. */ 1293 return 600000000; 1294 case H6_CLK_PLL_PERIPH0_2X: 1295 return sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0) * 2; 1296 case H6_CLK_APB2: 1297 /* XXX Controlled by a MUX. */ 1298 return 24000000; 1299 break; 1300 } 1301 1302 printf("%s: 0x%08x\n", __func__, idx); 1303 return 0; 1304 } 1305 1306 uint32_t 1307 sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1308 { 1309 switch (idx) { 1310 case H6_R_CLK_APB2: 1311 /* XXX Controlled by a MUX. */ 1312 return 24000000; 1313 break; 1314 } 1315 1316 printf("%s: 0x%08x\n", __func__, idx); 1317 return 0; 1318 } 1319 1320 uint32_t 1321 sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1322 { 1323 uint32_t parent; 1324 uint32_t reg, div; 1325 1326 switch (idx) { 1327 case R40_CLK_LOSC: 1328 return clock_get_frequency(sc->sc_node, "losc"); 1329 case R40_CLK_HOSC: 1330 return clock_get_frequency(sc->sc_node, "hosc"); 1331 case R40_CLK_PLL_PERIPH0: 1332 /* Not hardcoded, but recommended. */ 1333 return 600000000; 1334 case R40_CLK_PLL_PERIPH0_2X: 1335 return sxiccmu_r40_get_frequency(sc, R40_CLK_PLL_PERIPH0) * 2; 1336 case R40_CLK_AHB1: 1337 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1338 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1339 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1340 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1341 parent = R40_CLK_LOSC; 1342 break; 1343 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1344 parent = R40_CLK_HOSC; 1345 break; 1346 case CCU_AHB1_CLK_SRC_SEL_AXI: 1347 parent = R40_CLK_AXI; 1348 break; 1349 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1350 parent = R40_CLK_PLL_PERIPH0; 1351 div *= CCU_AHB1_PRE_DIV(reg); 1352 break; 1353 } 1354 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1355 case R40_CLK_APB2: 1356 /* XXX Controlled by a MUX. */ 1357 return 24000000; 1358 } 1359 1360 printf("%s: 0x%08x\n", __func__, idx); 1361 return 0; 1362 } 1363 1364 uint32_t 1365 sxiccmu_v3s_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1366 { 1367 uint32_t parent; 1368 uint32_t reg, div; 1369 1370 switch (idx) { 1371 case V3S_CLK_LOSC: 1372 return clock_get_frequency(sc->sc_node, "losc"); 1373 case V3S_CLK_HOSC: 1374 return clock_get_frequency(sc->sc_node, "hosc"); 1375 case V3S_CLK_PLL_PERIPH0: 1376 /* Not hardcoded, but recommended. */ 1377 return 600000000; 1378 case V3S_CLK_APB2: 1379 /* XXX Controlled by a MUX. */ 1380 return 24000000; 1381 case V3S_CLK_AHB1: 1382 reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); 1383 div = CCU_AHB1_CLK_DIV_RATIO(reg); 1384 switch (reg & CCU_AHB1_CLK_SRC_SEL) { 1385 case CCU_AHB1_CLK_SRC_SEL_LOSC: 1386 parent = V3S_CLK_LOSC; 1387 break; 1388 case CCU_AHB1_CLK_SRC_SEL_OSC24M: 1389 parent = V3S_CLK_HOSC; 1390 break; 1391 case CCU_AHB1_CLK_SRC_SEL_AXI: 1392 parent = V3S_CLK_AXI; 1393 break; 1394 case CCU_AHB1_CLK_SRC_SEL_PERIPH0: 1395 parent = V3S_CLK_PLL_PERIPH0; 1396 div *= CCU_AHB1_PRE_DIV(reg); 1397 break; 1398 default: 1399 return 0; 1400 } 1401 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1402 case V3S_CLK_AHB2: 1403 reg = SXIREAD4(sc, CCU_AHB2_CFG_REG); 1404 switch (reg & CCU_AHB2_CLK_CFG) { 1405 case 0: 1406 parent = V3S_CLK_AHB1; 1407 div = 1; 1408 break; 1409 case 1: 1410 parent = V3S_CLK_PLL_PERIPH0; 1411 div = 2; 1412 break; 1413 default: 1414 return 0; 1415 } 1416 return sxiccmu_ccu_get_frequency(sc, &parent) / div; 1417 } 1418 1419 printf("%s: 0x%08x\n", __func__, idx); 1420 return 0; 1421 } 1422 1423 uint32_t 1424 sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) 1425 { 1426 printf("%s: 0x%08x\n", __func__, idx); 1427 return 0; 1428 } 1429 1430 int 1431 sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 1432 { 1433 struct sxiccmu_softc *sc = cookie; 1434 uint32_t idx = cells[0]; 1435 1436 return sc->sc_set_frequency(sc, idx, freq); 1437 } 1438 1439 int 1440 sxiccmu_a10_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1441 { 1442 struct sxiccmu_clock clock; 1443 uint32_t parent, parent_freq; 1444 uint32_t reg; 1445 int k, n; 1446 int error; 1447 1448 switch (idx) { 1449 case A10_CLK_PLL_CORE: 1450 k = 1; n = 32; 1451 while (k <= 4 && (24000000 * n * k) < freq) 1452 k++; 1453 while (n >= 1 && (24000000 * n * k) > freq) 1454 n--; 1455 1456 reg = SXIREAD4(sc, A10_PLL1_CFG_REG); 1457 reg &= ~A10_PLL1_OUT_EXT_DIVP_MASK; 1458 reg &= ~A10_PLL1_FACTOR_N_MASK; 1459 reg &= ~A10_PLL1_FACTOR_K_MASK; 1460 reg &= ~A10_PLL1_FACTOR_M_MASK; 1461 reg |= (n << A10_PLL1_FACTOR_N_SHIFT); 1462 reg |= ((k - 1) << A10_PLL1_FACTOR_K_SHIFT); 1463 SXIWRITE4(sc, A10_PLL1_CFG_REG, reg); 1464 1465 /* No need to wait PLL to lock? */ 1466 1467 return 0; 1468 case A10_CLK_CPU: 1469 /* Switch to 24 MHz clock. */ 1470 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 1471 reg &= ~A10_CPU_CLK_SRC_SEL; 1472 reg |= A10_CPU_CLK_SRC_SEL_OSC24M; 1473 SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg); 1474 1475 error = sxiccmu_a10_set_frequency(sc, A10_CLK_PLL_CORE, freq); 1476 1477 /* Switch back to PLL. */ 1478 reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); 1479 reg &= ~A10_CPU_CLK_SRC_SEL; 1480 reg |= A10_CPU_CLK_SRC_SEL_PLL1; 1481 SXIWRITE4(sc, A10_CPU_AHB_APB0_CFG_REG, reg); 1482 return error; 1483 case A10_CLK_MMC0: 1484 case A10_CLK_MMC1: 1485 case A10_CLK_MMC2: 1486 case A10_CLK_MMC3: 1487 clock.sc_iot = sc->sc_iot; 1488 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1489 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1490 parent = A10_CLK_PLL_PERIPH; 1491 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1492 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1493 } 1494 1495 printf("%s: 0x%08x\n", __func__, idx); 1496 return -1; 1497 } 1498 1499 int 1500 sxiccmu_a23_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1501 { 1502 struct sxiccmu_clock clock; 1503 uint32_t parent, parent_freq; 1504 1505 switch (idx) { 1506 case A23_CLK_MMC0: 1507 case A23_CLK_MMC1: 1508 case A23_CLK_MMC2: 1509 clock.sc_iot = sc->sc_iot; 1510 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1511 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1512 parent = A23_CLK_PLL_PERIPH; 1513 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1514 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1515 } 1516 1517 printf("%s: 0x%08x\n", __func__, idx); 1518 return -1; 1519 } 1520 1521 int 1522 sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1523 { 1524 struct sxiccmu_clock clock; 1525 uint32_t parent, parent_freq; 1526 uint32_t reg; 1527 int k, n; 1528 int error; 1529 1530 switch (idx) { 1531 case A64_CLK_PLL_CPUX: 1532 k = 1; n = 32; 1533 while (k <= 4 && (24000000 * n * k) < freq) 1534 k++; 1535 while (n >= 1 && (24000000 * n * k) > freq) 1536 n--; 1537 1538 reg = SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG); 1539 reg &= ~A64_PLL_CPUX_OUT_EXT_DIVP_MASK; 1540 reg &= ~A64_PLL_CPUX_FACTOR_N_MASK; 1541 reg &= ~A64_PLL_CPUX_FACTOR_K_MASK; 1542 reg &= ~A64_PLL_CPUX_FACTOR_M_MASK; 1543 reg |= ((n - 1) << A64_PLL_CPUX_FACTOR_N_SHIFT); 1544 reg |= ((k - 1) << A64_PLL_CPUX_FACTOR_K_SHIFT); 1545 SXIWRITE4(sc, A64_PLL_CPUX_CTRL_REG, reg); 1546 1547 /* Wait for PLL to lock. */ 1548 while ((SXIREAD4(sc, A64_PLL_CPUX_CTRL_REG) & 1549 A64_PLL_CPUX_LOCK) == 0) { 1550 delay(200); 1551 } 1552 1553 return 0; 1554 case A64_CLK_CPUX: 1555 /* Switch to 24 MHz clock. */ 1556 reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG); 1557 reg &= ~A64_CPUX_CLK_SRC_SEL; 1558 reg |= A64_CPUX_CLK_SRC_SEL_OSC24M; 1559 SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg); 1560 1561 error = sxiccmu_a64_set_frequency(sc, A64_CLK_PLL_CPUX, freq); 1562 1563 /* Switch back to PLL. */ 1564 reg = SXIREAD4(sc, A64_CPUX_AXI_CFG_REG); 1565 reg &= ~A64_CPUX_CLK_SRC_SEL; 1566 reg |= A64_CPUX_CLK_SRC_SEL_PLL_CPUX; 1567 SXIWRITE4(sc, A64_CPUX_AXI_CFG_REG, reg); 1568 return error; 1569 case A64_CLK_MMC0: 1570 case A64_CLK_MMC1: 1571 case A64_CLK_MMC2: 1572 clock.sc_iot = sc->sc_iot; 1573 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1574 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1575 parent = A64_CLK_PLL_PERIPH0_2X; 1576 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1577 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1578 } 1579 1580 printf("%s: 0x%08x\n", __func__, idx); 1581 return -1; 1582 } 1583 1584 int 1585 sxiccmu_a80_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1586 { 1587 struct sxiccmu_clock clock; 1588 uint32_t parent, parent_freq; 1589 1590 switch (idx) { 1591 case A80_CLK_MMC0: 1592 case A80_CLK_MMC1: 1593 case A80_CLK_MMC2: 1594 clock.sc_iot = sc->sc_iot; 1595 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1596 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1597 parent = A80_CLK_PLL_PERIPH0; 1598 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1599 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1600 } 1601 1602 printf("%s: 0x%08x\n", __func__, idx); 1603 return -1; 1604 } 1605 1606 int 1607 sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1608 { 1609 struct sxiccmu_clock clock; 1610 uint32_t parent, parent_freq; 1611 uint32_t reg; 1612 int k, n; 1613 int error; 1614 1615 switch (idx) { 1616 case H3_CLK_PLL_CPUX: 1617 k = 1; n = 32; 1618 while (k <= 4 && (24000000 * n * k) < freq) 1619 k++; 1620 while (n >= 1 && (24000000 * n * k) > freq) 1621 n--; 1622 1623 reg = SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG); 1624 reg &= ~H3_PLL_CPUX_OUT_EXT_DIVP_MASK; 1625 reg &= ~H3_PLL_CPUX_FACTOR_N_MASK; 1626 reg &= ~H3_PLL_CPUX_FACTOR_K_MASK; 1627 reg &= ~H3_PLL_CPUX_FACTOR_M_MASK; 1628 reg |= ((n - 1) << H3_PLL_CPUX_FACTOR_N_SHIFT); 1629 reg |= ((k - 1) << H3_PLL_CPUX_FACTOR_K_SHIFT); 1630 SXIWRITE4(sc, H3_PLL_CPUX_CTRL_REG, reg); 1631 1632 /* Wait for PLL to lock. */ 1633 while ((SXIREAD4(sc, H3_PLL_CPUX_CTRL_REG) & 1634 H3_PLL_CPUX_LOCK) == 0) 1635 delay(1); 1636 1637 return 0; 1638 case H3_CLK_CPUX: 1639 /* Switch to 24 MHz clock. */ 1640 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1641 reg &= ~H3_CPUX_CLK_SRC_SEL; 1642 reg |= H3_CPUX_CLK_SRC_SEL_OSC24M; 1643 SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg); 1644 1645 error = sxiccmu_h3_set_frequency(sc, H3_CLK_PLL_CPUX, freq); 1646 1647 /* Switch back to PLL. */ 1648 reg = SXIREAD4(sc, H3_CPUX_AXI_CFG_REG); 1649 reg &= ~H3_CPUX_CLK_SRC_SEL; 1650 reg |= H3_CPUX_CLK_SRC_SEL_PLL_CPUX; 1651 SXIWRITE4(sc, H3_CPUX_AXI_CFG_REG, reg); 1652 return error; 1653 case H3_CLK_MMC0: 1654 case H3_CLK_MMC1: 1655 case H3_CLK_MMC2: 1656 clock.sc_iot = sc->sc_iot; 1657 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1658 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1659 parent = H3_CLK_PLL_PERIPH0; 1660 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1661 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1662 } 1663 1664 printf("%s: 0x%08x\n", __func__, idx); 1665 return -1; 1666 } 1667 1668 #define H6_SMHC0_CLK_REG 0x0830 1669 #define H6_SMHC1_CLK_REG 0x0834 1670 #define H6_SMHC2_CLK_REG 0x0838 1671 #define H6_SMHC_CLK_SRC_SEL (0x3 << 24) 1672 #define H6_SMHC_CLK_SRC_SEL_OSC24M (0x0 << 24) 1673 #define H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X (0x1 << 24) 1674 #define H6_SMHC_FACTOR_N_MASK (0x3 << 8) 1675 #define H6_SMHC_FACTOR_N_SHIFT 8 1676 #define H6_SMHC_FACTOR_M_MASK (0xf << 0) 1677 #define H6_SMHC_FACTOR_M_SHIFT 0 1678 1679 int 1680 sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset, 1681 uint32_t freq) 1682 { 1683 uint32_t parent_freq; 1684 uint32_t reg, m, n; 1685 uint32_t clk_src; 1686 1687 switch (freq) { 1688 case 400000: 1689 n = 2, m = 15; 1690 clk_src = H6_SMHC_CLK_SRC_SEL_OSC24M; 1691 break; 1692 case 20000000: 1693 case 25000000: 1694 case 26000000: 1695 case 50000000: 1696 case 52000000: 1697 n = 0, m = 0; 1698 clk_src = H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X; 1699 parent_freq = 1700 sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0_2X); 1701 while ((parent_freq / (1 << n) / 16) > freq) 1702 n++; 1703 while ((parent_freq / (1 << n) / (m + 1)) > freq) 1704 m++; 1705 break; 1706 default: 1707 return -1; 1708 } 1709 1710 reg = SXIREAD4(sc, offset); 1711 reg &= ~H6_SMHC_CLK_SRC_SEL; 1712 reg |= clk_src; 1713 reg &= ~H6_SMHC_FACTOR_N_MASK; 1714 reg |= n << H6_SMHC_FACTOR_N_SHIFT; 1715 reg &= ~H6_SMHC_FACTOR_M_MASK; 1716 reg |= m << H6_SMHC_FACTOR_M_SHIFT; 1717 SXIWRITE4(sc, offset, reg); 1718 1719 return 0; 1720 } 1721 1722 int 1723 sxiccmu_h6_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1724 { 1725 switch (idx) { 1726 case H6_CLK_MMC0: 1727 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG, freq); 1728 case H6_CLK_MMC1: 1729 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG, freq); 1730 case H6_CLK_MMC2: 1731 return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG, freq); 1732 } 1733 1734 printf("%s: 0x%08x\n", __func__, idx); 1735 return -1; 1736 } 1737 1738 int 1739 sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1740 { 1741 struct sxiccmu_clock clock; 1742 uint32_t parent, parent_freq; 1743 1744 switch (idx) { 1745 case R40_CLK_MMC0: 1746 case R40_CLK_MMC1: 1747 case R40_CLK_MMC2: 1748 case R40_CLK_MMC3: 1749 clock.sc_iot = sc->sc_iot; 1750 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1751 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1752 parent = R40_CLK_PLL_PERIPH0_2X; 1753 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1754 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1755 } 1756 1757 printf("%s: 0x%08x\n", __func__, idx); 1758 return -1; 1759 } 1760 1761 int 1762 sxiccmu_v3s_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1763 { 1764 struct sxiccmu_clock clock; 1765 uint32_t parent, parent_freq; 1766 1767 switch (idx) { 1768 case V3S_CLK_MMC0: 1769 case V3S_CLK_MMC1: 1770 case V3S_CLK_MMC2: 1771 clock.sc_iot = sc->sc_iot; 1772 bus_space_subregion(sc->sc_iot, sc->sc_ioh, 1773 sc->sc_gates[idx].reg, 4, &clock.sc_ioh); 1774 parent = V3S_CLK_PLL_PERIPH0; 1775 parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); 1776 return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); 1777 } 1778 1779 printf("%s: 0x%08x\n", __func__, idx); 1780 return -1; 1781 } 1782 1783 int 1784 sxiccmu_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) 1785 { 1786 printf("%s: 0x%08x\n", __func__, idx); 1787 return -1; 1788 } 1789 1790 void 1791 sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on) 1792 { 1793 struct sxiccmu_softc *sc = cookie; 1794 uint32_t idx = cells[0]; 1795 int reg, bit; 1796 1797 clock_enable_all(sc->sc_node); 1798 1799 if (idx >= sc->sc_ngates || 1800 (sc->sc_gates[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) { 1801 printf("%s: 0x%08x\n", __func__, cells[0]); 1802 return; 1803 } 1804 1805 /* If the clock can't be gated, simply return. */ 1806 if (sc->sc_gates[idx].reg == 0xffff && sc->sc_gates[idx].bit == 0xff) 1807 return; 1808 1809 reg = sc->sc_gates[idx].reg; 1810 bit = sc->sc_gates[idx].bit; 1811 1812 if (on) 1813 SXISET4(sc, reg, (1U << bit)); 1814 else 1815 SXICLR4(sc, reg, (1U << bit)); 1816 } 1817 1818 void 1819 sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert) 1820 { 1821 struct sxiccmu_softc *sc = cookie; 1822 uint32_t idx = cells[0]; 1823 int reg, bit; 1824 1825 reset_deassert_all(sc->sc_node); 1826 1827 if (idx >= sc->sc_nresets || 1828 (sc->sc_resets[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) { 1829 printf("%s: 0x%08x\n", __func__, cells[0]); 1830 return; 1831 } 1832 1833 reg = sc->sc_resets[idx].reg; 1834 bit = sc->sc_resets[idx].bit; 1835 1836 if (assert) 1837 SXICLR4(sc, reg, (1U << bit)); 1838 else 1839 SXISET4(sc, reg, (1U << bit)); 1840 } 1841