soc: renesas: rmobile-sysc: Set GENPD_FLAG_ALWAYS_ON for always-on domain
authorGeert Uytterhoeven <geert+renesas@glider.be>
Fri, 9 Aug 2019 13:43:07 +0000 (15:43 +0200)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Fri, 23 Aug 2019 07:58:01 +0000 (09:58 +0200)
Currently the R-Mobile "always-on" PM Domain is implemented by returning
-EBUSY from the generic_pm_domain.power_off() callback, and doing
nothing in the generic_pm_domain.power_on() callback.  However, this
means the PM Domain core code is not aware of the semantics of this
special domain, leading to boot warnings like the following on
SH/R-Mobile SoCs:

    sh_cmt e6130000.timer: PM domain c5 will not be powered off

Fix this by making the always-on nature of the domain explicit instead,
by setting the GENPD_FLAG_ALWAYS_ON flag.  This removes the need for the
domain to provide power control callbacks.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/soc/renesas/rmobile-sysc.c

index 421ae1c887d824d099235cbc2d0974b673d99736..54b616ad4a62aa8bf3bbc18327f43c96c3959926 100644 (file)
@@ -48,12 +48,8 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
 static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 {
        struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
-       unsigned int mask;
+       unsigned int mask = BIT(rmobile_pd->bit_shift);
 
-       if (rmobile_pd->bit_shift == ~0)
-               return -EBUSY;
-
-       mask = BIT(rmobile_pd->bit_shift);
        if (rmobile_pd->suspend) {
                int ret = rmobile_pd->suspend();
 
@@ -80,14 +76,10 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 
 static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
 {
-       unsigned int mask;
+       unsigned int mask = BIT(rmobile_pd->bit_shift);
        unsigned int retry_count;
        int ret = 0;
 
-       if (rmobile_pd->bit_shift == ~0)
-               return 0;
-
-       mask = BIT(rmobile_pd->bit_shift);
        if (__raw_readl(rmobile_pd->base + PSTR) & mask)
                return ret;
 
@@ -122,11 +114,15 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
        struct dev_power_governor *gov = rmobile_pd->gov;
 
        genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
-       genpd->power_off                = rmobile_pd_power_down;
-       genpd->power_on                 = rmobile_pd_power_up;
-       genpd->attach_dev               = cpg_mstp_attach_dev;
-       genpd->detach_dev               = cpg_mstp_detach_dev;
-       __rmobile_pd_power_up(rmobile_pd);
+       genpd->attach_dev = cpg_mstp_attach_dev;
+       genpd->detach_dev = cpg_mstp_detach_dev;
+
+       if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
+               genpd->power_off = rmobile_pd_power_down;
+               genpd->power_on = rmobile_pd_power_up;
+               __rmobile_pd_power_up(rmobile_pd);
+       }
+
        pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
 }
 
@@ -270,6 +266,11 @@ static void __init rmobile_setup_pm_domain(struct device_node *np,
                break;
 
        case PD_NORMAL:
+               if (pd->bit_shift == ~0) {
+                       /* Top-level always-on domain */
+                       pr_debug("PM domain %s is always-on domain\n", name);
+                       pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
+               }
                break;
        }