bdk: clock: improve PLLC init

- Use 6 as divm and div1 for OUT1 to avoid having very high frequency on OUT0
 There seems to be an undocumented silicon errata where PLLC OUT0 produces EMI
 to input mux logic in modules, even when not using it.
- Always check if PLL is enabled and disable first in order to avoid a silicon
 errata with hybrid PLLs
- Fix PLLC_FLL_LD_MEM value
This commit is contained in:
CTCaer
2025-11-26 14:48:47 +02:00
parent 9c028cd94a
commit 19285745b5
2 changed files with 14 additions and 10 deletions

View File

@@ -520,16 +520,20 @@ void clock_enable_pllx()
void clock_enable_pllc(u32 divn)
{
u32 enabled = CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_ENABLE;
u8 pll_divn_curr = (CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) >> 10) & 0xFF;
// Check if already enabled and configured.
if ((CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_ENABLE) && (pll_divn_curr == divn))
if (enabled && (pll_divn_curr == divn))
return;
// Take PLLC out of reset and set basic misc parameters.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) =
((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x8000 << 4); // PLLC_EXT_FRU.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM.
// WAR: Disable first to avoid HPLL overshoot.
if (enabled)
clock_disable_pllc();
// Take PLLC out of reset (misc) and set misc2 parameters.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = (0x8000 << 4); // PLLC_EXT_FRU.
CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF << 8; // PLLC_FLL_LD_MEM.
// Disable PLL and IDDQ in case they are on.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLL_BASE_ENABLE;
@@ -537,15 +541,15 @@ void clock_enable_pllc(u32 divn)
usleep(10);
// Set PLLC dividers.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 4; // DIVM: 4, DIVP: 1.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = (divn << 10) | 6; // DIVM: 6, DIVP: 1.
// Enable PLLC and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLL_BASE_ENABLE;
while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLL_BASE_LOCK))
;
// Disable PLLC_OUT1, enable reset and set div to 1.5.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = 1 << 8;
// Disable PLLC_OUT1, enable reset and set div to 1.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = 0;
// Enable PLLC_OUT1 and bring it out of reset.
CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR;