MLK-16416-2 soc:imx Add support to save/restore clock parents
authorViorel Suman <viorel.suman@nxp.com>
Mon, 11 Sep 2017 10:55:10 +0000 (13:55 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:38:32 +0000 (15:38 -0500)
In iMX8QM/iMX8QXP the clock parent set in HW is lost when devices are
powered up/down as part of runtime-pm or suspend/resume.
Add support to the power domain driver to save/restore clock parents
associated with devices as part of power up/down.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Reviewed-by: Ranjani Vaidyanathan <ranjani.vaidyanathan@nxp.com>
drivers/soc/imx/pm-domain-imx8.h
drivers/soc/imx/pm-domains.c

index e07f591..bbda879 100644 (file)
@@ -25,6 +25,7 @@ struct platform_device;
 
 struct imx8_pm_rsrc_clks {
        struct clk *clk;
+       struct clk *parent;
        u32 rate;
        struct list_head node;
 };
index 0d01bcf..dec7f14 100644 (file)
@@ -69,6 +69,11 @@ static int imx8_pd_power_on(struct generic_pm_domain *domain)
                 * may be lost.
                 */
                list_for_each_entry(imx8_rsrc_clk, &pd->clks, node) {
+
+                       if (imx8_rsrc_clk->parent)
+                               clk_set_parent(imx8_rsrc_clk->clk,
+                                       imx8_rsrc_clk->parent);
+
                        if (imx8_rsrc_clk->rate) {
                                /*
                                 * Need to read the clock so that rate in
@@ -99,8 +104,10 @@ static int imx8_pd_power_off(struct generic_pm_domain *domain)
                 * The SS is going to be powered off, store the clock rates
                 * that may be lost.
                 */
-               list_for_each_entry(imx8_rsrc_clk, &pd->clks, node)
+               list_for_each_entry(imx8_rsrc_clk, &pd->clks, node) {
+                       imx8_rsrc_clk->parent = clk_get_parent(imx8_rsrc_clk->clk);
                        imx8_rsrc_clk->rate = clk_hw_get_rate(__clk_get_hw(imx8_rsrc_clk->clk));
+               }
        }
        return imx8_pd_power(domain, false);
 }
@@ -140,41 +147,40 @@ static int imx8_attach_dev(struct generic_pm_domain *genpd, struct device *dev)
        struct imx8_pm_domain *pd;
        struct device_node *node = dev->of_node;
        struct of_phandle_args clkspec;
-       struct property *prop;
-       const __be32 *cur;
-       int rc, index = 0;
-       u32 rate;
+       int rc, index, num_clks;
 
        pd = container_of(genpd, struct imx8_pm_domain, pd);
-
        INIT_LIST_HEAD(&pd->clks);
-       of_property_for_each_u32(node, "assigned-clock-rates",
-               prop, cur, rate) {
-               if (rate) {
-                       struct imx8_pm_rsrc_clks *imx8_rsrc_clk;
-
-                       rc = of_parse_phandle_with_args(node, "assigned-clocks",
-                                       "#clock-cells", index, &clkspec);
-                       if (rc < 0) {
-                               /* skip empty (null) phandles */
-                               if (rc == -ENOENT)
-                                       continue;
-                               else
-                                       return rc;
-                       }
-                       if (clkspec.np == node)
-                               return 0;
-
-                       imx8_rsrc_clk = devm_kzalloc(dev,
-                               sizeof(*imx8_rsrc_clk), GFP_KERNEL);
-                       if (!imx8_rsrc_clk)
-                               return -ENOMEM;
 
-                       imx8_rsrc_clk->clk = of_clk_get_from_provider(&clkspec);
-                       if (!IS_ERR(imx8_rsrc_clk->clk))
-                               list_add_tail(&imx8_rsrc_clk->node, &pd->clks);
+       num_clks = of_count_phandle_with_args(node, "assigned-clocks",
+                                               "#clock-cells");
+       if (num_clks == -EINVAL)
+               pr_err("%s: Invalid value of assigned-clocks property at %s\n",
+                       pd->name, node->full_name);
+
+       for (index = 0; index < num_clks; index++) {
+               struct imx8_pm_rsrc_clks *imx8_rsrc_clk;
+
+               rc = of_parse_phandle_with_args(node, "assigned-clocks",
+                                       "#clock-cells", index, &clkspec);
+               if (rc < 0) {
+                       /* skip empty (null) phandles */
+                       if (rc == -ENOENT)
+                               continue;
+                       else
+                               return rc;
                }
-               index++;
+               if (clkspec.np == node)
+                       return 0;
+
+               imx8_rsrc_clk = devm_kzalloc(dev, sizeof(*imx8_rsrc_clk),
+                                       GFP_KERNEL);
+               if (!imx8_rsrc_clk)
+                       return -ENOMEM;
+
+               imx8_rsrc_clk->clk = of_clk_get_from_provider(&clkspec);
+               if (!IS_ERR(imx8_rsrc_clk->clk))
+                       list_add_tail(&imx8_rsrc_clk->node, &pd->clks);
        }
        return 0;
 }