summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorSiddhartha Agrawal <agrawals@codeaurora.org>2014-09-05 10:44:54 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:41:25 -0700
commit81a55379823f2c14cf98827ff704fe459e17de8d (patch)
treeae6d4fde9fc83db038c0bf57fd1579ffa9c34f61 /drivers/clk
parent840d2a0157c3d572214cb30162ea3a27adc57a6c (diff)
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 <agrawals@codeaurora.org> Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-20nm.c170
-rw-r--r--drivers/clk/msm/mdss/mdss-pll.c7
-rw-r--r--drivers/clk/msm/mdss/mdss-pll.h6
3 files changed, 124 insertions, 59 deletions
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 {