From a1bfcebba86803fb455e13e0ef263a40f14f538a Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Sat, 13 Sep 2025 17:21:41 -0400 Subject: [PATCH] stuff --- .../loader/source/oc/customize.cpp | 2 + .../loader/source/oc/customize.hpp | 2 + .../loader/source/oc/mtc_timing_value.hpp | 176 +++-- .../loader/source/oc/oc_common.hpp | 2 +- .../loader/source/oc/oc_loader.hpp | 2 +- .../stratosphere/loader/source/oc/oc_test.cpp | 12 +- .../stratosphere/loader/source/oc/oc_test.hpp | 2 +- .../stratosphere/loader/source/oc/pcv/pcv.hpp | 602 ++++++++---------- .../loader/source/oc/pcv/pcv_common.hpp | 2 +- .../loader/source/oc/pcv/pcv_erista.cpp | 43 +- .../loader/source/oc/pcv/pcv_mariko.cpp | 68 +- .../stratosphere/loader/source/oc/ptm/ptm.cpp | 2 +- .../stratosphere/loader/source/oc/ptm/ptm.hpp | 2 +- 13 files changed, 378 insertions(+), 539 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 642061e1..2ff48a89 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -43,6 +43,8 @@ volatile CustomizeTable C = { .marikoEmcDvbShift = 0, .latency = 0, .BL = 16, +.WL = 32, +.RL = 14, .tRFCpb = 140, .tRFCab = 280, .tRAS = 42, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp index 57597e62..8de6b909 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp @@ -72,6 +72,8 @@ typedef struct CustomizeTable { // RAM timings (u32) u32 latency; u32 BL; + u32 WL; + u32 RL; u32 tRFCpb; u32 tRFCab; u32 tRAS; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp index d34a2451..e12af6d1 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (c) 2023 hanai3Bi * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -12,100 +12,88 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * + * from GCC preprocessor output */ -#pragma once + #pragma once -#include "oc_common.hpp" + #include "oc_common.hpp" + namespace ams::ldr::oc { + #define MAX(A, B) std::max(A, B) + #define MIN(A, B) std::min(A, B) + #define CEIL(A) std::ceil(A) + #define FLOOR(A) std::floor(A) + namespace pcv::erista { + // tCK_avg (average clock period) in ns + const double tCK_avg = 1000'000. / C.eristaEmcMaxClock; -namespace ams::ldr::oc { - #define MAX(A, B) std::max(A, B) - #define MIN(A, B) std::min(A, B) - #define CEIL(A) std::ceil(A) - #define FLOOR(A) std::floor(A) - - // p78 The first valid data is available RL × t CK + t DQSCK + t DQSQ - //const u32 QUSE = RL + CEIL(C.tDQSCK_min/tCK_avg + C.tDQSQ); - - namespace pcv::erista { - // tCK_avg (average clock period) in ns - const double tCK_avg = 1000'000. / C.eristaEmcMaxClock; - - // Write Latency - const u32 WL = 14 + C.latency; - // Read Latency - const u32 RL = 32 + C.latency; - - // minimum number of cycles from any read command to any write command, irrespective of bank - const u32 R2W = CEIL (RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - WL + C.tWPRE + FLOOR(C.tRPST)) + 6; - - // Delay Time From WRITE-to-READ - const u32 W2R = WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg) - 6; - - // write-to-precharge time for commands to the same bank in cycles - const u32 WTP = WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg) - 8; - - // #_of_rows per die for 8Gb density - const u32 numOfRows = 65536; - // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] - // emc_clk_period = dram_clk / 2; - // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) - const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); - const u32 REFBW = MIN((u32)65536, REFRESH+64); - - // Write With Auto Precharge to to Power-Down Entry - const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6; - - // Additional time after t XP hasexpired until the MRR commandmay be issued - const double tMRRI = C.tRCD + 3 * tCK_avg; - - // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns - const double tPDEX2MRR = C.tXP + tMRRI; - } - namespace pcv::mariko { - // tCK_avg (average clock period) in ns - const double tCK_avg = 1000'000. / C.marikoEmcMaxClock; - // Write Latency - const u32 WL = 14 + C.latency; - // Read Latency - const u32 RL = 32 + C.latency; - - // minimum number of cycles from any read command to any write command, irrespective of bank - const u32 R2W = CEIL (RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - WL + C.tWPRE + FLOOR(C.tRPST)); - - // Delay Time From WRITE-to-READ - const u32 W2R = WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg); - - // write-to-precharge time for commands to the same bank in cycles - const u32 WTP = WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg); - - // Read-To-MRW delay - const u32 RTM = RL + C.BL/2 + CEIL(C.tDQSCK_max/tCK_avg) + FLOOR(C.tRPST) + CEIL(7.5/tCK_avg); - - // Write-To-MRW/MRR delay - const u32 WTM = WL + 1 + C.BL/2 + CEIL(7.5/tCK_avg); - - // Read With AP-To-MRW/MRR delay - const u32 RATM = RTM + CEIL(C.tRTP/ 1000/tCK_avg) - 8; - - // Write With AP-To-MRW/MRR delay - const u32 WATM = WTM + CEIL(C.tWR/tCK_avg); - - // #_of_rows per die for 8Gb density - const u32 numOfRows = 65536; - // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] - // emc_clk_period = dram_clk / 2; - // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) - const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); - const u32 REFBW = MIN((u32)65536, REFRESH+64); - - // Write With Auto Precharge to to Power-Down Entry - const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6; - - // Additional time after t XP hasexpired until the MRR commandmay be issued - const double tMRRI = C.tRCD + 3 * tCK_avg; - - // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns - const double tPDEX2MRR = C.tXP + tMRRI; - } -} + // minimum number of cycles from any read command to any write command, irrespective of bank + const u32 R2W = CEIL (C.RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - C.WL + C.tWPRE + FLOOR(C.tRPST)) + 6; + + // Delay Time From WRITE-to-READ + const u32 W2R = C.WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg) - 6; + + // write-to-precharge time for commands to the same bank in cycles + const u32 WTP = C.WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg) - 8; + + // #_of_rows per die for 8Gb density + const u32 numOfRows = 65536; + // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] + // emc_clk_period = dram_clk / 2; + // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) + const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); + const u32 REFBW = MIN((u32)65536, REFRESH+64); + + // Write With Auto Precharge to to Power-Down Entry + const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6; + + // Additional time after t XP hasexpired until the MRR commandmay be issued + const double tMRRI = C.tRCD + 3 * tCK_avg; + + // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns + const double tPDEX2MRR = C.tXP + tMRRI; + } + namespace pcv::mariko { + // tCK_avg (average clock period) in ns + const double tCK_avg = 1000'000. / C.marikoEmcMaxClock; + // minimum number of cycles from any read command to any write command, irrespective of bank + const u32 R2W = CEIL (C.RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - C.WL + C.tWPRE + FLOOR(C.tRPST)); + + // Delay Time From WRITE-to-READ + const u32 W2R = C.WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg); + + // write-to-precharge time for commands to the same bank in cycles + const u32 WTP = C.WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg); + + // Read-To-MRW delay + const u32 RTM = C.RL + C.BL/2 + CEIL(C.tDQSCK_max/tCK_avg) + FLOOR(C.tRPST) + CEIL(7.5/tCK_avg); + + // Write-To-MRW/MRR delay + const u32 WTM = C.WL + 1 + C.BL/2 + CEIL(7.5/tCK_avg); + + // Read With AP-To-MRW/MRR delay + const u32 RATM = RTM + CEIL(C.tRTP/tCK_avg) - 8; + + // Write With AP-To-MRW/MRR delay + const u32 WATM = WTM + CEIL(C.tWR/tCK_avg); + + // #_of_rows per die for 8Gb density + const u32 numOfRows = 65536; + // {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%] + // emc_clk_period = dram_clk / 2; + // 1600 MHz: 5894, but N' set to 6176 (~4.8% margin) + const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4); + const u32 REFBW = MIN((u32)65536, REFRESH+64); + + // Write With Auto Precharge to to Power-Down Entry + const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6; + + // Additional time after t XP hasexpired until the MRR commandmay be issued + const double tMRRI = C.tRCD + 3 * tCK_avg; + + // tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns + const double tPDEX2MRR = C.tXP + tMRRI; + } + } + \ No newline at end of file diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp index 72e1b8eb..1645c6af 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp index 8dbd9e15..e0445818 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp index 5288e0e0..c0cb1c75 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -77,13 +77,13 @@ Result Test_PcvDvfsTable() { // Customized table default assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.eristaCpuDvfsTable)) == 19); - assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTable)) == 22); - assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTableSLT)) == 25); + assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTable)) == 21); + assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoCpuDvfsTableSLT)) == 22); assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.eristaGpuDvfsTable)) == 12); - assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTable)) == 18); - assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableSLT)) == 18); - assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableHiOPT)) == 18); + assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTable)) == 17); + assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableSLT)) == 17); + assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::oc::C.marikoGpuDvfsTableHiOPT)) == 17); constexpr size_t limit = ams::ldr::oc::pcv::DvfsTableEntryLimit; cvb_entry_t customized_table[limit] = {}; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp index d0794b3c..32537644 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index 6f39a376..2411a1a7 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -1,6 +1,8 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * + * Copyright (c) 2023 hanai3Bi + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -19,297 +21,234 @@ #include "../oc_common.hpp" #include "pcv_common.hpp" -namespace ams::ldr::oc::pcv -{ +namespace ams::ldr::oc::pcv { - namespace mariko - { - constexpr cvb_entry_t CpuCvbTableDefault[] = { - // CPUB01_CVB_TABLE - {204000, {721589, -12695, 27}, {}}, - {306000, {747134, -14195, 27}, {}}, - {408000, {776324, -15705, 27}, {}}, - {510000, {809160, -17205, 27}, {}}, - {612000, {845641, -18715, 27}, {}}, - {714000, {885768, -20215, 27}, {}}, - {816000, {929540, -21725, 27}, {}}, - {918000, {976958, -23225, 27}, {}}, - {1020000, {1028021, -24725, 27}, {1120000}}, - {1122000, {1082730, -26235, 27}, {1120000}}, - {1224000, {1141084, -27735, 27}, {1120000}}, - {1326000, {1203084, -29245, 27}, {1120000}}, - {1428000, {1268729, -30745, 27}, {1120000}}, - {1581000, {1374032, -33005, 27}, {1120000}}, - {1683000, {1448791, -34505, 27}, {1120000}}, - {1785000, {1527196, -36015, 27}, {1120000}}, - {1887000, {1609246, -37515, 27}, {1120000}}, - {1963500, {1675751, -38635, 27}, {1120000}}, - {}, - }; +namespace mariko { + constexpr cvb_entry_t CpuCvbTableDefault[] = { + // CPUB01_CVB_TABLE + { 204000, { 721589, -12695, 27 }, {} }, + { 306000, { 747134, -14195, 27 }, {} }, + { 408000, { 776324, -15705, 27 }, {} }, + { 510000, { 809160, -17205, 27 }, {} }, + { 612000, { 845641, -18715, 27 }, {} }, + { 714000, { 885768, -20215, 27 }, {} }, + { 816000, { 929540, -21725, 27 }, {} }, + { 918000, { 976958, -23225, 27 }, {} }, + { 1020000, { 1028021, -24725, 27 }, { 1120000 } }, + { 1122000, { 1082730, -26235, 27 }, { 1120000 } }, + { 1224000, { 1141084, -27735, 27 }, { 1120000 } }, + { 1326000, { 1203084, -29245, 27 }, { 1120000 } }, + { 1428000, { 1268729, -30745, 27 }, { 1120000 } }, + { 1581000, { 1374032, -33005, 27 }, { 1120000 } }, + { 1683000, { 1448791, -34505, 27 }, { 1120000 } }, + { 1785000, { 1527196, -36015, 27 }, { 1120000 } }, + { 1887000, { 1609246, -37515, 27 }, { 1120000 } }, + { 1963500, { 1675751, -38635, 27 }, { 1120000 } }, + { }, + }; - constexpr u16 CpuMinVolts[] = {800, 637, 620, 610}; + constexpr u16 CpuMinVolts[] = { 800, 637, 620, 610 }; - constexpr u32 CpuClkOfficial = 1963'500; - constexpr u32 CpuVoltOfficial = 1120; + constexpr u32 CpuClkOfficial = 1963'500; + constexpr u32 CpuVoltOfficial = 1120; - constexpr cvb_entry_t GpuCvbTableDefault[] = { - // GPUB01_NA_CVB_TABLE - {76800, {}, { - 610000, - }}, - {153600, {}, { - 610000, - }}, - {230400, {}, { - 610000, - }}, - {307200, {}, { - 610000, - }}, - {384000, {}, { - 610000, - }}, - {460800, {}, { - 610000, - }}, - {537600, {}, {801688, -10900, -163, 298, -10599, 162}}, - {614400, {}, {824214, -5743, -452, 238, -6325, 81}}, - {691200, {}, {848830, -3903, -552, 119, -4030, -2}}, - {768000, {}, {891575, -4409, -584, 0, -2849, 39}}, - {844800, {}, {940071, -5367, -602, -60, -63, -93}}, - {921600, {}, {986765, -6637, -614, -179, 1905, -13}}, - {998400, {}, {1098475, -13529, -497, -179, 3626, 9}}, - {1075200, {}, {1163644, -12688, -648, 0, 1077, 40}}, - {1152000, {}, {1204812, -9908, -830, 0, 1469, 110}}, - {1228800, {}, {1277303, -11675, -859, 0, 3722, 313}}, - {1267200, {}, {1335531, -12567, -867, 0, 3681, 559}}, - {}, - }; + constexpr cvb_entry_t GpuCvbTableDefault[] = { + // GPUB01_NA_CVB_TABLE + { 76800, {}, { 610000, } }, + { 153600, {}, { 610000, } }, + { 230400, {}, { 610000, } }, + { 307200, {}, { 610000, } }, + { 384000, {}, { 610000, } }, + { 460800, {}, { 610000, } }, + { 537600, {}, { 801688, -10900, -163, 298, -10599, 162 } }, + { 614400, {}, { 824214, -5743, -452, 238, -6325, 81 } }, + { 691200, {}, { 848830, -3903, -552, 119, -4030, -2 } }, + { 768000, {}, { 891575, -4409, -584, 0, -2849, 39 } }, + { 844800, {}, { 940071, -5367, -602, -60, -63, -93 } }, + { 921600, {}, { 986765, -6637, -614, -179, 1905, -13 } }, + { 998400, {}, { 1098475, -13529, -497, -179, 3626, 9 } }, + { 1075200, {}, { 1163644, -12688, -648, 0, 1077, 40 } }, + { 1152000, {}, { 1204812, -9908, -830, 0, 1469, 110 } }, + { 1228800, {}, { 1277303, -11675, -859, 0, 3722, 313 } }, + { 1267200, {}, { 1335531, -12567, -867, 0, 3681, 559 } }, + { }, + }; - constexpr u32 GpuClkPllLimit = 1300'000'000; + constexpr u32 GpuClkPllLimit = 1300'000'000; - /* GPU Max Clock asm Pattern: - * - * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 - * - * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 - */ - inline constexpr u32 asm_pattern[] = {0x52820000, 0x72A001C0}; - inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) - { return ((ins1 ^ ins2) >> 5) == 0; }; - inline auto asm_get_rd = [](u32 ins) - { return ins & ((1 << 5) - 1); }; - inline auto asm_set_rd = [](u32 ins, u8 rd) - { return (ins & 0xFFFFFFE0) | (rd & 0x1F); }; - inline auto asm_set_imm16 = [](u32 ins, u16 imm) - { return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); }; - - inline bool GpuMaxClockPatternFn(u32 *ptr32) - { - return asm_compare_no_rd(*ptr32, asm_pattern[0]); - } - - constexpr emc_dvb_dvfs_table_t EmcDvbTableDefault[] = { - {204000, { - 637, - 637, - 637, - }}, - {408000, { - 637, - 637, - 637, - }}, - {800000, { - 637, - 637, - 637, - }}, - {1065600, { - 637, - 637, - 637, - }}, - {1331200, { - 650, - 637, - 637, - }}, - {1600000, { - 675, - 650, - 637, - }}, - }; - - constexpr u32 EmcClkOSAlt = 1331'200; - constexpr u32 EmcClkPllmLimit = 2133'000'000; - constexpr u32 EmcVddqDefault = 600'000; - constexpr u32 MemVdd2Default = 1100'000; - - constexpr u32 MTC_TABLE_REV = 3; - - void Patch(uintptr_t mapped_nso, size_t nso_size); + /* GPU Max Clock asm Pattern: + * + * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 + * + * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 + */ + inline constexpr u32 asm_pattern[] = { 0x52820000, 0x72A001C0 }; + inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) { return ((ins1 ^ ins2) >> 5) == 0; }; + inline auto asm_get_rd = [](u32 ins) { return ins & ((1 << 5) - 1); }; + inline auto asm_set_rd = [](u32 ins, u8 rd) { return (ins & 0xFFFFFFE0) | (rd & 0x1F); }; + inline auto asm_set_imm16 = [](u32 ins, u16 imm) { return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); }; + inline bool GpuMaxClockPatternFn(u32* ptr32) { + return asm_compare_no_rd(*ptr32, asm_pattern[0]); } - namespace erista - { - constexpr cvb_entry_t CpuCvbTableDefault[] = { - // CPU_PLL_CVB_TABLE_ODN - {204000, {721094}, {}}, - {306000, {754040}, {}}, - {408000, {786986}, {}}, - {510000, {819932}, {}}, - {612000, {852878}, {}}, - {714000, {885824}, {}}, - {816000, {918770}, {}}, - {918000, {951716}, {}}, - {1020000, {984662}, {-2875621, 358099, -8585}}, - {1122000, {1017608}, {-52225, 104159, -2816}}, - {1224000, {1050554}, {1076868, 8356, -727}}, - {1326000, {1083500}, {2208191, -84659, 1240}}, - {1428000, {1116446}, {2519460, -105063, 1611}}, - {1581000, {1130000}, {2889664, -122173, 1834}}, - {1683000, {1168000}, {5100873, -279186, 4747}}, - {1785000, {1227500}, {5100873, -279186, 4747}}, - {}, - }; + constexpr emc_dvb_dvfs_table_t EmcDvbTableDefault[] = { + { 204000, { 637, 637, 637, } }, + { 408000, { 637, 637, 637, } }, + { 800000, { 637, 637, 637, } }, + { 1065600, { 637, 637, 637, } }, + { 1331200, { 650, 637, 637, } }, + { 1600000, { 675, 650, 637, } }, + }; - constexpr u32 CpuVoltL4T = 1235'000; + constexpr u32 EmcClkOSAlt = 1331'200; + constexpr u32 EmcClkPllmLimit = 2133'000'000; + constexpr u32 EmcVddqDefault = 600'000; + constexpr u32 MemVdd2Default = 1100'000; - constexpr u16 CpuMinVolts[] = {950, 850, 825, 810}; + constexpr u32 MTC_TABLE_REV = 3; - inline bool CpuMaxVoltPatternFn(u32 *ptr32) - { - u32 val = *ptr32; - return (val == 1132 || val == 1170 || val == 1227); - } + void Patch(uintptr_t mapped_nso, size_t nso_size); - constexpr u32 GpuClkPllLimit = 921'600'000; +} - /* GPU Max Clock asm Pattern: - * - * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 - * - * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 - */ - inline constexpr u32 asm_pattern[] = {0x52820000, 0x72A001C0}; - inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) - { return ((ins1 ^ ins2) >> 5) == 0; }; - inline auto asm_get_rd = [](u32 ins) - { return ins & ((1 << 5) - 1); }; - inline auto asm_set_rd = [](u32 ins, u8 rd) - { return (ins & 0xFFFFFFE0) | (rd & 0x1F); }; - inline auto asm_set_imm16 = [](u32 ins, u16 imm) - { return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); }; +namespace erista { + constexpr cvb_entry_t CpuCvbTableDefault[] = { + // CPU_PLL_CVB_TABLE_ODN + { 204000, { 721094 }, {} }, + { 306000, { 754040 }, {} }, + { 408000, { 786986 }, {} }, + { 510000, { 819932 }, {} }, + { 612000, { 852878 }, {} }, + { 714000, { 885824 }, {} }, + { 816000, { 918770 }, {} }, + { 918000, { 951716 }, {} }, + { 1020000, { 984662 }, { -2875621, 358099, -8585 } }, + { 1122000, { 1017608 }, { -52225, 104159, -2816 } }, + { 1224000, { 1050554 }, { 1076868, 8356, -727 } }, + { 1326000, { 1083500 }, { 2208191, -84659, 1240 } }, + { 1428000, { 1116446 }, { 2519460, -105063, 1611 } }, + { 1581000, { 1130000 }, { 2889664, -122173, 1834 } }, + { 1683000, { 1168000 }, { 5100873, -279186, 4747 } }, + { 1785000, { 1227500 }, { 5100873, -279186, 4747 } }, + { }, + }; - inline bool GpuMaxClockPatternFn(u32 *ptr32) - { - return asm_compare_no_rd(*ptr32, asm_pattern[0]); - } + constexpr u32 CpuVoltL4T = 1235'000; - constexpr cvb_entry_t GpuCvbTableDefault[] = { - // NA_FREQ_CVB_TABLE - {76800, {}, {814294, 8144, -940, 808, -21583, 226}}, - {153600, {}, {856185, 8144, -940, 808, -21583, 226}}, - {230400, {}, {898077, 8144, -940, 808, -21583, 226}}, - {307200, {}, {939968, 8144, -940, 808, -21583, 226}}, - {384000, {}, {981860, 8144, -940, 808, -21583, 226}}, - {460800, {}, {1023751, 8144, -940, 808, -21583, 226}}, - {537600, {}, {1065642, 8144, -940, 808, -21583, 226}}, - {614400, {}, {1107534, 8144, -940, 808, -21583, 226}}, - {691200, {}, {1149425, 8144, -940, 808, -21583, 226}}, - {768000, {}, {1191317, 8144, -940, 808, -21583, 226}}, - {844800, {}, {1233208, 8144, -940, 808, -21583, 226}}, - {921600, {}, {1275100, 8144, -940, 808, -21583, 226}}, - {}, - }; + constexpr u16 CpuMinVolts[] = { 950, 850, 825, 810 }; - constexpr u32 MemVoltHOS = 1125'000; - constexpr u32 EmcClkPllmLimit = 1866'000'000; - - constexpr u32 MTC_TABLE_REV = 7; - - void Patch(uintptr_t mapped_nso, size_t nso_size); + inline bool CpuMaxVoltPatternFn(u32* ptr32) { + u32 val = *ptr32; + return (val == 1132 || val == 1170 || val == 1227); } - template - Result CpuFreqCvbTable(u32 *ptr) - { - cvb_entry_t *default_table = isMariko ? (cvb_entry_t *)(&mariko::CpuCvbTableDefault) : (cvb_entry_t *)(&erista::CpuCvbTableDefault); - cvb_entry_t *customize_table = const_cast(isMariko ? (C.marikoCpuUV ? C.marikoCpuDvfsTableSLT : C.marikoCpuDvfsTable) : C.eristaCpuDvfsTable); + constexpr u32 GpuClkPllLimit = 921'600'000; - u32 cpu_max_volt = isMariko ? C.marikoCpuMaxVolt : C.eristaCpuMaxVolt; - u32 cpu_freq_threshold = 1020'000; - if (isMariko) - { - cpu_freq_threshold = C.marikoCpuUV ? 2193'000 : 2091'000; - } - else - { - cpu_freq_threshold = cpu_max_volt >= 1235 ? 1887'000 : 1428'000; - } + /* GPU Max Clock asm Pattern: + * + * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 + * + * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 + */ + inline constexpr u32 asm_pattern[] = { 0x52820000, 0x72A001C0 }; + inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) { return ((ins1 ^ ins2) >> 5) == 0; }; + inline auto asm_get_rd = [](u32 ins) { return ins & ((1 << 5) - 1); }; + inline auto asm_set_rd = [](u32 ins, u8 rd) { return (ins & 0xFFFFFFE0) | (rd & 0x1F); }; + inline auto asm_set_imm16 = [](u32 ins, u16 imm) { return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); }; - size_t default_entry_count = GetDvfsTableEntryCount(default_table); - size_t default_table_size = default_entry_count * sizeof(cvb_entry_t); - size_t customize_entry_count = GetDvfsTableEntryCount(customize_table); - size_t customize_table_size = customize_entry_count * sizeof(cvb_entry_t); + inline bool GpuMaxClockPatternFn(u32* ptr32) { + return asm_compare_no_rd(*ptr32, asm_pattern[0]); + } - // Validate existing table - cvb_entry_t *table_free = reinterpret_cast(ptr) + 1; - void *cpu_cvb_table_head = reinterpret_cast(table_free) - default_table_size; - bool validated = std::memcmp(cpu_cvb_table_head, default_table, default_table_size) == 0; - R_UNLESS(validated, ldr::ResultInvalidCpuDvfs()); + constexpr cvb_entry_t GpuCvbTableDefault[] = { + // NA_FREQ_CVB_TABLE + { 76800, { }, { 814294, 8144, -940, 808, -21583, 226 } }, + { 153600, { }, { 856185, 8144, -940, 808, -21583, 226 } }, + { 230400, { }, { 898077, 8144, -940, 808, -21583, 226 } }, + { 307200, { }, { 939968, 8144, -940, 808, -21583, 226 } }, + { 384000, { }, { 981860, 8144, -940, 808, -21583, 226 } }, + { 460800, { }, { 1023751, 8144, -940, 808, -21583, 226 } }, + { 537600, { }, { 1065642, 8144, -940, 808, -21583, 226 } }, + { 614400, { }, { 1107534, 8144, -940, 808, -21583, 226 } }, + { 691200, { }, { 1149425, 8144, -940, 808, -21583, 226 } }, + { 768000, { }, { 1191317, 8144, -940, 808, -21583, 226 } }, + { 844800, { }, { 1233208, 8144, -940, 808, -21583, 226 } }, + { 921600, { }, { 1275100, 8144, -940, 808, -21583, 226 } }, + { }, + }; - std::memcpy(cpu_cvb_table_head, static_cast(customize_table), customize_table_size); + constexpr u32 MemVoltHOS = 1125'000; + constexpr u32 EmcClkPllmLimit = 1866'000'000; - // Patch CPU max volt - if (cpu_max_volt) - { - cvb_entry_t *entry = static_cast(cpu_cvb_table_head); - for (size_t i = 0; i < customize_entry_count; i++) - { - if (entry->freq >= cpu_freq_threshold) - { - if (isMariko) - { - PATCH_OFFSET(&(entry->cvb_pll_param.c0), cpu_max_volt * 1000); - } - else - { - PATCH_OFFSET(&(entry->cvb_dfll_param.c0), cpu_max_volt * 1000); - } + constexpr u32 MTC_TABLE_REV = 7; + + void Patch(uintptr_t mapped_nso, size_t nso_size); +} + +template +Result CpuFreqCvbTable(u32* ptr) { + cvb_entry_t* default_table = isMariko ? (cvb_entry_t *)(&mariko::CpuCvbTableDefault) : (cvb_entry_t *)(&erista::CpuCvbTableDefault); + cvb_entry_t* customize_table = const_cast(isMariko ? (C.marikoCpuUV ? C.marikoCpuDvfsTableSLT : C.marikoCpuDvfsTable) : C.eristaCpuDvfsTable); + + u32 cpu_max_volt = isMariko ? C.marikoCpuMaxVolt : C.eristaCpuMaxVolt; + u32 cpu_freq_threshold = 1020'000; + if (isMariko) { + cpu_freq_threshold = C.marikoCpuUV ? 2193'000 : 2091'000; + } else { + cpu_freq_threshold = cpu_max_volt >= 1235 ? 1887'000 : 1428'000; + } + + size_t default_entry_count = GetDvfsTableEntryCount(default_table); + size_t default_table_size = default_entry_count * sizeof(cvb_entry_t); + size_t customize_entry_count = GetDvfsTableEntryCount(customize_table); + size_t customize_table_size = customize_entry_count * sizeof(cvb_entry_t); + + // Validate existing table + cvb_entry_t* table_free = reinterpret_cast(ptr) + 1; + void* cpu_cvb_table_head = reinterpret_cast(table_free) - default_table_size; + bool validated = std::memcmp(cpu_cvb_table_head, default_table, default_table_size) == 0; + R_UNLESS(validated, ldr::ResultInvalidCpuDvfs()); + + std::memcpy(cpu_cvb_table_head, static_cast(customize_table), customize_table_size); + + // Patch CPU max volt + if (cpu_max_volt) { + cvb_entry_t* entry = static_cast(cpu_cvb_table_head); + for (size_t i = 0; i < customize_entry_count; i++) { + if (entry->freq >= cpu_freq_threshold) { + if (isMariko) { + PATCH_OFFSET(&(entry->cvb_pll_param.c0), cpu_max_volt * 1000); + } else { + PATCH_OFFSET(&(entry->cvb_dfll_param.c0), cpu_max_volt * 1000); } - entry++; } + entry++; } - - R_SUCCEED(); } - template - Result GpuFreqCvbTable(u32 *ptr) - { - cvb_entry_t *default_table = isMariko ? (cvb_entry_t *)(&mariko::GpuCvbTableDefault) : (cvb_entry_t *)(&erista::GpuCvbTableDefault); - cvb_entry_t *customize_table; - if (isMariko) - { - switch (C.marikoGpuUV) - { - case 0: + R_SUCCEED(); +} + +template +Result GpuFreqCvbTable(u32* ptr) { + cvb_entry_t* default_table = isMariko ? (cvb_entry_t *)(&mariko::GpuCvbTableDefault) : (cvb_entry_t *)(&erista::GpuCvbTableDefault); + cvb_entry_t* customize_table; + if (isMariko) { + switch (C.marikoGpuUV) { + case 0: customize_table = const_cast(C.marikoGpuDvfsTable); break; case 1: @@ -321,90 +260,81 @@ namespace ams::ldr::oc::pcv default: customize_table = const_cast(C.marikoGpuDvfsTable); break; - } - } - else - { - customize_table = const_cast(C.eristaGpuDvfsTable); } + } else { + customize_table = const_cast(C.eristaGpuDvfsTable); + } - size_t default_entry_count = GetDvfsTableEntryCount(default_table); - size_t default_table_size = default_entry_count * sizeof(cvb_entry_t); - size_t customize_entry_count = GetDvfsTableEntryCount(customize_table); - size_t customize_table_size = customize_entry_count * sizeof(cvb_entry_t); + size_t default_entry_count = GetDvfsTableEntryCount(default_table); + size_t default_table_size = default_entry_count * sizeof(cvb_entry_t); + size_t customize_entry_count = GetDvfsTableEntryCount(customize_table); + size_t customize_table_size = customize_entry_count * sizeof(cvb_entry_t); - // Validate existing table - cvb_entry_t *table_free = reinterpret_cast(ptr) + 1; - void *gpu_cvb_table_head = reinterpret_cast(table_free) - default_table_size; - bool validated = std::memcmp(gpu_cvb_table_head, default_table, default_table_size) == 0; - R_UNLESS(validated, ldr::ResultInvalidGpuDvfs()); + // Validate existing table + cvb_entry_t* table_free = reinterpret_cast(ptr) + 1; + void* gpu_cvb_table_head = reinterpret_cast(table_free) - default_table_size; + bool validated = std::memcmp(gpu_cvb_table_head, default_table, default_table_size) == 0; + R_UNLESS(validated, ldr::ResultInvalidGpuDvfs()); - std::memcpy(gpu_cvb_table_head, (void *)customize_table, customize_table_size); + std::memcpy(gpu_cvb_table_head, (void*)customize_table, customize_table_size); - // Patch GPU volt - if (isMariko && C.marikoGpuUV == 3) - { - cvb_entry_t *entry = static_cast(gpu_cvb_table_head); - for (size_t i = 0; i < customize_entry_count; i++) + // Patch GPU volt + if (isMariko && C.marikoGpuUV == 3) { + cvb_entry_t* entry = static_cast(gpu_cvb_table_head); + for (size_t i = 0; i < customize_entry_count; i++) { + u32 patched_voltage = C.marikoGpuVoltArray[i]; + if (C.marikoGpuVoltArray[i] < C.gpuVmin) { - if (C.marikoGpuVoltArray[i] < C.gpuVmin) - { - u32 patched_voltage = C.marikoGpuVoltArray[i]; - if(C.gpuVmax) { - if(patched_voltage > C.gpuVmax) { - patched_voltage = C.gpuVmax; - } - } - PATCH_OFFSET(&(entry->cvb_pll_param.c0), patched_voltage * 1000); - PATCH_OFFSET(&(entry->cvb_pll_param.c1), 0); - PATCH_OFFSET(&(entry->cvb_pll_param.c2), 0); - PATCH_OFFSET(&(entry->cvb_pll_param.c3), 0); - PATCH_OFFSET(&(entry->cvb_pll_param.c4), 0); - PATCH_OFFSET(&(entry->cvb_pll_param.c5), 0); - } - entry++; + patched_voltage = C.gpuVmin; } - } - else if (C.commonGpuVoltOffset) - { - cvb_entry_t *entry = static_cast(gpu_cvb_table_head); - for (size_t i = 0; i < customize_entry_count; i++) - { - PATCH_OFFSET(&(entry->cvb_pll_param.c0), (entry->cvb_pll_param.c0 - C.commonGpuVoltOffset * 1000)); - entry++; + if(C.marikoGpuVoltArray[i] > C.gpuVmax) { + patched_voltage = C.gpuVmax; } + + PATCH_OFFSET(&(entry->cvb_pll_param.c0), patched_voltage * 1000); + PATCH_OFFSET(&(entry->cvb_pll_param.c1), 0); + PATCH_OFFSET(&(entry->cvb_pll_param.c2), 0); + PATCH_OFFSET(&(entry->cvb_pll_param.c3), 0); + PATCH_OFFSET(&(entry->cvb_pll_param.c4), 0); + PATCH_OFFSET(&(entry->cvb_pll_param.c5), 0); + entry++; } - - R_SUCCEED(); - }; - - Result MemFreqPllmLimit(u32 *ptr); - Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 - - template - Result MemMtcCustomizeTable(T *dst, T *src) - { - constexpr u32 mtc_magic = std::is_same_v ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC; - R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic()); - - constexpr u32 ZERO_VAL = UINT32_MAX; - // Skip params from dvfs_ver to clock_src; - for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) - { - u32 *src_ent = reinterpret_cast(reinterpret_cast(src) + offset); - u32 *dst_ent = reinterpret_cast(reinterpret_cast(dst) + offset); - u32 src_val = *src_ent; - - if (src_val) - { - PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val); - } + } + else if (C.commonGpuVoltOffset) { + cvb_entry_t* entry = static_cast(gpu_cvb_table_head); + for (size_t i = 0; i < customize_entry_count; i++) { + PATCH_OFFSET(&(entry->cvb_pll_param.c0), (entry->cvb_pll_param.c0 - C.commonGpuVoltOffset*1000)); + entry++; } + } - R_SUCCEED(); - }; + R_SUCCEED(); +}; - void SafetyCheck(); - void Patch(uintptr_t mapped_nso, size_t nso_size); +Result MemFreqPllmLimit(u32* ptr); +Result MemVoltHandler(u32* ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 + +template +Result MemMtcCustomizeTable(T* dst, T* src) { + constexpr u32 mtc_magic = std::is_same_v ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC; + R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic()); + + constexpr u32 ZERO_VAL = UINT32_MAX; + // Skip params from dvfs_ver to clock_src; + for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) { + u32* src_ent = reinterpret_cast(reinterpret_cast(src) + offset); + u32* dst_ent = reinterpret_cast(reinterpret_cast(dst) + offset); + u32 src_val = *src_ent; + + if (src_val) { + PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val); + } + } + + R_SUCCEED(); +}; + +void SafetyCheck(); +void Patch(uintptr_t mapped_nso, size_t nso_size); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp index d65f4374..c225b136 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp index cc921656..6cf6004f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -1,6 +1,8 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * + * Copyright (c) 2023 hanai3Bi + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -16,7 +18,7 @@ #include "pcv.hpp" #include "../mtc_timing_value.hpp" - +#include "../customize.hpp" namespace ams::ldr::oc::pcv::erista { Result CpuVoltRange(u32* ptr) { @@ -157,43 +159,6 @@ void MemMtcTableCustomAdjust(EristaMtcTable* table) { table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV - 1 + MC_ARB_SFA); table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV - 2); - WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW)); - WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD)); - - table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1; - - WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP)); - WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); - WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); - - table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP) / MC_ARB_DIV); - table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); - - WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab)); - WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb)); - WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe)); - WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe)); - - table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV); - - WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); - - table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA; - - WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH); - WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4); - WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW); - - WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); - WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); - WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); - WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); - - table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); - table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA; - table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA; - u32 DA_TURNS = 0; DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_w2r / 2) << 24; //W2R TURN diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp index 13c8acbc..47630a5c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -1,6 +1,8 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * + * Copyright (c) 2023 hanai3Bi + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -16,6 +18,7 @@ #include "pcv.hpp" #include "../mtc_timing_value.hpp" +#include "../customize.hpp" namespace ams::ldr::oc::pcv::mariko { @@ -72,16 +75,12 @@ Result CpuVoltDfll(u32* ptr) { if (C.marikoCpuUV) { if (C.marikoCpuUV == 1) { PATCH_OFFSET(&(entry->tune0_low), 0x0000FF90); //process_id 0 - PATCH_OFFSET(&(entry->tune0_high), 0x0000FFFF); - PATCH_OFFSET(&(entry->tune1_low), 0x021107FF); - PATCH_OFFSET(&(entry->tune1_high), 0x00000000); - } - else if (C.marikoCpuUV == 2) { + } else if (C.marikoCpuUV == 2) { PATCH_OFFSET(&(entry->tune0_low), 0x0000FFA0); //process_id 1 - PATCH_OFFSET(&(entry->tune0_high), 0x0000FFFF); - PATCH_OFFSET(&(entry->tune1_low), 0x021107FF); - PATCH_OFFSET(&(entry->tune1_high), 0x00000000); } + PATCH_OFFSET(&(entry->tune0_high), 0x0000FFFF); + PATCH_OFFSET(&(entry->tune1_low), 0x021107FF); + PATCH_OFFSET(&(entry->tune1_high), 0x00000000); } R_SUCCEED(); @@ -109,9 +108,6 @@ Result GpuFreqMaxAsm(u32* ptr32) { case 2: max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq; break; - case 3: - max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTableUv3)->freq; - break; default: max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq; break; @@ -234,7 +230,7 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) { BITS = BITS & ~( ((1u << HIGH) << 1u) - (1u << LOW) ); #define ADJUST(TARGET) (u32)CEIL(TARGET * (C.marikoEmcMaxClock / EmcClkOSLimit)) - #define ADJUST_INVERSE(TARGET) (u32)(TARGET * (EmcClkOSLimit / 1000) / (C.marikoEmcMaxClock)) + #define ADJUST_INVERSE(TARGET) (u32)(TARGET * (EmcClkOSLimit / 1000) / (C.marikoEmcMaxClock / 1000)) // Burst MC Regs #define WRITE_PARAM_BURST_MC_REG(TABLE, PARAM, VALUE) TABLE->burst_mc_regs.PARAM = VALUE; @@ -349,50 +345,6 @@ void MemMtcTableCustomAdjust(MarikoMtcTable* table) { table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2; - - - WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW)); - WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD)); - - table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1; - table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1; - - WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP)); - WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); - WRITE_PARAM_ALL_REG(table, emc_tratm, RATM); - WRITE_PARAM_ALL_REG(table, emc_twatm, WATM); - WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); - - table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP) / MC_ARB_DIV); - table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); - - WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab)); - WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb)); - WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe)); - WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe)); - - table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV); - - WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); - - table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA; - - WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH); - WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4); - WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW); - - WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); - WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); - WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); - WRITE_PARAM_ALL_REG(table, emc_trtm, RTM); - WRITE_PARAM_ALL_REG(table, emc_twtm, WTM); - WRITE_PARAM_ALL_REG(table, emc_tratm, RATM); - WRITE_PARAM_ALL_REG(table, emc_twatm, WATM); - WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); - - table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); - table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA; - table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA; u32 DA_TURNS = 0; DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN @@ -617,4 +569,4 @@ void Patch(uintptr_t mapped_nso, size_t nso_size) { } } -} +} \ No newline at end of file diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp index 6e4abe8e..543415e5 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp index b819bc30..72360e44 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (C) hanai3bi (meha) + * Copyright (C) Switch-OC-Suite * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License,