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