1919#define CLKOUT3 3
2020#define CLKOUTMAX 4
2121
22+ /* Maximum SSI count for per-SSI clocks */
23+ #define ADG_SSI_MAX 10
24+
2225#define BRGCKR_31 (1 << 31)
2326#define BRRx_MASK (x ) (0x3FF & x)
2427
@@ -34,10 +37,14 @@ struct rsnd_adg {
3437 struct clk * adg ;
3538 struct clk * clkin [CLKINMAX ];
3639 struct clk * clkout [CLKOUTMAX ];
40+ /* RZ/G3E: per-SSI ADG clocks (adg-ssi-0 through adg-ssi-9) */
41+ struct clk * clk_adg_ssi [ADG_SSI_MAX ];
42+ struct clk * clk_ssif_supply ;
3743 struct clk * null_clk ;
3844 struct clk_onecell_data onecell ;
3945 struct rsnd_mod mod ;
4046 int clkin_rate [CLKINMAX ];
47+ bool ssi_clk_prepared ;
4148 int clkin_size ;
4249 int clkout_size ;
4350 u32 ckr ;
@@ -343,8 +350,16 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
343350
344351int rsnd_adg_ssi_clk_stop (struct rsnd_mod * ssi_mod )
345352{
353+ struct rsnd_priv * priv = rsnd_mod_to_priv (ssi_mod );
354+ struct rsnd_adg * adg = rsnd_priv_to_adg (priv );
355+ int id = rsnd_mod_id (ssi_mod );
356+
346357 rsnd_adg_set_ssi_clk (ssi_mod , 0 );
347358
359+ /* RZ/G3E: only disable here, unprepare is done in hw_free */
360+ clk_disable (adg -> clk_adg_ssi [id ]);
361+ clk_disable (adg -> clk_ssif_supply );
362+
348363 return 0 ;
349364}
350365
@@ -354,7 +369,8 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
354369 struct rsnd_adg * adg = rsnd_priv_to_adg (priv );
355370 struct device * dev = rsnd_priv_to_dev (priv );
356371 struct rsnd_mod * adg_mod = rsnd_mod_get (adg );
357- int data ;
372+ int id = rsnd_mod_id (ssi_mod );
373+ int ret , data ;
358374 u32 ckr = 0 ;
359375
360376 data = rsnd_adg_clk_query (priv , rate );
@@ -376,9 +392,63 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
376392 (ckr ) ? adg -> brg_rate [ADG_HZ_48 ] :
377393 adg -> brg_rate [ADG_HZ_441 ]);
378394
395+ /*
396+ * RZ/G3E: enable per-SSI and supply clocks
397+ */
398+ ret = clk_enable (adg -> clk_adg_ssi [id ]);
399+ if (ret ) {
400+ dev_err (dev , "Cannot enable adg-ssi-%d ADG clock\n" , id );
401+ return ret ;
402+ }
403+
404+ ret = clk_enable (adg -> clk_ssif_supply );
405+ if (ret ) {
406+ dev_err (dev , "Cannot enable SSIF supply clock\n" );
407+ clk_disable (adg -> clk_adg_ssi [id ]);
408+ return ret ;
409+ }
410+
379411 return 0 ;
380412}
381413
414+ static int rsnd_adg_ssi_clk_prepare (struct rsnd_adg * adg )
415+ {
416+ int i , ret ;
417+
418+ if (adg -> ssi_clk_prepared )
419+ return 0 ;
420+
421+ for (i = 0 ; i < ADG_SSI_MAX ; i ++ ) {
422+ ret = clk_prepare (adg -> clk_adg_ssi [i ]);
423+ if (ret )
424+ goto unwind ;
425+ }
426+ ret = clk_prepare (adg -> clk_ssif_supply );
427+ if (ret )
428+ goto unwind ;
429+
430+ adg -> ssi_clk_prepared = true;
431+ return 0 ;
432+
433+ unwind :
434+ while (i -- )
435+ clk_unprepare (adg -> clk_adg_ssi [i ]);
436+ return ret ;
437+ }
438+
439+ static void rsnd_adg_ssi_clk_unprepare (struct rsnd_adg * adg )
440+ {
441+ int i ;
442+
443+ if (!adg -> ssi_clk_prepared )
444+ return ;
445+ adg -> ssi_clk_prepared = false;
446+
447+ clk_unprepare (adg -> clk_ssif_supply );
448+ for (i = 0 ; i < ADG_SSI_MAX ; i ++ )
449+ clk_unprepare (adg -> clk_adg_ssi [i ]);
450+ }
451+
382452int rsnd_adg_clk_control (struct rsnd_priv * priv , int enable )
383453{
384454 struct rsnd_adg * adg = rsnd_priv_to_adg (priv );
@@ -417,6 +487,28 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
417487 }
418488 }
419489
490+ /*
491+ * rsnd_adg_clk_enable() might return error (_disable() will not).
492+ * We need to rollback in such case
493+ */
494+ /*
495+ * RZ/G3E per-SSI ADG and SSIF supply clocks.
496+ *
497+ * Follow the same style as for_each_rsnd_clkin() above: on enable,
498+ * try to prepare every clock and accumulate the error. On disable,
499+ * unprepare every clock. Absent optional clocks are NULL, for
500+ * which clk_prepare() and clk_unprepare() are no-ops.
501+ */
502+ if (enable ) {
503+ int sub_ret = rsnd_adg_ssi_clk_prepare (adg );
504+
505+ /* Preserve the first error from the clkin loop above. */
506+ if (sub_ret && !ret )
507+ ret = sub_ret ;
508+ } else {
509+ rsnd_adg_ssi_clk_unprepare (adg );
510+ }
511+
420512 /*
421513 * rsnd_adg_clk_enable() might return error (_disable() will not).
422514 * We need to rollback in such case
@@ -769,6 +861,31 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
769861#define rsnd_adg_clk_dbg_info (priv , m )
770862#endif
771863
864+ static int rsnd_adg_get_ssi_clks (struct rsnd_priv * priv )
865+ {
866+ struct rsnd_adg * adg = rsnd_priv_to_adg (priv );
867+ struct device * dev = rsnd_priv_to_dev (priv );
868+ char name [16 ];
869+ int i ;
870+
871+ /* SSIF supply clock */
872+ adg -> clk_ssif_supply = devm_clk_get_optional (dev , "ssif_supply" );
873+ if (IS_ERR (adg -> clk_ssif_supply ))
874+ return dev_err_probe (dev , PTR_ERR (adg -> clk_ssif_supply ),
875+ "failed to get ssif_supply clock\n" );
876+
877+ /* Per-SSI ADG clocks (RZ/G3E-only; no legacy dotted form exists) */
878+ for (i = 0 ; i < ADG_SSI_MAX ; i ++ ) {
879+ snprintf (name , sizeof (name ), "adg-ssi-%d" , i );
880+ adg -> clk_adg_ssi [i ] = devm_clk_get_optional (dev , name );
881+ if (IS_ERR (adg -> clk_adg_ssi [i ]))
882+ return dev_err_probe (dev , PTR_ERR (adg -> clk_adg_ssi [i ]),
883+ "failed to get %s clock\n" , name );
884+ }
885+
886+ return 0 ;
887+ }
888+
772889int rsnd_adg_probe (struct rsnd_priv * priv )
773890{
774891 struct reset_control * rstc ;
@@ -798,6 +915,11 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
798915 if (ret )
799916 return ret ;
800917
918+ /* RZ/G3E-specific: per-SSI ADG and SSIF supply clocks */
919+ ret = rsnd_adg_get_ssi_clks (priv );
920+ if (ret )
921+ return ret ;
922+
801923 ret = rsnd_adg_clk_enable (priv );
802924 if (ret )
803925 return ret ;
0 commit comments