diff mbox series

[4/4] drivers: clk: renesas: enable all clocks which is assinged to non Linux system

Message ID 87wmulrynq.wl-kuninori.morimoto.gx@renesas.com (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show
Series drivers: clk: renesas: enable all clocks which is assinged to non Linux system | expand

Commit Message

Kuninori Morimoto Nov. 14, 2023, 12:01 a.m. UTC
Some board might use Linux and another OS in the same time. In such
case, current Linux will stop necessary module clock when booting
which is not used on Linux side, but is used on another OS side.

To avoid such situation, renesas-cpg-mssr try to find
status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
<&cgp CPG_MOD xxx> clock (B).

Table 2.4: Values for status property
https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf

"reserved"
	Indicates that the device is operational, but should not be
	used. Typically this is used for devices that are controlled
	by another software component, such as platform firmware.

ex)
	scif5: serial@e6f30000 {
		...
(B)		clocks = <&cpg CPG_MOD 202>,
			 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
			 <&scif_clk>;
		...
(A)		status = "reserved";
	};

Cc: Aymeric Aillet <aymeric.aillet@iot.bzh>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
---
 drivers/clk/renesas/renesas-cpg-mssr.c | 116 +++++++++++++++++++++++--
 1 file changed, 107 insertions(+), 9 deletions(-)

Comments

kernel test robot Nov. 14, 2023, 1:10 p.m. UTC | #1
Hi Kuninori,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on geert-renesas-drivers/renesas-clk clk/clk-next linus/master v6.7-rc1 next-20231114]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kuninori-Morimoto/of-add-__of_device_is_status-and-makes-more-generic-status-check/20231114-081044
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/87wmulrynq.wl-kuninori.morimoto.gx%40renesas.com
patch subject: [PATCH 4/4] drivers: clk: renesas: enable all clocks which is assinged to non Linux system
config: loongarch-allmodconfig (https://download.01.org/0day-ci/archive/20231114/202311142059.XrPUseGq-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231114/202311142059.XrPUseGq-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311142059.XrPUseGq-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/clk/renesas/renesas-cpg-mssr.c:175: warning: Function parameter or member 'reserved_ids' not described in 'cpg_mssr_priv'
>> drivers/clk/renesas/renesas-cpg-mssr.c:175: warning: Function parameter or member 'num_reserved_ids' not described in 'cpg_mssr_priv'


vim +175 drivers/clk/renesas/renesas-cpg-mssr.c

17bcc8035d2d19 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  124  
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  125  /**
b5fb3b8859a491 drivers/clk/renesas/renesas-cpg-mssr.c  Krzysztof Kozlowski 2020-11-03  126   * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby
b5fb3b8859a491 drivers/clk/renesas/renesas-cpg-mssr.c  Krzysztof Kozlowski 2020-11-03  127   *                        and Software Reset Private Data
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  128   *
6197aa65c49055 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  129   * @rcdev: Optional reset controller entity
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  130   * @dev: CPG/MSSR device
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  131   * @base: CPG/MSSR register block base address
ffbf9cf3f9460e drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  132   * @reg_layout: CPG/MSSR register layout
a4ea6a0f83073f drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  133   * @rmw_lock: protects RMW register accesses
d2e4cb45af8fac drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2019-06-12  134   * @np: Device node in DT for this CPG/MSSR module
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  135   * @num_core_clks: Number of Core Clocks in clks[]
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  136   * @num_mod_clks: Number of Module Clocks in clks[]
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  137   * @last_dt_core_clk: ID of the last Core Clock exported to DT
1f4023cdd1bdbe drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-21  138   * @notifiers: Notifier chain to save/restore clock state for system resume
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  139   * @status_regs: Pointer to status registers array
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  140   * @control_regs: Pointer to control registers array
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  141   * @reset_regs: Pointer to reset registers array
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  142   * @reset_clear_regs:  Pointer to reset clearing registers array
24ece96554a963 drivers/clk/renesas/renesas-cpg-mssr.c  Lee Jones           2021-01-26  143   * @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control
24ece96554a963 drivers/clk/renesas/renesas-cpg-mssr.c  Lee Jones           2021-01-26  144   *                 [].val: Saved values of SMSTPCR[]
8f5e20b6b8848b drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2019-06-12  145   * @clks: Array containing all Core and Module Clocks
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  146   */
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  147  struct cpg_mssr_priv {
6197aa65c49055 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  148  #ifdef CONFIG_RESET_CONTROLLER
6197aa65c49055 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  149  	struct reset_controller_dev rcdev;
6197aa65c49055 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  150  #endif
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  151  	struct device *dev;
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  152  	void __iomem *base;
ffbf9cf3f9460e drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  153  	enum clk_reg_layout reg_layout;
a4ea6a0f83073f drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-01-20  154  	spinlock_t rmw_lock;
1f7db7bbf03182 drivers/clk/renesas/renesas-cpg-mssr.c  Chris Brandt        2018-09-24  155  	struct device_node *np;
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  156  
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  157  	unsigned int num_core_clks;
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  158  	unsigned int num_mod_clks;
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  159  	unsigned int last_dt_core_clk;
560869100b99a3 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-07  160  
1f4023cdd1bdbe drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-21  161  	struct raw_notifier_head notifiers;
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  162  	const u16 *status_regs;
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  163  	const u16 *control_regs;
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  164  	const u16 *reset_regs;
8b652aa8a1fb02 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2020-09-11  165  	const u16 *reset_clear_regs;
560869100b99a3 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-07  166  	struct {
560869100b99a3 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-07  167  		u32 mask;
560869100b99a3 drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2017-06-07  168  		u32 val;
470e3f0d0b1529 drivers/clk/renesas/renesas-cpg-mssr.c  Yoshihiro Shimoda   2021-12-01  169  	} smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
8f5e20b6b8848b drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2019-06-12  170  
b357c19f075f23 drivers/clk/renesas/renesas-cpg-mssr.c  Kuninori Morimoto   2023-11-14  171  	unsigned int *reserved_ids;
b357c19f075f23 drivers/clk/renesas/renesas-cpg-mssr.c  Kuninori Morimoto   2023-11-14  172  	unsigned int num_reserved_ids;
b357c19f075f23 drivers/clk/renesas/renesas-cpg-mssr.c  Kuninori Morimoto   2023-11-14  173  
8f5e20b6b8848b drivers/clk/renesas/renesas-cpg-mssr.c  Geert Uytterhoeven  2019-06-12  174  	struct clk *clks[];
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16 @175  };
f793d1e51705b2 drivers/clk/shmobile/renesas-cpg-mssr.c Geert Uytterhoeven  2015-10-16  176
Kuninori Morimoto Nov. 16, 2023, 1:04 a.m. UTC | #2
Hi kernel test

> kernel test robot noticed the following build warnings:
(snip)
> >> drivers/clk/renesas/renesas-cpg-mssr.c:175: warning: Function parameter or member 'reserved_ids' not described in 'cpg_mssr_priv'
> >> drivers/clk/renesas/renesas-cpg-mssr.c:175: warning: Function parameter or member 'num_reserved_ids' not described in 'cpg_mssr_priv'

Thank you for the report.
I will fixup it on v2.

Thank you for your help !!

Best regards
---
Kuninori Morimoto
Rob Herring Nov. 16, 2023, 7:23 p.m. UTC | #3
On Tue, Nov 14, 2023 at 12:01:14AM +0000, Kuninori Morimoto wrote:
> Some board might use Linux and another OS in the same time. In such
> case, current Linux will stop necessary module clock when booting
> which is not used on Linux side, but is used on another OS side.
> 
> To avoid such situation, renesas-cpg-mssr try to find
> status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
> <&cgp CPG_MOD xxx> clock (B).

See Stephen's presentation from Plumbers this week. The default behavior 
for unused clocks may be changing soon.

> 
> Table 2.4: Values for status property
> https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
> 
> "reserved"
> 	Indicates that the device is operational, but should not be
> 	used. Typically this is used for devices that are controlled
> 	by another software component, such as platform firmware.
> 
> ex)
> 	scif5: serial@e6f30000 {
> 		...
> (B)		clocks = <&cpg CPG_MOD 202>,
> 			 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
> 			 <&scif_clk>;
> 		...
> (A)		status = "reserved";
> 	};

I have some reservations about whether a reserved node should be touched 
at all by Linux. I suppose since it is platform specific, it's okay. I 
don't think we could apply such behavior globally.

Rob
Geert Uytterhoeven Nov. 16, 2023, 9:08 p.m. UTC | #4
Hi Rob,

On Thu, Nov 16, 2023 at 8:23 PM Rob Herring <robh@kernel.org> wrote:
> On Tue, Nov 14, 2023 at 12:01:14AM +0000, Kuninori Morimoto wrote:
> > Some board might use Linux and another OS in the same time. In such
> > case, current Linux will stop necessary module clock when booting
> > which is not used on Linux side, but is used on another OS side.
> >
> > To avoid such situation, renesas-cpg-mssr try to find
> > status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
> > <&cgp CPG_MOD xxx> clock (B).
>
> See Stephen's presentation from Plumbers this week. The default behavior
> for unused clocks may be changing soon.

Thank you!

ou mean "Make sync_state()/handoff work for the common clk
framework"[1]? IIUIC, that presentation didn't cover the problem we are
facing, except for the big "Kconfig for clk_ignore_unused=true" hammer.

> > Table 2.4: Values for status property
> > https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
> >
> > "reserved"
> >       Indicates that the device is operational, but should not be
> >       used. Typically this is used for devices that are controlled
> >       by another software component, such as platform firmware.
> >
> > ex)
> >       scif5: serial@e6f30000 {
> >               ...
> > (B)           clocks = <&cpg CPG_MOD 202>,
> >                        <&cpg CPG_CORE R8A7795_CLK_S3D1>,
> >                        <&scif_clk>;
> >               ...
> > (A)           status = "reserved";
> >       };
>
> I have some reservations about whether a reserved node should be touched
> at all by Linux. I suppose since it is platform specific, it's okay. I
> don't think we could apply such behavior globally.

That's an interesting comment, as the issue is that currently Linux
does touch (resources belonging to) reserved nodes, and this patch
would prevent doing that for module clock resources;-)

The core issue is that Linux distinguishes only between two cases:
  1. "device is used by Linux" (if a driver is available),
     as indicated by 'status = "okay"' in DT, or
  2. "device is unused by Linux".
On a heterogenous system, the latter actually comprises two cases:
  2a. "device is unused", or
  2b. "device is used by another OS running on another CPU core".

Looking for 'status = "reserved"' allows us to distinguish between 2a
and 2b, and can prevent disabling clocks that are used by another OS.
Probably we need a similar solution for power domains.

Do you have a better or alternative suggestion?
Thanks!

[1] https://lpc.events/event/17/contributions/1432/
    https://www.youtube.com/watch?v=NSSSIVQgsIk?t=164m

Gr{oetje,eeting}s,

                        Geert
Stephen Boyd Nov. 27, 2023, 9:32 p.m. UTC | #5
Quoting Geert Uytterhoeven (2023-11-16 13:08:46)
> On Thu, Nov 16, 2023 at 8:23 PM Rob Herring <robh@kernel.org> wrote:
> > On Tue, Nov 14, 2023 at 12:01:14AM +0000, Kuninori Morimoto wrote:
> > > Some board might use Linux and another OS in the same time. In such
> > > case, current Linux will stop necessary module clock when booting
> > > which is not used on Linux side, but is used on another OS side.
> > >
> > > To avoid such situation, renesas-cpg-mssr try to find
> > > status = "reserved" devices (A), and add CLK_IGNORE_UNUSED flag to its
> > > <&cgp CPG_MOD xxx> clock (B).
> >
> > See Stephen's presentation from Plumbers this week. The default behavior
> > for unused clocks may be changing soon.
> 
> Thank you!
> 
> ou mean "Make sync_state()/handoff work for the common clk
> framework"[1]? IIUIC, that presentation didn't cover the problem we are
> facing, except for the big "Kconfig for clk_ignore_unused=true" hammer.

:)

> 
> > > Table 2.4: Values for status property
> > > https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
> > >
> > > "reserved"
> > >       Indicates that the device is operational, but should not be
> > >       used. Typically this is used for devices that are controlled
> > >       by another software component, such as platform firmware.
> > >
> > > ex)
> > >       scif5: serial@e6f30000 {
> > >               ...
> > > (B)           clocks = <&cpg CPG_MOD 202>,
> > >                        <&cpg CPG_CORE R8A7795_CLK_S3D1>,
> > >                        <&scif_clk>;
> > >               ...
> > > (A)           status = "reserved";
> > >       };
> >
> > I have some reservations about whether a reserved node should be touched
> > at all by Linux. I suppose since it is platform specific, it's okay. I
> > don't think we could apply such behavior globally.
> 
> That's an interesting comment, as the issue is that currently Linux
> does touch (resources belonging to) reserved nodes, and this patch
> would prevent doing that for module clock resources;-)

I think I get it.

> 
> The core issue is that Linux distinguishes only between two cases:
>   1. "device is used by Linux" (if a driver is available),
>      as indicated by 'status = "okay"' in DT, or
>   2. "device is unused by Linux".
> On a heterogenous system, the latter actually comprises two cases:
>   2a. "device is unused", or
>   2b. "device is used by another OS running on another CPU core".
> 
> Looking for 'status = "reserved"' allows us to distinguish between 2a
> and 2b, and can prevent disabling clocks that are used by another OS.
> Probably we need a similar solution for power domains.
> 
> Do you have a better or alternative suggestion?

Does the protected-clocks property work? That basically says "don't use
these clks in the OS". The driver implementation would not register
those clks and then the framework would be unaware of their existence,
leading to them never being disabled during late init.

This approach also looks OK to me, basically programmatically creating
the protected-clocks list by parsing DT for reserved consumer nodes and
then figuring out that no consumer exists so we can skip registering the
clk entirely, or add the flag. I'm not sure we want to implement that
policy globally, because maybe someone really wants to disable the clk
still to clean up bootloader state and then let a remoteproc use the clk
later.

Do you want to keep those clks registered with the framework? Is there
any benefit to keeping clks around if linux can't do anything with them?
Kuninori Morimoto Nov. 27, 2023, 11:48 p.m. UTC | #6
Hi Stephen

Thank you for your feedback

> Does the protected-clocks property work? That basically says "don't use
> these clks in the OS". The driver implementation would not register
> those clks and then the framework would be unaware of their existence,
> leading to them never being disabled during late init.
> 
> This approach also looks OK to me, basically programmatically creating
> the protected-clocks list by parsing DT for reserved consumer nodes and
> then figuring out that no consumer exists so we can skip registering the
> clk entirely, or add the flag. I'm not sure we want to implement that
> policy globally, because maybe someone really wants to disable the clk
> still to clean up bootloader state and then let a remoteproc use the clk
> later.
> 
> Do you want to keep those clks registered with the framework? Is there
> any benefit to keeping clks around if linux can't do anything with them?

Actually, this idea (= using "protected-clocks" property style) was our 1st
idea, but I noticed that it is not enough. Because clock driver is possible
to know which module was not used on Linux, but other driver can't, in this
idea. For example, power-domain control driver might want to know about it.

In case of using "protected-clocks" property, we need to have same/similar
settings on each driver, but in case of using "status = reserved", all
driver is possible to know it. It has consistent, and no contradict like
some module was listed as "protected-clocks" on clock / power driver,
but has "status = ok" on its driver, etc.

It seems we have different opinions around here ?

Our other idea was having "unassigned" node instead of
"status = reserved", like below.
clock driver checks "unassigned" node's "devices" property, and
ignore/disable listed device's "clocks".

	unassigned {
		devices = <&scif1>, <&hsusb>;
	};

	scif1: serial@xxxx {
		status = "disabled";
		clocks = <&cpg CPG_MOD 206>,
			 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
			 <&scif_clk>;
		...
	};

	hsusb: usb@xxxx {
		status = "disabled";
		clocks = <&cpg CPG_MOD 704>, <&cpg CPG_MOD 703>;
		...
	};



Thank you for your help !!

Best regards
---
Kuninori Morimoto
Stephen Boyd Dec. 1, 2023, 10:39 p.m. UTC | #7
Quoting Kuninori Morimoto (2023-11-27 23:48:04)
> 
> Hi Stephen
> 
> Thank you for your feedback
> 
> > Does the protected-clocks property work? That basically says "don't use
> > these clks in the OS". The driver implementation would not register
> > those clks and then the framework would be unaware of their existence,
> > leading to them never being disabled during late init.
> > 
> > This approach also looks OK to me, basically programmatically creating
> > the protected-clocks list by parsing DT for reserved consumer nodes and
> > then figuring out that no consumer exists so we can skip registering the
> > clk entirely, or add the flag. I'm not sure we want to implement that
> > policy globally, because maybe someone really wants to disable the clk
> > still to clean up bootloader state and then let a remoteproc use the clk
> > later.
> > 
> > Do you want to keep those clks registered with the framework? Is there
> > any benefit to keeping clks around if linux can't do anything with them?
> 
> Actually, this idea (= using "protected-clocks" property style) was our 1st
> idea, but I noticed that it is not enough. Because clock driver is possible
> to know which module was not used on Linux, but other driver can't, in this
> idea. For example, power-domain control driver might want to know about it.
> 
> In case of using "protected-clocks" property, we need to have same/similar
> settings on each driver, but in case of using "status = reserved", all
> driver is possible to know it. It has consistent, and no contradict like
> some module was listed as "protected-clocks" on clock / power driver,
> but has "status = ok" on its driver, etc.
> 
> It seems we have different opinions around here ?

I don't really have any opinion here.

> 
> Our other idea was having "unassigned" node instead of
> "status = reserved", like below.
> clock driver checks "unassigned" node's "devices" property, and
> ignore/disable listed device's "clocks".
> 
>         unassigned {
>                 devices = <&scif1>, <&hsusb>;
>         };

This approach looks like the chosen node. I'd say what you have done in
this patch series is better. The protected-clocks property is really
about clks that shouldn't be used by the OS on some board. In your case
it sounds like you want to still be able to read the clk hardware? Does
anything go wrong if you let some consumer get the clk and change
settings? Do you want to prevent that from happening? I'm mostly
thinking it may be useful to have this logic be common in the clk
framework by having the framework search through DT and figure out that
the only consumers are reserved and thus we should treat those clks as
read-only in the framework.
Kuninori Morimoto Dec. 4, 2023, 12:26 a.m. UTC | #8
Hi Stephen

Thank you for your feedback

> In your case
> it sounds like you want to still be able to read the clk hardware? Does
> anything go wrong if you let some consumer get the clk and change
> settings? Do you want to prevent that from happening?

We want to do by this patch-set is to ignoring specific device/clk from Linux.
If Linux side change the specific clk settings, other OS side will get damage.

> I'm mostly
> thinking it may be useful to have this logic be common in the clk
> framework by having the framework search through DT and figure out that
> the only consumers are reserved and thus we should treat those clks as
> read-only in the framework.

"this logic" = "this patch-set idea" = "check status=reserved" ?

If so, now I quick checked the code. I think it is difficult or makes the code
complex if we try implement it on framework or common code.
Because the idea itself is very easy (= just adding the CLK_IGNORE_UNUSED),
but how to judge the clks is very vender/driver specific.
In our case, we need to think about total clock number, conver Linux
number to HW number, etc, etc.


# I will goto OSS-Japan conference after tomorrow, thus no response
# from me until next week.

Thank you for your help !!

Best regards
---
Renesas Electronics
Ph.D. Kuninori Morimoto
diff mbox series

Patch

diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index cb80d1bf6c7c..3781861bdfa0 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -168,6 +168,9 @@  struct cpg_mssr_priv {
 		u32 val;
 	} smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
 
+	unsigned int *reserved_ids;
+	unsigned int num_reserved_ids;
+
 	struct clk *clks[];
 };
 
@@ -453,6 +456,19 @@  static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
 			break;
 		}
 
+	/*
+	 * Ignore reserved device.
+	 * see
+	 *	cpg_mssr_reserved_init()
+	 */
+	for (i = 0; i < priv->num_reserved_ids; i++) {
+		if (id == priv->reserved_ids[i]) {
+			dev_info(dev, "Ignore Linux non-assigned mod (%s)\n", mod->name);
+			init.flags |= CLK_IGNORE_UNUSED;
+			break;
+		}
+	}
+
 	clk = clk_register(NULL, &clock->hw);
 	if (IS_ERR(clk))
 		goto fail;
@@ -949,6 +965,75 @@  static const struct dev_pm_ops cpg_mssr_pm = {
 #define DEV_PM_OPS	NULL
 #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
 
+static void __init cpg_mssr_reserved_exit(struct cpg_mssr_priv *priv)
+{
+	kfree(priv->reserved_ids);
+}
+
+static int __init cpg_mssr_reserved_init(struct cpg_mssr_priv *priv,
+					 const struct cpg_mssr_info *info)
+{
+	struct device_node *root = of_find_node_by_path("/soc");
+	struct device_node *node = NULL;
+	struct of_phandle_args clkspec;
+	unsigned int *ids = NULL;
+	unsigned int num = 0;
+
+	/*
+	 * Because cpg_mssr_info has .num_hw_mod_clks which indicates number of all Module Clocks,
+	 * and clk_disable_unused() will disable all unused clocks, the device which is assigned to
+	 * non-Linux system will be disabled when Linux was booted.
+	 *
+	 * To avoid such situation, renesas-cpg-mssr assumes the device which has
+	 * status = "reserved" is assigned to non-Linux system, and add CLK_IGNORE_UNUSED flag
+	 * to its clocks if it was CPG_MOD.
+	 * see also
+	 *	cpg_mssr_register_mod_clk()
+	 *
+	 *	scif5: serial@e6f30000 {
+	 *		...
+	 * =>		clocks = <&cpg CPG_MOD 202>,
+	 *			 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+	 *			 <&scif_clk>;
+	 *			 ...
+	 *		 status = "reserved";
+	 *	};
+	 */
+	for_each_reserved_child_of_node(root, node) {
+		unsigned int i = 0;
+
+		while (!of_parse_phandle_with_args(node, "clocks", "#clock-cells", i++, &clkspec)) {
+
+			of_node_put(clkspec.np);
+
+			if (clkspec.np == priv->dev->of_node &&
+			    clkspec.args[0] == CPG_MOD) {
+
+				ids = krealloc_array(ids, (num + 1), sizeof(*ids), GFP_KERNEL);
+				if (!ids)
+					return -ENOMEM;
+
+				ids[num] = info->num_total_core_clks +
+						MOD_CLK_PACK(clkspec.args[1]);
+
+				num++;
+			}
+		}
+	}
+
+	priv->num_reserved_ids	= num;
+	priv->reserved_ids	= ids;
+
+	return 0;
+}
+
+static void __init cpg_mssr_common_exit(struct cpg_mssr_priv *priv)
+{
+	if (priv->base)
+		iounmap(priv->base);
+	kfree(priv);
+}
+
 static int __init cpg_mssr_common_init(struct device *dev,
 				       struct device_node *np,
 				       const struct cpg_mssr_info *info)
@@ -1012,9 +1097,7 @@  static int __init cpg_mssr_common_init(struct device *dev,
 	return 0;
 
 out_err:
-	if (priv->base)
-		iounmap(priv->base);
-	kfree(priv);
+	cpg_mssr_common_exit(priv);
 
 	return error;
 }
@@ -1029,6 +1112,10 @@  void __init cpg_mssr_early_init(struct device_node *np,
 	if (error)
 		return;
 
+	error = cpg_mssr_reserved_init(cpg_mssr_priv, info);
+	if (error)
+		goto err;
+
 	for (i = 0; i < info->num_early_core_clks; i++)
 		cpg_mssr_register_core_clk(&info->early_core_clks[i], info,
 					   cpg_mssr_priv);
@@ -1037,6 +1124,12 @@  void __init cpg_mssr_early_init(struct device_node *np,
 		cpg_mssr_register_mod_clk(&info->early_mod_clks[i], info,
 					  cpg_mssr_priv);
 
+	cpg_mssr_reserved_exit(cpg_mssr_priv);
+
+	return;
+
+err:
+	cpg_mssr_common_exit(cpg_mssr_priv);
 }
 
 static int __init cpg_mssr_probe(struct platform_device *pdev)
@@ -1060,6 +1153,10 @@  static int __init cpg_mssr_probe(struct platform_device *pdev)
 	priv->dev = dev;
 	dev_set_drvdata(dev, priv);
 
+	error = cpg_mssr_reserved_init(priv, info);
+	if (error)
+		return error;
+
 	for (i = 0; i < info->num_core_clks; i++)
 		cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
 
@@ -1070,22 +1167,23 @@  static int __init cpg_mssr_probe(struct platform_device *pdev)
 					 cpg_mssr_del_clk_provider,
 					 np);
 	if (error)
-		return error;
+		goto reserve_err;
 
 	error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
 					info->num_core_pm_clks);
 	if (error)
-		return error;
+		goto reserve_err;
 
 	/* Reset Controller not supported for Standby Control SoCs */
 	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
-		return 0;
+		goto reserve_err;
 
 	error = cpg_mssr_reset_controller_register(priv);
-	if (error)
-		return error;
 
-	return 0;
+reserve_err:
+	cpg_mssr_reserved_exit(priv);
+
+	return error;
 }
 
 static struct platform_driver cpg_mssr_driver = {