diff --git a/msm/dp/dp_catalog.c b/msm/dp/dp_catalog.c index 37b68a7e88..1ed5f52e93 100644 --- a/msm/dp/dp_catalog.c +++ b/msm/dp/dp_catalog.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ @@ -1938,6 +1938,22 @@ static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl, wmb(); } +u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + struct dp_io_data *io_data; + + if (!dp_catalog) { + DP_ERR("invalid input\n"); + return 0; + } + + catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); + io_data = catalog->io.dp_ahb; + + return dp_read(DP_HW_VERSION); +} + static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, char *name, u8 **out_buf, u32 *out_buf_len) { diff --git a/msm/dp/dp_catalog.h b/msm/dp/dp_catalog.h index f73a1713ff..f5c804bebf 100644 --- a/msm/dp/dp_catalog.h +++ b/msm/dp/dp_catalog.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_CATALOG_H_ @@ -336,4 +336,5 @@ struct dp_catalog_sub *dp_catalog_get_v420(struct device *dev, struct dp_catalog_sub *dp_catalog_get_v200(struct device *dev, struct dp_catalog *catalog, struct dp_catalog_io *io); +u32 dp_catalog_get_dp_core_version(struct dp_catalog *dp_catalog); #endif /* _DP_CATALOG_H_ */ diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 224d0054af..2ce9c24b55 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -1919,6 +1919,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) pll_in.aux = dp->aux; pll_in.parser = dp->parser; + pll_in.dp_core_revision = dp_catalog_get_dp_core_version(dp->catalog); dp->pll = dp_pll_get(&pll_in); if (IS_ERR(dp->pll)) { diff --git a/msm/dp/dp_pll.c b/msm/dp/dp_pll.c index 31f91c84ce..3f31b856f2 100644 --- a/msm/dp/dp_pll.c +++ b/msm/dp/dp_pll.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -74,6 +74,34 @@ static void dp_pll_clock_unregister(struct dp_pll *pll) } } +int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks) +{ + int rc = 0, i = 0; + struct platform_device *pdev; + struct clk *clk; + + if (!pll || !clks) { + DP_ERR("input not initialized\n"); + return -EINVAL; + } + + pdev = pll->pdev; + + for (i = 0; i < num_clks; i++) { + clks[i].priv = pll; + + clk = clk_register(&pdev->dev, &clks[i].hw); + if (IS_ERR(clk)) { + DP_ERR("%s registration failed for DP: %d\n", + clk_hw_get_name(&clks[i].hw), pll->index); + return -EINVAL; + } + pll->clk_data->clks[i] = clk; + } + + return rc; +} + struct dp_pll *dp_pll_get(struct dp_pll_in *in) { int rc = 0; @@ -93,6 +121,7 @@ struct dp_pll *dp_pll_get(struct dp_pll_in *in) pll->pdev = in->pdev; pll->parser = in->parser; pll->aux = in->aux; + pll->dp_core_revision = in->dp_core_revision; parser = pll->parser; pdev = pll->pdev; diff --git a/msm/dp/dp_pll.h b/msm/dp/dp_pll.h index 19bfbe5f2e..eca3435d3c 100644 --- a/msm/dp/dp_pll.h +++ b/msm/dp/dp_pll.h @@ -80,6 +80,7 @@ struct dp_pll { struct dp_aux *aux; struct dp_pll_io io; struct clk_onecell_data *clk_data; + u32 dp_core_revision; int (*pll_cfg)(struct dp_pll *pll, unsigned long rate); int (*pll_prepare)(struct dp_pll *pll); @@ -128,8 +129,10 @@ struct dp_pll_in { struct platform_device *pdev; struct dp_aux *aux; struct dp_parser *parser; + u32 dp_core_revision; }; +int dp_pll_clock_register_helper(struct dp_pll *pll, struct dp_pll_vco_clk *clks, int num_clks); struct dp_pll *dp_pll_get(struct dp_pll_in *in); void dp_pll_put(struct dp_pll *pll); #endif /* __DP_PLL_H */ diff --git a/msm/dp/dp_pll_5nm.c b/msm/dp/dp_pll_5nm.c index fb40271bce..effe800060 100644 --- a/msm/dp/dp_pll_5nm.c +++ b/msm/dp/dp_pll_5nm.c @@ -121,6 +121,8 @@ #define DP_VCO_RATE_9720MHZDIV1000 9720000UL #define DP_VCO_RATE_10800MHZDIV1000 10800000UL +#define DP_PLL_NUM_CLKS 2 + #define DP_5NM_C_READY BIT(0) #define DP_5NM_FREQ_DONE BIT(0) #define DP_5NM_PLL_LOCKED BIT(1) @@ -826,17 +828,33 @@ static const struct clk_ops pll_vco_div_clk_ops = { .set_rate = dp_pll_vco_div_clk_set_rate, }; -static struct dp_pll_vco_clk dp_phy_pll_link_clk = { +static struct dp_pll_vco_clk dp0_phy_pll_clks[DP_PLL_NUM_CLKS] = { + { .hw.init = &(struct clk_init_data) { - .name = "dp_phy_pll_link_clk", + .name = "dp0_phy_pll_link_clk", .ops = &pll_link_clk_ops, + }, + }, + { + .hw.init = &(struct clk_init_data) { + .name = "dp0_phy_pll_vco_div_clk", + .ops = &pll_vco_div_clk_ops, + }, }, }; -static struct dp_pll_vco_clk dp_phy_pll_vco_div_clk = { +static struct dp_pll_vco_clk dp_phy_pll_clks[DP_PLL_NUM_CLKS] = { + { + .hw.init = &(struct clk_init_data) { + .name = "dp_phy_pll_link_clk", + .ops = &pll_link_clk_ops, + }, + }, + { .hw.init = &(struct clk_init_data) { .name = "dp_phy_pll_vco_div_clk", .ops = &pll_vco_div_clk_ops, + }, }, }; @@ -844,9 +862,9 @@ static struct dp_pll_db dp_pdb; int dp_pll_clock_register_5nm(struct dp_pll *pll) { - int rc = 0, num_clks = 2; + int rc = 0; struct platform_device *pdev; - struct clk *clk; + struct dp_pll_vco_clk *pll_clks; if (!pll) { DP_ERR("pll data not initialized\n"); @@ -858,46 +876,36 @@ int dp_pll_clock_register_5nm(struct dp_pll *pll) if (!pll->clk_data) return -ENOMEM; - pll->clk_data->clks = kcalloc(num_clks, sizeof(struct clk *), + pll->clk_data->clks = kcalloc(DP_PLL_NUM_CLKS, sizeof(struct clk *), GFP_KERNEL); if (!pll->clk_data->clks) { kfree(pll->clk_data); return -ENOMEM; } - pll->clk_data->clk_num = num_clks; + pll->clk_data->clk_num = DP_PLL_NUM_CLKS; pll->priv = &dp_pdb; dp_pdb.pll = pll; - dp_phy_pll_link_clk.priv = pll; - dp_phy_pll_vco_div_clk.priv = pll; - pll->pll_cfg = dp_pll_configure; pll->pll_prepare = dp_pll_prepare; pll->pll_unprepare = dp_pll_unprepare; - clk = clk_register(&pdev->dev, &dp_phy_pll_link_clk.hw); - if (IS_ERR(clk)) { - DP_ERR("%s registration failed for DP: %d\n", - clk_hw_get_name(&dp_phy_pll_link_clk.hw), pll->index); - rc = -EINVAL; - goto clk_reg_fail; - } - pll->clk_data->clks[0] = clk; + if (pll->dp_core_revision >= 0x10040000) + pll_clks = dp0_phy_pll_clks; + else + pll_clks = dp_phy_pll_clks; - clk = clk_register(&pdev->dev, &dp_phy_pll_vco_div_clk.hw); - if (IS_ERR(clk)) { - DP_ERR("%s registration failed for DP: %d\n", - clk_hw_get_name(&dp_phy_pll_vco_div_clk.hw), pll->index); - rc = -EINVAL; + rc = dp_pll_clock_register_helper(pll, pll_clks, DP_PLL_NUM_CLKS); + if (rc) { + DP_ERR("Clock register failed rc=%d\n", rc); goto clk_reg_fail; } - pll->clk_data->clks[1] = clk; rc = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, pll->clk_data); if (rc) { - DP_ERR("Clock register failed rc=%d\n", rc); + DP_ERR("Clock add provider failed rc=%d\n", rc); goto clk_reg_fail; }