Skip to content

Commit 47899d5

Browse files
John Madieubroonie
authored andcommitted
ASoC: rsnd: adg: Add per-SSI ADG and SSIF supply clock management
RZ/G3E's ADG module requires explicit clock management for SSI audio interfaces that differs from R-Car Gen2/Gen3/Gen4: - Per-SSI ADG clocks (adg-ssi-N, or adg.ssi.N in legacy bindings) for each SSI module - A shared SSIF supply clock for the SSI subsystem These clocks are acquired using optional APIs, making them transparent to platforms that do not require them. Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://patch.msgid.link/20260525110230.4014435-14-john.madieu.xa@bp.renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 9267b89 commit 47899d5

1 file changed

Lines changed: 123 additions & 1 deletion

File tree

  • sound/soc/renesas/rcar

sound/soc/renesas/rcar/adg.c

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
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

344351
int 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+
382452
int 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+
772889
int 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

Comments
 (0)