Merge "clk: qcom: Add properties for marking clocks as critical"

This commit is contained in:
qctecmdr 2021-02-15 06:09:14 -08:00 • committed by Gerrit - the friendly Code Review server
commit 367c7ae1ca
4 changed files with 66 additions and 0 deletions

View file

@ -269,6 +269,7 @@ EXPORT_SYMBOL(clk_is_regmap_clk);
*/
int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk)
{
const struct clk_ops *ops;
int ret;
rclk->dev = dev;
@ -278,6 +279,14 @@ int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk)
else if (dev && dev->parent)
rclk->regmap = dev_get_regmap(dev->parent, NULL);
if (rclk->flags & QCOM_CLK_IS_CRITICAL) {
ops = rclk->hw.init->ops;
if (ops && ops->enable)
ops->enable(&rclk->hw);
return 0;
}
ret = devm_clk_hw_register(dev, &rclk->hw);
if (!ret)
list_add(&rclk->list_node, &clk_regmap_list);

View file

@ -51,6 +51,8 @@ struct clk_regmap {
struct clk_regmap_ops *ops;
struct list_head list_node;
struct device *dev;
#define QCOM_CLK_IS_CRITICAL BIT(0)
unsigned long flags;
};
#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)

View file

@ -232,6 +232,47 @@ static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc)
}
}
/* Set QCOM_CLK_IS_CRITICAL on clocks specified in dt */
static void qcom_cc_set_critical(struct device *dev, struct qcom_cc *cc)
{
struct of_phandle_args args;
struct device_node *np;
struct property *prop;
const __be32 *p;
u32 clock_idx;
u32 i;
int cnt;
of_property_for_each_u32(dev->of_node, "qcom,critical-clocks", prop, p, i) {
if (i >= cc->num_rclks)
continue;
cc->rclks[i]->flags |= QCOM_CLK_IS_CRITICAL;
}
of_property_for_each_u32(dev->of_node, "qcom,critical-devices", prop, p, i) {
np = of_find_node_by_phandle(i);
if (!np)
continue;
cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells");
for (i = 0; i < cnt; i++) {
of_parse_phandle_with_args(np, "clocks", "#clock-cells",
i, &args);
clock_idx = args.args[0];
if (args.np != dev->of_node || clock_idx >= cc->num_rclks)
continue;
cc->rclks[clock_idx]->flags |= QCOM_CLK_IS_CRITICAL;
of_node_put(args.np);
}
of_node_put(np);
}
}
static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@ -310,6 +351,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
cc->num_clk_hws = num_clk_hws;
qcom_cc_drop_protected(dev, cc);
qcom_cc_set_critical(dev, cc);
for (i = 0; i < num_clk_hws; i++) {
if (!clk_hws[i])
@ -329,6 +371,14 @@ int qcom_cc_really_probe(struct platform_device *pdev,
return ret;
clk_hw_populate_clock_opp_table(dev->of_node, &rclks[i]->hw);
/*
* Critical clocks are enabled by devm_clk_register_regmap()
* and registration skipped. So remove from rclks so that the
* get() callback returns NULL and client requests are stubbed.
*/
if (rclks[i]->flags & QCOM_CLK_IS_CRITICAL)
rclks[i] = NULL;
}
ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc);

View file

@ -84,4 +84,9 @@ int qcom_cc_runtime_init(struct platform_device *pdev,
int qcom_cc_runtime_suspend(struct device *dev);
int qcom_cc_runtime_resume(struct device *dev);
static inline const char *qcom_clk_hw_get_name(const struct clk_hw *hw)
{
return hw->init ? hw->init->name : clk_hw_get_name(hw);
}
#endif