From d9ab9f4823603900aa72c1dde1e2694fc84af594 Mon Sep 17 00:00:00 2001 From: Steven Dan Date: Thu, 18 Jun 2026 23:18:12 +0800 Subject: [PATCH] DFS for FS control 3 --- .../src/extensions/tile1_clk.h | 14 ++++++++++ .../src/extensions/tile1_clk.xc | 27 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.h index 6e4a1ab..47424e0 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.h @@ -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 diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.xc b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.xc index bbc69a4..82b6372 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/tile1_clk.xc @@ -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: