From 81a55379823f2c14cf98827ff704fe459e17de8d Mon Sep 17 00:00:00 2001 From: Siddhartha Agrawal Date: Fri, 5 Sep 2014 10:44:54 -0700 Subject: clk: msm: mdss: Add support for DSI PLL 1 clock registration Setup DSI 1 PLL clock heirarchy. This is needed for instances where we need to turn off the second pll in case of current leak issue. Change-Id: I694af1fa9591b2345709687c9e7b1d69f15b56a9 [veeras@codeaurora.org: As part of 3.18 upgrade, removing changes in include/dt-bindings/clock/msm-clocks-8994.h from this gerrit] Signed-off-by: Siddhartha Agrawal Signed-off-by: Veera Sundaram Sankaran --- drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c | 170 ++++++++++++++++++++----------- drivers/clk/msm/mdss/mdss-pll.c | 7 ++ drivers/clk/msm/mdss/mdss-pll.h | 6 ++ 3 files changed, 124 insertions(+), 59 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c b/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c index 34a1e4dd24b2..a4bfa3c2dfcc 100644 --- a/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c +++ b/drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c @@ -56,6 +56,20 @@ static int vco_set_rate_20nm(struct clk *c, unsigned long rate) return rc; } +static int pll1_vco_set_rate_20nm(struct clk *c, unsigned long rate) +{ + struct dsi_pll_vco_clk *vco = to_vco_clk(c); + struct mdss_pll_resources *pll_res = vco->priv; + + mdss_pll_resource_enable(pll_res, true); + __dsi_pll_disable(pll_res->pll_base); + mdss_pll_resource_enable(pll_res, false); + + pr_debug("Configuring PLL1 registers.\n"); + + return 0; +} + static int shadow_vco_set_rate_20nm(struct clk *c, unsigned long rate) { int rc; @@ -111,6 +125,11 @@ static int dsi_pll_enable_seq_8994(struct mdss_pll_resources *dsi_pll_res) } /* Op structures */ + +static struct clk_ops pll1_clk_ops_dsi_vco = { + .set_rate = pll1_vco_set_rate_20nm, +}; + static struct clk_ops clk_ops_dsi_vco = { .set_rate = vco_set_rate_20nm, .round_rate = pll_20nm_vco_round_rate, @@ -175,6 +194,15 @@ static struct clk_mux_ops mdss_pixel_mux_ops = { .get_mux_sel = get_mdss_pixel_mux_sel, }; +static struct dsi_pll_vco_clk mdss_dsi1_vco_clk_src = { + .c = { + .dbg_name = "mdss_dsi1_vco_clk_src", + .ops = &pll1_clk_ops_dsi_vco, + .flags = CLKFLAG_NO_RATE_CACHE, + CLK_INIT(mdss_dsi1_vco_clk_src.c), + }, +}; + static struct dsi_pll_vco_clk dsi_vco_clk_8994 = { .ref_clk_rate = 19200000, .min_rate = 1000000000, @@ -435,6 +463,10 @@ static struct mux_clk mdss_byte_clk_mux = { } }; +static struct clk_lookup mdss_dsi_pll_1_cc_8994[] = { + CLK_LIST(mdss_dsi1_vco_clk_src), +}; + static struct clk_lookup mdss_dsi_pllcc_8994[] = { CLK_LIST(mdss_pixel_clk_mux), CLK_LIST(mdss_byte_clk_mux), @@ -519,68 +551,88 @@ int dsi_pll_clock_register_20nm(struct platform_device *pdev, return -EPROBE_DEFER; } - /* Set client data to mux, div and vco clocks */ - byte_clk_src.priv = pll_res; - pixel_clk_src.priv = pll_res; - bypass_lp_div_mux_8994.priv = pll_res; - indirect_path_div2_clk_8994.priv = pll_res; - ndiv_clk_8994.priv = pll_res; - fixed_hr_oclk2_div_clk_8994.priv = pll_res; - hr_oclk3_div_clk_8994.priv = pll_res; - dsi_vco_clk_8994.priv = pll_res; - - shadow_byte_clk_src.priv = pll_res; - shadow_pixel_clk_src.priv = pll_res; - shadow_bypass_lp_div_mux_8994.priv = pll_res; - shadow_indirect_path_div2_clk_8994.priv = pll_res; - shadow_ndiv_clk_8994.priv = pll_res; - shadow_fixed_hr_oclk2_div_clk_8994.priv = pll_res; - shadow_hr_oclk3_div_clk_8994.priv = pll_res; - shadow_dsi_vco_clk_8994.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - - /* Set clock source operations */ - pixel_clk_src_ops = clk_ops_slave_div; - pixel_clk_src_ops.prepare = dsi_pll_div_prepare; - - ndiv_clk_ops = clk_ops_div; - ndiv_clk_ops.prepare = dsi_pll_div_prepare; - - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = dsi_pll_div_prepare; - - bypass_lp_div_mux_clk_ops = clk_ops_gen_mux; - bypass_lp_div_mux_clk_ops.prepare = dsi_pll_mux_prepare; - - clk_ops_gen_mux_dsi = clk_ops_gen_mux; - clk_ops_gen_mux_dsi.round_rate = parent_round_rate; - clk_ops_gen_mux_dsi.set_rate = parent_set_rate; - - shadow_pixel_clk_src_ops = clk_ops_slave_div; - shadow_pixel_clk_src_ops.prepare = dsi_pll_div_prepare; - - shadow_byte_clk_src_ops = clk_ops_div; - shadow_byte_clk_src_ops.prepare = dsi_pll_div_prepare; + /* + * Set client data to mux, div and vco clocks. + * This needs to be done only for PLL0 since, that is the one in + * use. + **/ + if (!pll_res->index) { + byte_clk_src.priv = pll_res; + pixel_clk_src.priv = pll_res; + bypass_lp_div_mux_8994.priv = pll_res; + indirect_path_div2_clk_8994.priv = pll_res; + ndiv_clk_8994.priv = pll_res; + fixed_hr_oclk2_div_clk_8994.priv = pll_res; + hr_oclk3_div_clk_8994.priv = pll_res; + dsi_vco_clk_8994.priv = pll_res; + + shadow_byte_clk_src.priv = pll_res; + shadow_pixel_clk_src.priv = pll_res; + shadow_bypass_lp_div_mux_8994.priv = pll_res; + shadow_indirect_path_div2_clk_8994.priv = pll_res; + shadow_ndiv_clk_8994.priv = pll_res; + shadow_fixed_hr_oclk2_div_clk_8994.priv = pll_res; + shadow_hr_oclk3_div_clk_8994.priv = pll_res; + shadow_dsi_vco_clk_8994.priv = pll_res; + + pll_res->vco_delay = VCO_DELAY_USEC; + + /* Set clock source operations */ + pixel_clk_src_ops = clk_ops_slave_div; + pixel_clk_src_ops.prepare = dsi_pll_div_prepare; + + ndiv_clk_ops = clk_ops_div; + ndiv_clk_ops.prepare = dsi_pll_div_prepare; + + byte_clk_src_ops = clk_ops_div; + byte_clk_src_ops.prepare = dsi_pll_div_prepare; + + bypass_lp_div_mux_clk_ops = clk_ops_gen_mux; + bypass_lp_div_mux_clk_ops.prepare = dsi_pll_mux_prepare; + + clk_ops_gen_mux_dsi = clk_ops_gen_mux; + clk_ops_gen_mux_dsi.round_rate = parent_round_rate; + clk_ops_gen_mux_dsi.set_rate = parent_set_rate; + + shadow_pixel_clk_src_ops = clk_ops_slave_div; + shadow_pixel_clk_src_ops.prepare = dsi_pll_div_prepare; + + shadow_byte_clk_src_ops = clk_ops_div; + shadow_byte_clk_src_ops.prepare = dsi_pll_div_prepare; + } else { + mdss_dsi1_vco_clk_src.priv = pll_res; + } if (pll_res->target_id == MDSS_PLL_TARGET_8994) { - pll_res->gdsc_cb.notifier_call = - dsi_pll_regulator_notifier_call; - INIT_WORK(&pll_res->pll_off, dsi_pll_off_work); - - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8994, ARRAY_SIZE(mdss_dsi_pllcc_8994)); - if (rc) { - pr_err("Clock register failed\n"); - rc = -EPROBE_DEFER; - } - pll_reg = mdss_pll_get_mp_by_reg_name(pll_res, "gdsc"); - if (pll_reg) { - pr_debug("Registering for gdsc regulator events\n"); - if (regulator_register_notifier(pll_reg->vreg, - &(pll_res->gdsc_cb))) - pr_err("Regulator notification registration failed!\n"); + if (pll_res->index) { + rc = of_msm_clock_register(pdev->dev.of_node, + mdss_dsi_pll_1_cc_8994, + ARRAY_SIZE(mdss_dsi_pll_1_cc_8994)); + if (rc) { + pr_err("Clock register failed\n"); + rc = -EPROBE_DEFER; + } + } else { + rc = of_msm_clock_register(pdev->dev.of_node, + mdss_dsi_pllcc_8994, + ARRAY_SIZE(mdss_dsi_pllcc_8994)); + if (rc) { + pr_err("Clock register failed\n"); + rc = -EPROBE_DEFER; + } + pll_res->gdsc_cb.notifier_call = + dsi_pll_regulator_notifier_call; + INIT_WORK(&pll_res->pll_off, dsi_pll_off_work); + + pll_reg = mdss_pll_get_mp_by_reg_name(pll_res, "gdsc"); + if (pll_reg) { + pr_debug("Registering for gdsc regulator events\n"); + if (regulator_register_notifier(pll_reg->vreg, + &(pll_res->gdsc_cb))) + pr_err("Regulator notification registration failed!\n"); + } } + } else { pr_err("Invalid target ID\n"); rc = -EINVAL; diff --git a/drivers/clk/msm/mdss/mdss-pll.c b/drivers/clk/msm/mdss/mdss-pll.c index cda571ec070b..d5119cc548c0 100644 --- a/drivers/clk/msm/mdss/mdss-pll.c +++ b/drivers/clk/msm/mdss/mdss-pll.c @@ -227,6 +227,13 @@ static int mdss_pll_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, pll_res); + rc = of_property_read_u32(pdev->dev.of_node, "cell-index", + &pll_res->index); + if (rc) { + pr_err("Unable to get the cell-index rc=%d\n", rc); + pll_res->index = 0; + } + pll_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_base"); if (!pll_base_reg) { diff --git a/drivers/clk/msm/mdss/mdss-pll.h b/drivers/clk/msm/mdss/mdss-pll.h index e90394a0a0f3..20642a9270f0 100644 --- a/drivers/clk/msm/mdss/mdss-pll.h +++ b/drivers/clk/msm/mdss/mdss-pll.h @@ -119,6 +119,12 @@ struct mdss_pll_resources { */ struct work_struct pll_off; + /* + * PLL index if multiple index are available. Eg. in case of + * DSI we have 2 plls. + */ + uint32_t index; + }; struct mdss_pll_vco_calc { -- cgit v1.2.3