clk: renesas: rzg2l-cpg: Refactor Runtime PM clock validation
[ Upstream commit f6f73b891bf6beff069fcacc7b4a796e1009bf26 ] Refactor rzg2l_cpg_attach_dev to delegate clock validation for Runtime PM to the updated rzg2l_cpg_is_pm_clk function. Ensure validation of clocks associated with the power domain while excluding external and core clocks. Prevent incorrect Runtime PM management for clocks outside the domain's scope. Update rzg2l_cpg_is_pm_clk to operate on a per-power-domain basis. Verify clkspec.np against the domain's device node, check argument validity, and validate clock type (CPG_MOD). Use the no_pm_mod_clks array to exclude specific clocks from PM management. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/20241216210201.239855-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3a95341c65
commit
ff5c6e3d25
@@ -1549,28 +1549,6 @@ static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv)
|
||||
return devm_reset_controller_register(priv->dev, &priv->rcdev);
|
||||
}
|
||||
|
||||
static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv,
|
||||
const struct of_phandle_args *clkspec)
|
||||
{
|
||||
const struct rzg2l_cpg_info *info = priv->info;
|
||||
unsigned int id;
|
||||
unsigned int i;
|
||||
|
||||
if (clkspec->args_count != 2)
|
||||
return false;
|
||||
|
||||
if (clkspec->args[0] != CPG_MOD)
|
||||
return false;
|
||||
|
||||
id = clkspec->args[1] + info->num_total_core_clks;
|
||||
for (i = 0; i < info->num_no_pm_mod_clks; i++) {
|
||||
if (info->no_pm_mod_clks[i] == id)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure
|
||||
* @onecell_data: cell data
|
||||
@@ -1595,45 +1573,73 @@ struct rzg2l_cpg_pd {
|
||||
u16 id;
|
||||
};
|
||||
|
||||
static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_pd *pd,
|
||||
const struct of_phandle_args *clkspec)
|
||||
{
|
||||
if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
|
||||
return false;
|
||||
|
||||
switch (clkspec->args[0]) {
|
||||
case CPG_MOD: {
|
||||
struct rzg2l_cpg_priv *priv = pd->priv;
|
||||
const struct rzg2l_cpg_info *info = priv->info;
|
||||
unsigned int id = clkspec->args[1];
|
||||
|
||||
if (id >= priv->num_mod_clks)
|
||||
return false;
|
||||
|
||||
id += info->num_total_core_clks;
|
||||
|
||||
for (unsigned int i = 0; i < info->num_no_pm_mod_clks; i++) {
|
||||
if (info->no_pm_mod_clks[i] == id)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case CPG_CORE:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
|
||||
{
|
||||
struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd);
|
||||
struct rzg2l_cpg_priv *priv = pd->priv;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args clkspec;
|
||||
bool once = true;
|
||||
struct clk *clk;
|
||||
unsigned int i;
|
||||
int error;
|
||||
int i = 0;
|
||||
|
||||
while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
|
||||
&clkspec)) {
|
||||
if (rzg2l_cpg_is_pm_clk(priv, &clkspec)) {
|
||||
if (once) {
|
||||
once = false;
|
||||
error = pm_clk_create(dev);
|
||||
if (error) {
|
||||
of_node_put(clkspec.np);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
clk = of_clk_get_from_provider(&clkspec);
|
||||
of_node_put(clkspec.np);
|
||||
if (IS_ERR(clk)) {
|
||||
error = PTR_ERR(clk);
|
||||
goto fail_destroy;
|
||||
}
|
||||
|
||||
error = pm_clk_add_clk(dev, clk);
|
||||
if (error) {
|
||||
dev_err(dev, "pm_clk_add_clk failed %d\n",
|
||||
error);
|
||||
goto fail_put;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) {
|
||||
if (!rzg2l_cpg_is_pm_clk(pd, &clkspec)) {
|
||||
of_node_put(clkspec.np);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (once) {
|
||||
once = false;
|
||||
error = pm_clk_create(dev);
|
||||
if (error) {
|
||||
of_node_put(clkspec.np);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
clk = of_clk_get_from_provider(&clkspec);
|
||||
of_node_put(clkspec.np);
|
||||
if (IS_ERR(clk)) {
|
||||
error = PTR_ERR(clk);
|
||||
goto fail_destroy;
|
||||
}
|
||||
|
||||
error = pm_clk_add_clk(dev, clk);
|
||||
if (error) {
|
||||
dev_err(dev, "pm_clk_add_clk failed %d\n", error);
|
||||
goto fail_put;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user