]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: renesas: rzg2l-cpg: Refactor Runtime PM clock validation
authorLad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Mon, 16 Dec 2024 21:02:01 +0000 (21:02 +0000)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 3 Feb 2025 10:05:34 +0000 (11:05 +0100)
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>
drivers/clk/renesas/rzg2l-cpg.c

index ddf722ca79eb0feb28c2aeecf3eb8460f551a2a6..6e4a51427bd2b0ae7b07cae3bef6ffd583c87d43 100644 (file)
@@ -1538,28 +1538,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
@@ -1584,45 +1562,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);
+
+       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);
-                       if (IS_ERR(clk)) {
-                               error = PTR_ERR(clk);
-                               goto fail_destroy;
-                       }
+                       continue;
+               }
 
-                       error = pm_clk_add_clk(dev, clk);
+               if (once) {
+                       once = false;
+                       error = pm_clk_create(dev);
                        if (error) {
-                               dev_err(dev, "pm_clk_add_clk failed %d\n",
-                                       error);
-                               goto fail_put;
+                               of_node_put(clkspec.np);
+                               goto err;
                        }
-               } else {
-                       of_node_put(clkspec.np);
                }
-               i++;
+               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;
+               }
        }
 
        return 0;