1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/bus.h> 31 32 #include <dev/clk/clk.h> 33 34 #include <dev/clk/rockchip/rk_clk_pll.h> 35 36 #include "clkdev_if.h" 37 38 struct rk_clk_pll_sc { 39 uint32_t base_offset; 40 41 uint32_t gate_offset; 42 uint32_t gate_shift; 43 44 uint32_t mode_reg; 45 uint32_t mode_shift; 46 47 uint32_t flags; 48 49 struct rk_clk_pll_rate *rates; 50 struct rk_clk_pll_rate *frac_rates; 51 }; 52 53 #define WRITE4(_clk, off, val) \ 54 CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) 55 #define READ4(_clk, off, val) \ 56 CLKDEV_READ_4(clknode_get_device(_clk), off, val) 57 #define DEVICE_LOCK(_clk) \ 58 CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) 59 #define DEVICE_UNLOCK(_clk) \ 60 CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) 61 62 #define RK_CLK_PLL_MASK_SHIFT 16 63 64 #if 0 65 #define dprintf(format, arg...) \ 66 printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg) 67 #else 68 #define dprintf(format, arg...) 69 #endif 70 71 static int 72 rk_clk_pll_set_gate(struct clknode *clk, bool enable) 73 { 74 struct rk_clk_pll_sc *sc; 75 uint32_t val = 0; 76 77 sc = clknode_get_softc(clk); 78 79 if ((sc->flags & RK_CLK_PLL_HAVE_GATE) == 0) 80 return (0); 81 82 dprintf("%sabling gate\n", enable ? "En" : "Dis"); 83 if (!enable) 84 val |= 1 << sc->gate_shift; 85 dprintf("sc->gate_shift: %x\n", sc->gate_shift); 86 val |= (1 << sc->gate_shift) << RK_CLK_PLL_MASK_SHIFT; 87 dprintf("Write: gate_offset=%x, val=%x\n", sc->gate_offset, val); 88 DEVICE_LOCK(clk); 89 WRITE4(clk, sc->gate_offset, val); 90 DEVICE_UNLOCK(clk); 91 92 return (0); 93 } 94 95 /* CON0 */ 96 #define RK3066_CLK_PLL_REFDIV_SHIFT 8 97 #define RK3066_CLK_PLL_REFDIV_MASK 0x3F00 98 #define RK3066_CLK_PLL_POSTDIV_SHIFT 0 99 #define RK3066_CLK_PLL_POSTDIV_MASK 0x000F 100 /* CON1 */ 101 #define RK3066_CLK_PLL_LOCK_MASK (1U << 31) 102 #define RK3066_CLK_PLL_FBDIV_SHIFT 0 103 #define RK3066_CLK_PLL_FBDIV_MASK 0x0FFF 104 /* CON2 */ 105 106 /* CON3 */ 107 #define RK3066_CLK_PLL_RESET (1 << 5) 108 #define RK3066_CLK_PLL_TEST (1 << 4) 109 #define RK3066_CLK_PLL_ENSAT (1 << 3) 110 #define RK3066_CLK_PLL_FASTEN (1 << 2) 111 #define RK3066_CLK_PLL_POWER_DOWN (1 << 1) 112 #define RK3066_CLK_PLL_BYPASS (1 << 0) 113 114 #define RK3066_CLK_PLL_MODE_SLOW 0 115 #define RK3066_CLK_PLL_MODE_NORMAL 1 116 #define RK3066_CLK_PLL_MODE_DEEP_SLOW 2 117 #define RK3066_CLK_PLL_MODE_MASK 0x3 118 119 static int 120 rk3066_clk_pll_init(struct clknode *clk, device_t dev) 121 { 122 struct rk_clk_pll_sc *sc; 123 uint32_t reg; 124 125 sc = clknode_get_softc(clk); 126 127 DEVICE_LOCK(clk); 128 READ4(clk, sc->mode_reg, ®); 129 DEVICE_UNLOCK(clk); 130 131 reg = (reg >> sc->mode_shift) & RK3066_CLK_PLL_MODE_MASK; 132 clknode_init_parent_idx(clk, reg); 133 134 return (0); 135 } 136 137 static int 138 rk3066_clk_pll_set_mux(struct clknode *clk, int idx) 139 { 140 uint32_t reg; 141 struct rk_clk_pll_sc *sc; 142 143 sc = clknode_get_softc(clk); 144 145 reg = (idx & RK3066_CLK_PLL_MODE_MASK) << sc->mode_shift; 146 reg |= (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) << 147 RK_CLK_PLL_MASK_SHIFT; 148 149 DEVICE_LOCK(clk); 150 WRITE4(clk, sc->mode_reg, reg); 151 DEVICE_UNLOCK(clk); 152 return(0); 153 } 154 155 static int 156 rk3066_clk_pll_recalc(struct clknode *clk, uint64_t *freq) 157 { 158 struct rk_clk_pll_sc *sc; 159 uint64_t rate; 160 uint32_t refdiv, fbdiv, postdiv; 161 uint32_t raw0, raw1, raw2, reg; 162 163 sc = clknode_get_softc(clk); 164 165 DEVICE_LOCK(clk); 166 167 READ4(clk, sc->base_offset, &raw0); 168 READ4(clk, sc->base_offset + 4, &raw1); 169 READ4(clk, sc->base_offset + 8, &raw2); 170 READ4(clk, sc->mode_reg, ®); 171 172 DEVICE_UNLOCK(clk); 173 174 reg = (reg >> sc->mode_shift) & RK3066_CLK_PLL_MODE_MASK; 175 176 if (reg != RK3066_CLK_PLL_MODE_NORMAL) 177 return (0); 178 179 if (!(raw1 & RK3066_CLK_PLL_LOCK_MASK)) { 180 *freq = 0; 181 return (0); 182 } 183 184 /* TODO MUX */ 185 refdiv = (raw0 & RK3066_CLK_PLL_REFDIV_MASK) >> 186 RK3066_CLK_PLL_REFDIV_SHIFT; 187 refdiv += 1; 188 postdiv = (raw0 & RK3066_CLK_PLL_POSTDIV_MASK) >> 189 RK3066_CLK_PLL_POSTDIV_SHIFT; 190 postdiv += 1; 191 fbdiv = (raw1 & RK3066_CLK_PLL_FBDIV_MASK) >> 192 RK3066_CLK_PLL_FBDIV_SHIFT; 193 fbdiv += 1; 194 195 rate = *freq * fbdiv; 196 rate /= refdiv; 197 *freq = rate / postdiv; 198 199 return (0); 200 } 201 202 static int 203 rk3066_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, 204 int flags, int *stop) 205 { 206 struct rk_clk_pll_rate *rates; 207 struct rk_clk_pll_sc *sc; 208 uint32_t reg; 209 int rv, timeout; 210 211 sc = clknode_get_softc(clk); 212 213 if (sc->rates == NULL) 214 return (EINVAL); 215 216 for (rates = sc->rates; rates->freq; rates++) { 217 if (rates->freq == *fout) 218 break; 219 } 220 if (rates->freq == 0) { 221 *stop = 1; 222 return (EINVAL); 223 } 224 225 DEVICE_LOCK(clk); 226 227 /* Setting to slow mode during frequency change */ 228 reg = (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) << 229 RK_CLK_PLL_MASK_SHIFT; 230 dprintf("Set PLL_MODEREG to %x\n", reg); 231 WRITE4(clk, sc->mode_reg, reg); 232 233 /* Reset PLL */ 234 WRITE4(clk, sc->base_offset + 12, RK3066_CLK_PLL_RESET | 235 RK3066_CLK_PLL_RESET << RK_CLK_PLL_MASK_SHIFT); 236 237 /* Setting postdiv and refdiv */ 238 reg = 0; 239 reg |= RK3066_CLK_PLL_POSTDIV_MASK << 16; 240 reg |= (rates->postdiv1 - 1) << RK3066_CLK_PLL_POSTDIV_SHIFT; 241 242 reg |= RK3066_CLK_PLL_REFDIV_MASK << 16; 243 reg |= (rates->refdiv - 1)<< RK3066_CLK_PLL_REFDIV_SHIFT; 244 245 dprintf("Set PLL_CON0 to %x\n", reg); 246 WRITE4(clk, sc->base_offset, reg); 247 248 249 /* Setting fbdiv (no write mask)*/ 250 READ4(clk, sc->base_offset + 4, ®); 251 reg &= ~RK3066_CLK_PLL_FBDIV_MASK; 252 reg |= RK3066_CLK_PLL_FBDIV_MASK << 16; 253 reg = (rates->fbdiv - 1) << RK3066_CLK_PLL_FBDIV_SHIFT; 254 255 dprintf("Set PLL_CON1 to %x\n", reg); 256 WRITE4(clk, sc->base_offset + 0x4, reg); 257 258 /* PLL loop bandwidth adjust */ 259 reg = rates->bwadj - 1; 260 dprintf("Set PLL_CON2 to %x (%x)\n", reg, rates->bwadj); 261 WRITE4(clk, sc->base_offset + 0x8, reg); 262 263 /* Clear reset */ 264 WRITE4(clk, sc->base_offset + 12, 265 RK3066_CLK_PLL_RESET << RK_CLK_PLL_MASK_SHIFT); 266 DELAY(100000); 267 268 /* Reading lock */ 269 for (timeout = 1000; timeout >= 0; timeout--) { 270 READ4(clk, sc->base_offset + 0x4, ®); 271 if ((reg & RK3066_CLK_PLL_LOCK_MASK) != 0) 272 break; 273 DELAY(1); 274 } 275 276 rv = 0; 277 if (timeout < 0) { 278 device_printf(clknode_get_device(clk), 279 "%s - Timedout while waiting for lock.\n", 280 clknode_get_name(clk)); 281 dprintf("PLL_CON1: %x\n", reg); 282 rv = ETIMEDOUT; 283 } 284 285 /* Set back to normal mode */ 286 reg = (RK3066_CLK_PLL_MODE_NORMAL << sc->mode_shift); 287 reg |= (RK3066_CLK_PLL_MODE_MASK << sc->mode_shift) << 288 RK_CLK_PLL_MASK_SHIFT; 289 dprintf("Set PLL_MODEREG to %x\n", reg); 290 WRITE4(clk, sc->mode_reg, reg); 291 292 DEVICE_UNLOCK(clk); 293 *stop = 1; 294 rv = clknode_set_parent_by_idx(clk, 1); 295 return (rv); 296 } 297 298 static clknode_method_t rk3066_clk_pll_clknode_methods[] = { 299 /* Device interface */ 300 CLKNODEMETHOD(clknode_init, rk3066_clk_pll_init), 301 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate), 302 CLKNODEMETHOD(clknode_recalc_freq, rk3066_clk_pll_recalc), 303 CLKNODEMETHOD(clknode_set_freq, rk3066_clk_pll_set_freq), 304 CLKNODEMETHOD(clknode_set_mux, rk3066_clk_pll_set_mux), 305 CLKNODEMETHOD_END 306 }; 307 308 DEFINE_CLASS_1(rk3066_clk_pll_clknode, rk3066_clk_pll_clknode_class, 309 rk3066_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class); 310 311 int 312 rk3066_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef) 313 { 314 struct clknode *clk; 315 struct rk_clk_pll_sc *sc; 316 317 clk = clknode_create(clkdom, &rk3066_clk_pll_clknode_class, 318 &clkdef->clkdef); 319 if (clk == NULL) 320 return (1); 321 322 sc = clknode_get_softc(clk); 323 324 sc->base_offset = clkdef->base_offset; 325 sc->gate_offset = clkdef->gate_offset; 326 sc->gate_shift = clkdef->gate_shift; 327 sc->mode_reg = clkdef->mode_reg; 328 sc->mode_shift = clkdef->mode_shift; 329 sc->flags = clkdef->flags; 330 sc->rates = clkdef->rates; 331 sc->frac_rates = clkdef->frac_rates; 332 333 clknode_register(clkdom, clk); 334 335 return (0); 336 } 337 338 #define RK3328_CLK_PLL_FBDIV_OFFSET 0 339 #define RK3328_CLK_PLL_FBDIV_SHIFT 0 340 #define RK3328_CLK_PLL_FBDIV_MASK 0xFFF 341 342 #define RK3328_CLK_PLL_POSTDIV1_OFFSET 0 343 #define RK3328_CLK_PLL_POSTDIV1_SHIFT 12 344 #define RK3328_CLK_PLL_POSTDIV1_MASK 0x7000 345 346 #define RK3328_CLK_PLL_DSMPD_OFFSET 4 347 #define RK3328_CLK_PLL_DSMPD_SHIFT 12 348 #define RK3328_CLK_PLL_DSMPD_MASK 0x1000 349 350 #define RK3328_CLK_PLL_REFDIV_OFFSET 4 351 #define RK3328_CLK_PLL_REFDIV_SHIFT 0 352 #define RK3328_CLK_PLL_REFDIV_MASK 0x3F 353 354 #define RK3328_CLK_PLL_POSTDIV2_OFFSET 4 355 #define RK3328_CLK_PLL_POSTDIV2_SHIFT 6 356 #define RK3328_CLK_PLL_POSTDIV2_MASK 0x1C0 357 358 #define RK3328_CLK_PLL_FRAC_OFFSET 8 359 #define RK3328_CLK_PLL_FRAC_SHIFT 0 360 #define RK3328_CLK_PLL_FRAC_MASK 0xFFFFFF 361 362 #define RK3328_CLK_PLL_LOCK_MASK 0x400 363 364 #define RK3328_CLK_PLL_MODE_SLOW 0 365 #define RK3328_CLK_PLL_MODE_NORMAL 1 366 #define RK3328_CLK_PLL_MODE_MASK 0x1 367 368 static int 369 rk3328_clk_pll_init(struct clknode *clk, device_t dev) 370 { 371 clknode_init_parent_idx(clk, 0); 372 373 return (0); 374 } 375 376 static int 377 rk3328_clk_pll_recalc(struct clknode *clk, uint64_t *freq) 378 { 379 struct rk_clk_pll_sc *sc; 380 uint64_t rate; 381 uint32_t dsmpd, refdiv, fbdiv; 382 uint32_t postdiv1, postdiv2, frac; 383 uint32_t raw1, raw2, raw3; 384 385 sc = clknode_get_softc(clk); 386 387 DEVICE_LOCK(clk); 388 389 READ4(clk, sc->base_offset, &raw1); 390 READ4(clk, sc->base_offset + 4, &raw2); 391 READ4(clk, sc->base_offset + 8, &raw3); 392 393 fbdiv = (raw1 & RK3328_CLK_PLL_FBDIV_MASK) >> RK3328_CLK_PLL_FBDIV_SHIFT; 394 postdiv1 = (raw1 & RK3328_CLK_PLL_POSTDIV1_MASK) >> RK3328_CLK_PLL_POSTDIV1_SHIFT; 395 396 dsmpd = (raw2 & RK3328_CLK_PLL_DSMPD_MASK) >> RK3328_CLK_PLL_DSMPD_SHIFT; 397 refdiv = (raw2 & RK3328_CLK_PLL_REFDIV_MASK) >> RK3328_CLK_PLL_REFDIV_SHIFT; 398 postdiv2 = (raw2 & RK3328_CLK_PLL_POSTDIV2_MASK) >> RK3328_CLK_PLL_POSTDIV2_SHIFT; 399 400 frac = (raw3 & RK3328_CLK_PLL_FRAC_MASK) >> RK3328_CLK_PLL_FRAC_SHIFT; 401 402 DEVICE_UNLOCK(clk); 403 404 rate = *freq * fbdiv / refdiv; 405 if (dsmpd == 0) { 406 /* Fractional mode */ 407 uint64_t frac_rate; 408 409 frac_rate = *freq * frac / refdiv; 410 rate += frac_rate >> 24; 411 } 412 413 *freq = rate / postdiv1 / postdiv2; 414 415 if (*freq % 2) 416 *freq = *freq + 1; 417 418 return (0); 419 } 420 421 static int 422 rk3328_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, 423 int flags, int *stop) 424 { 425 struct rk_clk_pll_rate *rates; 426 struct rk_clk_pll_sc *sc; 427 uint32_t reg; 428 int timeout; 429 430 sc = clknode_get_softc(clk); 431 432 if (sc->rates) 433 rates = sc->rates; 434 else if (sc->frac_rates) 435 rates = sc->frac_rates; 436 else 437 return (EINVAL); 438 439 for (; rates->freq; rates++) { 440 if (rates->freq == *fout) 441 break; 442 } 443 if (rates->freq == 0) { 444 *stop = 1; 445 return (EINVAL); 446 } 447 448 DEVICE_LOCK(clk); 449 450 /* Setting to slow mode during frequency change */ 451 reg = (RK3328_CLK_PLL_MODE_MASK << sc->mode_shift) << 452 RK_CLK_PLL_MASK_SHIFT; 453 dprintf("Set PLL_MODEREG to %x\n", reg); 454 WRITE4(clk, sc->mode_reg, reg); 455 456 /* Setting postdiv1 and fbdiv */ 457 reg = (rates->postdiv1 << RK3328_CLK_PLL_POSTDIV1_SHIFT) | 458 (rates->fbdiv << RK3328_CLK_PLL_FBDIV_SHIFT); 459 reg |= (RK3328_CLK_PLL_POSTDIV1_MASK | RK3328_CLK_PLL_FBDIV_MASK) << 16; 460 dprintf("Set PLL_CON0 to %x\n", reg); 461 WRITE4(clk, sc->base_offset, reg); 462 463 /* Setting dsmpd, postdiv2 and refdiv */ 464 reg = (rates->dsmpd << RK3328_CLK_PLL_DSMPD_SHIFT) | 465 (rates->postdiv2 << RK3328_CLK_PLL_POSTDIV2_SHIFT) | 466 (rates->refdiv << RK3328_CLK_PLL_REFDIV_SHIFT); 467 reg |= (RK3328_CLK_PLL_DSMPD_MASK | 468 RK3328_CLK_PLL_POSTDIV2_MASK | 469 RK3328_CLK_PLL_REFDIV_MASK) << RK_CLK_PLL_MASK_SHIFT; 470 dprintf("Set PLL_CON1 to %x\n", reg); 471 WRITE4(clk, sc->base_offset + 0x4, reg); 472 473 /* Setting frac */ 474 READ4(clk, sc->base_offset + 0x8, ®); 475 reg &= ~RK3328_CLK_PLL_FRAC_MASK; 476 reg |= rates->frac << RK3328_CLK_PLL_FRAC_SHIFT; 477 dprintf("Set PLL_CON2 to %x\n", reg); 478 WRITE4(clk, sc->base_offset + 0x8, reg); 479 480 /* Reading lock */ 481 for (timeout = 1000; timeout; timeout--) { 482 READ4(clk, sc->base_offset + 0x4, ®); 483 if ((reg & RK3328_CLK_PLL_LOCK_MASK) == 0) 484 break; 485 DELAY(1); 486 } 487 488 /* Set back to normal mode */ 489 reg = (RK3328_CLK_PLL_MODE_NORMAL << sc->mode_shift); 490 reg |= (RK3328_CLK_PLL_MODE_MASK << sc->mode_shift) << 491 RK_CLK_PLL_MASK_SHIFT; 492 dprintf("Set PLL_MODEREG to %x\n", reg); 493 WRITE4(clk, sc->mode_reg, reg); 494 495 DEVICE_UNLOCK(clk); 496 497 *stop = 1; 498 return (0); 499 } 500 501 static clknode_method_t rk3328_clk_pll_clknode_methods[] = { 502 /* Device interface */ 503 CLKNODEMETHOD(clknode_init, rk3328_clk_pll_init), 504 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate), 505 CLKNODEMETHOD(clknode_recalc_freq, rk3328_clk_pll_recalc), 506 CLKNODEMETHOD(clknode_set_freq, rk3328_clk_pll_set_freq), 507 CLKNODEMETHOD_END 508 }; 509 510 DEFINE_CLASS_1(rk3328_clk_pll_clknode, rk3328_clk_pll_clknode_class, 511 rk3328_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class); 512 513 int 514 rk3328_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef) 515 { 516 struct clknode *clk; 517 struct rk_clk_pll_sc *sc; 518 519 clk = clknode_create(clkdom, &rk3328_clk_pll_clknode_class, 520 &clkdef->clkdef); 521 if (clk == NULL) 522 return (1); 523 524 sc = clknode_get_softc(clk); 525 526 sc->base_offset = clkdef->base_offset; 527 sc->gate_offset = clkdef->gate_offset; 528 sc->gate_shift = clkdef->gate_shift; 529 sc->mode_reg = clkdef->mode_reg; 530 sc->mode_shift = clkdef->mode_shift; 531 sc->flags = clkdef->flags; 532 sc->rates = clkdef->rates; 533 sc->frac_rates = clkdef->frac_rates; 534 535 clknode_register(clkdom, clk); 536 537 return (0); 538 } 539 540 #define RK3399_CLK_PLL_FBDIV_OFFSET 0 541 #define RK3399_CLK_PLL_FBDIV_SHIFT 0 542 #define RK3399_CLK_PLL_FBDIV_MASK 0xFFF 543 544 #define RK3399_CLK_PLL_POSTDIV2_OFFSET 4 545 #define RK3399_CLK_PLL_POSTDIV2_SHIFT 12 546 #define RK3399_CLK_PLL_POSTDIV2_MASK 0x7000 547 548 #define RK3399_CLK_PLL_POSTDIV1_OFFSET 4 549 #define RK3399_CLK_PLL_POSTDIV1_SHIFT 8 550 #define RK3399_CLK_PLL_POSTDIV1_MASK 0x700 551 552 #define RK3399_CLK_PLL_REFDIV_OFFSET 4 553 #define RK3399_CLK_PLL_REFDIV_SHIFT 0 554 #define RK3399_CLK_PLL_REFDIV_MASK 0x3F 555 556 #define RK3399_CLK_PLL_FRAC_OFFSET 8 557 #define RK3399_CLK_PLL_FRAC_SHIFT 0 558 #define RK3399_CLK_PLL_FRAC_MASK 0xFFFFFF 559 560 #define RK3399_CLK_PLL_DSMPD_OFFSET 0xC 561 #define RK3399_CLK_PLL_DSMPD_SHIFT 3 562 #define RK3399_CLK_PLL_DSMPD_MASK 0x8 563 564 #define RK3399_CLK_PLL_LOCK_OFFSET 8 565 #define RK3399_CLK_PLL_LOCK_MASK 0x400 566 567 #define RK3399_CLK_PLL_MODE_OFFSET 0xC 568 #define RK3399_CLK_PLL_MODE_MASK 0x300 569 #define RK3399_CLK_PLL_MODE_SLOW 0 570 #define RK3399_CLK_PLL_MODE_NORMAL 1 571 #define RK3399_CLK_PLL_MODE_DEEPSLOW 2 572 #define RK3399_CLK_PLL_MODE_SHIFT 8 573 574 #define RK3399_CLK_PLL_WRITE_MASK 0xFFFF0000 575 576 static int 577 rk3399_clk_pll_init(struct clknode *clk, device_t dev) 578 { 579 clknode_init_parent_idx(clk, 0); 580 581 return (0); 582 } 583 584 static int 585 rk3399_clk_pll_recalc(struct clknode *clk, uint64_t *freq) 586 { 587 struct rk_clk_pll_sc *sc; 588 uint32_t dsmpd, refdiv, fbdiv; 589 uint32_t postdiv1, postdiv2, fracdiv; 590 uint32_t con1, con2, con3, con4; 591 uint64_t foutvco; 592 uint32_t mode; 593 sc = clknode_get_softc(clk); 594 595 DEVICE_LOCK(clk); 596 READ4(clk, sc->base_offset, &con1); 597 READ4(clk, sc->base_offset + 4, &con2); 598 READ4(clk, sc->base_offset + 8, &con3); 599 READ4(clk, sc->base_offset + 0xC, &con4); 600 DEVICE_UNLOCK(clk); 601 602 /* 603 * if we are in slow mode the output freq 604 * is the parent one, the 24Mhz external oscillator 605 * if we are in deep mode the output freq is 32.768khz 606 */ 607 mode = (con4 & RK3399_CLK_PLL_MODE_MASK) >> RK3399_CLK_PLL_MODE_SHIFT; 608 if (mode == RK3399_CLK_PLL_MODE_SLOW) { 609 dprintf("pll in slow mode, con4=%x\n", con4); 610 return (0); 611 } else if (mode == RK3399_CLK_PLL_MODE_DEEPSLOW) { 612 dprintf("pll in deep slow, con4=%x\n", con4); 613 *freq = 32768; 614 return (0); 615 } 616 617 dprintf("con0: %x\n", con1); 618 dprintf("con1: %x\n", con2); 619 dprintf("con2: %x\n", con3); 620 dprintf("con3: %x\n", con4); 621 622 fbdiv = (con1 & RK3399_CLK_PLL_FBDIV_MASK) 623 >> RK3399_CLK_PLL_FBDIV_SHIFT; 624 625 postdiv1 = (con2 & RK3399_CLK_PLL_POSTDIV1_MASK) 626 >> RK3399_CLK_PLL_POSTDIV1_SHIFT; 627 postdiv2 = (con2 & RK3399_CLK_PLL_POSTDIV2_MASK) 628 >> RK3399_CLK_PLL_POSTDIV2_SHIFT; 629 refdiv = (con2 & RK3399_CLK_PLL_REFDIV_MASK) 630 >> RK3399_CLK_PLL_REFDIV_SHIFT; 631 632 fracdiv = (con3 & RK3399_CLK_PLL_FRAC_MASK) 633 >> RK3399_CLK_PLL_FRAC_SHIFT; 634 fracdiv >>= 24; 635 636 dsmpd = (con4 & RK3399_CLK_PLL_DSMPD_MASK) >> RK3399_CLK_PLL_DSMPD_SHIFT; 637 638 dprintf("fbdiv: %d\n", fbdiv); 639 dprintf("postdiv1: %d\n", postdiv1); 640 dprintf("postdiv2: %d\n", postdiv2); 641 dprintf("refdiv: %d\n", refdiv); 642 dprintf("fracdiv: %d\n", fracdiv); 643 dprintf("dsmpd: %d\n", dsmpd); 644 645 dprintf("parent freq=%ju\n", *freq); 646 647 if (dsmpd == 0) { 648 /* Fractional mode */ 649 foutvco = *freq / refdiv * (fbdiv + fracdiv); 650 } else { 651 /* Integer mode */ 652 foutvco = *freq / refdiv * fbdiv; 653 } 654 dprintf("foutvco: %ju\n", foutvco); 655 656 *freq = foutvco / postdiv1 / postdiv2; 657 dprintf("freq: %ju\n", *freq); 658 659 return (0); 660 } 661 662 static int 663 rk3399_clk_pll_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, 664 int flags, int *stop) 665 { 666 struct rk_clk_pll_rate *rates; 667 struct rk_clk_pll_sc *sc; 668 uint32_t reg; 669 int timeout; 670 671 sc = clknode_get_softc(clk); 672 673 if (sc->rates) 674 rates = sc->rates; 675 else if (sc->frac_rates) 676 rates = sc->frac_rates; 677 else 678 return (EINVAL); 679 680 for (; rates->freq; rates++) { 681 if (rates->freq == *fout) 682 break; 683 } 684 if (rates->freq == 0) { 685 *stop = 1; 686 return (EINVAL); 687 } 688 689 DEVICE_LOCK(clk); 690 691 /* Set to slow mode during frequency change */ 692 reg = RK3399_CLK_PLL_MODE_SLOW << RK3399_CLK_PLL_MODE_SHIFT; 693 reg |= RK3399_CLK_PLL_MODE_MASK << RK_CLK_PLL_MASK_SHIFT; 694 WRITE4(clk, sc->base_offset + 0xC, reg); 695 696 /* Setting fbdiv */ 697 reg = rates->fbdiv << RK3399_CLK_PLL_FBDIV_SHIFT; 698 reg |= RK3399_CLK_PLL_FBDIV_MASK << RK_CLK_PLL_MASK_SHIFT; 699 WRITE4(clk, sc->base_offset, reg); 700 701 /* Setting postdiv1, postdiv2 and refdiv */ 702 reg = rates->postdiv1 << RK3399_CLK_PLL_POSTDIV1_SHIFT; 703 reg |= rates->postdiv2 << RK3399_CLK_PLL_POSTDIV2_SHIFT; 704 reg |= rates->refdiv << RK3399_CLK_PLL_REFDIV_SHIFT; 705 reg |= (RK3399_CLK_PLL_POSTDIV1_MASK | RK3399_CLK_PLL_POSTDIV2_MASK | 706 RK3399_CLK_PLL_REFDIV_MASK) << RK_CLK_PLL_MASK_SHIFT; 707 WRITE4(clk, sc->base_offset + 0x4, reg); 708 709 /* Setting frac */ 710 READ4(clk, sc->base_offset + 0x8, ®); 711 reg &= ~RK3399_CLK_PLL_FRAC_MASK; 712 reg |= rates->frac << RK3399_CLK_PLL_FRAC_SHIFT; 713 WRITE4(clk, sc->base_offset + 0x8, reg | RK3399_CLK_PLL_WRITE_MASK); 714 715 /* Set dsmpd */ 716 reg = rates->dsmpd << RK3399_CLK_PLL_DSMPD_SHIFT; 717 reg |= RK3399_CLK_PLL_DSMPD_MASK << RK_CLK_PLL_MASK_SHIFT; 718 WRITE4(clk, sc->base_offset + 0xC, reg); 719 720 /* Reading lock */ 721 for (timeout = 1000; timeout; timeout--) { 722 READ4(clk, sc->base_offset + RK3399_CLK_PLL_LOCK_OFFSET, ®); 723 if ((reg & RK3399_CLK_PLL_LOCK_MASK) == 0) 724 break; 725 DELAY(1); 726 } 727 728 /* Set back to normal mode */ 729 reg = RK3399_CLK_PLL_MODE_NORMAL << RK3399_CLK_PLL_MODE_SHIFT; 730 reg |= RK3399_CLK_PLL_MODE_MASK << RK_CLK_PLL_MASK_SHIFT; 731 WRITE4(clk, sc->base_offset + 0xC, reg); 732 733 DEVICE_UNLOCK(clk); 734 735 *stop = 1; 736 return (0); 737 } 738 739 static clknode_method_t rk3399_clk_pll_clknode_methods[] = { 740 /* Device interface */ 741 CLKNODEMETHOD(clknode_init, rk3399_clk_pll_init), 742 CLKNODEMETHOD(clknode_set_gate, rk_clk_pll_set_gate), 743 CLKNODEMETHOD(clknode_recalc_freq, rk3399_clk_pll_recalc), 744 CLKNODEMETHOD(clknode_set_freq, rk3399_clk_pll_set_freq), 745 CLKNODEMETHOD_END 746 }; 747 748 DEFINE_CLASS_1(rk3399_clk_pll_clknode, rk3399_clk_pll_clknode_class, 749 rk3399_clk_pll_clknode_methods, sizeof(struct rk_clk_pll_sc), clknode_class); 750 751 int 752 rk3399_clk_pll_register(struct clkdom *clkdom, struct rk_clk_pll_def *clkdef) 753 { 754 struct clknode *clk; 755 struct rk_clk_pll_sc *sc; 756 757 clk = clknode_create(clkdom, &rk3399_clk_pll_clknode_class, 758 &clkdef->clkdef); 759 if (clk == NULL) 760 return (1); 761 762 sc = clknode_get_softc(clk); 763 764 sc->base_offset = clkdef->base_offset; 765 sc->gate_offset = clkdef->gate_offset; 766 sc->gate_shift = clkdef->gate_shift; 767 sc->flags = clkdef->flags; 768 sc->rates = clkdef->rates; 769 sc->frac_rates = clkdef->frac_rates; 770 771 clknode_register(clkdom, clk); 772 773 return (0); 774 } 775