DFS for FS control 3

This commit is contained in:
Steven Dan
2026-06-18 23:18:12 +08:00
parent ffda68d54a
commit d9ab9f4823
2 changed files with 41 additions and 0 deletions

View File

@@ -31,6 +31,20 @@
#define C1_TILE1_LP_XCORE_DIV_DEFAULT 40
#endif
/* SSwitch (xCONNECT fabric) deep-idle gate (AN02022 "Slow switch clock").
* Defaults to following C1_DFS_EN (FPS build only); set to 0 to disable. */
#ifndef C1_SSWITCH_DFS_EN
#define C1_SSWITCH_DFS_EN C1_DFS_EN
#endif
/* SSwitch low-power divider (SSDIV register value N). switch clock =
* SystemFrequency / (N+1). Engaged ONLY while FPS is OFF (bypass audio never
* crosses the switch). 59 -> ~10 MHz (captures most dynamic-power savings with
* safe LED/cmd latency). Lower = more savings, e.g. 599 -> 1 MHz per AN02022. */
#ifndef C1_SSWITCH_LP_DIV_DEFAULT
#define C1_SSWITCH_LP_DIV_DEFAULT 598
#endif
/* ~100 us settle after restoring full speed (100 MHz timer ticks). */
#define C1_TILE1_CLK_SETTLE_TICKS 10000

View File

@@ -24,6 +24,7 @@ static unsigned c1_tile1_state = C1_TILE1_ACTIVE;
static timer c1_tile1_tmr;
static unsigned c1_tile1_grace_target = 0;
static int c1_tile1_grace_armed = 0;
static int c1_sswitch_is_slow = 0; /* C1_SSWITCH_DFS_EN: 1 while xCONNECT fabric is divided down */
/* ---- clock primitives (AN02022 "xcore.ai Clock Frequency Control") ----
*
@@ -86,6 +87,32 @@ void c1_tile1_power_tick(void)
GET_SHARED_GLOBAL(aud_stream, g_audio_streaming);
int tile1_needed = (fps != 0) && (aud_stream != 0);
#if C1_SSWITCH_DFS_EN
/* SSwitch (xCONNECT fabric) deep-idle (AN02022 "Slow switch clock").
* Slow the fabric ONLY while FPS is OFF: in bypass, audio runs tile[0]-local
* and never crosses the switch, and USB is tile[0]-local, so the fabric can be
* divided for dynamic-power savings. Restore to full speed FIRST whenever FPS
* is on -- before the tile[1] clock restore / audio resume handled by the
* state machine below (the clock_up cross-tile write and any resumed audio
* frames need the fabric back at 600 MHz). */
if (fps != 0)
{
if (c1_sswitch_is_slow)
{
write_sswitch_reg(get_tile_id(tile[0]), XS1_SSWITCH_CLK_DIVIDER_NUM, 0); /* SSDIV=0 => 600 MHz */
c1_sswitch_is_slow = 0;
}
}
else /* FPS off => bypass, no audio crosses the switch */
{
if (!c1_sswitch_is_slow)
{
write_sswitch_reg(get_tile_id(tile[0]), XS1_SSWITCH_CLK_DIVIDER_NUM, C1_SSWITCH_LP_DIV_DEFAULT);
c1_sswitch_is_slow = 1;
}
}
#endif
switch (c1_tile1_state)
{
case C1_TILE1_ACTIVE: