Merge tag 'drm-misc-next-fixes-2021-09-09' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / dsi / phy / dsi_phy_7nm.c
index 7c23d4c..cb297b0 100644 (file)
@@ -83,7 +83,7 @@ struct dsi_pll_7nm {
 #define to_pll_7nm(x)  container_of(x, struct dsi_pll_7nm, clk_hw)
 
 /*
- * Global list of private DSI PLL struct pointers. We need this for Dual DSI
+ * Global list of private DSI PLL struct pointers. We need this for bonded DSI
  * mode, where the master PLL's clk_ops needs access the slave's private data
  */
 static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX];
@@ -256,7 +256,7 @@ static void dsi_pll_commit(struct dsi_pll_7nm *pll, struct dsi_pll_config *confi
                  (config->frac_div_start & 0x30000) >> 16);
        dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40);
        dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */
+       dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, pll->phy->cphy_mode ? 0x00 : 0x10);
        dsi_phy_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, config->pll_clock_inverters);
 }
 
@@ -642,7 +642,8 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
 
        /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
        hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
-                                         CLK_SET_RATE_PARENT, 1, 8);
+                                         CLK_SET_RATE_PARENT, 1,
+                                         pll_7nm->phy->cphy_mode ? 7 : 8);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail;
@@ -663,32 +664,47 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide
        snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
        snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
 
-       hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent,
-                                         0, 1, 4);
+       if (pll_7nm->phy->cphy_mode)
+               hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 2, 7);
+       else
+               hw = devm_clk_hw_register_fixed_factor(dev, clk_name, parent, 0, 1, 4);
        if (IS_ERR(hw)) {
                ret = PTR_ERR(hw);
                goto fail;
        }
 
-       snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
-       snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
-       snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
-       snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
-       snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
-
-       hw = devm_clk_hw_register_mux(dev, clk_name,
-                                ((const char *[]){
-                                parent, parent2, parent3, parent4
-                                }), 4, 0, pll_7nm->phy->base +
-                                REG_DSI_7nm_PHY_CMN_CLK_CFG1,
-                                0, 2, 0, NULL);
-       if (IS_ERR(hw)) {
-               ret = PTR_ERR(hw);
-               goto fail;
+       /* in CPHY mode, pclk_mux will always have post_out_div as parent
+        * don't register a pclk_mux clock and just use post_out_div instead
+        */
+       if (pll_7nm->phy->cphy_mode) {
+               u32 data;
+
+               data = dsi_phy_read(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1);
+               dsi_phy_write(pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data | 3);
+
+               snprintf(parent, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
+       } else {
+               snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
+               snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->phy->id);
+               snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->phy->id);
+               snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->phy->id);
+               snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->phy->id);
+
+               hw = devm_clk_hw_register_mux(dev, clk_name,
+                                       ((const char *[]){
+                                       parent, parent2, parent3, parent4
+                                       }), 4, 0, pll_7nm->phy->base +
+                                       REG_DSI_7nm_PHY_CMN_CLK_CFG1,
+                                       0, 2, 0, NULL);
+               if (IS_ERR(hw)) {
+                       ret = PTR_ERR(hw);
+                       goto fail;
+               }
+
+               snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
        }
 
        snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->phy->id);
-       snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->phy->id);
 
        /* PIX CLK DIV : DIV_CTRL_7_4*/
        hw = devm_clk_hw_register_divider(dev, clk_name, parent,
@@ -813,15 +829,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        struct msm_dsi_dphy_timing *timing = &phy->timing;
        void __iomem *base = phy->base;
        bool less_than_1500_mhz;
-       u32 vreg_ctrl_0, glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
+       u32 vreg_ctrl_0, vreg_ctrl_1, lane_ctrl0;
+       u32 glbl_pemph_ctrl_0;
+       u32 glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0;
        u32 glbl_rescode_top_ctrl, glbl_rescode_bot_ctrl;
        u32 data;
 
        DBG("");
 
-       if (msm_dsi_dphy_timing_calc_v4(timing, clk_req)) {
+       if (phy->cphy_mode)
+               ret = msm_dsi_cphy_timing_calc_v4(timing, clk_req);
+       else
+               ret = msm_dsi_dphy_timing_calc_v4(timing, clk_req);
+       if (ret) {
                DRM_DEV_ERROR(&phy->pdev->dev,
-                       "%s: D-PHY timing calculation failed\n", __func__);
+                       "%s: PHY timing calculation failed\n", __func__);
                return -EINVAL;
        }
 
@@ -842,6 +864,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        /* Alter PHY configurations if data rate less than 1.5GHZ*/
        less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000);
 
+       /* For C-PHY, no low power settings for lower clk rate */
+       if (phy->cphy_mode)
+               less_than_1500_mhz = false;
+
        if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_1) {
                vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
                glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d :  0x00;
@@ -856,6 +882,17 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
                glbl_rescode_bot_ctrl = 0x3c;
        }
 
+       if (phy->cphy_mode) {
+               vreg_ctrl_0 = 0x51;
+               vreg_ctrl_1 = 0x55;
+               glbl_pemph_ctrl_0 = 0x11;
+               lane_ctrl0 = 0x17;
+       } else {
+               vreg_ctrl_1 = 0x5c;
+               glbl_pemph_ctrl_0 = 0x00;
+               lane_ctrl0 = 0x1f;
+       }
+
        /* de-assert digital and pll power down */
        data = BIT(6) | BIT(5);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data);
@@ -876,15 +913,22 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG0, 0x21);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG1, 0x84);
 
+       if (phy->cphy_mode)
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_CTRL, BIT(6));
+
        /* Enable LDO */
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0, vreg_ctrl_0);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, 0x5c);
+       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, vreg_ctrl_1);
+
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x00);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL,
                      glbl_str_swi_cal_sel_ctrl);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0,
                      glbl_hstx_str_ctrl_0);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0, 0x00);
+       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0,
+                     glbl_pemph_ctrl_0);
+       if (phy->cphy_mode)
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_1, 0x01);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL,
                      glbl_rescode_top_ctrl);
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL,
@@ -894,10 +938,11 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        /* Remove power down from all blocks */
        dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x7f);
 
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0x1f);
+       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, lane_ctrl0);
 
        /* Select full-rate mode */
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
+       if (!phy->cphy_mode)
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40);
 
        ret = dsi_7nm_set_usecase(phy);
        if (ret) {
@@ -907,22 +952,36 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        }
 
        /* DSI PHY timings */
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
-                     timing->shared_timings.clk_pre);
-       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
-                     timing->shared_timings.clk_post);
+       if (phy->cphy_mode) {
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5,
+                       timing->shared_timings.clk_pre);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->clk_prepare);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7,
+                       timing->shared_timings.clk_post);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
+       } else {
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12,
+                       timing->shared_timings.clk_pre);
+               dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13,
+                       timing->shared_timings.clk_post);
+       }
 
        /* DSI lane settings */
        dsi_phy_hw_v4_0_lane_settings(phy);
@@ -932,6 +991,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
        return 0;
 }
 
+static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
+{
+       void __iomem *base = phy->base;
+       u32 data;
+
+       data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
+       if (enable)
+               data |= BIT(5) | BIT(6);
+       else
+               data &= ~(BIT(5) | BIT(6));
+       dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1, data);
+
+       return enable;
+}
+
 static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
 {
        void __iomem *base = phy->base;
@@ -972,6 +1046,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = {
                .pll_init = dsi_pll_7nm_init,
                .save_pll_state = dsi_7nm_pll_save_state,
                .restore_pll_state = dsi_7nm_pll_restore_state,
+               .set_continuous_clock = dsi_7nm_set_continuous_clock,
        },
        .min_pll_rate = 600000000UL,
 #ifdef CONFIG_64BIT
@@ -998,9 +1073,36 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = {
                .pll_init = dsi_pll_7nm_init,
                .save_pll_state = dsi_7nm_pll_save_state,
                .restore_pll_state = dsi_7nm_pll_restore_state,
+               .set_continuous_clock = dsi_7nm_set_continuous_clock,
        },
        .min_pll_rate = 1000000000UL,
        .max_pll_rate = 3500000000UL,
        .io_start = { 0xae94400, 0xae96400 },
        .num_dsi_phy = 2,
 };
+
+const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs = {
+       .has_phy_lane = true,
+       .reg_cfg = {
+               .num = 1,
+               .regs = {
+                       {"vdds", 37550, 0},
+               },
+       },
+       .ops = {
+               .enable = dsi_7nm_phy_enable,
+               .disable = dsi_7nm_phy_disable,
+               .pll_init = dsi_pll_7nm_init,
+               .save_pll_state = dsi_7nm_pll_save_state,
+               .restore_pll_state = dsi_7nm_pll_restore_state,
+       },
+       .min_pll_rate = 600000000UL,
+#ifdef CONFIG_64BIT
+       .max_pll_rate = 5000000000ULL,
+#else
+       .max_pll_rate = ULONG_MAX,
+#endif
+       .io_start = { 0xae94400 },
+       .num_dsi_phy = 1,
+       .quirks = DSI_PHY_7NM_QUIRK_V4_1,
+};