aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk/renesas/rzg2l-cpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/renesas/rzg2l-cpg.c')
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 88bf39e8c79c..ddf722ca79eb 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -548,7 +548,7 @@ static unsigned long
rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
unsigned long rate)
{
- unsigned long foutpostdiv_rate;
+ unsigned long foutpostdiv_rate, foutvco_rate;
params->pl5_intin = rate / MEGA;
params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA);
@@ -557,10 +557,11 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
params->pl5_postdiv2 = 1;
params->pl5_spread = 0x16;
- foutpostdiv_rate =
- EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv *
- ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) /
- (params->pl5_postdiv1 * params->pl5_postdiv2);
+ foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
+ (params->pl5_intin << 24) + params->pl5_fracin),
+ params->pl5_refdiv) >> 24;
+ foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate,
+ params->pl5_postdiv1 * params->pl5_postdiv2);
return foutpostdiv_rate;
}
@@ -1680,23 +1681,31 @@ static int rzg2l_cpg_power_off(struct generic_pm_domain *domain)
return 0;
}
-static int __init rzg2l_cpg_pd_setup(struct rzg2l_cpg_pd *pd, bool always_on)
+static int __init rzg2l_cpg_pd_setup(struct rzg2l_cpg_pd *pd)
{
+ bool always_on = !!(pd->genpd.flags & GENPD_FLAG_ALWAYS_ON);
struct dev_power_governor *governor;
+ int ret;
+
+ if (always_on)
+ governor = &pm_domain_always_on_gov;
+ else
+ governor = &simple_qos_governor;
pd->genpd.flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
pd->genpd.attach_dev = rzg2l_cpg_attach_dev;
pd->genpd.detach_dev = rzg2l_cpg_detach_dev;
- if (always_on) {
- pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
- governor = &pm_domain_always_on_gov;
- } else {
- pd->genpd.power_on = rzg2l_cpg_power_on;
- pd->genpd.power_off = rzg2l_cpg_power_off;
- governor = &simple_qos_governor;
- }
+ pd->genpd.power_on = rzg2l_cpg_power_on;
+ pd->genpd.power_off = rzg2l_cpg_power_off;
+
+ ret = pm_genpd_init(&pd->genpd, governor, !always_on);
+ if (ret)
+ return ret;
- return pm_genpd_init(&pd->genpd, governor, !always_on);
+ if (always_on)
+ ret = rzg2l_cpg_power_on(&pd->genpd);
+
+ return ret;
}
static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
@@ -1711,8 +1720,9 @@ static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
return -ENOMEM;
pd->genpd.name = np->name;
+ pd->genpd.flags = GENPD_FLAG_ALWAYS_ON;
pd->priv = priv;
- ret = rzg2l_cpg_pd_setup(pd, true);
+ ret = rzg2l_cpg_pd_setup(pd);
if (ret)
return ret;
@@ -1777,7 +1787,6 @@ static int __init rzg2l_cpg_add_pm_domains(struct rzg2l_cpg_priv *priv)
return ret;
for (unsigned int i = 0; i < info->num_pm_domains; i++) {
- bool always_on = !!(info->pm_domains[i].flags & RZG2L_PD_F_ALWAYS_ON);
struct rzg2l_cpg_pd *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
@@ -1785,20 +1794,15 @@ static int __init rzg2l_cpg_add_pm_domains(struct rzg2l_cpg_priv *priv)
return -ENOMEM;
pd->genpd.name = info->pm_domains[i].name;
+ pd->genpd.flags = info->pm_domains[i].genpd_flags;
pd->conf = info->pm_domains[i].conf;
pd->id = info->pm_domains[i].id;
pd->priv = priv;
- ret = rzg2l_cpg_pd_setup(pd, always_on);
+ ret = rzg2l_cpg_pd_setup(pd);
if (ret)
return ret;
- if (always_on) {
- ret = rzg2l_cpg_power_on(&pd->genpd);
- if (ret)
- return ret;
- }
-
domains->domains[i] = &pd->genpd;
/* Parent should be on the very first entry of info->pm_domains[]. */
if (!i) {