mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
clk: qcom: Add support to proxy vote until clk controllers sync states
Clock consumers gets deferred due to their dependencies during device boot/probes, and can not put essential vdd vote before clock late init clk_disable_unused() un-votes them. This behavior breaks functionality of keeping clocks/feature continuously enabled from boot to HLOS. Putting proxy vdd votes will ensure that votes are hold till consumer sync states and it gives chance to consumers act on necessary votes when it's ready. Also clock controller can not rely on consumers to vote vdd votes during boot/probe sequence in all paths of clk provided consumed APIs. Putting proxy votes makes sure that clk driver can access it's provided register access. Change-Id: I79301ff354b3ab53cc7c05db5e1dc75223228de6 Signed-off-by: Vivek Aknurwar <viveka@codeaurora.org>
This commit is contained in:
parent
95882c4f49
commit
9530c87bec
|
|
@ -272,6 +272,10 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_vdd_proxy_vote(&pdev->dev, desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (desc->num_resets) {
|
||||
ret = devm_reset_controller_register(dev, &reset->rcdev);
|
||||
if (ret)
|
||||
|
|
@ -363,6 +367,8 @@ void qcom_cc_sync_state(struct device *dev, const struct qcom_cc_desc *desc)
|
|||
{
|
||||
dev_info(dev, "sync-state\n");
|
||||
clk_sync_state(dev);
|
||||
|
||||
clk_vdd_proxy_unvote(dev, desc);
|
||||
}
|
||||
EXPORT_SYMBOL(qcom_cc_sync_state);
|
||||
|
||||
|
|
|
|||
|
|
@ -200,3 +200,41 @@ int clk_regulator_init(struct device *dev, const struct qcom_cc_desc *desc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int clk_vdd_proxy_vote(struct device *dev, const struct qcom_cc_desc *desc)
|
||||
{
|
||||
struct clk_vdd_class_data vdd_data;
|
||||
struct clk_vdd_class *vdd_class;
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < desc->num_clk_regulators; i++) {
|
||||
vdd_data.vdd_class = vdd_class = desc->clk_regulators[i];
|
||||
|
||||
ret = clk_vote_vdd_level(&vdd_data,
|
||||
vdd_class->num_levels - 1);
|
||||
if (ret)
|
||||
WARN(ret, "%s failed, ret=%d\n", __func__, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int clk_vdd_proxy_unvote(struct device *dev, const struct qcom_cc_desc *desc)
|
||||
{
|
||||
struct clk_vdd_class_data vdd_data;
|
||||
struct clk_vdd_class *vdd_class;
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < desc->num_clk_regulators; i++) {
|
||||
vdd_data.vdd_class = vdd_class = desc->clk_regulators[i];
|
||||
|
||||
ret = clk_unvote_vdd_level(&vdd_data,
|
||||
vdd_class->num_levels - 1);
|
||||
if (ret)
|
||||
WARN(ret, "clk_unvote_vdd_level failed ret=%d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,4 +71,6 @@ int clk_find_vdd_level(struct clk_hw *hw, struct clk_vdd_class_data *vdd_data,
|
|||
int clk_vote_vdd_level(struct clk_vdd_class_data *vdd_class, int level);
|
||||
int clk_unvote_vdd_level(struct clk_vdd_class_data *vdd_class, int level);
|
||||
int clk_regulator_init(struct device *dev, const struct qcom_cc_desc *desc);
|
||||
int clk_vdd_proxy_vote(struct device *dev, const struct qcom_cc_desc *desc);
|
||||
int clk_vdd_proxy_unvote(struct device *dev, const struct qcom_cc_desc *desc);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user