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