From 4480e7a8a5a9907b57c1d8b53463ac7520ce17bd Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 23 Aug 2021 15:10:24 -0700 Subject: [PATCH] fusee_cpp: implement bpmp overclock --- .../mariko_fatal/source/fatal_display.hpp | 1 + fusee_cpp/program/source/fusee_display.cpp | 28 ++-- fusee_cpp/program/source/fusee_display.hpp | 2 + fusee_cpp/program/source/fusee_main.cpp | 8 ++ .../libexosphere/include/exosphere/clkrst.hpp | 13 ++ .../libexosphere/source/clkrst/clkrst_api.cpp | 136 ++++++++++++++++++ .../include/vapours/tegra/tegra_clkrst.hpp | 19 ++- 7 files changed, 191 insertions(+), 16 deletions(-) diff --git a/exosphere/mariko_fatal/source/fatal_display.hpp b/exosphere/mariko_fatal/source/fatal_display.hpp index f2d6d6e1c..522582b6a 100644 --- a/exosphere/mariko_fatal/source/fatal_display.hpp +++ b/exosphere/mariko_fatal/source/fatal_display.hpp @@ -23,6 +23,7 @@ namespace ams::secmon::fatal { constexpr inline size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32); void InitializeDisplay(); + void ShowDisplay(); void ShowDisplay(const ams::impl::FatalErrorContext *f_ctx, const Result save_result); } diff --git a/fusee_cpp/program/source/fusee_display.cpp b/fusee_cpp/program/source/fusee_display.cpp index 93607a105..4a28eadd5 100644 --- a/fusee_cpp/program/source/fusee_display.cpp +++ b/fusee_cpp/program/source/fusee_display.cpp @@ -572,6 +572,16 @@ namespace ams::nxboot { g_display_initialized = false; } + void ShowDisplay() { + /* Enable backlight. */ + constexpr auto DisplayBrightness = 100; + if (g_lcd_vendor == 0x2050) { + EnableBacklightForVendor2050ForAula(DisplayBrightness); + } else { + EnableBacklightForGeneric(DisplayBrightness); + } + } + void ShowFatalError(const ams::impl::FatalErrorContext *f_ctx, const Result save_result) { /* If needed, initialize the display. */ if (!IsDisplayInitialized()) { @@ -601,13 +611,8 @@ namespace ams::nxboot { /* Ensure the device will see consistent data. */ hw::FlushDataCache(g_frame_buffer, FrameBufferSize); - /* Enable backlight. */ - constexpr auto DisplayBrightness = 100; - if (g_lcd_vendor == 0x2050) { - EnableBacklightForVendor2050ForAula(DisplayBrightness); - } else { - EnableBacklightForGeneric(DisplayBrightness); - } + /* Show the console. */ + ShowDisplay(); } void ShowFatalError(const char *fmt, ...) { @@ -635,13 +640,8 @@ namespace ams::nxboot { /* Ensure the device will see consistent data. */ hw::FlushDataCache(g_frame_buffer, FrameBufferSize); - /* Enable backlight. */ - constexpr auto DisplayBrightness = 100; - if (g_lcd_vendor == 0x2050) { - EnableBacklightForVendor2050ForAula(DisplayBrightness); - } else { - EnableBacklightForGeneric(DisplayBrightness); - } + /* Show the console. */ + ShowDisplay(); WaitForReboot(); } diff --git a/fusee_cpp/program/source/fusee_display.hpp b/fusee_cpp/program/source/fusee_display.hpp index 372f6dd34..b3a9b68d4 100644 --- a/fusee_cpp/program/source/fusee_display.hpp +++ b/fusee_cpp/program/source/fusee_display.hpp @@ -26,4 +26,6 @@ namespace ams::nxboot { void InitializeDisplay(); void FinalizeDisplay(); + void ShowDisplay(); + } diff --git a/fusee_cpp/program/source/fusee_main.cpp b/fusee_cpp/program/source/fusee_main.cpp index 8e0f4fd4f..84a1276e8 100644 --- a/fusee_cpp/program/source/fusee_main.cpp +++ b/fusee_cpp/program/source/fusee_main.cpp @@ -63,6 +63,9 @@ namespace ams::nxboot { /* Perform secure hardware initialization. */ SecureInitialize(true); + /* Overclock the bpmp. */ + clkrst::SetBpmpClockRate(fuse::GetSocType() == fuse::SocType_Mariko ? clkrst::BpmpClockRate_589MHz : clkrst::BpmpClockRate_576MHz); + /* Initialize Sdram. */ InitializeSdram(); @@ -88,7 +91,12 @@ namespace ams::nxboot { /* Read our overlay file. */ ReadFuseeSecondary(); + /* Initialize display (splash screen will be visible from this point onwards). */ + InitializeDisplay(); + ShowDisplay(); + /* TODO */ + WaitForReboot(); /* TODO */ AMS_INFINITE_LOOP(); diff --git a/libraries/libexosphere/include/exosphere/clkrst.hpp b/libraries/libexosphere/include/exosphere/clkrst.hpp index de926f80f..3f344b254 100644 --- a/libraries/libexosphere/include/exosphere/clkrst.hpp +++ b/libraries/libexosphere/include/exosphere/clkrst.hpp @@ -52,4 +52,17 @@ namespace ams::clkrst { void DisableSor1Clock(); void DisableKfuseClock(); + + enum BpmpClockRate { + BpmpClockRate_408MHz, + BpmpClockRate_544MHz, + BpmpClockRate_576MHz, + BpmpClockRate_589MHz, + + BpmpClockRate_Count, + }; + + BpmpClockRate GetBpmpClockRate(); + BpmpClockRate SetBpmpClockRate(BpmpClockRate rate); + } \ No newline at end of file diff --git a/libraries/libexosphere/source/clkrst/clkrst_api.cpp b/libraries/libexosphere/source/clkrst/clkrst_api.cpp index 27a9cf6ac..69d3632b7 100644 --- a/libraries/libexosphere/source/clkrst/clkrst_api.cpp +++ b/libraries/libexosphere/source/clkrst/clkrst_api.cpp @@ -21,6 +21,8 @@ namespace ams::clkrst { constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceClkRst.GetAddress(); + constinit BpmpClockRate g_bpmp_clock_rate = BpmpClockRate_408MHz; + struct ClockParameters { uintptr_t reset_offset; uintptr_t clk_enb_offset; @@ -99,6 +101,64 @@ namespace ams::clkrst { DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(Cache2Clock, L, CACHE2); DEFINE_CLOCK_PARAMETERS_WITHOUT_CLKDIV(Cram2Clock, U, CRAM2); + constexpr const u32 PllcDivn[] = { + [BpmpClockRate_408MHz] = 0, + [BpmpClockRate_544MHz] = 85, + [BpmpClockRate_576MHz] = 90, + [BpmpClockRate_589MHz] = 92, + }; + + void EnablePllc(BpmpClockRate rate) { + const u32 desired_divn = PllcDivn[rate]; + + /* Check if we're already enabled. */ + const bool is_enabled = reg::HasValue(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_ENABLE, ENABLE)); + const bool is_good_divn = reg::HasValue(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_VALUE(PLLC_BASE_PLLC_DIVN, desired_divn)); + if (is_enabled && is_good_divn) { + return; + } + + /* Take PLLC out of reset. */ + reg::Write(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC, (reg::Read(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC) & 0xBFF0000F) | (0x80000 << 4)); + reg::SetBits(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC2, 0xF0 << 8); + + /* Disable pll. */ + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_ENABLE, DISABLE)); + reg::ClearBits(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC1, (1u << 27)); + util::WaitMicroSeconds(10); + + /* Set dividers. */ + reg::Write(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_VALUE(PLLC_BASE_PLLC_DIVM, 4), + CLK_RST_REG_BITS_VALUE(PLLC_BASE_PLLC_DIVN, desired_divn)); + + /* Enable pll. */ + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_ENABLE, ENABLE)); + while (!reg::HasValue(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_LOCK, LOCK))) { + /* ... */ + } + + /* Disable PLLC_OUT1. */ + reg::Write(g_register_address + CLK_RST_CONTROLLER_PLLC_OUT, CLK_RST_REG_BITS_VALUE(PLLC_OUT_PLLC_OUT1_RATIO, 1)); + + /* Enable PLLC_OUT1. */ + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_OUT, CLK_RST_REG_BITS_ENUM(PLLC_OUT_PLLC_OUT1_RSTN, RESET_DISABLE), + CLK_RST_REG_BITS_ENUM(PLLC_OUT_PLLC_OUT1_CLKEN, ENABLE)); + util::WaitMicroSeconds(1'000); + } + + void DisablePllc() { + /* Disable PLLC/PLLC_OUT1. */ + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_OUT, CLK_RST_REG_BITS_ENUM(PLLC_OUT_PLLC_OUT1_RSTN, RESET_ENABLE), + CLK_RST_REG_BITS_ENUM(PLLC_OUT_PLLC_OUT1_CLKEN, DISABLE)); + + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_ENABLE, DISABLE)); + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_REF_DIS, REF_DISABLE)); + reg::ReadWrite(g_register_address + CLK_RST_CONTROLLER_PLLC_BASE, CLK_RST_REG_BITS_ENUM(PLLC_BASE_PLLC_REF_DIS, REF_DISABLE)); + reg::SetBits(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC1, (1u << 27)); + reg::SetBits(g_register_address + CLK_RST_CONTROLLER_PLLC_MISC, (1u << 30)); + util::WaitMicroSeconds(10); + } + } void SetRegisterAddress(uintptr_t address) { @@ -208,4 +268,80 @@ namespace ams::clkrst { DisableClock(KfuseClock); } + BpmpClockRate GetBpmpClockRate() { + return g_bpmp_clock_rate; + } + + BpmpClockRate SetBpmpClockRate(BpmpClockRate rate) { + /* Get the current rate. */ + const auto prev_rate = g_bpmp_clock_rate; + + /* Cap our rate. */ + if (rate >= BpmpClockRate_Count) { + rate = BpmpClockRate_589MHz; + } + + /* Configure the rate. */ + if (rate != BpmpClockRate_408MHz) { + /* If we were previously overclocked, restore to PLLP_OUT. */ + if (prev_rate != BpmpClockRate_408MHz) { + reg::Write(g_register_address + CLK_RST_CONTROLLER_SCLK_BURST_POLICY, CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SYS_STATE, RUN), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_FIQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IRQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IDLE_SOURCE, PLLP_OUT0)); + util::WaitMicroSeconds(1'000); + } + + /* Configure PLLC. */ + EnablePllc(rate); + + /* Set SCLK. */ + reg::Write(g_register_address + CLK_RST_CONTROLLER_CLK_SYSTEM_RATE, CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_HCLK_DIS, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_AHB_RATE, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_PCLK_DIS, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_APB_RATE, 3)); + + reg::Write(g_register_address + CLK_RST_CONTROLLER_SCLK_BURST_POLICY, CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SYS_STATE, RUN), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_FIQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IRQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE, PLLC_OUT1), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IDLE_SOURCE, CLKM)); + } else { + /* Configure to use PLLP_OUT0. */ + reg::Write(g_register_address + CLK_RST_CONTROLLER_SCLK_BURST_POLICY, CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SYS_STATE, RUN), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_FIQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_IRQ, NOP), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_FIQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IRQ_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_RUN_SOURCE, PLLP_OUT0), + CLK_RST_REG_BITS_ENUM(SCLK_BURST_POLICY_SWAKEUP_IDLE_SOURCE, CLKM)); + util::WaitMicroSeconds(1'000); + + reg::Write(g_register_address + CLK_RST_CONTROLLER_CLK_SYSTEM_RATE, CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_HCLK_DIS, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_AHB_RATE, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_PCLK_DIS, 0), + CLK_RST_REG_BITS_VALUE(CLK_SYSTEM_RATE_APB_RATE, 2)); + + /* Disable PLLC. */ + DisablePllc(); + } + + /* Set the clock rate. */ + g_bpmp_clock_rate = rate; + + /* Return the previous rate. */ + return prev_rate; + } + } diff --git a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp index cdd2d5c1c..b1f8a859e 100644 --- a/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp +++ b/libraries/libvapours/include/vapours/tegra/tegra_clkrst.hpp @@ -41,6 +41,10 @@ #define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE (0x030) #define CLK_RST_CONTROLLER_MISC_CLK_ENB (0x048) #define CLK_RST_CONTROLLER_OSC_CTRL (0x050) +#define CLK_RST_CONTROLLER_PLLC_BASE (0x080) +#define CLK_RST_CONTROLLER_PLLC_OUT (0x084) +#define CLK_RST_CONTROLLER_PLLC_MISC (0x088) +#define CLK_RST_CONTROLLER_PLLC_MISC1 (0x08C) #define CLK_RST_CONTROLLER_PLLM_BASE (0x090) #define CLK_RST_CONTROLLER_PLLM_MISC1 (0x098) #define CLK_RST_CONTROLLER_PLLM_MISC2 (0x09C) @@ -56,6 +60,7 @@ #define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2 (0x388) #define CLK_RST_CONTROLLER_SPARE_REG0 (0x55C) #define CLK_RST_CONTROLLER_PLLC4_BASE (0x5A4) +#define CLK_RST_CONTROLLER_PLLC_MISC2 (0x5D0) #define CLK_RST_CONTROLLER_PLLMB_BASE (0x5E8) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA (0x0F8) @@ -74,7 +79,6 @@ DEFINE_CLK_RST_REG_BIT_ENUM(SCLK_BURST_POLICY_CPU_AUTO_SWAKEUP_FROM_FIQ, 26, NOP DEFINE_CLK_RST_REG_BIT_ENUM(SCLK_BURST_POLICY_COP_AUTO_SWAKEUP_FROM_FIQ, 27, NOP, BURST); DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(SCLK_BURST_POLICY_SYS_STATE, 28, STDBY, IDLE, RUN, RSVD3, IRQ, RSVD5, RSVD6, RSVD7, FIQ, RSVD9, RSVD10, RSVD11, RSVD12, RSVD13, RSVD14, RSVD15); - DEFINE_CLK_RST_REG(SUPER_SCLK_DIVIDER_SUPER_SDIV_DIVISOR, 0, 8); DEFINE_CLK_RST_REG(SUPER_SCLK_DIVIDER_SUPER_SDIV_DIVIDEND, 8, 8); DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_SCLK_DIVIDER_SUPER_SDIV_DIS_FROM_CPU_IRQ, 24, NOP, DISABLE); @@ -83,7 +87,6 @@ DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_SCLK_DIVIDER_SUPER_SDIV_DIS_FROM_CPU_FIQ, 26, DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_SCLK_DIVIDER_SUPER_SDIV_DIS_FROM_COP_FIQ, 27, NOP, DISABLE); DEFINE_CLK_RST_REG_BIT_ENUM(SUPER_SCLK_DIVIDER_SUPER_SDIV_ENB, 31, DISABLE, ENABLE); - DEFINE_CLK_RST_REG(CLK_SYSTEM_RATE_APB_RATE, 0, 2); DEFINE_CLK_RST_REG(CLK_SYSTEM_RATE_PCLK_DIS, 3, 1); DEFINE_CLK_RST_REG(CLK_SYSTEM_RATE_AHB_RATE, 4, 2); @@ -95,6 +98,18 @@ DEFINE_CLK_RST_REG_BIT_ENUM(OSC_CTRL_XOE, 0, DISABLE, ENABLE); DEFINE_CLK_RST_REG(OSC_CTRL_XOFS, 4, 6); DEFINE_CLK_RST_REG_FOUR_BIT_ENUM(OSC_CTRL_OSC_FREQ, 28, OSC13, OSC16P8, RSVD2, RSVD3, OSC19P2, OSC38P4, RSVD6, RSVD7, OSC12, OSC48, RSVD10, RSVD11, OSC26, RSVD13, RSVD14, RSVD15); +DEFINE_CLK_RST_REG(PLLC_BASE_PLLC_DIVM, 0, 8); +DEFINE_CLK_RST_REG(PLLC_BASE_PLLC_DIVN, 10, 8); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_BASE_PLLC_LOCK, 27, NOT_LOCK, LOCK); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_BASE_PLLC_REF_DIS, 29, REF_ENABLE, REF_DISABLE); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_BASE_PLLC_ENABLE, 30, DISABLE, ENABLE); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_BASE_PLLC_BYPASS, 31, DISABLE, ENABLE); + +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_OUT_PLLC_OUT1_RSTN, 0, RESET_ENABLE, RESET_DISABLE); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_OUT_PLLC_OUT1_CLKEN, 1, DISABLE, ENABLE); +DEFINE_CLK_RST_REG(PLLC_OUT_PLLC_OUT1_RATIO, 8, 8); +DEFINE_CLK_RST_REG_BIT_ENUM(PLLC_OUT_PLLC_OUT1_DIV_BYP, 16, DISABLE, ENABLE); + DEFINE_CLK_RST_REG(PLLM_BASE_PLLM_DIVM, 0, 8); DEFINE_CLK_RST_REG(PLLM_BASE_PLLM_DIVN, 8, 8); DEFINE_CLK_RST_REG(PLLM_BASE_PLLM_DIVP, 20, 5);