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

drm/bridge: cdns: Convert to phy framework

Now that we have everything we need in the phy framework to allow to tune
the phy parameters, let's convert the Cadence DSI bridge to that API
instead of creating a ad-hoc driver for its phy.

Acked-by: Sean Paul <sean@poorly.run>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/8772ad061f07cd91fa48bb05880095b25eccec08.1548085432.git-series.maxime.ripard@bootlin.com

+60 -426
+1
drivers/gpu/drm/bridge/Kconfig
··· 30 30 select DRM_KMS_HELPER 31 31 select DRM_MIPI_DSI 32 32 select DRM_PANEL_BRIDGE 33 + select GENERIC_PHY_MIPI_DPHY 33 34 depends on OF 34 35 help 35 36 Support Cadence DPI to DSI bridge. This is an internal
+59 -426
drivers/gpu/drm/bridge/cdns-dsi.c
··· 23 23 #include <linux/pm_runtime.h> 24 24 #include <linux/reset.h> 25 25 26 + #include <linux/phy/phy.h> 27 + #include <linux/phy/phy-mipi-dphy.h> 28 + 26 29 #define IP_CONF 0x0 27 30 #define SP_HS_FIFO_DEPTH(x) (((x) & GENMASK(30, 26)) >> 26) 28 31 #define SP_LP_FIFO_DEPTH(x) (((x) & GENMASK(25, 21)) >> 21) ··· 424 421 #define DSI_NULL_FRAME_OVERHEAD 6 425 422 #define DSI_EOT_PKT_SIZE 4 426 423 427 - #define REG_WAKEUP_TIME_NS 800 428 - #define DPHY_PLL_RATE_HZ 108000000 429 - 430 - /* DPHY registers */ 431 - #define DPHY_PMA_CMN(reg) (reg) 432 - #define DPHY_PMA_LCLK(reg) (0x100 + (reg)) 433 - #define DPHY_PMA_LDATA(lane, reg) (0x200 + ((lane) * 0x100) + (reg)) 434 - #define DPHY_PMA_RCLK(reg) (0x600 + (reg)) 435 - #define DPHY_PMA_RDATA(lane, reg) (0x700 + ((lane) * 0x100) + (reg)) 436 - #define DPHY_PCS(reg) (0xb00 + (reg)) 437 - 438 - #define DPHY_CMN_SSM DPHY_PMA_CMN(0x20) 439 - #define DPHY_CMN_SSM_EN BIT(0) 440 - #define DPHY_CMN_TX_MODE_EN BIT(9) 441 - 442 - #define DPHY_CMN_PWM DPHY_PMA_CMN(0x40) 443 - #define DPHY_CMN_PWM_DIV(x) ((x) << 20) 444 - #define DPHY_CMN_PWM_LOW(x) ((x) << 10) 445 - #define DPHY_CMN_PWM_HIGH(x) (x) 446 - 447 - #define DPHY_CMN_FBDIV DPHY_PMA_CMN(0x4c) 448 - #define DPHY_CMN_FBDIV_VAL(low, high) (((high) << 11) | ((low) << 22)) 449 - #define DPHY_CMN_FBDIV_FROM_REG (BIT(10) | BIT(21)) 450 - 451 - #define DPHY_CMN_OPIPDIV DPHY_PMA_CMN(0x50) 452 - #define DPHY_CMN_IPDIV_FROM_REG BIT(0) 453 - #define DPHY_CMN_IPDIV(x) ((x) << 1) 454 - #define DPHY_CMN_OPDIV_FROM_REG BIT(6) 455 - #define DPHY_CMN_OPDIV(x) ((x) << 7) 456 - 457 - #define DPHY_PSM_CFG DPHY_PCS(0x4) 458 - #define DPHY_PSM_CFG_FROM_REG BIT(0) 459 - #define DPHY_PSM_CLK_DIV(x) ((x) << 1) 460 - 461 424 struct cdns_dsi_output { 462 425 struct mipi_dsi_device *dev; 463 426 struct drm_panel *panel; 464 427 struct drm_bridge *bridge; 428 + union phy_configure_opts phy_opts; 465 429 }; 466 430 467 431 enum cdns_dsi_input_id { ··· 437 467 CDNS_DSC_INPUT, 438 468 }; 439 469 440 - struct cdns_dphy_cfg { 441 - u8 pll_ipdiv; 442 - u8 pll_opdiv; 443 - u16 pll_fbdiv; 444 - unsigned long lane_bps; 445 - unsigned int nlanes; 446 - }; 447 - 448 470 struct cdns_dsi_cfg { 449 471 unsigned int hfp; 450 472 unsigned int hsa; 451 473 unsigned int hbp; 452 474 unsigned int hact; 453 475 unsigned int htotal; 454 - }; 455 - 456 - struct cdns_dphy; 457 - 458 - enum cdns_dphy_clk_lane_cfg { 459 - DPHY_CLK_CFG_LEFT_DRIVES_ALL = 0, 460 - DPHY_CLK_CFG_LEFT_DRIVES_RIGHT = 1, 461 - DPHY_CLK_CFG_LEFT_DRIVES_LEFT = 2, 462 - DPHY_CLK_CFG_RIGHT_DRIVES_ALL = 3, 463 - }; 464 - 465 - struct cdns_dphy_ops { 466 - int (*probe)(struct cdns_dphy *dphy); 467 - void (*remove)(struct cdns_dphy *dphy); 468 - void (*set_psm_div)(struct cdns_dphy *dphy, u8 div); 469 - void (*set_clk_lane_cfg)(struct cdns_dphy *dphy, 470 - enum cdns_dphy_clk_lane_cfg cfg); 471 - void (*set_pll_cfg)(struct cdns_dphy *dphy, 472 - const struct cdns_dphy_cfg *cfg); 473 - unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy); 474 - }; 475 - 476 - struct cdns_dphy { 477 - struct cdns_dphy_cfg cfg; 478 - void __iomem *regs; 479 - struct clk *psm_clk; 480 - struct clk *pll_ref_clk; 481 - const struct cdns_dphy_ops *ops; 482 476 }; 483 477 484 478 struct cdns_dsi_input { ··· 462 528 struct reset_control *dsi_p_rst; 463 529 struct clk *dsi_sys_clk; 464 530 bool link_initialized; 465 - struct cdns_dphy *dphy; 531 + struct phy *dphy; 466 532 }; 467 533 468 534 static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input) ··· 488 554 return mode->hsync_start - mode->hdisplay; 489 555 490 556 return mode->crtc_hsync_start - mode->crtc_hdisplay; 491 - } 492 - 493 - static int cdns_dsi_get_dphy_pll_cfg(struct cdns_dphy *dphy, 494 - struct cdns_dphy_cfg *cfg, 495 - unsigned int dpi_htotal, 496 - unsigned int dpi_bpp, 497 - unsigned int dpi_hz, 498 - unsigned int dsi_htotal, 499 - unsigned int dsi_nlanes, 500 - unsigned int *dsi_hfp_ext) 501 - { 502 - u64 dlane_bps, dlane_bps_max, fbdiv, fbdiv_max, adj_dsi_htotal; 503 - unsigned long pll_ref_hz = clk_get_rate(dphy->pll_ref_clk); 504 - 505 - memset(cfg, 0, sizeof(*cfg)); 506 - 507 - cfg->nlanes = dsi_nlanes; 508 - 509 - if (pll_ref_hz < 9600000 || pll_ref_hz >= 150000000) 510 - return -EINVAL; 511 - else if (pll_ref_hz < 19200000) 512 - cfg->pll_ipdiv = 1; 513 - else if (pll_ref_hz < 38400000) 514 - cfg->pll_ipdiv = 2; 515 - else if (pll_ref_hz < 76800000) 516 - cfg->pll_ipdiv = 4; 517 - else 518 - cfg->pll_ipdiv = 8; 519 - 520 - /* 521 - * Make sure DSI htotal is aligned on a lane boundary when calculating 522 - * the expected data rate. This is done by extending HFP in case of 523 - * misalignment. 524 - */ 525 - adj_dsi_htotal = dsi_htotal; 526 - if (dsi_htotal % dsi_nlanes) 527 - adj_dsi_htotal += dsi_nlanes - (dsi_htotal % dsi_nlanes); 528 - 529 - dlane_bps = (u64)dpi_hz * adj_dsi_htotal; 530 - 531 - /* data rate in bytes/sec is not an integer, refuse the mode. */ 532 - if (do_div(dlane_bps, dsi_nlanes * dpi_htotal)) 533 - return -EINVAL; 534 - 535 - /* data rate was in bytes/sec, convert to bits/sec. */ 536 - dlane_bps *= 8; 537 - 538 - if (dlane_bps > 2500000000UL || dlane_bps < 160000000UL) 539 - return -EINVAL; 540 - else if (dlane_bps >= 1250000000) 541 - cfg->pll_opdiv = 1; 542 - else if (dlane_bps >= 630000000) 543 - cfg->pll_opdiv = 2; 544 - else if (dlane_bps >= 320000000) 545 - cfg->pll_opdiv = 4; 546 - else if (dlane_bps >= 160000000) 547 - cfg->pll_opdiv = 8; 548 - 549 - /* 550 - * Allow a deviation of 0.2% on the per-lane data rate to try to 551 - * recover a potential mismatch between DPI and PPI clks. 552 - */ 553 - dlane_bps_max = dlane_bps + DIV_ROUND_DOWN_ULL(dlane_bps, 500); 554 - fbdiv_max = DIV_ROUND_DOWN_ULL(dlane_bps_max * 2 * 555 - cfg->pll_opdiv * cfg->pll_ipdiv, 556 - pll_ref_hz); 557 - fbdiv = DIV_ROUND_UP_ULL(dlane_bps * 2 * cfg->pll_opdiv * 558 - cfg->pll_ipdiv, 559 - pll_ref_hz); 560 - 561 - /* 562 - * Iterate over all acceptable fbdiv and try to find an adjusted DSI 563 - * htotal length providing an exact match. 564 - * 565 - * Note that we could do something even trickier by relying on the fact 566 - * that a new line is not necessarily aligned on a lane boundary, so, 567 - * by making adj_dsi_htotal non aligned on a dsi_lanes we can improve a 568 - * bit the precision. With this, the step would be 569 - * 570 - * pll_ref_hz / (2 * opdiv * ipdiv * nlanes) 571 - * 572 - * instead of 573 - * 574 - * pll_ref_hz / (2 * opdiv * ipdiv) 575 - * 576 - * The drawback of this approach is that we would need to make sure the 577 - * number or lines is a multiple of the realignment periodicity which is 578 - * a function of the number of lanes and the original misalignment. For 579 - * example, for NLANES = 4 and HTOTAL % NLANES = 3, it takes 4 lines 580 - * to realign on a lane: 581 - * LINE 0: expected number of bytes, starts emitting first byte of 582 - * LINE 1 on LANE 3 583 - * LINE 1: expected number of bytes, starts emitting first 2 bytes of 584 - * LINE 2 on LANES 2 and 3 585 - * LINE 2: expected number of bytes, starts emitting first 3 bytes of 586 - * of LINE 3 on LANES 1, 2 and 3 587 - * LINE 3: one byte less, now things are realigned on LANE 0 for LINE 4 588 - * 589 - * I figured this extra complexity was not worth the benefit, but if 590 - * someone really has unfixable mismatch, that would be something to 591 - * investigate. 592 - */ 593 - for (; fbdiv <= fbdiv_max; fbdiv++) { 594 - u32 rem; 595 - 596 - adj_dsi_htotal = (u64)fbdiv * pll_ref_hz * dsi_nlanes * 597 - dpi_htotal; 598 - 599 - /* 600 - * Do the division in 2 steps to avoid an overflow on the 601 - * divider. 602 - */ 603 - rem = do_div(adj_dsi_htotal, dpi_hz); 604 - if (rem) 605 - continue; 606 - 607 - rem = do_div(adj_dsi_htotal, 608 - cfg->pll_opdiv * cfg->pll_ipdiv * 2 * 8); 609 - if (rem) 610 - continue; 611 - 612 - cfg->pll_fbdiv = fbdiv; 613 - *dsi_hfp_ext = adj_dsi_htotal - dsi_htotal; 614 - break; 615 - } 616 - 617 - /* No match, let's just reject the display mode. */ 618 - if (!cfg->pll_fbdiv) 619 - return -EINVAL; 620 - 621 - dlane_bps = DIV_ROUND_DOWN_ULL((u64)dpi_hz * adj_dsi_htotal * 8, 622 - dsi_nlanes * dpi_htotal); 623 - cfg->lane_bps = dlane_bps; 624 - 625 - return 0; 626 - } 627 - 628 - static int cdns_dphy_setup_psm(struct cdns_dphy *dphy) 629 - { 630 - unsigned long psm_clk_hz = clk_get_rate(dphy->psm_clk); 631 - unsigned long psm_div; 632 - 633 - if (!psm_clk_hz || psm_clk_hz > 100000000) 634 - return -EINVAL; 635 - 636 - psm_div = DIV_ROUND_CLOSEST(psm_clk_hz, 1000000); 637 - if (dphy->ops->set_psm_div) 638 - dphy->ops->set_psm_div(dphy, psm_div); 639 - 640 - return 0; 641 - } 642 - 643 - static void cdns_dphy_set_clk_lane_cfg(struct cdns_dphy *dphy, 644 - enum cdns_dphy_clk_lane_cfg cfg) 645 - { 646 - if (dphy->ops->set_clk_lane_cfg) 647 - dphy->ops->set_clk_lane_cfg(dphy, cfg); 648 - } 649 - 650 - static void cdns_dphy_set_pll_cfg(struct cdns_dphy *dphy, 651 - const struct cdns_dphy_cfg *cfg) 652 - { 653 - if (dphy->ops->set_pll_cfg) 654 - dphy->ops->set_pll_cfg(dphy, cfg); 655 - } 656 - 657 - static unsigned long cdns_dphy_get_wakeup_time_ns(struct cdns_dphy *dphy) 658 - { 659 - return dphy->ops->get_wakeup_time_ns(dphy); 660 557 } 661 558 662 559 static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing, ··· 551 786 return 0; 552 787 } 553 788 554 - static int cdns_dphy_validate(struct cdns_dsi *dsi, 789 + static int cdns_dsi_adjust_phy_config(struct cdns_dsi *dsi, 555 790 struct cdns_dsi_cfg *dsi_cfg, 556 - struct cdns_dphy_cfg *dphy_cfg, 791 + struct phy_configure_opts_mipi_dphy *phy_cfg, 557 792 const struct drm_display_mode *mode, 558 793 bool mode_valid_check) 559 794 { 560 795 struct cdns_dsi_output *output = &dsi->output; 796 + unsigned long long dlane_bps; 797 + unsigned long adj_dsi_htotal; 561 798 unsigned long dsi_htotal; 562 - unsigned int dsi_hfp_ext = 0; 563 - 564 - int ret; 799 + unsigned long dpi_htotal; 800 + unsigned long dpi_hz; 801 + unsigned int dsi_hfp_ext; 802 + unsigned int lanes = output->dev->lanes; 565 803 566 804 dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD; 567 805 if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) ··· 573 805 dsi_htotal += dsi_cfg->hact; 574 806 dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD; 575 807 576 - if (mode_valid_check) 577 - ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, 578 - mode->htotal, 579 - mipi_dsi_pixel_format_to_bpp(output->dev->format), 580 - mode->clock * 1000, 581 - dsi_htotal, 582 - output->dev->lanes, 583 - &dsi_hfp_ext); 584 - else 585 - ret = cdns_dsi_get_dphy_pll_cfg(dsi->dphy, dphy_cfg, 586 - mode->crtc_htotal, 587 - mipi_dsi_pixel_format_to_bpp(output->dev->format), 588 - mode->crtc_clock * 1000, 589 - dsi_htotal, 590 - output->dev->lanes, 591 - &dsi_hfp_ext); 592 - if (ret) 593 - return ret; 808 + /* 809 + * Make sure DSI htotal is aligned on a lane boundary when calculating 810 + * the expected data rate. This is done by extending HFP in case of 811 + * misalignment. 812 + */ 813 + adj_dsi_htotal = dsi_htotal; 814 + if (dsi_htotal % lanes) 815 + adj_dsi_htotal += lanes - (dsi_htotal % lanes); 594 816 817 + dpi_hz = (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000; 818 + dlane_bps = (unsigned long long)dpi_hz * adj_dsi_htotal; 819 + 820 + /* data rate in bytes/sec is not an integer, refuse the mode. */ 821 + dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal; 822 + if (do_div(dlane_bps, lanes * dpi_htotal)) 823 + return -EINVAL; 824 + 825 + /* data rate was in bytes/sec, convert to bits/sec. */ 826 + phy_cfg->hs_clk_rate = dlane_bps * 8; 827 + 828 + dsi_hfp_ext = adj_dsi_htotal - dsi_htotal; 595 829 dsi_cfg->hfp += dsi_hfp_ext; 596 830 dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext; 597 831 ··· 603 833 static int cdns_dsi_check_conf(struct cdns_dsi *dsi, 604 834 const struct drm_display_mode *mode, 605 835 struct cdns_dsi_cfg *dsi_cfg, 606 - struct cdns_dphy_cfg *dphy_cfg, 607 836 bool mode_valid_check) 608 837 { 609 838 struct cdns_dsi_output *output = &dsi->output; 839 + struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy; 610 840 unsigned long dsi_hss_hsa_hse_hbp; 611 841 unsigned int nlanes = output->dev->lanes; 612 842 int ret; ··· 615 845 if (ret) 616 846 return ret; 617 847 618 - ret = cdns_dphy_validate(dsi, dsi_cfg, dphy_cfg, mode, mode_valid_check); 848 + phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000, 849 + mipi_dsi_pixel_format_to_bpp(output->dev->format), 850 + nlanes, phy_cfg); 851 + 852 + ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check); 853 + if (ret) 854 + return ret; 855 + 856 + ret = phy_validate(dsi->dphy, PHY_MODE_MIPI_DPHY, 0, &output->phy_opts); 619 857 if (ret) 620 858 return ret; 621 859 ··· 636 858 * is empty before we start a receiving a new line on the DPI 637 859 * interface. 638 860 */ 639 - if ((u64)dphy_cfg->lane_bps * 861 + if ((u64)phy_cfg->hs_clk_rate * 640 862 mode_to_dpi_hfp(mode, mode_valid_check) * nlanes < 641 863 (u64)dsi_hss_hsa_hse_hbp * 642 864 (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000) ··· 667 889 struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge); 668 890 struct cdns_dsi *dsi = input_to_dsi(input); 669 891 struct cdns_dsi_output *output = &dsi->output; 670 - struct cdns_dphy_cfg dphy_cfg; 671 892 struct cdns_dsi_cfg dsi_cfg; 672 893 int bpp, ret; 673 894 ··· 686 909 if ((mode->hdisplay * bpp) % 32) 687 910 return MODE_H_ILLEGAL; 688 911 689 - ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, true); 912 + ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, true); 690 913 if (ret) 691 914 return MODE_BAD; 692 915 ··· 709 932 pm_runtime_put(dsi->base.dev); 710 933 } 711 934 712 - static void cdns_dsi_hs_init(struct cdns_dsi *dsi, 713 - const struct cdns_dphy_cfg *dphy_cfg) 935 + static void cdns_dsi_hs_init(struct cdns_dsi *dsi) 714 936 { 937 + struct cdns_dsi_output *output = &dsi->output; 715 938 u32 status; 716 939 717 940 /* ··· 722 945 DPHY_CMN_PDN | DPHY_PLL_PDN, 723 946 dsi->regs + MCTL_DPHY_CFG0); 724 947 725 - /* 726 - * Configure the internal PSM clk divider so that the DPHY has a 727 - * 1MHz clk (or something close). 728 - */ 729 - WARN_ON_ONCE(cdns_dphy_setup_psm(dsi->dphy)); 730 - 731 - /* 732 - * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes 733 - * and 8 data lanes, each clk lane can be attache different set of 734 - * data lanes. The 2 groups are named 'left' and 'right', so here we 735 - * just say that we want the 'left' clk lane to drive the 'left' data 736 - * lanes. 737 - */ 738 - cdns_dphy_set_clk_lane_cfg(dsi->dphy, DPHY_CLK_CFG_LEFT_DRIVES_LEFT); 739 - 740 - /* 741 - * Configure the DPHY PLL that will be used to generate the TX byte 742 - * clk. 743 - */ 744 - cdns_dphy_set_pll_cfg(dsi->dphy, dphy_cfg); 745 - 746 - /* Start TX state machine. */ 747 - writel(DPHY_CMN_SSM_EN | DPHY_CMN_TX_MODE_EN, 748 - dsi->dphy->regs + DPHY_CMN_SSM); 948 + phy_init(dsi->dphy); 949 + phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY); 950 + phy_configure(dsi->dphy, &output->phy_opts); 951 + phy_power_on(dsi->dphy); 749 952 750 953 /* Activate the PLL and wait until it's locked. */ 751 954 writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR); ··· 735 978 status & PLL_LOCKED, 100, 100)); 736 979 /* De-assert data and clock reset lines. */ 737 980 writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN | 738 - DPHY_D_RSTB(dphy_cfg->nlanes) | DPHY_C_RSTB, 981 + DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB, 739 982 dsi->regs + MCTL_DPHY_CFG0); 740 983 } 741 984 ··· 781 1024 struct cdns_dsi *dsi = input_to_dsi(input); 782 1025 struct cdns_dsi_output *output = &dsi->output; 783 1026 struct drm_display_mode *mode; 784 - struct cdns_dphy_cfg dphy_cfg; 1027 + struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy; 785 1028 unsigned long tx_byte_period; 786 1029 struct cdns_dsi_cfg dsi_cfg; 787 1030 u32 tmp, reg_wakeup, div; ··· 794 1037 bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format); 795 1038 nlanes = output->dev->lanes; 796 1039 797 - WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, &dphy_cfg, false)); 1040 + WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false)); 798 1041 799 - cdns_dsi_hs_init(dsi, &dphy_cfg); 1042 + cdns_dsi_hs_init(dsi); 800 1043 cdns_dsi_init_link(dsi); 801 1044 802 1045 writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa), ··· 832 1075 tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes); 833 1076 834 1077 tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8, 835 - dphy_cfg.lane_bps); 836 - reg_wakeup = cdns_dphy_get_wakeup_time_ns(dsi->dphy) / 837 - tx_byte_period; 1078 + phy_cfg->hs_clk_rate); 1079 + reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period; 838 1080 writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp), 839 1081 dsi->regs + VID_DPHY_TIME); 840 1082 ··· 1147 1391 reset_control_deassert(dsi->dsi_p_rst); 1148 1392 clk_prepare_enable(dsi->dsi_p_clk); 1149 1393 clk_prepare_enable(dsi->dsi_sys_clk); 1150 - clk_prepare_enable(dsi->dphy->psm_clk); 1151 - clk_prepare_enable(dsi->dphy->pll_ref_clk); 1152 1394 1153 1395 return 0; 1154 1396 } ··· 1155 1401 { 1156 1402 struct cdns_dsi *dsi = dev_get_drvdata(dev); 1157 1403 1158 - clk_disable_unprepare(dsi->dphy->pll_ref_clk); 1159 - clk_disable_unprepare(dsi->dphy->psm_clk); 1160 1404 clk_disable_unprepare(dsi->dsi_sys_clk); 1161 1405 clk_disable_unprepare(dsi->dsi_p_clk); 1162 1406 reset_control_assert(dsi->dsi_p_rst); ··· 1164 1412 1165 1413 static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume, 1166 1414 NULL); 1167 - 1168 - static unsigned long cdns_dphy_ref_get_wakeup_time_ns(struct cdns_dphy *dphy) 1169 - { 1170 - /* Default wakeup time is 800 ns (in a simulated environment). */ 1171 - return 800; 1172 - } 1173 - 1174 - static void cdns_dphy_ref_set_pll_cfg(struct cdns_dphy *dphy, 1175 - const struct cdns_dphy_cfg *cfg) 1176 - { 1177 - u32 fbdiv_low, fbdiv_high; 1178 - 1179 - fbdiv_low = (cfg->pll_fbdiv / 4) - 2; 1180 - fbdiv_high = cfg->pll_fbdiv - fbdiv_low - 2; 1181 - 1182 - writel(DPHY_CMN_IPDIV_FROM_REG | DPHY_CMN_OPDIV_FROM_REG | 1183 - DPHY_CMN_IPDIV(cfg->pll_ipdiv) | 1184 - DPHY_CMN_OPDIV(cfg->pll_opdiv), 1185 - dphy->regs + DPHY_CMN_OPIPDIV); 1186 - writel(DPHY_CMN_FBDIV_FROM_REG | 1187 - DPHY_CMN_FBDIV_VAL(fbdiv_low, fbdiv_high), 1188 - dphy->regs + DPHY_CMN_FBDIV); 1189 - writel(DPHY_CMN_PWM_HIGH(6) | DPHY_CMN_PWM_LOW(0x101) | 1190 - DPHY_CMN_PWM_DIV(0x8), 1191 - dphy->regs + DPHY_CMN_PWM); 1192 - } 1193 - 1194 - static void cdns_dphy_ref_set_psm_div(struct cdns_dphy *dphy, u8 div) 1195 - { 1196 - writel(DPHY_PSM_CFG_FROM_REG | DPHY_PSM_CLK_DIV(div), 1197 - dphy->regs + DPHY_PSM_CFG); 1198 - } 1199 - 1200 - /* 1201 - * This is the reference implementation of DPHY hooks. Specific integration of 1202 - * this IP may have to re-implement some of them depending on how they decided 1203 - * to wire things in the SoC. 1204 - */ 1205 - static const struct cdns_dphy_ops ref_dphy_ops = { 1206 - .get_wakeup_time_ns = cdns_dphy_ref_get_wakeup_time_ns, 1207 - .set_pll_cfg = cdns_dphy_ref_set_pll_cfg, 1208 - .set_psm_div = cdns_dphy_ref_set_psm_div, 1209 - }; 1210 - 1211 - static const struct of_device_id cdns_dphy_of_match[] = { 1212 - { .compatible = "cdns,dphy", .data = &ref_dphy_ops }, 1213 - { /* sentinel */ }, 1214 - }; 1215 - 1216 - static struct cdns_dphy *cdns_dphy_probe(struct platform_device *pdev) 1217 - { 1218 - const struct of_device_id *match; 1219 - struct cdns_dphy *dphy; 1220 - struct of_phandle_args args; 1221 - struct resource res; 1222 - int ret; 1223 - 1224 - ret = of_parse_phandle_with_args(pdev->dev.of_node, "phys", 1225 - "#phy-cells", 0, &args); 1226 - if (ret) 1227 - return ERR_PTR(-ENOENT); 1228 - 1229 - match = of_match_node(cdns_dphy_of_match, args.np); 1230 - if (!match || !match->data) 1231 - return ERR_PTR(-EINVAL); 1232 - 1233 - dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL); 1234 - if (!dphy) 1235 - return ERR_PTR(-ENOMEM); 1236 - 1237 - dphy->ops = match->data; 1238 - 1239 - ret = of_address_to_resource(args.np, 0, &res); 1240 - if (ret) 1241 - return ERR_PTR(ret); 1242 - 1243 - dphy->regs = devm_ioremap_resource(&pdev->dev, &res); 1244 - if (IS_ERR(dphy->regs)) 1245 - return ERR_CAST(dphy->regs); 1246 - 1247 - dphy->psm_clk = of_clk_get_by_name(args.np, "psm"); 1248 - if (IS_ERR(dphy->psm_clk)) 1249 - return ERR_CAST(dphy->psm_clk); 1250 - 1251 - dphy->pll_ref_clk = of_clk_get_by_name(args.np, "pll_ref"); 1252 - if (IS_ERR(dphy->pll_ref_clk)) { 1253 - ret = PTR_ERR(dphy->pll_ref_clk); 1254 - goto err_put_psm_clk; 1255 - } 1256 - 1257 - if (dphy->ops->probe) { 1258 - ret = dphy->ops->probe(dphy); 1259 - if (ret) 1260 - goto err_put_pll_ref_clk; 1261 - } 1262 - 1263 - return dphy; 1264 - 1265 - err_put_pll_ref_clk: 1266 - clk_put(dphy->pll_ref_clk); 1267 - 1268 - err_put_psm_clk: 1269 - clk_put(dphy->psm_clk); 1270 - 1271 - return ERR_PTR(ret); 1272 - } 1273 - 1274 - static void cdns_dphy_remove(struct cdns_dphy *dphy) 1275 - { 1276 - if (dphy->ops->remove) 1277 - dphy->ops->remove(dphy); 1278 - 1279 - clk_put(dphy->pll_ref_clk); 1280 - clk_put(dphy->psm_clk); 1281 - } 1282 1415 1283 1416 static int cdns_dsi_drm_probe(struct platform_device *pdev) 1284 1417 { ··· 1203 1566 if (irq < 0) 1204 1567 return irq; 1205 1568 1206 - dsi->dphy = cdns_dphy_probe(pdev); 1569 + dsi->dphy = devm_phy_get(&pdev->dev, "dphy"); 1207 1570 if (IS_ERR(dsi->dphy)) 1208 1571 return PTR_ERR(dsi->dphy); 1209 1572 1210 1573 ret = clk_prepare_enable(dsi->dsi_p_clk); 1211 1574 if (ret) 1212 - goto err_remove_dphy; 1575 + return ret; 1213 1576 1214 1577 val = readl(dsi->regs + ID_REG); 1215 1578 if (REV_VENDOR_ID(val) != 0xcad) { ··· 1267 1630 err_disable_pclk: 1268 1631 clk_disable_unprepare(dsi->dsi_p_clk); 1269 1632 1270 - err_remove_dphy: 1271 - cdns_dphy_remove(dsi->dphy); 1272 - 1273 1633 return ret; 1274 1634 } 1275 1635 ··· 1276 1642 1277 1643 mipi_dsi_host_unregister(&dsi->base); 1278 1644 pm_runtime_disable(&pdev->dev); 1279 - cdns_dphy_remove(dsi->dphy); 1280 1645 1281 1646 return 0; 1282 1647 }