Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy/rockchip: inno-dsidphy: generalize parameter handling

During review it came to light that exposing the pll clock outside is
not the right approach and struct phy_configure_opts_mipi_dphy exists
just for that reason to transfer parameters to the phy.

So drop the exposed clock and rely on the phy configure options
to bring in the correct rate. That way we can also just drop the
open coded timing struct and default values function.

Fixes: b7535a3bc0ba ("phy/rockchip: Add support for Innosilicon MIPI/LVDS/TTL PHY")
Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Heiko Stuebner and committed by
Kishon Vijay Abraham I
f0684c1a cb18b9a9

+103 -223
+1
drivers/phy/rockchip/Kconfig
··· 39 39 tristate "Rockchip Innosilicon MIPI/LVDS/TTL PHY driver" 40 40 depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF 41 41 select GENERIC_PHY 42 + select GENERIC_PHY_MIPI_DPHY 42 43 help 43 44 Enable this to support the Rockchip MIPI/LVDS/TTL PHY with 44 45 Innosilicon IP block.
+102 -223
drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
··· 16 16 #include <linux/platform_device.h> 17 17 #include <linux/reset.h> 18 18 #include <linux/phy/phy.h> 19 + #include <linux/phy/phy-mipi-dphy.h> 19 20 #include <linux/pm_runtime.h> 20 21 #include <linux/mfd/syscon.h> 21 22 ··· 168 167 #define DSI_PHY_STATUS 0xb0 169 168 #define PHY_LOCK BIT(0) 170 169 171 - struct mipi_dphy_timing { 172 - unsigned int clkmiss; 173 - unsigned int clkpost; 174 - unsigned int clkpre; 175 - unsigned int clkprepare; 176 - unsigned int clksettle; 177 - unsigned int clktermen; 178 - unsigned int clktrail; 179 - unsigned int clkzero; 180 - unsigned int dtermen; 181 - unsigned int eot; 182 - unsigned int hsexit; 183 - unsigned int hsprepare; 184 - unsigned int hszero; 185 - unsigned int hssettle; 186 - unsigned int hsskip; 187 - unsigned int hstrail; 188 - unsigned int init; 189 - unsigned int lpx; 190 - unsigned int taget; 191 - unsigned int tago; 192 - unsigned int tasure; 193 - unsigned int wakeup; 194 - }; 195 - 196 170 struct inno_dsidphy { 197 171 struct device *dev; 198 172 struct clk *ref_clk; ··· 177 201 void __iomem *host_base; 178 202 struct reset_control *rst; 179 203 enum phy_mode mode; 204 + struct phy_configure_opts_mipi_dphy dphy_cfg; 180 205 206 + struct clk *pll_clk; 181 207 struct { 182 208 struct clk_hw hw; 183 209 u8 prediv; ··· 216 238 writel(tmp, inno->phy_base + reg); 217 239 } 218 240 219 - static void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing, 220 - unsigned long period) 241 + static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno, 242 + unsigned long rate) 221 243 { 222 - /* Global Operation Timing Parameters */ 223 - timing->clkmiss = 0; 224 - timing->clkpost = 70000 + 52 * period; 225 - timing->clkpre = 8 * period; 226 - timing->clkprepare = 65000; 227 - timing->clksettle = 95000; 228 - timing->clktermen = 0; 229 - timing->clktrail = 80000; 230 - timing->clkzero = 260000; 231 - timing->dtermen = 0; 232 - timing->eot = 0; 233 - timing->hsexit = 120000; 234 - timing->hsprepare = 65000 + 4 * period; 235 - timing->hszero = 145000 + 6 * period; 236 - timing->hssettle = 85000 + 6 * period; 237 - timing->hsskip = 40000; 238 - timing->hstrail = max(8 * period, 60000 + 4 * period); 239 - timing->init = 100000000; 240 - timing->lpx = 60000; 241 - timing->taget = 5 * timing->lpx; 242 - timing->tago = 4 * timing->lpx; 243 - timing->tasure = 2 * timing->lpx; 244 - timing->wakeup = 1000000000; 244 + unsigned long prate = clk_get_rate(inno->ref_clk); 245 + unsigned long best_freq = 0; 246 + unsigned long fref, fout; 247 + u8 min_prediv, max_prediv; 248 + u8 _prediv, best_prediv = 1; 249 + u16 _fbdiv, best_fbdiv = 1; 250 + u32 min_delta = UINT_MAX; 251 + 252 + /* 253 + * The PLL output frequency can be calculated using a simple formula: 254 + * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2 255 + * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2 256 + */ 257 + fref = prate / 2; 258 + if (rate > 1000000000UL) 259 + fout = 1000000000UL; 260 + else 261 + fout = rate; 262 + 263 + /* 5Mhz < Fref / prediv < 40MHz */ 264 + min_prediv = DIV_ROUND_UP(fref, 40000000); 265 + max_prediv = fref / 5000000; 266 + 267 + for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) { 268 + u64 tmp; 269 + u32 delta; 270 + 271 + tmp = (u64)fout * _prediv; 272 + do_div(tmp, fref); 273 + _fbdiv = tmp; 274 + 275 + /* 276 + * The possible settings of feedback divider are 277 + * 12, 13, 14, 16, ~ 511 278 + */ 279 + if (_fbdiv == 15) 280 + continue; 281 + 282 + if (_fbdiv < 12 || _fbdiv > 511) 283 + continue; 284 + 285 + tmp = (u64)_fbdiv * fref; 286 + do_div(tmp, _prediv); 287 + 288 + delta = abs(fout - tmp); 289 + if (!delta) { 290 + best_prediv = _prediv; 291 + best_fbdiv = _fbdiv; 292 + best_freq = tmp; 293 + break; 294 + } else if (delta < min_delta) { 295 + best_prediv = _prediv; 296 + best_fbdiv = _fbdiv; 297 + best_freq = tmp; 298 + min_delta = delta; 299 + } 300 + } 301 + 302 + if (best_freq) { 303 + inno->pll.prediv = best_prediv; 304 + inno->pll.fbdiv = best_fbdiv; 305 + inno->pll.rate = best_freq; 306 + } 307 + 308 + return best_freq; 245 309 } 246 310 247 311 static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno) 248 312 { 249 - struct mipi_dphy_timing gotp; 313 + struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg; 250 314 const struct { 251 315 unsigned long rate; 252 316 u8 hs_prepare; ··· 308 288 { 800000000, 0x21, 0x1f, 0x09, 0x29}, 309 289 {1000000000, 0x09, 0x20, 0x09, 0x27}, 310 290 }; 311 - u32 t_txbyteclkhs, t_txclkesc, ui; 291 + u32 t_txbyteclkhs, t_txclkesc; 312 292 u32 txbyteclkhs, txclkesc, esc_clk_div; 313 293 u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait; 314 294 u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero; 315 295 unsigned int i; 296 + 297 + inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate); 316 298 317 299 /* Select MIPI mode */ 318 300 phy_update_bits(inno, REGISTER_PART_LVDS, 0x03, ··· 350 328 txclkesc = txbyteclkhs / esc_clk_div; 351 329 t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc); 352 330 353 - ui = div_u64(PSEC_PER_SEC, inno->pll.rate); 354 - 355 - memset(&gotp, 0, sizeof(gotp)); 356 - mipi_dphy_timing_get_default(&gotp, ui); 357 - 358 331 /* 359 332 * The value of counter for HS Ths-exit 360 333 * Ths-exit = Tpin_txbyteclkhs * value 361 334 */ 362 - hs_exit = DIV_ROUND_UP(gotp.hsexit, t_txbyteclkhs); 335 + hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs); 363 336 /* 364 337 * The value of counter for HS Tclk-post 365 338 * Tclk-post = Tpin_txbyteclkhs * value 366 339 */ 367 - clk_post = DIV_ROUND_UP(gotp.clkpost, t_txbyteclkhs); 340 + clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs); 368 341 /* 369 342 * The value of counter for HS Tclk-pre 370 343 * Tclk-pre = Tpin_txbyteclkhs * value 371 344 */ 372 - clk_pre = DIV_ROUND_UP(gotp.clkpre, t_txbyteclkhs); 345 + clk_pre = DIV_ROUND_UP(cfg->clk_pre, t_txbyteclkhs); 373 346 374 347 /* 375 348 * The value of counter for HS Tlpx Time 376 349 * Tlpx = Tpin_txbyteclkhs * (2 + value) 377 350 */ 378 - lpx = DIV_ROUND_UP(gotp.lpx, t_txbyteclkhs); 351 + lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs); 379 352 if (lpx >= 2) 380 353 lpx -= 2; 381 354 ··· 379 362 * Tta-go for turnaround 380 363 * Tta-go = Ttxclkesc * value 381 364 */ 382 - ta_go = DIV_ROUND_UP(gotp.tago, t_txclkesc); 365 + ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc); 383 366 /* 384 367 * The value of counter for HS Tta-sure 385 368 * Tta-sure for turnaround 386 369 * Tta-sure = Ttxclkesc * value 387 370 */ 388 - ta_sure = DIV_ROUND_UP(gotp.tasure, t_txclkesc); 371 + ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc); 389 372 /* 390 373 * The value of counter for HS Tta-wait 391 374 * Tta-wait for turnaround 392 375 * Tta-wait = Ttxclkesc * value 393 376 */ 394 - ta_wait = DIV_ROUND_UP(gotp.taget, t_txclkesc); 377 + ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc); 395 378 396 379 for (i = 0; i < ARRAY_SIZE(timings); i++) 397 380 if (inno->pll.rate <= timings[i].rate) ··· 496 479 struct inno_dsidphy *inno = phy_get_drvdata(phy); 497 480 498 481 clk_prepare_enable(inno->pclk_phy); 482 + clk_prepare_enable(inno->ref_clk); 499 483 pm_runtime_get_sync(inno->dev); 500 484 501 485 /* Bandgap power on */ ··· 542 524 LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN); 543 525 544 526 pm_runtime_put(inno->dev); 527 + clk_disable_unprepare(inno->ref_clk); 545 528 clk_disable_unprepare(inno->pclk_phy); 546 529 547 530 return 0; ··· 565 546 return 0; 566 547 } 567 548 549 + static int inno_dsidphy_configure(struct phy *phy, 550 + union phy_configure_opts *opts) 551 + { 552 + struct inno_dsidphy *inno = phy_get_drvdata(phy); 553 + int ret; 554 + 555 + if (inno->mode != PHY_MODE_MIPI_DPHY) 556 + return -EINVAL; 557 + 558 + ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy); 559 + if (ret) 560 + return ret; 561 + 562 + memcpy(&inno->dphy_cfg, &opts->mipi_dphy, sizeof(inno->dphy_cfg)); 563 + 564 + return 0; 565 + } 566 + 568 567 static const struct phy_ops inno_dsidphy_ops = { 568 + .configure = inno_dsidphy_configure, 569 569 .set_mode = inno_dsidphy_set_mode, 570 570 .power_on = inno_dsidphy_power_on, 571 571 .power_off = inno_dsidphy_power_off, 572 572 .owner = THIS_MODULE, 573 573 }; 574 - 575 - static unsigned long inno_dsidphy_pll_round_rate(struct inno_dsidphy *inno, 576 - unsigned long prate, 577 - unsigned long rate, 578 - u8 *prediv, u16 *fbdiv) 579 - { 580 - unsigned long best_freq = 0; 581 - unsigned long fref, fout; 582 - u8 min_prediv, max_prediv; 583 - u8 _prediv, best_prediv = 1; 584 - u16 _fbdiv, best_fbdiv = 1; 585 - u32 min_delta = UINT_MAX; 586 - 587 - /* 588 - * The PLL output frequency can be calculated using a simple formula: 589 - * PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2 590 - * PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2 591 - */ 592 - fref = prate / 2; 593 - if (rate > 1000000000UL) 594 - fout = 1000000000UL; 595 - else 596 - fout = rate; 597 - 598 - /* 5Mhz < Fref / prediv < 40MHz */ 599 - min_prediv = DIV_ROUND_UP(fref, 40000000); 600 - max_prediv = fref / 5000000; 601 - 602 - for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) { 603 - u64 tmp; 604 - u32 delta; 605 - 606 - tmp = (u64)fout * _prediv; 607 - do_div(tmp, fref); 608 - _fbdiv = tmp; 609 - 610 - /* 611 - * The possible settings of feedback divider are 612 - * 12, 13, 14, 16, ~ 511 613 - */ 614 - if (_fbdiv == 15) 615 - continue; 616 - 617 - if (_fbdiv < 12 || _fbdiv > 511) 618 - continue; 619 - 620 - tmp = (u64)_fbdiv * fref; 621 - do_div(tmp, _prediv); 622 - 623 - delta = abs(fout - tmp); 624 - if (!delta) { 625 - best_prediv = _prediv; 626 - best_fbdiv = _fbdiv; 627 - best_freq = tmp; 628 - break; 629 - } else if (delta < min_delta) { 630 - best_prediv = _prediv; 631 - best_fbdiv = _fbdiv; 632 - best_freq = tmp; 633 - min_delta = delta; 634 - } 635 - } 636 - 637 - if (best_freq) { 638 - *prediv = best_prediv; 639 - *fbdiv = best_fbdiv; 640 - } 641 - 642 - return best_freq; 643 - } 644 - 645 - static long inno_dsidphy_pll_clk_round_rate(struct clk_hw *hw, 646 - unsigned long rate, 647 - unsigned long *prate) 648 - { 649 - struct inno_dsidphy *inno = hw_to_inno(hw); 650 - unsigned long fout; 651 - u16 fbdiv = 1; 652 - u8 prediv = 1; 653 - 654 - fout = inno_dsidphy_pll_round_rate(inno, *prate, rate, 655 - &prediv, &fbdiv); 656 - 657 - return fout; 658 - } 659 - 660 - static int inno_dsidphy_pll_clk_set_rate(struct clk_hw *hw, 661 - unsigned long rate, 662 - unsigned long parent_rate) 663 - { 664 - struct inno_dsidphy *inno = hw_to_inno(hw); 665 - unsigned long fout; 666 - u16 fbdiv = 1; 667 - u8 prediv = 1; 668 - 669 - fout = inno_dsidphy_pll_round_rate(inno, parent_rate, rate, 670 - &prediv, &fbdiv); 671 - 672 - dev_dbg(inno->dev, "fin=%lu, fout=%lu, prediv=%u, fbdiv=%u\n", 673 - parent_rate, fout, prediv, fbdiv); 674 - 675 - inno->pll.prediv = prediv; 676 - inno->pll.fbdiv = fbdiv; 677 - inno->pll.rate = fout; 678 - 679 - return 0; 680 - } 681 - 682 - static unsigned long 683 - inno_dsidphy_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long prate) 684 - { 685 - struct inno_dsidphy *inno = hw_to_inno(hw); 686 - 687 - /* PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2 */ 688 - return (prate / inno->pll.prediv * inno->pll.fbdiv) / 2; 689 - } 690 - 691 - static const struct clk_ops inno_dsidphy_pll_clk_ops = { 692 - .round_rate = inno_dsidphy_pll_clk_round_rate, 693 - .set_rate = inno_dsidphy_pll_clk_set_rate, 694 - .recalc_rate = inno_dsidphy_pll_clk_recalc_rate, 695 - }; 696 - 697 - static int inno_dsidphy_pll_register(struct inno_dsidphy *inno) 698 - { 699 - struct device *dev = inno->dev; 700 - struct clk *clk; 701 - const char *parent_name; 702 - struct clk_init_data init; 703 - int ret; 704 - 705 - parent_name = __clk_get_name(inno->ref_clk); 706 - 707 - init.name = "mipi_dphy_pll"; 708 - ret = of_property_read_string(dev->of_node, "clock-output-names", 709 - &init.name); 710 - if (ret < 0) 711 - dev_dbg(dev, "phy should set clock-output-names property\n"); 712 - 713 - init.ops = &inno_dsidphy_pll_clk_ops; 714 - init.parent_names = &parent_name; 715 - init.num_parents = 1; 716 - init.flags = 0; 717 - 718 - inno->pll.hw.init = &init; 719 - clk = devm_clk_register(dev, &inno->pll.hw); 720 - if (IS_ERR(clk)) { 721 - ret = PTR_ERR(clk); 722 - dev_err(dev, "failed to register PLL: %d\n", ret); 723 - return ret; 724 - } 725 - 726 - return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, 727 - &inno->pll.hw); 728 - } 729 574 730 575 static int inno_dsidphy_probe(struct platform_device *pdev) 731 576 { ··· 646 763 dev_err(dev, "failed to register phy provider: %d\n", ret); 647 764 return ret; 648 765 } 649 - 650 - ret = inno_dsidphy_pll_register(inno); 651 - if (ret) 652 - return ret; 653 766 654 767 pm_runtime_enable(dev); 655 768