DFS for FS control 2
This commit is contained in:
@@ -24,8 +24,9 @@
|
||||
#if C1_DFS_EN
|
||||
|
||||
/* Default low-power divider for tile[1] core clock when idle.
|
||||
* The register is programmed with (value - 1); result = 600 MHz / N.
|
||||
* 40 -> ~15 MHz (ds1-proven start point). Sweep lower via SET_TILE1_DIV. */
|
||||
* Per AN02022 (xcore.ai Clock Frequency Control): the per-tile divider XCDIV is
|
||||
* programmed with (divide - 1), i.e. tile_clk = SystemFrequency / N.
|
||||
* 40 -> ~15 MHz (ds1-proven start point). Sweep lower via SET_TILE1_DIV (HID 0xB6). */
|
||||
#ifndef C1_TILE1_LP_XCORE_DIV_DEFAULT
|
||||
#define C1_TILE1_LP_XCORE_DIV_DEFAULT 40
|
||||
#endif
|
||||
|
||||
@@ -25,27 +25,54 @@ static timer c1_tile1_tmr;
|
||||
static unsigned c1_tile1_grace_target = 0;
|
||||
static int c1_tile1_grace_armed = 0;
|
||||
|
||||
/* ---- clock primitives (mirror ds1 enable_tile1_core_divider / up / down) ---- */
|
||||
/* ---- clock primitives (AN02022 "xcore.ai Clock Frequency Control") ----
|
||||
*
|
||||
* We throttle tile[1] ONLY, using the per-tile xcore clock divider
|
||||
* (XS1_PSWITCH_PLL_CLK_DIVIDER_NUM, field XCDIV). Per AN02022:
|
||||
*
|
||||
* tile_clk = SystemFrequency / (XCDIV + 1) (register value = divide - 1)
|
||||
*
|
||||
* and "Setting the tile clock divider does not take effect until the tile
|
||||
* allows the divider to be used, which is achieved by calling
|
||||
* setps(XS1_PS_XCORE_CTRL0, 0x10)" (XCORE_CTRL0 bit 4).
|
||||
*
|
||||
* Scope note (why NOT the AN's "Low power configurations" bypass): that mode
|
||||
* bypasses the System PLL (XS1_SSWITCH_PLL_CTL_NUM, BYPASS bit) to drop
|
||||
* PLL_AVDD power to ~0 — but the System PLL is the single node-level PLL
|
||||
* shared by BOTH tiles, so bypass would also slow tile[0] (USB/I2S/EQ lose
|
||||
* 600 MHz). It is intentionally NOT used here. The cross-tile PSWITCH writes
|
||||
* below target tile[1] explicitly and are safe to issue from tile[0], where
|
||||
* the power state machine (c1_tile1_power_tick) runs. */
|
||||
|
||||
/* Local to tile[1]: uses per-core setps/getps. */
|
||||
/* Program the per-tile divider. `divide` is the desired ratio (>=1). */
|
||||
static void c1_tile1_set_xcdiv(unsigned divide)
|
||||
{
|
||||
if (divide == 0) divide = 1; /* XCDIV = divide - 1; 0 would mean /1 */
|
||||
write_pswitch_reg(get_tile_id(tile[1]), XS1_PSWITCH_PLL_CLK_DIVIDER_NUM, divide - 1);
|
||||
}
|
||||
|
||||
/* One-time enable. MUST run LOCALLY on tile[1] (uses per-core setps/getps).
|
||||
* Enables the tile's local divider output so the XCDIV value takes effect. */
|
||||
void c1_tile1_clk_enable(void)
|
||||
{
|
||||
/* Program divider = 1 (full speed), then enable the divider output path
|
||||
* via XCORE_CTRL0 bit 4. */
|
||||
write_pswitch_reg(get_tile_id(tile[1]), XS1_PSWITCH_PLL_CLK_DIVIDER_NUM, 1 - 1);
|
||||
/* XCDIV = 0 (full speed) first, then enable the divider output (bit 4).
|
||||
* Only set bit 4, preserving the other XCORE_CTRL0 bits — safer than the
|
||||
* AN's literal setps(...,0x10) which overwrites the whole register. */
|
||||
c1_tile1_set_xcdiv(1);
|
||||
unsigned val = getps(XS1_PS_XCORE_CTRL0);
|
||||
setps(XS1_PS_XCORE_CTRL0, val | (1u << 4));
|
||||
}
|
||||
|
||||
/* Restore tile[1] to full speed: XCDIV = 0 => divide by 1 => 600 MHz. */
|
||||
void c1_tile1_clock_up(void)
|
||||
{
|
||||
write_pswitch_reg(get_tile_id(tile[1]), XS1_PSWITCH_PLL_CLK_DIVIDER_NUM, 1 - 1); /* /1 => 600 MHz */
|
||||
c1_tile1_set_xcdiv(1);
|
||||
}
|
||||
|
||||
/* Throttle tile[1] core clock to SystemFrequency / div. */
|
||||
void c1_tile1_clock_down(unsigned div)
|
||||
{
|
||||
if (div == 0) div = 1;
|
||||
write_pswitch_reg(get_tile_id(tile[1]), XS1_PSWITCH_PLL_CLK_DIVIDER_NUM, div - 1);
|
||||
c1_tile1_set_xcdiv(div);
|
||||
}
|
||||
|
||||
/* ---- policy tick ----
|
||||
|
||||
Reference in New Issue
Block a user