From c99a87dd09a53866f641d4ae0a935be1e1032173 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Tue, 7 Jan 2020 06:46:22 +0200 Subject: [PATCH] clock: Move PLLC config from bpmp.c to clock.c --- bootloader/soc/bpmp.c | 35 ++++---------------------------- bootloader/soc/clock.c | 45 +++++++++++++++++++++++++++++++++++++++++ bootloader/soc/clock.h | 4 +++- nyx/nyx_gui/soc/bpmp.c | 35 ++++---------------------------- nyx/nyx_gui/soc/clock.c | 45 +++++++++++++++++++++++++++++++++++++++++ nyx/nyx_gui/soc/clock.h | 4 +++- 6 files changed, 104 insertions(+), 64 deletions(-) diff --git a/bootloader/soc/bpmp.c b/bootloader/soc/bpmp.c index 70155be..550ebbe 100644 --- a/bootloader/soc/bpmp.c +++ b/bootloader/soc/bpmp.c @@ -253,30 +253,8 @@ void bpmp_clk_rate_set(bpmp_freq_t fid) msleep(1); // Wait a bit for clock source change. } - // 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) | (0x80000 << 4); // PLLC_EXT_FRU. - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. - - // Disable PLL and IDDQ in case they are on. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; - usleep(10); - - // Set PLLC4 dividers. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = 4 | (pll_divn[fid] << 10); // DIVM: 4, DIVP: 1. - - // Enable PLLC4 and wait for Phase and Frequency lock. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE; - while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK)) - ; - - // Disable PLLC_OUT1, enable reset and set div to 1.5. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = (1 << 8); - - // Enable PLLC_OUT1 and bring it out of reset. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); - msleep(1); // Wait a bit for clock source change. + // Configure and enable PLLC. + clock_enable_pllc(pll_divn[fid]); // Set SCLK / HCLK / PCLK. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK. @@ -288,13 +266,8 @@ void bpmp_clk_rate_set(bpmp_freq_t fid) msleep(1); // Wait a bit for clock source change. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK. - // Disable PLLC and PLLC_OUT1. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; - usleep(10); + // Disable PLLC to save power. + clock_disable_pllc(); } bpmp_clock_set = fid; } diff --git a/bootloader/soc/clock.c b/bootloader/soc/clock.c index dda6d4b..a3e1782 100644 --- a/bootloader/soc/clock.c +++ b/bootloader/soc/clock.c @@ -228,6 +228,51 @@ void clock_disable_pwm() clock_disable(&_clock_pwm); } +void clock_enable_pllc(u32 divn) +{ + 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) & PLLCX_BASE_ENABLE) && (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) | (0x80000 << 4); // PLLC_EXT_FRU. + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. + + // Disable PLL and IDDQ in case they are on. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; + usleep(10); + + // Set PLLC4 dividers. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = 4 | (divn << 10); // DIVM: 4, DIVP: 1. + + // Enable PLLC4 and wait for Phase and Frequency lock. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE; + while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK)) + ; + + // Disable PLLC_OUT1, enable reset and set div to 1.5. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = (1 << 8); + + // Enable PLLC_OUT1 and bring it out of reset. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + msleep(1); // Wait a bit for clock source change. +} + +void clock_disable_pllc() +{ + // Disable PLLC and PLLC_OUT1. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; + usleep(10); +} + #define L_SWR_SDMMC1_RST (1 << 14) #define L_SWR_SDMMC2_RST (1 << 9) #define L_SWR_SDMMC4_RST (1 << 15) diff --git a/bootloader/soc/clock.h b/bootloader/soc/clock.h index ebe443d..3679b46 100644 --- a/bootloader/soc/clock.h +++ b/bootloader/soc/clock.h @@ -190,9 +190,11 @@ void clock_enable_coresight(); void clock_disable_coresight(); void clock_enable_pwm(); void clock_disable_pwm(); +void clock_enable_pllc(u32 divn); +void clock_disable_pllc(); void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val); void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type); -int clock_sdmmc_is_not_reset_and_enabled(u32 id); +int clock_sdmmc_is_not_reset_and_enabled(u32 id); void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_disable(u32 id); diff --git a/nyx/nyx_gui/soc/bpmp.c b/nyx/nyx_gui/soc/bpmp.c index 0a46f15..3784b21 100644 --- a/nyx/nyx_gui/soc/bpmp.c +++ b/nyx/nyx_gui/soc/bpmp.c @@ -253,30 +253,8 @@ void bpmp_clk_rate_set(bpmp_freq_t fid) msleep(1); // Wait a bit for clock source change. } - // 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) | (0x80000 << 4); // PLLC_EXT_FRU. - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. - - // Disable PLL and IDDQ in case they are on. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; - usleep(10); - - // Set PLLC4 dividers. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = 4 | (pll_divn[fid] << 10); // DIVM: 4, DIVP: 1. - - // Enable PLLC4 and wait for Phase and Frequency lock. - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE; - while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK)) - ; - - // Disable PLLC_OUT1, enable reset and set div to 1.5. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = (1 << 8); - - // Enable PLLC_OUT1 and bring it out of reset. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); - msleep(1); // Wait a bit for clock source change. + // Configure and enable PLLC. + clock_enable_pllc(pll_divn[fid]); // Set SCLK / HCLK / PCLK. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK. @@ -288,13 +266,8 @@ void bpmp_clk_rate_set(bpmp_freq_t fid) msleep(1); // Wait a bit for clock source change. CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK. - // Disable PLLC and PLLC_OUT1. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; - usleep(10); + // Disable PLLC to save power. + clock_disable_pllc(); } bpmp_clock_set = fid; } diff --git a/nyx/nyx_gui/soc/clock.c b/nyx/nyx_gui/soc/clock.c index dda6d4b..a3e1782 100644 --- a/nyx/nyx_gui/soc/clock.c +++ b/nyx/nyx_gui/soc/clock.c @@ -228,6 +228,51 @@ void clock_disable_pwm() clock_disable(&_clock_pwm); } +void clock_enable_pllc(u32 divn) +{ + 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) & PLLCX_BASE_ENABLE) && (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) | (0x80000 << 4); // PLLC_EXT_FRU. + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. + + // Disable PLL and IDDQ in case they are on. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) &= ~PLLC_MISC1_IDDQ; + usleep(10); + + // Set PLLC4 dividers. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) = 4 | (divn << 10); // DIVM: 4, DIVP: 1. + + // Enable PLLC4 and wait for Phase and Frequency lock. + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_ENABLE; + while (!(CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) & PLLCX_BASE_LOCK)) + ; + + // Disable PLLC_OUT1, enable reset and set div to 1.5. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = (1 << 8); + + // Enable PLLC_OUT1 and bring it out of reset. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + msleep(1); // Wait a bit for clock source change. +} + +void clock_disable_pllc() +{ + // Disable PLLC and PLLC_OUT1. + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; + CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; + usleep(10); +} + #define L_SWR_SDMMC1_RST (1 << 14) #define L_SWR_SDMMC2_RST (1 << 9) #define L_SWR_SDMMC4_RST (1 << 15) diff --git a/nyx/nyx_gui/soc/clock.h b/nyx/nyx_gui/soc/clock.h index ebe443d..3679b46 100644 --- a/nyx/nyx_gui/soc/clock.h +++ b/nyx/nyx_gui/soc/clock.h @@ -190,9 +190,11 @@ void clock_enable_coresight(); void clock_disable_coresight(); void clock_enable_pwm(); void clock_disable_pwm(); +void clock_enable_pllc(u32 divn); +void clock_disable_pllc(); void clock_sdmmc_config_clock_source(u32 *pout, u32 id, u32 val); void clock_sdmmc_get_card_clock_div(u32 *pout, u16 *pdivisor, u32 type); -int clock_sdmmc_is_not_reset_and_enabled(u32 id); +int clock_sdmmc_is_not_reset_and_enabled(u32 id); void clock_sdmmc_enable(u32 id, u32 val); void clock_sdmmc_disable(u32 id);