1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020 Rockchip Electronics Co. Ltd. 4 * 5 * Author: Guochun Huang <hero.huang@rock-chips.com> 6 */ 7 8 #include "rk628_cru.h" 9 10 #define REFCLK_RATE 24000000UL 11 #define MIN_FREF_RATE 10000000UL 12 #define MAX_FREF_RATE 800000000UL 13 #define MIN_FREFDIV_RATE 1000000UL 14 #define MAX_FREFDIV_RATE 100000000UL 15 #define MIN_FVCO_RATE 600000000UL 16 #define MAX_FVCO_RATE 1600000000UL 17 #define MIN_FOUTPOSTDIV_RATE 12000000UL 18 #define MAX_FOUTPOSTDIV_RATE 1600000000UL 19 20 static void rational_best_approximation(unsigned long given_numerator, 21 unsigned long given_denominator, 22 unsigned long max_numerator, 23 unsigned long max_denominator, 24 unsigned long *best_numerator, 25 unsigned long *best_denominator) 26 { 27 unsigned long n, d, n0, d0, n1, d1; 28 29 n = given_numerator; 30 d = given_denominator; 31 n0 = d1 = 0; 32 n1 = d0 = 1; 33 for (;;) { 34 unsigned long t, a; 35 36 if ((n1 > max_numerator) || (d1 > max_denominator)) { 37 n1 = n0; 38 d1 = d0; 39 break; 40 } 41 if (d == 0) 42 break; 43 t = d; 44 a = n / d; 45 d = n % d; 46 n = t; 47 t = n0 + a * n1; 48 n0 = n1; 49 n1 = t; 50 t = d0 + a * d1; 51 d0 = d1; 52 d1 = t; 53 } 54 *best_numerator = n1; 55 *best_denominator = d1; 56 } 57 58 static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628, 59 unsigned int id) 60 { 61 unsigned long parent_rate = REFCLK_RATE; 62 u32 postdiv1, fbdiv, dsmpd, postdiv2, refdiv, frac, bypass; 63 u32 con0 = 0, con1 = 0, con2 = 0; 64 u64 foutvco, foutpostdiv; 65 u32 offset, val = 0; 66 67 if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION) 68 return 0; 69 70 rk628_i2c_read(rk628, CRU_MODE_CON00, &val); 71 if (id == CGU_CLK_CPLL) { 72 val &= CLK_CPLL_MODE_MASK; 73 val >>= CLK_CPLL_MODE_SHIFT; 74 if (val == CLK_CPLL_MODE_OSC) 75 return parent_rate; 76 77 offset = 0x00; 78 } else if (id == CGU_CLK_GPLL) { 79 val &= CLK_GPLL_MODE_MASK; 80 val >>= CLK_GPLL_MODE_SHIFT; 81 if (val == CLK_GPLL_MODE_OSC) 82 return parent_rate; 83 84 offset = 0x20; 85 } else { 86 val &= CLK_APLL_MODE_MASK; 87 val >>= CLK_APLL_MODE_SHIFT; 88 if (val == CLK_APLL_MODE_OSC) 89 return parent_rate; 90 91 offset = 0x40; 92 } 93 94 rk628_i2c_read(rk628, offset + CRU_CPLL_CON0, &con0); 95 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &con1); 96 rk628_i2c_read(rk628, offset + CRU_CPLL_CON2, &con2); 97 98 bypass = (con0 & PLL_BYPASS_MASK) >> PLL_BYPASS_SHIFT; 99 postdiv1 = (con0 & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT; 100 fbdiv = (con0 & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; 101 dsmpd = (con1 & PLL_DSMPD_MASK) >> PLL_DSMPD_SHIFT; 102 postdiv2 = (con1 & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT; 103 refdiv = (con1 & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT; 104 frac = (con2 & PLL_FRAC_MASK) >> PLL_FRAC_SHIFT; 105 106 if (bypass) 107 return parent_rate; 108 109 foutvco = parent_rate * fbdiv; 110 do_div(foutvco, refdiv); 111 112 if (!dsmpd) { 113 u64 frac_rate = (u64)parent_rate * frac; 114 115 do_div(frac_rate, refdiv); 116 foutvco += frac_rate >> 24; 117 } 118 119 foutpostdiv = foutvco; 120 do_div(foutpostdiv, postdiv1); 121 do_div(foutpostdiv, postdiv2); 122 123 return foutpostdiv; 124 } 125 126 static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628, 127 unsigned int id, 128 unsigned long rate) 129 { 130 unsigned long fin = REFCLK_RATE, fout = rate; 131 u8 min_refdiv, max_refdiv, postdiv; 132 u8 dsmpd = 1, postdiv1 = 0, postdiv2 = 0, refdiv = 0; 133 u16 fbdiv = 0; 134 u32 frac = 0; 135 u64 foutvco, foutpostdiv, div1, div2; 136 u32 offset, val = 0; 137 138 /* 139 * FREF : 10MHz ~ 800MHz 140 * FREFDIV : 1MHz ~ 40MHz 141 * FOUTVCO : 400MHz ~ 1.6GHz 142 * FOUTPOSTDIV : 8MHz ~ 1.6GHz 143 */ 144 if (fin < MIN_FREF_RATE || fin > MAX_FREF_RATE) 145 return 0; 146 147 if (fout < MIN_FOUTPOSTDIV_RATE || fout > MAX_FOUTPOSTDIV_RATE) 148 return 0; 149 150 if (id == CGU_CLK_CPLL) 151 offset = 0x00; 152 else if (id == CGU_CLK_GPLL) 153 offset = 0x20; 154 else 155 offset = 0x40; 156 157 if (id != CGU_CLK_APLL) 158 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(1)); 159 160 if (fin == fout) { 161 rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, PLL_BYPASS(1)); 162 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0)); 163 while (1) { 164 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val); 165 if (val & PLL_LOCK) 166 break; 167 } 168 return fin; 169 } 170 171 min_refdiv = fin / MAX_FREFDIV_RATE + 1; 172 max_refdiv = fin / MIN_FREFDIV_RATE; 173 if (max_refdiv > 64) 174 max_refdiv = 64; 175 176 if (fout < MIN_FVCO_RATE) { 177 div1 = DIV_ROUND_UP(MIN_FVCO_RATE, fout); 178 div2 = DIV_ROUND_UP(MAX_FVCO_RATE, fout); 179 for (postdiv = div1; postdiv <= div2; postdiv++) { 180 /* fix prime number that can not find right div*/ 181 for (postdiv2 = 1; postdiv2 < 8; postdiv2++) { 182 if (postdiv % postdiv2) 183 continue; 184 postdiv1 = postdiv / postdiv2; 185 if (postdiv1 > 0 && postdiv1 < 8) 186 break; 187 } 188 if (postdiv2 > 7) 189 continue; 190 else 191 break; 192 } 193 if (postdiv > div2) 194 return 0; 195 fout *= postdiv1 * postdiv2; 196 } else { 197 postdiv1 = 1; 198 postdiv2 = 1; 199 } 200 201 for (refdiv = min_refdiv; refdiv <= max_refdiv; refdiv++) { 202 u64 tmp, frac_rate; 203 204 if (fin % refdiv) 205 continue; 206 207 tmp = (u64)fout * refdiv; 208 do_div(tmp, fin); 209 fbdiv = tmp; 210 if (fbdiv < 10 || fbdiv > 1600) 211 continue; 212 213 tmp = (u64)fbdiv * fin; 214 do_div(tmp, refdiv); 215 if (fout < MIN_FVCO_RATE || fout > MAX_FVCO_RATE) 216 continue; 217 218 frac_rate = fout - tmp; 219 220 if (frac_rate) { 221 tmp = (u64)frac_rate * refdiv; 222 tmp <<= 24; 223 do_div(tmp, fin); 224 frac = tmp; 225 dsmpd = 0; 226 } 227 228 break; 229 } 230 231 /* 232 * If DSMPD = 1 (DSM is disabled, "integer mode") 233 * FOUTVCO = FREF / REFDIV * FBDIV 234 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 235 * 236 * If DSMPD = 0 (DSM is enabled, "fractional mode") 237 * FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 2^24) 238 * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2 239 */ 240 foutvco = fin * fbdiv; 241 do_div(foutvco, refdiv); 242 243 if (!dsmpd) { 244 u64 frac_rate = (u64)fin * frac; 245 246 do_div(frac_rate, refdiv); 247 foutvco += frac_rate >> 24; 248 } 249 250 foutpostdiv = foutvco; 251 do_div(foutpostdiv, postdiv1); 252 do_div(foutpostdiv, postdiv2); 253 254 rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, 255 PLL_BYPASS(0) | PLL_POSTDIV1(postdiv1) | 256 PLL_FBDIV(fbdiv)); 257 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, 258 PLL_DSMPD(dsmpd) | PLL_POSTDIV2(postdiv2) | 259 PLL_REFDIV(refdiv)); 260 rk628_i2c_write(rk628, offset + CRU_CPLL_CON2, PLL_FRAC(frac)); 261 262 if (id != CGU_CLK_APLL) 263 rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0)); 264 265 while (1) { 266 rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val); 267 if (val & PLL_LOCK) 268 break; 269 } 270 271 return (unsigned long)foutpostdiv; 272 } 273 274 static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628, 275 unsigned long rate) 276 { 277 unsigned long m, n, parent_rate; 278 u32 val = 0; 279 280 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val); 281 val &= SCLK_VOP_SEL_MASK; 282 val >>= SCLK_VOP_SEL_SHIFT; 283 if (val == SCLK_VOP_SEL_GPLL) 284 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 285 else 286 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 287 288 rational_best_approximation(rate, parent_rate, 289 GENMASK(15, 0), GENMASK(15, 0), 290 &m, &n); 291 rk628_i2c_write(rk628, CRU_CLKSEL_CON13, m << 16 | n); 292 293 return rate; 294 } 295 296 static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628) 297 { 298 unsigned long rate, parent_rate, m, n; 299 u32 mux, div = 0; 300 301 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux); 302 mux &= CLK_UART_SRC_SEL_MASK; 303 mux >>= SCLK_VOP_SEL_SHIFT; 304 if (mux == SCLK_VOP_SEL_GPLL) 305 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 306 else 307 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 308 309 rk628_i2c_read(rk628, CRU_CLKSEL_CON13, &div); 310 m = div >> 16 & 0xffff; 311 n = div & 0xffff; 312 rate = parent_rate * m / n; 313 314 return rate; 315 } 316 317 static unsigned long rk628_cru_clk_get_rate_clk_imodet(struct rk628 *rk628) 318 { 319 unsigned long rate, parent_rate, n; 320 u32 mux = 0, div = 0; 321 322 rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &mux); 323 mux &= CLK_IMODET_SEL_MASK; 324 mux >>= CLK_IMODET_SEL_SHIFT; 325 if (mux == SCLK_VOP_SEL_GPLL) 326 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 327 else 328 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 329 330 rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &div); 331 n = div & 0x1f; 332 rate = parent_rate / (n + 1); 333 334 return rate; 335 } 336 337 static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628, 338 unsigned long rate) 339 { 340 unsigned long m, n, parent_rate; 341 u32 val = 0; 342 343 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val); 344 val &= CLK_RX_READ_SEL_MASK; 345 val >>= CLK_RX_READ_SEL_SHIFT; 346 if (val == CLK_RX_READ_SEL_GPLL) 347 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 348 else 349 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 350 351 rational_best_approximation(rate, parent_rate, 352 GENMASK(15, 0), GENMASK(15, 0), 353 &m, &n); 354 rk628_i2c_write(rk628, CRU_CLKSEL_CON14, m << 16 | n); 355 356 return rate; 357 } 358 359 static unsigned long rk628_cru_clk_get_rate_uart_src(struct rk628 *rk628) 360 { 361 unsigned long rate, parent_rate; 362 u32 mux, div = 0; 363 364 rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &mux); 365 mux &= SCLK_VOP_SEL_MASK; 366 if (mux == CLK_UART_SRC_SEL_GPLL) 367 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 368 else 369 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 370 371 rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &div); 372 div &= CLK_UART_SRC_DIV_MASK; 373 div >>= CLK_UART_SRC_DIV_SHIFT; 374 rate = parent_rate / (div + 1); 375 376 return rate; 377 } 378 379 static unsigned long rk628_cru_clk_set_rate_sclk_uart(struct rk628 *rk628, 380 unsigned long rate) 381 { 382 unsigned long m, n, parent_rate; 383 384 parent_rate = rk628_cru_clk_get_rate_uart_src(rk628); 385 386 if (rate == REFCLK_RATE) { 387 rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 388 SCLK_UART_SEL(SCLK_UART_SEL_OSC)); 389 return rate; 390 } else if (rate == parent_rate) { 391 rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 392 SCLK_UART_SEL(SCLK_UART_SEL_UART_SRC)); 393 return rate; 394 } 395 396 rk628_i2c_write(rk628, CRU_CLKSEL_CON06, 397 SCLK_UART_SEL(SCLK_UART_SEL_UART_FRAC)); 398 399 rational_best_approximation(rate, parent_rate, 400 GENMASK(15, 0), GENMASK(15, 0), 401 &m, &n); 402 rk628_i2c_write(rk628, CRU_CLKSEL_CON20, m << 16 | n); 403 404 return rate; 405 } 406 407 static unsigned long rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 *rk628, unsigned long rate) 408 { 409 u64 parent_rate; 410 u8 div; 411 412 if (rk628->version >= RK628F_VERSION) 413 parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_APLL, rate*4); 414 else 415 parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_GPLL, rate*4); 416 div = DIV_ROUND_CLOSEST(parent_rate, rate); 417 do_div(parent_rate, div); 418 rate = parent_rate; 419 if (rk628->version >= RK628F_VERSION) 420 rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) | 421 CLK_HDMIRX_AUD_SEL_V2(2)); 422 else 423 rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) | 424 CLK_HDMIRX_AUD_SEL_V1(1)); 425 return rate; 426 } 427 428 static unsigned long rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 *rk628) 429 { 430 unsigned long rate; 431 u64 parent_rate; 432 u8 div = 0; 433 u32 val = 0; 434 435 rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val); 436 div = ((val & CLK_HDMIRX_AUD_DIV_MASK) >> 6) + 1; 437 if (rk628->version >= RK628F_VERSION) 438 val = (val & CLK_HDMIRX_AUD_SEL_MASK_V2) >> 14; 439 else 440 val = (val & CLK_HDMIRX_AUD_SEL_MASK_V1) >> 15; 441 if (!val) 442 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 443 else if (val == 2) 444 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_APLL); 445 else 446 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 447 do_div(parent_rate, div); 448 rate = parent_rate; 449 return rate; 450 } 451 452 static unsigned long 453 rk628_cru_clk_get_rate_bt1120_dec_parent(struct rk628 *rk628) 454 { 455 unsigned long parent_rate; 456 u32 mux; 457 458 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux); 459 mux &= CLK_BT1120DEC_SEL_MASK; 460 if (mux == CLK_BT1120DEC_SEL_GPLL) 461 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL); 462 else 463 parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL); 464 465 return parent_rate; 466 } 467 468 static unsigned long rk628_cru_clk_set_rate_bt1120_dec(struct rk628 *rk628, 469 unsigned long rate) 470 { 471 unsigned long parent_rate; 472 u32 div; 473 474 parent_rate = rk628_cru_clk_get_rate_bt1120_dec_parent(rk628); 475 div = DIV_ROUND_UP(parent_rate, rate); 476 rk628_i2c_write(rk628, CRU_CLKSEL_CON02, CLK_BT1120DEC_DIV(div-1)); 477 478 return parent_rate / div; 479 } 480 481 static unsigned long rk628_cru_clk_get_rate_bt1120_dec(struct rk628 *rk628) 482 { 483 unsigned long parent_rate; 484 u32 div = 0; 485 486 parent_rate = rk628_cru_clk_get_rate_bt1120_dec_parent(rk628); 487 488 rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &div); 489 div = (div & 0x1f) + 1; 490 491 return parent_rate / div; 492 } 493 494 int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id, 495 unsigned long rate) 496 { 497 if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION) 498 return -EINVAL; 499 500 switch (id) { 501 case CGU_CLK_APLL: 502 case CGU_CLK_CPLL: 503 case CGU_CLK_GPLL: 504 rk628_cru_clk_set_rate_pll(rk628, id, rate); 505 break; 506 case CGU_CLK_RX_READ: 507 rk628_cru_clk_set_rate_rx_read(rk628, rate); 508 break; 509 case CGU_SCLK_VOP: 510 rk628_cru_clk_set_rate_sclk_vop(rk628, rate); 511 break; 512 case CGU_SCLK_UART: 513 rk628_cru_clk_set_rate_sclk_uart(rk628, rate); 514 break; 515 case CGU_BT1120DEC: 516 rk628_cru_clk_set_rate_bt1120_dec(rk628, rate); 517 break; 518 case CGU_CLK_HDMIRX_AUD: 519 rk628_cru_clk_set_rate_sclk_hdmirx_aud(rk628, rate); 520 break; 521 default: 522 return -EINVAL; 523 } 524 525 return 0; 526 } 527 528 unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id) 529 { 530 unsigned long rate; 531 532 if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION) 533 return 0; 534 535 switch (id) { 536 case CGU_CLK_APLL: 537 case CGU_CLK_CPLL: 538 case CGU_CLK_GPLL: 539 rate = rk628_cru_clk_get_rate_pll(rk628, id); 540 break; 541 case CGU_SCLK_VOP: 542 rate = rk628_cru_clk_get_rate_sclk_vop(rk628); 543 break; 544 case CGU_CLK_IMODET: 545 rate = rk628_cru_clk_get_rate_clk_imodet(rk628); 546 break; 547 case CGU_CLK_HDMIRX_AUD: 548 rate = rk628_cru_clk_get_rate_sclk_hdmirx_aud(rk628); 549 break; 550 case CGU_BT1120DEC: 551 rate = rk628_cru_clk_get_rate_bt1120_dec(rk628); 552 break; 553 default: 554 return 0; 555 } 556 557 return rate; 558 } 559 560 void rk628_cru_init(struct rk628 *rk628) 561 { 562 u32 val = 0; 563 u8 mcu_mode; 564 565 rk628_i2c_read(rk628, GRF_SYSTEM_STATUS0, &val); 566 mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1; 567 if (mcu_mode || rk628->version >= RK628F_VERSION) { 568 rk628_i2c_write(rk628, CRU_MODE_CON00, HIWORD_UPDATE(1, 4, 4)); 569 return; 570 } 571 rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d); 572 mdelay(1); 573 rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004); 574 mdelay(1); 575 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080); 576 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083); 577 rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063); 578 mdelay(1); 579 rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005); 580 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003); 581 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); 582 rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028); 583 mdelay(1); 584 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b); 585 rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063); 586 mdelay(1); 587 rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b); 588 } 589