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