1 /* $OpenBSD: amlclock.c,v 1.11 2020/05/18 10:40:38 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <machine/intr.h> 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_clock.h> 28 #include <dev/ofw/ofw_misc.h> 29 #include <dev/ofw/fdt.h> 30 31 /* Clock IDs */ 32 #define G12A_SYS_PLL 0 33 #define G12A_FCLK_DIV2 2 34 #define G12A_FCLK_DIV3 3 35 #define G12A_FCLK_DIV4 4 36 #define G12A_FCLK_DIV5 5 37 #define G12A_FCLK_DIV7 6 38 #define G12A_MPLL1 12 39 #define G12A_MPLL2 13 40 #define G12A_I2C 24 41 #define G12A_SD_EMMC_A 33 42 #define G12A_SD_EMMC_B 34 43 #define G12A_SD_EMMC_C 35 44 #define G12A_SD_EMMC_A_CLK0 60 45 #define G12A_SD_EMMC_B_CLK0 61 46 #define G12A_SD_EMMC_C_CLK0 62 47 #define G12A_USB 47 48 #define G12A_FCLK_DIV2P5 99 49 #define G12A_CPU_CLK 187 50 #define G12A_PCIE_PLL 201 51 #define G12A_TS 212 52 #define G12B_SYS1_PLL 214 53 #define G12B_CPUB_CLK 224 54 55 /* Registers */ 56 #define HHI_PCIE_PLL_CNTL0 0x26 57 #define HHI_PCIE_PLL_CNTL1 0x27 58 #define HHI_PCIE_PLL_CNTL2 0x28 59 #define HHI_PCIE_PLL_CNTL3 0x29 60 #define HHI_PCIE_PLL_CNTL4 0x2a 61 #define HHI_PCIE_PLL_CNTL5 0x2b 62 #define HHI_GCLK_MPEG0 0x50 63 #define HHI_GCLK_MPEG1 0x51 64 #define HHI_MPEG_CLK_CNTL 0x5d 65 #define HHI_TS_CLK_CNTL 0x64 66 #define HHI_SYS_CPU_CLK_CNTL0 0x67 67 #define HHI_SYS_CPU_CLK_DYN_ENABLE (1 << 26) 68 #define HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT(x) (((x) >> 20) & 0x3f) 69 #define HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_MASK (0x3f << 20) 70 #define HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_SHIFT 20 71 #define HHI_SYS_CPU_CLK_POSTMUX1 (1 << 18) 72 #define HHI_SYS_CPU_CLK_PREMUX1(x) (((x) >> 16) & 0x3) 73 #define HHI_SYS_CPU_CLK_PREMUX1_MASK (0x3 << 16) 74 #define HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV2 (0x1 << 16) 75 #define HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV3 (0x2 << 16) 76 #define HHI_SYS_CPU_CLK_FINAL_MUX_SEL (1 << 11) 77 #define HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL (1 << 10) 78 #define HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT(x) (((x) >> 4) & 0x3f) 79 #define HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_MASK (0x3f << 4) 80 #define HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_SHIFT 4 81 #define HHI_SYS_CPU_CLK_POSTMUX0 (1 << 2) 82 #define HHI_SYS_CPU_CLK_PREMUX0(x) (((x) >> 0) & 0x3) 83 #define HHI_SYS_CPU_CLK_PREMUX0_MASK (0x3 << 0) 84 #define HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV2 (0x1 << 0) 85 #define HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV3 (0x2 << 0) 86 #define HHI_SYS_CPUB_CLK_CNTL 0x82 87 #define HHI_NAND_CLK_CNTL 0x97 88 #define HHI_SD_EMMC_CLK_CNTL 0x99 89 #define HHI_SYS_PLL_CNTL0 0xbd 90 #define HHI_SYS_DPLL_LOCK (1 << 31) 91 #define HHI_SYS_DPLL_RESET (1 << 29) 92 #define HHI_SYS_DPLL_EN (1 << 28) 93 #define HHI_SYS_DPLL_OD(x) (((x) >> 16) & 0x7) 94 #define HHI_SYS_DPLL_OD_MASK (0x7 << 16) 95 #define HHI_SYS_DPLL_OD_SHIFT 16 96 #define HHI_SYS_DPLL_N(x) (((x) >> 10) & 0x1f) 97 #define HHI_SYS_DPLL_N_MASK (0x1f << 10) 98 #define HHI_SYS_DPLL_N_SHIFT 10 99 #define HHI_SYS_DPLL_M(x) (((x) >> 0) & 0xff) 100 #define HHI_SYS_DPLL_M_MASK (0xff << 0) 101 #define HHI_SYS_DPLL_M_SHIFT 0 102 #define HHI_SYS1_PLL_CNTL0 0xe0 103 104 #define HREAD4(sc, reg) \ 105 (regmap_read_4((sc)->sc_rm, (reg) << 2)) 106 #define HWRITE4(sc, reg, val) \ 107 regmap_write_4((sc)->sc_rm, (reg) << 2, (val)) 108 #define HSET4(sc, reg, bits) \ 109 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 110 #define HCLR4(sc, reg, bits) \ 111 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 112 113 struct amlclock_gate { 114 uint8_t reg; 115 uint8_t bit; 116 }; 117 118 struct amlclock_gate aml_g12a_gates[] = { 119 [G12A_I2C] = { HHI_GCLK_MPEG0, 9 }, 120 [G12A_SD_EMMC_A] = { HHI_GCLK_MPEG0, 24 }, 121 [G12A_SD_EMMC_B] = { HHI_GCLK_MPEG0, 25 }, 122 [G12A_SD_EMMC_C] = { HHI_GCLK_MPEG0, 26 }, 123 [G12A_USB] = { HHI_GCLK_MPEG1, 26 }, 124 125 [G12A_SD_EMMC_A_CLK0] = { HHI_SD_EMMC_CLK_CNTL, 7 }, 126 [G12A_SD_EMMC_B_CLK0] = { HHI_SD_EMMC_CLK_CNTL, 23 }, 127 [G12A_SD_EMMC_C_CLK0] = { HHI_NAND_CLK_CNTL, 7 }, 128 129 [G12A_TS] = { HHI_TS_CLK_CNTL, 8 }, 130 }; 131 132 struct amlclock_softc { 133 struct device sc_dev; 134 struct regmap *sc_rm; 135 int sc_node; 136 uint32_t sc_g12b; 137 138 struct amlclock_gate *sc_gates; 139 int sc_ngates; 140 141 struct clock_device sc_cd; 142 uint32_t sc_xtal; 143 }; 144 145 int amlclock_match(struct device *, void *, void *); 146 void amlclock_attach(struct device *, struct device *, void *); 147 148 struct cfattach amlclock_ca = { 149 sizeof (struct amlclock_softc), amlclock_match, amlclock_attach 150 }; 151 152 struct cfdriver amlclock_cd = { 153 NULL, "amlclock", DV_DULL 154 }; 155 156 uint32_t amlclock_get_frequency(void *, uint32_t *); 157 int amlclock_set_frequency(void *, uint32_t *, uint32_t); 158 void amlclock_enable(void *, uint32_t *, int); 159 160 int 161 amlclock_match(struct device *parent, void *match, void *aux) 162 { 163 struct fdt_attach_args *faa = aux; 164 165 return (OF_is_compatible(faa->fa_node, "amlogic,g12a-clkc") || 166 OF_is_compatible(faa->fa_node, "amlogic,g12b-clkc") || 167 OF_is_compatible(faa->fa_node, "amlogic,sm1-clkc")); 168 } 169 170 void 171 amlclock_attach(struct device *parent, struct device *self, void *aux) 172 { 173 struct amlclock_softc *sc = (struct amlclock_softc *)self; 174 struct fdt_attach_args *faa = aux; 175 176 sc->sc_rm = regmap_bynode(OF_parent(faa->fa_node)); 177 if (sc->sc_rm == NULL) { 178 printf(": no registers\n"); 179 return; 180 } 181 182 sc->sc_node = faa->fa_node; 183 printf("\n"); 184 185 if (OF_is_compatible(faa->fa_node, "amlogic,g12b-clkc")) 186 sc->sc_g12b = 1; 187 188 sc->sc_gates = aml_g12a_gates; 189 sc->sc_ngates = nitems(aml_g12a_gates); 190 191 sc->sc_xtal = clock_get_frequency(sc->sc_node, "xtal"); 192 193 sc->sc_cd.cd_node = faa->fa_node; 194 sc->sc_cd.cd_cookie = sc; 195 sc->sc_cd.cd_get_frequency = amlclock_get_frequency; 196 sc->sc_cd.cd_set_frequency = amlclock_set_frequency; 197 sc->sc_cd.cd_enable = amlclock_enable; 198 clock_register(&sc->sc_cd); 199 } 200 201 uint32_t 202 amlclock_get_cpu_freq(struct amlclock_softc *sc, bus_size_t offset) 203 { 204 uint32_t reg, mux, div; 205 uint32_t idx; 206 207 reg = HREAD4(sc, offset); 208 if (reg & HHI_SYS_CPU_CLK_FINAL_MUX_SEL) { 209 if (sc->sc_g12b && offset == HHI_SYS_CPU_CLK_CNTL0) 210 idx = G12B_SYS1_PLL; 211 else 212 idx = G12A_SYS_PLL; 213 return amlclock_get_frequency(sc, &idx); 214 } 215 if (reg & HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL) { 216 div = (reg & HHI_SYS_CPU_CLK_POSTMUX1) ? 217 (HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT(reg) + 1) : 1; 218 mux = HHI_SYS_CPU_CLK_PREMUX1(reg); 219 } else { 220 div = (reg & HHI_SYS_CPU_CLK_POSTMUX0) ? 221 (HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT(reg) + 1) : 1; 222 mux = HHI_SYS_CPU_CLK_PREMUX0(reg); 223 } 224 switch (mux) { 225 case 0: 226 return sc->sc_xtal / div; 227 case 1: 228 idx = G12A_FCLK_DIV2; 229 break; 230 case 2: 231 idx = G12A_FCLK_DIV3; 232 break; 233 case 3: 234 return 0; 235 } 236 return amlclock_get_frequency(sc, &idx) / div; 237 } 238 239 int 240 amlclock_set_cpu_freq(struct amlclock_softc *sc, bus_size_t offset, 241 uint32_t freq) 242 { 243 uint32_t reg, div; 244 uint32_t parent_freq; 245 uint32_t idx; 246 247 /* 248 * For clock frequencies above 1GHz we have to use 249 * SYS_PLL/SYS1_PLL. 250 */ 251 reg = HREAD4(sc, offset); 252 if (freq > 1000000000) { 253 /* 254 * Switch to a fixed clock if we're currently using 255 * SYS_PLL/SYS1_PLL. Doesn't really matter which one. 256 */ 257 if (reg & HHI_SYS_CPU_CLK_FINAL_MUX_SEL) { 258 reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL; 259 HWRITE4(sc, offset, reg); 260 delay(100); 261 } 262 263 if (sc->sc_g12b && offset == HHI_SYS_CPU_CLK_CNTL0) 264 idx = G12B_SYS1_PLL; 265 else 266 idx = G12A_SYS_PLL; 267 amlclock_set_frequency(sc, &idx, freq); 268 269 /* Switch to SYS_PLL/SYS1_PLL. */ 270 reg |= HHI_SYS_CPU_CLK_FINAL_MUX_SEL; 271 HWRITE4(sc, offset, reg); 272 delay(100); 273 274 return 0; 275 } 276 277 /* 278 * There are two signal paths for frequencies up to 1GHz. If 279 * we're using one, we can program the dividers for the other 280 * one and switch to it. The pre-divider can be either 2 or 3 281 * and can't be bypassed, so take this into account and only 282 * allow frequencies that include such a divider. 283 */ 284 div = 2; 285 parent_freq = 2000000000; 286 while (parent_freq / div > freq) 287 div++; 288 while ((div % 2) != 0 && (div % 3) != 0) 289 div++; 290 if (div > 32) 291 return EINVAL; 292 if ((div % 2) == 0) { 293 parent_freq /= 2; 294 div /= 2; 295 } else { 296 parent_freq /= 3; 297 div /= 3; 298 } 299 300 if (reg & HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL) { 301 /* premux0 */ 302 reg = HREAD4(sc, offset); 303 reg &= ~HHI_SYS_CPU_CLK_PREMUX0_MASK; 304 if (parent_freq == 1000000000) 305 reg |= HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV2; 306 else 307 reg |= HHI_SYS_CPU_CLK_PREMUX0_FCLK_DIV3; 308 HWRITE4(sc, offset, reg); 309 delay(100); 310 311 /* mux0 divider */ 312 HSET4(sc, offset, HHI_SYS_CPU_CLK_DYN_ENABLE); 313 reg = HREAD4(sc, offset); 314 reg &= ~HHI_SYS_CPU_CLK_DYN_ENABLE; 315 reg &= ~HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_MASK; 316 reg |= ((div - 1) << HHI_SYS_CPU_CLK_MUX0_DIVN_TCNT_SHIFT); 317 HWRITE4(sc, offset, reg); 318 319 /* postmux0 */ 320 if (div != 1) 321 HSET4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX0); 322 else 323 HCLR4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX0); 324 325 /* final_dyn_mux_sel and final_mux_sel */ 326 reg = HREAD4(sc, offset); 327 reg &= ~HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL; 328 reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL; 329 HWRITE4(sc, offset, reg); 330 delay(100); 331 } else { 332 /* premux1 */ 333 reg = HREAD4(sc, offset); 334 reg &= ~HHI_SYS_CPU_CLK_PREMUX1_MASK; 335 if (parent_freq == 1000000000) 336 reg |= HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV2; 337 else 338 reg |= HHI_SYS_CPU_CLK_PREMUX1_FCLK_DIV3; 339 HWRITE4(sc, offset, reg); 340 delay(100); 341 342 /* mux1 divider */ 343 HSET4(sc, offset, HHI_SYS_CPU_CLK_DYN_ENABLE); 344 reg = HREAD4(sc, offset); 345 reg &= ~HHI_SYS_CPU_CLK_DYN_ENABLE; 346 reg &= ~HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_MASK; 347 reg |= ((div - 1) << HHI_SYS_CPU_CLK_MUX1_DIVN_TCNT_SHIFT); 348 HWRITE4(sc, offset, reg); 349 350 /* postmux1 */ 351 if (div != 1) 352 HSET4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX1); 353 else 354 HCLR4(sc, offset, HHI_SYS_CPU_CLK_POSTMUX1); 355 356 /* final_dyn_mux_sel and final_mux_sel */ 357 reg = HREAD4(sc, offset); 358 reg |= HHI_SYS_CPU_CLK_FINAL_DYN_MUX_SEL; 359 reg &= ~HHI_SYS_CPU_CLK_FINAL_MUX_SEL; 360 HWRITE4(sc, offset, reg); 361 delay(100); 362 } 363 364 return 0; 365 } 366 367 int 368 amlclock_set_pll_freq(struct amlclock_softc *sc, bus_size_t offset, 369 uint32_t freq) 370 { 371 uint32_t reg, div; 372 uint32_t m, n = 1; 373 int timo; 374 375 /* 376 * The multiplier should be between 128 and 255. If 377 * necessary, adjust the divider to achieve this. 378 */ 379 div = 1; 380 while ((div * (uint64_t)freq) / sc->sc_xtal < 128) 381 div *= 2; 382 if (div > 128) 383 return EINVAL; 384 m = (div * (uint64_t)freq) / sc->sc_xtal; 385 if (m > 255) 386 return EINVAL; 387 388 HSET4(sc, offset, HHI_SYS_DPLL_RESET); 389 HCLR4(sc, offset, HHI_SYS_DPLL_EN); 390 391 reg = HREAD4(sc, offset); 392 reg &= ~HHI_SYS_DPLL_OD_MASK; 393 reg |= ((fls(div) - 1) << HHI_SYS_DPLL_OD_SHIFT); 394 reg &= ~(HHI_SYS_DPLL_M_MASK | HHI_SYS_DPLL_N_MASK); 395 reg |= (m << HHI_SYS_DPLL_M_SHIFT); 396 reg |= (n << HHI_SYS_DPLL_N_SHIFT); 397 HWRITE4(sc, offset, reg); 398 399 HSET4(sc, offset, HHI_SYS_DPLL_RESET); 400 HSET4(sc, offset, HHI_SYS_DPLL_EN); 401 HCLR4(sc, offset, HHI_SYS_DPLL_RESET); 402 403 for (timo = 24000000; timo > 0; timo--) { 404 if (HREAD4(sc, offset) & HHI_SYS_DPLL_LOCK) 405 return 0; 406 } 407 408 return ETIMEDOUT; 409 } 410 411 uint32_t 412 amlclock_get_frequency(void *cookie, uint32_t *cells) 413 { 414 struct amlclock_softc *sc = cookie; 415 uint32_t idx = cells[0]; 416 uint32_t reg, mux, div; 417 uint32_t m, n; 418 419 switch (idx) { 420 case G12A_SYS_PLL: 421 reg = HREAD4(sc, HHI_SYS_PLL_CNTL0); 422 div = 1 << HHI_SYS_DPLL_OD(reg); 423 m = HHI_SYS_DPLL_M(reg); 424 n = HHI_SYS_DPLL_N(reg); 425 return (((uint64_t)sc->sc_xtal * m) / n) / div; 426 case G12B_SYS1_PLL: 427 reg = HREAD4(sc, HHI_SYS1_PLL_CNTL0); 428 div = 1 << HHI_SYS_DPLL_OD(reg); 429 m = HHI_SYS_DPLL_M(reg); 430 n = HHI_SYS_DPLL_N(reg); 431 return (((uint64_t)sc->sc_xtal * m) / n) / div; 432 case G12A_FCLK_DIV2: 433 return 1000000000; 434 case G12A_FCLK_DIV3: 435 return 666666666; 436 case G12A_FCLK_DIV4: 437 return 500000000; 438 case G12A_FCLK_DIV5: 439 return 400000000; 440 case G12A_FCLK_DIV7: 441 return 285714285; 442 case G12A_FCLK_DIV2P5: 443 return 800000000; 444 445 case G12A_I2C: 446 reg = HREAD4(sc, HHI_MPEG_CLK_CNTL); 447 mux = (reg >> 12) & 0x7; 448 div = ((reg >> 0) & 0x7f) + 1; 449 switch (mux) { 450 case 0: 451 return sc->sc_xtal / div; 452 case 2: 453 idx = G12A_FCLK_DIV7; 454 break; 455 case 3: 456 idx = G12A_MPLL1; 457 break; 458 case 4: 459 idx = G12A_MPLL2; 460 break; 461 case 5: 462 idx = G12A_FCLK_DIV4; 463 break; 464 case 6: 465 idx = G12A_FCLK_DIV3; 466 break; 467 case 7: 468 idx = G12A_FCLK_DIV5; 469 break; 470 default: 471 goto fail; 472 } 473 return amlclock_get_frequency(sc, &idx) / div; 474 case G12A_SD_EMMC_A_CLK0: 475 reg = HREAD4(sc, HHI_SD_EMMC_CLK_CNTL); 476 mux = (reg >> 9) & 0x7; 477 div = ((reg >> 0) & 0x7f) + 1; 478 switch (mux) { 479 case 0: 480 return sc->sc_xtal / div; 481 case 1: 482 idx = G12A_FCLK_DIV2; 483 break; 484 case 2: 485 idx = G12A_FCLK_DIV3; 486 break; 487 case 3: 488 idx = G12A_FCLK_DIV5; 489 break; 490 case 4: 491 idx = G12A_FCLK_DIV7; 492 break; 493 default: 494 goto fail; 495 } 496 return amlclock_get_frequency(sc, &idx) / div; 497 case G12A_SD_EMMC_B_CLK0: 498 reg = HREAD4(sc, HHI_SD_EMMC_CLK_CNTL); 499 mux = (reg >> 25) & 0x7; 500 div = ((reg >> 16) & 0x7f) + 1; 501 switch (mux) { 502 case 0: 503 return sc->sc_xtal / div; 504 case 1: 505 idx = G12A_FCLK_DIV2; 506 break; 507 case 2: 508 idx = G12A_FCLK_DIV3; 509 break; 510 case 3: 511 idx = G12A_FCLK_DIV5; 512 break; 513 case 4: 514 idx = G12A_FCLK_DIV7; 515 break; 516 default: 517 goto fail; 518 } 519 return amlclock_get_frequency(sc, &idx) / div; 520 case G12A_SD_EMMC_C_CLK0: 521 reg = HREAD4(sc, HHI_NAND_CLK_CNTL); 522 mux = (reg >> 9) & 0x7; 523 div = ((reg >> 0) & 0x7f) + 1; 524 switch (mux) { 525 case 0: 526 return sc->sc_xtal / div; 527 case 1: 528 idx = G12A_FCLK_DIV2; 529 break; 530 case 2: 531 idx = G12A_FCLK_DIV3; 532 break; 533 case 3: 534 idx = G12A_FCLK_DIV5; 535 break; 536 case 4: 537 idx = G12A_FCLK_DIV7; 538 break; 539 default: 540 goto fail; 541 } 542 return amlclock_get_frequency(sc, &idx) / div; 543 case G12A_CPU_CLK: 544 return amlclock_get_cpu_freq(sc, HHI_SYS_CPU_CLK_CNTL0); 545 case G12B_CPUB_CLK: 546 return amlclock_get_cpu_freq(sc, HHI_SYS_CPUB_CLK_CNTL); 547 } 548 549 fail: 550 printf("%s: 0x%08x\n", __func__, idx); 551 return 0; 552 } 553 554 int 555 amlclock_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 556 { 557 struct amlclock_softc *sc = cookie; 558 uint32_t idx = cells[0]; 559 560 switch (idx) { 561 case G12A_SYS_PLL: 562 return amlclock_set_pll_freq(sc, HHI_SYS_PLL_CNTL0, freq); 563 case G12B_SYS1_PLL: 564 return amlclock_set_pll_freq(sc, HHI_SYS1_PLL_CNTL0, freq); 565 case G12A_PCIE_PLL: 566 /* Fixed at 100 MHz. */ 567 if (freq != 100000000) 568 return -1; 569 HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x20090496); 570 HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x30090496); 571 HWRITE4(sc, HHI_PCIE_PLL_CNTL1, 0x00000000); 572 HWRITE4(sc, HHI_PCIE_PLL_CNTL2, 0x00001100); 573 HWRITE4(sc, HHI_PCIE_PLL_CNTL3, 0x10058e00); 574 HWRITE4(sc, HHI_PCIE_PLL_CNTL4, 0x000100c0); 575 HWRITE4(sc, HHI_PCIE_PLL_CNTL5, 0x68000048); 576 HWRITE4(sc, HHI_PCIE_PLL_CNTL5, 0x68000068); 577 delay(20); 578 HWRITE4(sc, HHI_PCIE_PLL_CNTL4, 0x008100c0); 579 delay(10); 580 HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x34090496); 581 HWRITE4(sc, HHI_PCIE_PLL_CNTL0, 0x14090496); 582 delay(10); 583 HWRITE4(sc, HHI_PCIE_PLL_CNTL2, 0x00001000); 584 return 0; 585 case G12A_CPU_CLK: 586 return amlclock_set_cpu_freq(sc, HHI_SYS_CPU_CLK_CNTL0, freq); 587 case G12B_CPUB_CLK: 588 return amlclock_set_cpu_freq(sc, HHI_SYS_CPUB_CLK_CNTL, freq); 589 } 590 591 printf("%s: 0x%08x\n", __func__, idx); 592 return -1; 593 } 594 595 void 596 amlclock_enable(void *cookie, uint32_t *cells, int on) 597 { 598 struct amlclock_softc *sc = cookie; 599 uint32_t idx = cells[0]; 600 601 if (idx < sc->sc_ngates && sc->sc_gates[idx].reg != 0) { 602 if (on) 603 HSET4(sc, sc->sc_gates[idx].reg, 604 (1U << sc->sc_gates[idx].bit)); 605 else 606 HCLR4(sc, sc->sc_gates[idx].reg, 607 (1U << sc->sc_gates[idx].bit)); 608 return; 609 } 610 611 switch (idx) { 612 case G12A_FCLK_DIV2: 613 case G12A_PCIE_PLL: 614 /* Already enabled. */ 615 return; 616 } 617 618 printf("%s: 0x%08x\n", __func__, idx); 619 } 620