From e8a264fa1178a250947c384a6f1cd162a373333f Mon Sep 17 00:00:00 2001 From: Lightos1 Date: Sun, 8 Feb 2026 18:46:10 +0100 Subject: [PATCH] New timings, fix budget gpu dvfs --- .../source/oc/mariko/calculate_timings.cpp | 49 ++--------- .../loader/source/oc/mariko/timing_tables.cpp | 75 +--------------- .../loader/source/oc/mariko/timing_tables.hpp | 19 +--- .../loader/source/oc/mtc_timing_value.hpp | 66 +++++++------- .../stratosphere/loader/source/oc/pcv/pcv.hpp | 10 +++ .../loader/source/oc/pcv/pcv_mariko.cpp | 87 ++++++++----------- 6 files changed, 89 insertions(+), 217 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp index d2446bfb..832795c1 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp @@ -20,47 +20,14 @@ namespace ams::ldr::hoc::pcv::mariko { - u32 GetRext() { + void GetRext() { if (auto r = FindRext()) { - return r->correct; + rext = r->rext; + return; } - return 0x1A; - } - void CalculateTWTPDEN() { - tWTPDEN = tW2P + 1 + CEIL(tDQSS_max / tCK_avg) + CEIL(tDQS2DQ_max / tCK_avg) + 6; - if (C.marikoEmcMaxClock >= 2'233'000 && C.marikoEmcMaxClock < 2'533'000) tWTPDEN++; - if (C.marikoEmcMaxClock >= 2'433'000 && C.marikoEmcMaxClock < 2'800'000) tWTPDEN--; - } - - void CalculateTR2W() { - tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (C.t6_tRTW * 3); - - if (auto patch = FindTR2WPatch()) { - tR2W += patch->adjust; - } - } - - void CalculatePdex2rw() { - double freq_mhz = C.marikoEmcMaxClock / 1000.0; - - double pdex_local = (0.011 * freq_mhz) - 1.443; - pdex2rw = static_cast(ROUND(pdex_local)); - - if (pdex2rw < 22) pdex2rw = 22; - if (pdex2rw > 33) pdex2rw = 33; - - if (auto patch = FindPdex2rwPatch()) { - pdex2rw += patch->adjust; - } - } - - void CalculateCke2pden() { - cke2pden = (static_cast((C.marikoEmcMaxClock / 1000.0) * 0.00875) - 0.65); - - if (auto patch = FindCke2pdenPatch()) { - cke2pden += patch->adjust; - } + /* Fallback. */ + rext = 0x1A; } void CalculateMrw2() { @@ -93,11 +60,7 @@ namespace ams::ldr::hoc::pcv::mariko { } void CalculateTimings() { - rext = GetRext(); - CalculateTWTPDEN(); - CalculateTR2W(); - CalculatePdex2rw(); - CalculateCke2pden(); + GetRext(); CalculateMrw2(); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp index 102e4a9b..1ab70a8f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp @@ -36,78 +36,11 @@ namespace ams::ldr::hoc::pcv::mariko { const u32 g_rext_table_size = sizeof(g_rext_table) / sizeof(g_rext_table[0]); const ReplacePatch *FindRext() { - for (u32 i = 0; i < g_rext_table_size; i++) - if (g_rext_table[i].freq == C.marikoEmcMaxClock) + for (u32 i = 0; i < g_rext_table_size; i++) { + if (g_rext_table[i].freq >= C.marikoEmcMaxClock) { return &g_rext_table[i]; - return nullptr; - } - - const AdjustPatch g_tr2w_patches[] = { - {2'500'000, 1}, - {2'533'000, 1}, - {2'566'000, 1}, - {2'866'000, -1}, - {3'100'000, 1}, - {3'133'000, 1}, - }; - - const u32 g_tr2w_table_size = sizeof(g_tr2w_patches) / sizeof(g_tr2w_patches[0]); - - const AdjustPatch *FindTR2WPatch() { - for (u32 i = 0; i < g_tr2w_table_size; i++) - if (g_tr2w_patches[i].freq == C.marikoEmcMaxClock) - return &g_tr2w_patches[i]; - return nullptr; - } - - const AdjustPatch g_pdex2rw_patches[] = { - {2'166'000, 1}, - {2'300'000, 1}, - {2'333'000, 1}, - {2'433'000, 1}, - {2'533'000, 0}, - {2'633'000, -1}, - {2'666'000, -1}, - {2'733'000, -1}, - {2'766'000, -1}, - {2'800'000, -1}, - {2'833'000, -1}, - {2'933'000, -1}, - {3'066'000, 1}, - }; - - const u32 g_pdex2rw_table_size = sizeof(g_pdex2rw_patches) / sizeof(g_pdex2rw_patches[0]); - - const AdjustPatch *FindPdex2rwPatch() { - for (u32 i = 0; i < g_pdex2rw_table_size; i++) - if (g_pdex2rw_patches[i].freq == C.marikoEmcMaxClock) - return &g_pdex2rw_patches[i]; - return nullptr; - } - - const AdjustPatch g_cke2pden_patches[] = { - {2'133'000, 1}, - {2'166'000, 1}, - {2'266'000, 1}, - {2'300'000, 1}, - {2'366'000, 1}, - {2'400'000, 1}, - {2'500'000, 1}, - {2'633'000, 1}, - {2'733'000, 1}, - {2'833'000, 1}, - {2'866'000, 1}, - {2'966'000, 1}, - {3'066'000, 1}, - {3'100'000, 1}, - }; - - const u32 g_cke2pden_table_size = sizeof(g_cke2pden_patches) / sizeof(g_cke2pden_patches[0]); - - const AdjustPatch *FindCke2pdenPatch() { - for (u32 i = 0; i < g_cke2pden_table_size; i++) - if (g_cke2pden_patches[i].freq == C.marikoEmcMaxClock) - return &g_cke2pden_patches[i]; + } + } return nullptr; } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp index 429cd3c4..c4719369 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp @@ -21,28 +21,11 @@ namespace ams::ldr::hoc::pcv::mariko { struct ReplacePatch { u32 freq; - u32 correct; + u32 rext; }; extern const ReplacePatch g_rext_table[]; extern const u32 g_rext_table_size; const ReplacePatch *FindRext(); - struct AdjustPatch { - u32 freq; - s32 adjust; - }; - - extern const AdjustPatch g_tr2w_patches[]; - extern const u32 g_tr2w_table_size; - const AdjustPatch *FindTR2WPatch(); - - extern const AdjustPatch g_pdex2rw_patches[]; - extern const u32 g_pdex2rw_table_size; - const AdjustPatch *FindPdex2rwPatch(); - - extern const AdjustPatch g_cke2pden_patches[]; - extern const u32 g_cke2pden_table_size; - const AdjustPatch *FindCke2pdenPatch(); - } 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 6d5cd99b..23588ea2 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -21,19 +21,19 @@ #include "oc_common.hpp" namespace ams::ldr::hoc { - #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) - #define ROUND(A) std::lround(A) + #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) + #define ROUND(A) std::lround(A) #define PACK_U32(high, low) ((static_cast(high) << 16) | (static_cast(low) & 0xFFFF)) #define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast(high & 0xF) << 28) | (static_cast(low) & 0xFF)) /* Primary timings. */ - const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; - const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; - const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 }; + const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; + const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; + const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 }; const std::array tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */ const std::array tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 }; const std::array tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; @@ -96,7 +96,7 @@ namespace ams::ldr::hoc { const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5; const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (C.eristaEmcMaxClock / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg)); - + const u32 wdv = WL; const u32 wsv = WL - 2; const u32 wev = 0xA + (WL - 14); @@ -139,43 +139,41 @@ namespace ams::ldr::hoc { const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; - const u32 tR2P = 12 + ((RL_DBI - 32) / 2); - inline u32 tR2W; - const u32 tRTM = RL + 9 + (tDQSCK_max / tCK_avg) + FLOOR(tRPST) + CEIL(10 / tCK_avg); // Fix? - const u32 tRATM = tRTM + CEIL(10 / tCK_avg) - 12; // Fix? + const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0); + const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3); + const u32 tRTM = FLOOR((10.0 + RL_DBI) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg); + const u32 tRATM = CEIL((tRTM - 10.0) + (RL_DBI * 0.426)); inline u32 rext; - const u32 rdv = FLOOR(17.02046755653219 + (RL_DBI + (ramFreqMhz * 0.00510056573299173))); - const u32 qpop = rdv - 14; - const u32 quse_width = CEIL(((3.7165006256863955 - ramFreqMhz) + (-0.002446584377651142 * ramFreqMhz)) - FLOOR(ramFreqMhz / -0.9952024303111688)); - const u32 quse = CEIL(MIN(RL_DBI + (2.991255208275918 - (quse_width + (-0.00511180626826906 * ramFreqMhz))), ramFreqMhz * 0.021333773138874437)); - const u32 einput_duration = CEIL(quse_width + (ramFreqMhz * 0.01) + 4); - const u32 einput = 5 + qpop - einput_duration; - const u32 ibdly = 0x10000000 + FLOOR(MAX(RL_DBI - 1.9999956603408224, quse - 5.9999987787411175) + (-0.0011929079761504341 * ramFreqMhz)); - const u32 qrst_duration = FLOOR((ramFreqMhz * 0.001477125119082522) + 4.272302254983803); - const u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); - const u32 qrst = PACK_U32(qrst_duration, qrstLow); - const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); - - const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5; - inline u32 tWTPDEN; - const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * ramFreqMhz), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg)); - const u32 tWTM = WL + (BL / 2) + 1 + CEIL(7.5 / tCK_avg); - const u32 tWATM = tWTM + CEIL(tWR / tCK_avg); + const u32 rdv = RL_DBI + FLOOR((5.105 / tCK_avg) + 17.017); + const u32 qpop = rdv - 14; + const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782); + const u32 quse = FLOOR(RL_DBI + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg); + const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width; + const u32 einput = quse - CEIL(9.928 / tCK_avg); + const u32 qrst_duration = FLOOR(8.399 - tCK_avg); + const u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); + const u32 qrst = PACK_U32(qrst_duration, qrstLow); + const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); + const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); + const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5; + const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast(tW2P))) + (BL / 2)); + const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - FLOOR(tWTR / tCK_avg); + const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753)); + const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0; const u32 wdv = WL; const u32 wsv = WL - 2; const u32 wev = 0xA + (WL - 14); const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); - const u32 obdlyLow = WL - MIN(static_cast(WL), 12 - (CEIL(-0.0003991 * ramFreqMhz) * 2)); + const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); - inline u32 pdex2rw; - inline u32 cke2pden; + const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361))); - const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * ramFreqMhz)); + const u32 tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0; const double tMMRI = tRCD + (tCK_avg * 3); const double pdex2mrr = tMMRI + 10; /* Do this properly? */ diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index ab52f759..31854886 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -122,6 +122,16 @@ namespace ams::ldr::hoc::pcv { {0xFFFFFFFF, 35}, }; + static const u32 ramBrackets[][22] = { + { 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, + { 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, + { 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, + { 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }, + }; + + static const u32 gpuBudgetDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800}; + + /* GPU Max Clock asm Pattern: * * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) 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 b5cc8ce6..44b19be1 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -50,49 +50,31 @@ namespace ams::ldr::hoc::pcv::mariko { return ramScale; } - /* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */ - - static unsigned int ramBrackets[][22] = - { - { 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, - { 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, - { 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, - { 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, } - }; - - unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800}; - - int GetSpeedoBracket (int speedo) - { - int speedoBracket = 3; - if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) { - speedoBracket = !!(1625 < speedo); + u32 GetSpeedoBracket() { + u32 speedoBracket = 3; + if ((C.gpuSpeedo < 1754) && (speedoBracket = 2, C.gpuSpeedo < 1690)) { + speedoBracket = !!(1625 < C.gpuSpeedo); } return speedoBracket; } - unsigned int GetGpuVoltage (unsigned int freq, int speedo) - { - long int lVar1; - int bracket = GetSpeedoBracket(speedo); + u32 GetGpuBudgetDvfsVoltage() { + u32 bracket = GetSpeedoBracket(); - if (freq < 1601) + if (ramFreqMhz <= 1600) return 0; - lVar1 = 0; - do - { - if (freq <= ramBrackets[bracket][lVar1])//*(unsigned int *)((ulong)DAT_001491e0 * 0x58 + 1280960 + lVar1 * 4)) - return gpuDvfsArray[lVar1];//*(undefined4 *)((long)(int)lVar1 * 4 + 1281312); - - lVar1++; - } while (lVar1 != 22); + for (u32 voltageIndex = 0; voltageIndex < 22; voltageIndex++) { + if (ramFreqMhz <= ramBrackets[bracket][voltageIndex]) { + return gpuBudgetDvfsArray[voltageIndex]; + } + } return 800; } - + /* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */ u32 GetAutoVoltage() { u32 voltage = GetGpuVminVoltage(); voltage = GetRamVminAdjustment(voltage); @@ -127,31 +109,31 @@ namespace ams::ldr::hoc::pcv::mariko { /* C.marikoGpuVmin is zero OR one, auto voltage is applied. */ /* Get vmin depending on speedo and ram clock. */ - u32 autoVmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuVoltage(C.marikoEmcMaxClock / 1000, C.gpuSpeedo); + u32 autoVmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage(); PATCH_OFFSET(ptr, autoVmin); R_SUCCEED(); } Result GpuVoltThermals(u32 *ptr) { - u32 vmin = std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern)); - if (vmin) { + if (std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern))) { R_THROW(ldr::ResultInvalidGpuDvfs()); } + u32 vmin = C.marikoGpuVmin; + /* Automatic voltage. */ - if (!C.marikoGpuVmin) { - vmin = GetAutoVoltage(); + if (!C.marikoGpuVmin || C.marikoGpuVmin == 1) { + vmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage(); PATCH_OFFSET(ptr, vmin); PATCH_OFFSET(ptr + 3, vmin); PATCH_OFFSET(ptr + 6, vmin); PATCH_OFFSET(ptr + 9, vmin); } else { /* Manual voltage. */ - PATCH_OFFSET(ptr, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 3, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 6, C.marikoGpuVmin); - PATCH_OFFSET(ptr + 9, C.marikoGpuVmin); - vmin = C.marikoGpuVmin; + PATCH_OFFSET(ptr, vmin); + PATCH_OFFSET(ptr + 3, vmin); + PATCH_OFFSET(ptr + 6, vmin); + PATCH_OFFSET(ptr + 9, vmin); } PATCH_OFFSET(ptr + 12, vmin); @@ -434,17 +416,21 @@ namespace ams::ldr::hoc::pcv::mariko { */ #define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \ - TABLE->burst_regs.PARAM = (VALUE); \ - TABLE->shadow_regs_ca_train.PARAM = (VALUE); \ - TABLE->shadow_regs_rdwr_train.PARAM = (VALUE); + TABLE->burst_regs.PARAM = VALUE; \ + TABLE->shadow_regs_ca_train.PARAM = VALUE; \ + TABLE->shadow_regs_rdwr_train.PARAM = VALUE; - #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / (tCK_avg))) + #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) /* Ram power down */ /* B31: DRAM_CLKSTOP_PD */ /* B30: DRAM_CLKSTOP_SR */ /* B29: DRAM_ACPD */ - WRITE_PARAM_ALL_REG(table, emc_cfg, C.hpMode ? 0x13200000 : 0xF3200000); + if (C.hpMode) { + WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000); + } else { + WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000); + } u32 refresh_raw = 0xFFFF; if (C.t8_tREFI != 6) { @@ -470,9 +456,9 @@ namespace ams::ldr::hoc::pcv::mariko { WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW)); WRITE_PARAM_ALL_REG(table, emc_trpab, MIN(GET_CYCLE_CEIL(tRPab), static_cast(0x3F))); WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR)); - WRITE_PARAM_ALL_REG(table, emc_tcke, tCKE); + WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(7.425) + 2); WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP)); - WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8); // TODO analyse + WRITE_PARAM_ALL_REG(table, emc_tclkstop, tCLKSTOP); WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P); WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W); WRITE_PARAM_ALL_REG(table, emc_trtm, tRTM); @@ -490,12 +476,11 @@ namespace ams::ldr::hoc::pcv::mariko { WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control); WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw); WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw); - WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.75)); + WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.763)); WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75)); WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(1.05)); WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0)); - WRITE_PARAM_ALL_REG(table, emc_cke2pden, /* cke2pden */ GET_CYCLE_CEIL(8.5)); - (void) cke2pden; + WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(8.499)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr)); WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN); WRITE_PARAM_ALL_REG(table, emc_einput, einput);