diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 349af277291d..9015d505f4dc 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -55,6 +55,7 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_name, \ + .flags = CLK_ENABLE_HAND_OFF, \ .parent_names = (const char *[]){ "xo_board" }, \ .num_parents = 1, \ }, \ @@ -72,6 +73,7 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_active, \ + .flags = CLK_ENABLE_HAND_OFF, \ .parent_names = (const char *[]){ "xo_board" }, \ .num_parents = 1, \ }, \ @@ -95,6 +97,7 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_name, \ + .flags = CLK_ENABLE_HAND_OFF, \ .parent_names = (const char *[]){ "xo_board" }, \ .num_parents = 1, \ }, \ @@ -113,6 +116,7 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_active, \ + .flags = CLK_ENABLE_HAND_OFF, \ .parent_names = (const char *[]){ "xo_board" }, \ .num_parents = 1, \ }, \ @@ -177,6 +181,8 @@ struct rpm_smd_clk_desc { static DEFINE_MUTEX(rpm_smd_clk_lock); +static int clk_smd_rpm_prepare(struct clk_hw *hw); + static int clk_smd_rpm_handoff(struct clk_hw *hw) { int ret = 0; @@ -198,6 +204,8 @@ static int clk_smd_rpm_handoff(struct clk_hw *hw) if (ret) return ret; + ret = clk_smd_rpm_prepare(hw); + return ret; } @@ -462,12 +470,20 @@ static int clk_vote_bimc(struct clk_hw *hw, uint32_t rate) return ret; } +static int clk_smd_rpm_is_enabled(struct clk_hw *hw) +{ + struct clk_smd_rpm *r = to_clk_smd_rpm(hw); + + return r->enabled; +} + static const struct clk_ops clk_smd_rpm_ops = { .prepare = clk_smd_rpm_prepare, .unprepare = clk_smd_rpm_unprepare, .set_rate = clk_smd_rpm_set_rate, .round_rate = clk_smd_rpm_round_rate, .recalc_rate = clk_smd_rpm_recalc_rate, + .is_enabled = clk_smd_rpm_is_enabled, }; static const struct clk_ops clk_smd_rpm_branch_ops = { @@ -475,6 +491,7 @@ static const struct clk_ops clk_smd_rpm_branch_ops = { .unprepare = clk_smd_rpm_unprepare, .round_rate = clk_smd_rpm_round_rate, .recalc_rate = clk_smd_rpm_recalc_rate, + .is_enabled = clk_smd_rpm_is_enabled, }; /* msm8916 */ @@ -817,6 +834,17 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) goto err; } + for (i = (desc->num_rpm_clks + 1); i < num_clks; i++) { + if (!hw_clks[i]) { + clks[i] = ERR_PTR(-ENOENT); + continue; + } + + ret = voter_clk_handoff(hw_clks[i]); + if (ret) + goto err; + } + ret = clk_smd_rpm_enable_scaling(); if (ret) goto err; diff --git a/drivers/clk/qcom/clk-voter.c b/drivers/clk/qcom/clk-voter.c index d3409b9e6b64..60e319620e1b 100644 --- a/drivers/clk/qcom/clk-voter.c +++ b/drivers/clk/qcom/clk-voter.c @@ -123,6 +123,16 @@ static unsigned long voter_clk_recalc_rate(struct clk_hw *hw, return v->rate; } +int voter_clk_handoff(struct clk_hw *hw) +{ + struct clk_voter *v = to_clk_voter(hw); + + v->enabled = true; + + return 0; +} +EXPORT_SYMBOL(voter_clk_handoff); + struct clk_ops clk_ops_voter = { .prepare = voter_clk_prepare, .unprepare = voter_clk_unprepare, diff --git a/drivers/clk/qcom/clk-voter.h b/drivers/clk/qcom/clk-voter.h index 27092ae7d131..abc26cd94cd5 100644 --- a/drivers/clk/qcom/clk-voter.h +++ b/drivers/clk/qcom/clk-voter.h @@ -36,6 +36,7 @@ extern struct clk_ops clk_ops_voter; .hw.init = &(struct clk_init_data){ \ .ops = &clk_ops_voter, \ .name = #clk_name, \ + .flags = CLK_ENABLE_HAND_OFF, \ .parent_names = (const char *[]){ #_parent_name }, \ .num_parents = 1, \ }, \ @@ -47,4 +48,6 @@ extern struct clk_ops clk_ops_voter; #define DEFINE_CLK_BRANCH_VOTER(clk_name, _parent_name) \ __DEFINE_CLK_VOTER(clk_name, _parent_name, 1000, 1) +int voter_clk_handoff(struct clk_hw *hw); + #endif