diff --git a/pll/dp_pll_7nm.c b/pll/dp_pll_7nm.c index f31ec09b5a2a..480c00fda658 100644 --- a/pll/dp_pll_7nm.c +++ b/pll/dp_pll_7nm.c @@ -100,6 +100,20 @@ static struct dp_pll_vco_clk dp_vco_clk = { }, }; +static struct clk_fixed_factor dp_phy_pll_link_clk = { + .div = 10, + .mult = 1, + + .hw.init = &(struct clk_init_data){ + .name = "dp_phy_pll_link_clk", + .parent_names = + (const char *[]){ "dp_vco_clk" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + static struct clk_fixed_factor dp_link_clk_divsel_ten = { .div = 10, .mult = 1, @@ -206,6 +220,25 @@ static unsigned long mux_recalc_rate(struct clk_hw *hw, return (vco->rate / 2); } +static struct clk_regmap_mux dp_phy_pll_vco_div_clk = { + .reg = 0x64, + .shift = 0, + .width = 2, + + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "dp_phy_pll_vco_div_clk", + .parent_names = + (const char *[]){"dp_vco_divsel_two_clk_src", + "dp_vco_divsel_four_clk_src", + "dp_vco_divsel_six_clk_src"}, + .num_parents = 3, + .ops = &mux_clk_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + static struct clk_regmap_mux dp_vco_divided_clk_src_mux = { .reg = 0x64, .shift = 0, @@ -260,13 +293,27 @@ int dp_pll_clock_register_7nm(struct platform_device *pdev, /* Set client data for vco, mux and div clocks */ regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops, pll_res, &dp_pll_7nm_cfg); - dp_vco_divided_clk_src_mux.clkr.regmap = regmap; mux_clk_ops = clk_regmap_mux_closest_ops; mux_clk_ops.determine_rate = clk_mux_determine_rate; mux_clk_ops.recalc_rate = mux_recalc_rate; dp_vco_clk.priv = pll_res; + /* + * Consumer for the pll clock expects, the DP_LINK_CLK_DIVSEL_TEN and + * DP_VCO_DIVIDED_CLK_SRC_MUX clock names to be "dp_phy_pll_link_clk" + * and "dp_phy_pll_vco_div_clk" respectively for a V2 pll interface + * target. + */ + if (pll_res->pll_interface_type == MDSS_DP_PLL_7NM_V2) { + mdss_dp_pllcc_7nm[DP_LINK_CLK_DIVSEL_TEN] = + &dp_phy_pll_link_clk.hw; + mdss_dp_pllcc_7nm[DP_VCO_DIVIDED_CLK_SRC_MUX] = + &dp_phy_pll_vco_div_clk.clkr.hw; + dp_phy_pll_vco_div_clk.clkr.regmap = regmap; + } else + dp_vco_divided_clk_src_mux.clkr.regmap = regmap; + for (i = DP_VCO_CLK; i <= DP_VCO_DIVIDED_CLK_SRC_MUX; i++) { pr_debug("reg clk: %d index: %d\n", i, pll_res->index); clk = devm_clk_register(&pdev->dev, mdss_dp_pllcc_7nm[i]); diff --git a/pll/dp_pll_7nm_util.c b/pll/dp_pll_7nm_util.c index 5c565c8599a7..10f3e15aac8f 100644 --- a/pll/dp_pll_7nm_util.c +++ b/pll/dp_pll_7nm_util.c @@ -48,11 +48,6 @@ #define TXn_TX_POL_INV 0x005C #define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0060 -#define TXn_TRAN_DRVR_EMP_EN 0x00B8 -#define TXn_TX_INTERFACE_MODE 0x00BC - -#define TXn_VMODE_CTRL1 0x00E8 - /* PLL register offset */ #define QSERDES_COM_BG_TIMER 0x000C #define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0044 @@ -90,6 +85,13 @@ #define QSERDES_COM_SVS_MODE_CLK_SEL 0x0184 +/* Tx tran offsets */ +#define DP_TRAN_DRVR_EMP_EN 0x0000 +#define DP_TX_INTERFACE_MODE 0x0004 + +/* Tx VMODE offsets */ +#define DP_VMODE_CTRL1 0x0000 + #define DP_PHY_PLL_POLL_SLEEP_US 500 #define DP_PHY_PLL_POLL_TIMEOUT_US 10000 @@ -326,30 +328,30 @@ static int dp_config_vco_rate_7nm(struct dp_pll_vco_clk *vco, /* TX-0 register configuration */ MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_VMODE_CTRL1, 0x40); + MDSS_PLL_REG_W(dp_res->ln_tx0_vmode_base, DP_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_INTERFACE_SELECT, 0x3b); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_CLKBUF_ENABLE, 0x0f); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRAN_DRVR_EMP_EN, + MDSS_PLL_REG_W(dp_res->ln_tx0_tran_base, DP_TRAN_DRVR_EMP_EN, pdb->txn_tran_drv_emp_en); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_INTERFACE_MODE, 0x00); + MDSS_PLL_REG_W(dp_res->ln_tx0_tran_base, DP_TX_INTERFACE_MODE, 0x00); MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_BAND, 0x4); /* TX-1 register configuration */ MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_VMODE_CTRL1, 0x40); + MDSS_PLL_REG_W(dp_res->ln_tx1_vmode_base, DP_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_INTERFACE_SELECT, 0x3b); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_CLKBUF_ENABLE, 0x0f); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRAN_DRVR_EMP_EN, + MDSS_PLL_REG_W(dp_res->ln_tx1_tran_base, DP_TRAN_DRVR_EMP_EN, pdb->txn_tran_drv_emp_en); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_INTERFACE_MODE, 0x00); + MDSS_PLL_REG_W(dp_res->ln_tx1_tran_base, DP_TX_INTERFACE_MODE, 0x00); MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_BAND, 0x4); /* Make sure the PHY register writes are done */ wmb(); diff --git a/pll/pll_drv.c b/pll/pll_drv.c index 4b5c9fb178ee..5e0cd4cf4e7a 100644 --- a/pll/pll_drv.c +++ b/pll/pll_drv.c @@ -132,6 +132,8 @@ static int mdss_pll_resource_parse(struct platform_device *pdev, pll_res->pll_interface_type = MDSS_DP_PLL_10NM; else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_7nm")) pll_res->pll_interface_type = MDSS_DP_PLL_7NM; + else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_7nm_v2")) + pll_res->pll_interface_type = MDSS_DP_PLL_7NM_V2; else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm")) pll_res->pll_interface_type = MDSS_DSI_PLL_7NM; else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm_v2")) @@ -174,6 +176,7 @@ static int mdss_pll_clock_register(struct platform_device *pdev, rc = dsi_pll_clock_register_7nm(pdev, pll_res); break; case MDSS_DP_PLL_7NM: + case MDSS_DP_PLL_7NM_V2: rc = dp_pll_clock_register_7nm(pdev, pll_res); break; case MDSS_DSI_PLL_28LPM: @@ -303,12 +306,36 @@ static int mdss_pll_probe(struct platform_device *pdev) return -ENOMEM; } + if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx0_tran_base, + "ln_tx0_tran_base")) { + pr_err("Unable to remap Lane TX0 base resources\n"); + return -ENOMEM; + } + + if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx0_vmode_base, + "ln_tx0_vmode_base")) { + pr_err("Unable to remap Lane TX0 base resources\n"); + return -ENOMEM; + } + if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx1_base, "ln_tx1_base")) { pr_err("Unable to remap Lane TX1 base resources\n"); return -ENOMEM; } + if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx1_tran_base, + "ln_tx1_tran_base")) { + pr_err("Unable to remap Lane TX1 base resources\n"); + return -ENOMEM; + } + + if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx1_vmode_base, + "ln_tx1_vmode_base")) { + pr_err("Unable to remap Lane TX1 base resources\n"); + return -ENOMEM; + } + if (mdss_pll_get_ioresurces(pdev, &pll_res->gdsc_base, "gdsc_base")) { pr_err("Unable to remap gdsc base resources\n"); return -ENOMEM; @@ -357,6 +384,7 @@ static const struct of_device_id mdss_pll_dt_match[] = { {.compatible = "qcom,mdss_dsi_pll_7nm_v2"}, {.compatible = "qcom,mdss_dsi_pll_7nm_v4_1"}, {.compatible = "qcom,mdss_dp_pll_7nm"}, + {.compatible = "qcom,mdss_dp_pll_7nm_v2"}, {.compatible = "qcom,mdss_dsi_pll_28lpm"}, {.compatible = "qcom,mdss_dsi_pll_14nm"}, {.compatible = "qcom,mdss_dp_pll_14nm"}, diff --git a/pll/pll_drv.h b/pll/pll_drv.h index 15d766e69937..22a6c1571a2d 100644 --- a/pll/pll_drv.h +++ b/pll/pll_drv.h @@ -40,6 +40,7 @@ enum { MDSS_DSI_PLL_7NM_V2, MDSS_DSI_PLL_7NM_V4_1, MDSS_DP_PLL_7NM, + MDSS_DP_PLL_7NM_V2, MDSS_DSI_PLL_28LPM, MDSS_DSI_PLL_14NM, MDSS_DP_PLL_14NM, @@ -89,7 +90,11 @@ struct mdss_pll_resources { void __iomem *pll_base; void __iomem *phy_base; void __iomem *ln_tx0_base; + void __iomem *ln_tx0_tran_base; + void __iomem *ln_tx0_vmode_base; void __iomem *ln_tx1_base; + void __iomem *ln_tx1_tran_base; + void __iomem *ln_tx1_vmode_base; void __iomem *gdsc_base; void __iomem *dyn_pll_base;