Commit 3a0e8484 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven

clk: renesas: rcar-gen3: Add boost support to Z clocks

Add support for switching the Z and Z2 clocks between normal and boost
modes, by requesting clock rate changes to parent PLLs.

Inspired by a patch in the BSP by Takeshi Kihara
<takeshi.kihara.df@renesas.com>.
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Acked-by: default avatarStephen Boyd <sboyd@kernel.org>
Reviewed-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20210326120100.1577596-8-geert+renesas@glider.be
parent 3f707956
...@@ -165,6 +165,7 @@ struct cpg_z_clk { ...@@ -165,6 +165,7 @@ struct cpg_z_clk {
struct clk_hw hw; struct clk_hw hw;
void __iomem *reg; void __iomem *reg;
void __iomem *kick_reg; void __iomem *kick_reg;
unsigned long max_rate; /* Maximum rate for normal mode */
unsigned int fixed_div; unsigned int fixed_div;
u32 mask; u32 mask;
}; };
...@@ -190,7 +191,18 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, ...@@ -190,7 +191,18 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw,
{ {
struct cpg_z_clk *zclk = to_z_clk(hw); struct cpg_z_clk *zclk = to_z_clk(hw);
unsigned int min_mult, max_mult, mult; unsigned int min_mult, max_mult, mult;
unsigned long prate; unsigned long rate, prate;
rate = min(req->rate, req->max_rate);
if (rate <= zclk->max_rate) {
/* Set parent rate to initial value for normal modes */
prate = zclk->max_rate;
} else {
/* Set increased parent rate for boost modes */
prate = rate;
}
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
prate * zclk->fixed_div);
prate = req->best_parent_rate / zclk->fixed_div; prate = req->best_parent_rate / zclk->fixed_div;
min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
...@@ -198,7 +210,7 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, ...@@ -198,7 +210,7 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw,
if (max_mult < min_mult) if (max_mult < min_mult)
return -EINVAL; return -EINVAL;
mult = DIV_ROUND_CLOSEST_ULL(req->rate * 32ULL, prate); mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
mult = clamp(mult, min_mult, max_mult); mult = clamp(mult, min_mult, max_mult);
req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
...@@ -268,7 +280,7 @@ static struct clk * __init cpg_z_clk_register(const char *name, ...@@ -268,7 +280,7 @@ static struct clk * __init cpg_z_clk_register(const char *name,
init.name = name; init.name = name;
init.ops = &cpg_z_clk_ops; init.ops = &cpg_z_clk_ops;
init.flags = 0; init.flags = CLK_SET_RATE_PARENT;
init.parent_names = &parent_name; init.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
...@@ -279,9 +291,13 @@ static struct clk * __init cpg_z_clk_register(const char *name, ...@@ -279,9 +291,13 @@ static struct clk * __init cpg_z_clk_register(const char *name,
zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
clk = clk_register(NULL, &zclk->hw); clk = clk_register(NULL, &zclk->hw);
if (IS_ERR(clk)) if (IS_ERR(clk)) {
kfree(zclk); kfree(zclk);
return clk;
}
zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
zclk->fixed_div;
return clk; return clk;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment