Skip to content

Commit 03108a2

Browse files
prabhakarladgeertu
authored andcommitted
clk: renesas: rzv2h: Add selective Runtime PM support for clocks
Update `rzv2h_cpg_attach_dev` to prevent external and core clocks not tied to the power domain from being managed by Runtime PM. This ensures that only clocks originating from the domain are controlled, thereby avoiding unintended handling of external and core clocks. Additionally, introduce a `no_pm` flag in `mod_clock` and `rzv2h_mod_clk` structures to exclude specific clocks from Runtime PM when needed. Some clocks, such as those in the CRU block, require unique enable/disable sequences that are incompatible with standard Runtime PM. For example, the CSI-2 D-PHY clock initialization requires toggling individual clocks, making Runtime PM unsuitable. The helper function `rzv2h_cpg_is_pm_clk()` checks whether a clock should be managed by Runtime PM based on this `no_pm` flag. New macros, such as `DEF_MOD_NO_PM`, allow straightforward declaration of clocks that bypass PM. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/20241202203916.48668-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
1 parent 8b2a89f commit 03108a2

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

drivers/clk/renesas/rzv2h-cpg.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct pll_clk {
9898
*
9999
* @priv: CPG private data
100100
* @hw: handle between common and hardware-specific interfaces
101+
* @no_pm: flag to indicate PM is not supported
101102
* @on_index: register offset
102103
* @on_bit: ON/MON bit
103104
* @mon_index: monitor register offset
@@ -106,6 +107,7 @@ struct pll_clk {
106107
struct mod_clock {
107108
struct rzv2h_cpg_priv *priv;
108109
struct clk_hw hw;
110+
bool no_pm;
109111
u8 on_index;
110112
u8 on_bit;
111113
s8 mon_index;
@@ -541,6 +543,7 @@ rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
541543
clock->on_bit = mod->on_bit;
542544
clock->mon_index = mod->mon_index;
543545
clock->mon_bit = mod->mon_bit;
546+
clock->no_pm = mod->no_pm;
544547
clock->priv = priv;
545548
clock->hw.init = &init;
546549

@@ -668,17 +671,51 @@ struct rzv2h_cpg_pd {
668671
struct generic_pm_domain genpd;
669672
};
670673

674+
static bool rzv2h_cpg_is_pm_clk(struct rzv2h_cpg_pd *pd,
675+
const struct of_phandle_args *clkspec)
676+
{
677+
if (clkspec->np != pd->genpd.dev.of_node || clkspec->args_count != 2)
678+
return false;
679+
680+
switch (clkspec->args[0]) {
681+
case CPG_MOD: {
682+
struct rzv2h_cpg_priv *priv = pd->priv;
683+
unsigned int id = clkspec->args[1];
684+
struct mod_clock *clock;
685+
686+
if (id >= priv->num_mod_clks)
687+
return false;
688+
689+
if (priv->clks[priv->num_core_clks + id] == ERR_PTR(-ENOENT))
690+
return false;
691+
692+
clock = to_mod_clock(__clk_get_hw(priv->clks[priv->num_core_clks + id]));
693+
694+
return !clock->no_pm;
695+
}
696+
697+
case CPG_CORE:
698+
default:
699+
return false;
700+
}
701+
}
702+
671703
static int rzv2h_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
672704
{
705+
struct rzv2h_cpg_pd *pd = container_of(domain, struct rzv2h_cpg_pd, genpd);
673706
struct device_node *np = dev->of_node;
674707
struct of_phandle_args clkspec;
675708
bool once = true;
676709
struct clk *clk;
710+
unsigned int i;
677711
int error;
678-
int i = 0;
679712

680-
while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
681-
&clkspec)) {
713+
for (i = 0; !of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, &clkspec); i++) {
714+
if (!rzv2h_cpg_is_pm_clk(pd, &clkspec)) {
715+
of_node_put(clkspec.np);
716+
continue;
717+
}
718+
682719
if (once) {
683720
once = false;
684721
error = pm_clk_create(dev);
@@ -700,7 +737,6 @@ static int rzv2h_cpg_attach_dev(struct generic_pm_domain *domain, struct device
700737
error);
701738
goto fail_put;
702739
}
703-
i++;
704740
}
705741

706742
return 0;

drivers/clk/renesas/rzv2h-cpg.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ enum clk_types {
100100
* @name: handle between common and hardware-specific interfaces
101101
* @parent: id of parent clock
102102
* @critical: flag to indicate the clock is critical
103+
* @no_pm: flag to indicate PM is not supported
103104
* @on_index: control register index
104105
* @on_bit: ON bit
105106
* @mon_index: monitor register index
@@ -109,28 +110,33 @@ struct rzv2h_mod_clk {
109110
const char *name;
110111
u16 parent;
111112
bool critical;
113+
bool no_pm;
112114
u8 on_index;
113115
u8 on_bit;
114116
s8 mon_index;
115117
u8 mon_bit;
116118
};
117119

118-
#define DEF_MOD_BASE(_name, _parent, _critical, _onindex, _onbit, _monindex, _monbit) \
120+
#define DEF_MOD_BASE(_name, _parent, _critical, _no_pm, _onindex, _onbit, _monindex, _monbit) \
119121
{ \
120122
.name = (_name), \
121123
.parent = (_parent), \
122124
.critical = (_critical), \
125+
.no_pm = (_no_pm), \
123126
.on_index = (_onindex), \
124127
.on_bit = (_onbit), \
125128
.mon_index = (_monindex), \
126129
.mon_bit = (_monbit), \
127130
}
128131

129132
#define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit) \
130-
DEF_MOD_BASE(_name, _parent, false, _onindex, _onbit, _monindex, _monbit)
133+
DEF_MOD_BASE(_name, _parent, false, false, _onindex, _onbit, _monindex, _monbit)
131134

132135
#define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit) \
133-
DEF_MOD_BASE(_name, _parent, true, _onindex, _onbit, _monindex, _monbit)
136+
DEF_MOD_BASE(_name, _parent, true, false, _onindex, _onbit, _monindex, _monbit)
137+
138+
#define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit) \
139+
DEF_MOD_BASE(_name, _parent, false, true, _onindex, _onbit, _monindex, _monbit)
134140

135141
/**
136142
* struct rzv2h_reset - Reset definitions

0 commit comments

Comments
 (0)