Thread (8 messages) 8 messages, 3 authors, 2021-05-31

Re: [PATCH 1/3] soc: mtk-pm-domains: Fix the clock prepared issue

From: Enric Balletbo Serra <eballetbo@gmail.com>
Date: 2021-05-31 21:38:41
Also in: linux-arm-kernel, lkml

Hi Hsin-Yi,

Thank you for the patch.

Missatge de Hsin-Yi Wang [off-list ref] del dia dl., 31 de maig
2021 a les 6:35:
From: Weiyi Lu <redacted>

In this new power domain driver, when adding one power domain
it will prepare the depenedent clocks at the same.
Typo: s/depenedent/dependent/
So we only do clk_bulk_enable/disable control during power ON/OFF.
When system suspend, the pm runtime framework will forcely power off
power domains. However, the dependent clocks are disabled but kept
preapred.
Typo: s/preapred/prepared
In MediaTek clock drivers, PLL would be turned ON when we do
clk_bulk_prepare control.

Clock hierarchy:
PLL -->
       DIV_CK -->
                 CLK_MUX
                 (may be dependent clocks)
                         -->
                             SUBSYS_CG
                             (may be dependent clocks)

It will lead some unexpected clock states during system suspend.
This patch will fix by doing prepare_enable/disable_unprepare on
dependent clocks at the same time while we are going to power on/off
any power domain.
I think it would be nice to have a Fixes tag here, so this can be
backported more easily.
Signed-off-by: Weiyi Lu <redacted>
Signed-off-by: Hsin-Yi Wang <redacted>
Reviewed-by: Enric Balletbo i Serra <redacted>
quoted hunk ↗ jump to hunk
---
 drivers/soc/mediatek/mtk-pm-domains.c | 31 +++++++--------------------
 1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c
index 0af00efa0ef8..536d8c64b2b4 100644
--- a/drivers/soc/mediatek/mtk-pm-domains.c
+++ b/drivers/soc/mediatek/mtk-pm-domains.c
@@ -211,7 +211,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
        if (ret)
                return ret;

-       ret = clk_bulk_enable(pd->num_clks, pd->clks);
+       ret = clk_bulk_prepare_enable(pd->num_clks, pd->clks);
        if (ret)
                goto err_reg;
@@ -229,7 +229,7 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
        regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
        regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);

-       ret = clk_bulk_enable(pd->num_subsys_clks, pd->subsys_clks);
+       ret = clk_bulk_prepare_enable(pd->num_subsys_clks, pd->subsys_clks);
        if (ret)
                goto err_pwr_ack;
@@ -246,9 +246,9 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
 err_disable_sram:
        scpsys_sram_disable(pd);
 err_disable_subsys_clks:
-       clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks);
+       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);
 err_pwr_ack:
-       clk_bulk_disable(pd->num_clks, pd->clks);
+       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);
 err_reg:
        scpsys_regulator_disable(pd->supply);
        return ret;
@@ -269,7 +269,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
        if (ret < 0)
                return ret;

-       clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks);
+       clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks);

        /* subsys power off */
        regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
@@ -284,7 +284,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
        if (ret < 0)
                return ret;

-       clk_bulk_disable(pd->num_clks, pd->clks);
+       clk_bulk_disable_unprepare(pd->num_clks, pd->clks);

        scpsys_regulator_disable(pd->supply);
@@ -405,14 +405,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
                pd->subsys_clks[i].clk = clk;
        }

-       ret = clk_bulk_prepare(pd->num_clks, pd->clks);
-       if (ret)
-               goto err_put_subsys_clocks;
-
-       ret = clk_bulk_prepare(pd->num_subsys_clks, pd->subsys_clks);
-       if (ret)
-               goto err_unprepare_clocks;
-
        /*
         * Initially turn on all domains to make the domains usable
         * with !CONFIG_PM and to get the hardware in sync with the
@@ -427,7 +419,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
                ret = scpsys_power_on(&pd->genpd);
                if (ret < 0) {
                        dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
-                       goto err_unprepare_clocks;
+                       goto err_put_subsys_clocks;
                }
        }
@@ -435,7 +427,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
                ret = -EINVAL;
                dev_err(scpsys->dev,
                        "power domain with id %d already exists, check your device-tree\n", id);
-               goto err_unprepare_subsys_clocks;
+               goto err_put_subsys_clocks;
        }

        if (!pd->data->name)
@@ -455,10 +447,6 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no

        return scpsys->pd_data.domains[id];

-err_unprepare_subsys_clocks:
-       clk_bulk_unprepare(pd->num_subsys_clks, pd->subsys_clks);
-err_unprepare_clocks:
-       clk_bulk_unprepare(pd->num_clks, pd->clks);
 err_put_subsys_clocks:
        clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
 err_put_clocks:
@@ -537,10 +525,7 @@ static void scpsys_remove_one_domain(struct scpsys_domain *pd)
                        "failed to remove domain '%s' : %d - state may be inconsistent\n",
                        pd->genpd.name, ret);

-       clk_bulk_unprepare(pd->num_clks, pd->clks);
        clk_bulk_put(pd->num_clks, pd->clks);
-
-       clk_bulk_unprepare(pd->num_subsys_clks, pd->subsys_clks);
        clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
 }

--
2.32.0.rc0.204.g9fa02ecfa5-goog


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help