From 679fd4fd79f40d9b1058a072c569fbbfb99dd5a7 Mon Sep 17 00:00:00 2001 From: Lightos1 <124387232+Lightos1@users.noreply.github.com> Date: Wed, 21 Jan 2026 18:50:36 +0100 Subject: [PATCH] 1866/1600 support --- .../source/oc/mariko/calculate_timings.cpp | 71 +++++++-------- .../loader/source/oc/mariko/timing_tables.cpp | 87 ------------------- .../loader/source/oc/mariko/timing_tables.hpp | 16 ---- .../loader/source/oc/mtc_timing_value.hpp | 35 ++++---- .../stratosphere/loader/source/oc/pcv/pcv.hpp | 4 +- .../loader/source/oc/pcv/pcv_mariko.cpp | 15 ++-- 6 files changed, 60 insertions(+), 168 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 c6796da9..22146959 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp @@ -27,29 +27,6 @@ namespace ams::ldr::oc::pcv::mariko { return 0x1A; } - /* TODO: This function is quite uggly, refactor! */ - void CalculateMiscTimings() { - einput_duration = 0x1C; - - for (u32 i = 0; i < g_misc_table_size; i++) { - const auto& e = g_misc_table[i]; - if (C.marikoEmcMaxClock >= e.min_freq) { - if (e.einput) einput_duration = e.einput; - } - } - - rext = GetRext(); - } - - void CalculateIbdly() { - /* Ibdly is so inconsistent, I am using the most common value and then checking with a lookup table. */ - ibdly = 0x1000001D + C.mem_burst_read_latency; - - if (auto patch = FindIbdlyPatch()) { - ibdly += patch->adjust; - } - } - 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++; @@ -64,19 +41,6 @@ namespace ams::ldr::oc::pcv::mariko { } } - void CalculateQsafe() { - qsafe = ROUND((C.marikoEmcMaxClock / 1000.0) / 138.0 + 37.4) + C.mem_burst_read_latency; - if (auto patch = FindQsafePatch()) { - qsafe += patch->adjust; - } - } - - void CalculateQpop() { - qpop = FLOOR(((C.marikoEmcMaxClock / 1000.0) - 2133 + 167) / 200.0) + 0x2D + C.mem_burst_read_latency; - - if (C.marikoEmcMaxClock >= 3'133'000) qpop++; - } - void CalculatePdex2rw() { double freq_mhz = C.marikoEmcMaxClock / 1000.0; @@ -99,15 +63,42 @@ namespace ams::ldr::oc::pcv::mariko { } } + void CalculateMrw2() { + static const u8 rlMapDBI[8] = { + 6, 12, 16, 22, 28, 32, 36, 40 + }; + + static const u8 wlMapSetA[8] = { + 4, 6, 8, 10, 12, 14, 16, 18 + }; + + u32 rlIndex = 0; + u32 wlIndex = 0; + + for (u32 i = 0; i < std::size(rlMapDBI); ++i) { + if (rlMapDBI[i] == RL_DBI) { + rlIndex = i; + break; + } + } + + for (u32 i = 0; i < std::size(wlMapSetA); ++i) { + if (wlMapSetA[i] == WL) { + wlIndex = i; + break; + } + } + + mrw2 = static_cast(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); + } + void CalculateTimings() { - CalculateMiscTimings(); - CalculateIbdly(); + rext = GetRext(); CalculateTWTPDEN(); CalculateTR2W(); - CalculateQsafe(); - CalculateQpop(); CalculatePdex2rw(); CalculateCke2pden(); + 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 492c61ef..68699706 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp @@ -19,34 +19,6 @@ namespace ams::ldr::oc::pcv::mariko { - const MiscTimings g_misc_table[] = { - {1'866'000, 0x20, }, - {2'133'000, 0x24, }, - {2'166'000, 0, }, - {2'233'000, 0x25, }, - {2'300'000, 0x26, }, - {2'333'000, 0x27, }, - {2'366'000, 0x26, }, - {2'433'000, 0x27, }, - {2'466'000, 0x2A, }, - {2'500'000, 0x28, }, - {2'533'000, 0x29, }, - {2'566'000, 0, }, - {2'633'000, 0x2A, }, - {2'700'000, 0x2B, }, - {2'733'000, 0x2C, }, - {2'766'000, 0x2B, }, - {2'833'000, 0x2C, }, - {2'866'000, 0, }, - {2'900'000, 0, }, - {2'933'000, 0x2E, }, - {2'966'000, 0, }, - {3'033'000, 0x2F, }, - {3'133'000, 0x31, }, - }; - - const u32 g_misc_table_size = sizeof(g_misc_table) / sizeof(g_misc_table[0]); - const ReplacePatch g_rext_table[] = { {2'133'000, 0x1A}, {2'166'000, 0x19}, {2'200'000, 0x19}, {2'233'000, 0x19}, {2'266'000, 0x1A}, {2'300'000, 0x1B}, @@ -70,34 +42,6 @@ namespace ams::ldr::oc::pcv::mariko { return nullptr; } - const AdjustPatch g_ibdly_patches[] = { - {2'133'000, -2}, - {2'166'000, -1}, - {2'200'000, -1}, - {2'233'000, -1}, - {2'266'000, -1}, - {2'300'000, -2}, - {2'333'000, -2}, - {2'500'000, -1}, - {2'533'000, -2}, - {2'566'000, -1}, - {2'600'000, -1}, - {2'633'000, -1}, - {2'666'000, -1}, - {2'700'000, -2}, - {2'733'000, -2}, - {2'933'000, -1}, - }; - - const u32 g_ibdly_table_size = sizeof(g_ibdly_patches) / sizeof(g_ibdly_patches[0]); - - const AdjustPatch *FindIbdlyPatch() { - for (u32 i = 0; i < g_ibdly_table_size; i++) - if (g_ibdly_patches[i].freq == C.marikoEmcMaxClock) - return &g_ibdly_patches[i]; - return nullptr; - } - const AdjustPatch g_tr2w_patches[] = { {2'500'000, 1}, {2'533'000, 1}, @@ -116,37 +60,6 @@ namespace ams::ldr::oc::pcv::mariko { return nullptr; } - const AdjustPatch g_qsafe_patches[] = { - {2'166'000, 1}, - {2'200'000, 1}, - {2'500'000, -1}, - {2'533'000, -1}, - {2'666'000, -1}, - {2'700'000, -1}, - {2'733'000, -1}, - {2'800'000, -1}, - {2'833'000, -1}, - {2'866'000, -1}, - {2'900'000, -1}, - {2'933'000, -2}, - {2'966'000, -1}, - {3'000'000, -1}, - {3'033'000, -1}, - {3'066'000, -2}, - {3'100'000, -2}, - {3'166'000, -1}, - {3'200'000, -1}, - }; - - const u32 g_qsafe_table_size = sizeof(g_qsafe_patches) / sizeof(g_qsafe_patches[0]); - - const AdjustPatch *FindQsafePatch() { - for (u32 i = 0; i < g_qsafe_table_size; i++) - if (g_qsafe_patches[i].freq == C.marikoEmcMaxClock) - return &g_qsafe_patches[i]; - return nullptr; - } - const AdjustPatch g_pdex2rw_patches[] = { {2'166'000, 1}, {2'300'000, 1}, 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 06176a49..893007d2 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp @@ -33,18 +33,10 @@ namespace ams::ldr::oc::pcv::mariko { s32 adjust; }; - extern const AdjustPatch g_ibdly_patches[]; - extern const u32 g_ibdly_table_size; - const AdjustPatch *FindIbdlyPatch(); - extern const AdjustPatch g_tr2w_patches[]; extern const u32 g_tr2w_table_size; const AdjustPatch *FindTR2WPatch(); - extern const AdjustPatch g_qsafe_patches[]; - extern const u32 g_qsafe_table_size; - const AdjustPatch *FindQsafePatch(); - extern const AdjustPatch g_pdex2rw_patches[]; extern const u32 g_pdex2rw_table_size; const AdjustPatch *FindPdex2rwPatch(); @@ -53,12 +45,4 @@ namespace ams::ldr::oc::pcv::mariko { extern const u32 g_cke2pden_table_size; const AdjustPatch *FindCke2pdenPatch(); - struct MiscTimings { - u32 min_freq; - u32 einput; - }; - - extern const MiscTimings g_misc_table[]; - extern const u32 g_misc_table_size; - } 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 aaf1bd13..6c0be364 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -81,6 +81,7 @@ namespace ams::ldr::oc { namespace pcv::mariko { const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock; + const double ramFreqMhz = C.marikoEmcMaxClock / 1000.0; const u32 tRCD = tRCD_values[C.t1_tRCD]; const u32 tRPpb = tRP_values[C.t2_tRP]; @@ -95,44 +96,44 @@ namespace ams::ldr::oc { const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; - const u32 tR2P = 12 + (C.mem_burst_read_latency / 2); + const u32 tR2P = 12 + (C.mem_burst_read_latency / 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 rdv = FLOOR(17.02046755653219 + (RL_DBI + ((C.marikoEmcMaxClock / 1000.0) * 0.00510056573299173))); - const u32 quse = FLOOR((-0.0048159 * (C.marikoEmcMaxClock / 1000.0)) + RL_DBI) + (FLOOR((C.marikoEmcMaxClock / 1000.0) * 0.0050997) * 1.5134); - const u32 einput = quse - ((C.marikoEmcMaxClock / 1000.0) * 0.01); - - inline u32 einput_duration; - inline u32 ibdly; - - const u32 obdly = 0x10000000 + CEIL(MAX((WL + (2.072347067198409 * CEIL(((C.marikoEmcMaxClock / 1000.0) * -0.0008701518090699537) + 1.1926184709583145))) - 12.368815500608948, -1.8792921762826563e-9)); - const u32 quse_width = CEIL(((3.7165006256863955 - (C.marikoEmcMaxClock / 1000.0)) + (-0.002446584377651142 * (C.marikoEmcMaxClock / 1000.0))) - FLOOR((C.marikoEmcMaxClock / 1000.0) / -0.9952024303111688)); inline u32 rext; - const u32 qrstHighDuration = FLOOR(((C.marikoEmcMaxClock / 1000.0) * 0.001477125119082522) + 4.272302254983803); - const u32 qrstLow = CEIL(MAX(((C.marikoEmcMaxClock / 1000.0) * -0.010085158701622026) + ((rdv + (-15.612107759528982 - quse_width)) - qrstHighDuration), -0.0004475366008085334)); - const u32 qrst = PACK_U32(qrstHighDuration, qrstLow); - inline u32 qsafe; - inline u32 qpop; + 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((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 * (C.marikoEmcMaxClock / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg)); + 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 wdv = WL; const u32 wsv = WL - 2; const u32 wev = 0xA + C.mem_burst_write_latency; + const u32 obdly = 0x10000000 + WL - MIN(static_cast(WL), 12 - (CEIL(-0.0003991 * ramFreqMhz) * 2)); inline u32 pdex2rw; inline u32 cke2pden; - const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * (C.marikoEmcMaxClock / 1000.0))); + const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * ramFreqMhz)); const double tMMRI = tRCD + (tCK_avg * 3); const double pdex2mrr = tMMRI + 10; /* Do this properly? */ + + inline u8 mrw2; } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index face5620..c66a8bb9 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -206,7 +206,7 @@ namespace ams::ldr::oc::pcv { constexpr u32 CpuVoltL4T = 1235'000; static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 }; - static const u32 cpuVoltDvfsOffsets[] = { 5, 6, 7, 9, 8 }; + static const u32 cpuVoltDvfsOffsets[] = { 5, 6, 7, 8, 9 }; static_assert(sizeof(cpuVoltDvfsPattern) == sizeof(cpuVoltDvfsOffsets), "Invalid cpuVoltDvfsPattern"); static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 }; @@ -216,7 +216,7 @@ namespace ams::ldr::oc::pcv { constexpr u32 GpuVminOfficial = 810; static const u32 gpuVoltDvfsPattern[] = { 1150, 1000, 100, 1000, 10, }; - static const u32 gpuVoltDvfsOffsets[] = { 1, 2, 3, 4, 5, }; + static const u32 gpuVoltDvfsOffsets[] = { 1, 2, 3, 4, 5, }; static_assert(sizeof(gpuVoltDvfsPattern) == sizeof(gpuVoltDvfsOffsets), "Invalid gpuVoltDvfsPattern"); static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 }; 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 1110c097..8d774c08 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -434,7 +434,7 @@ namespace ams::ldr::oc::pcv::mariko { 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_tpd, GET_CYCLE_CEIL(tXP)); - WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8); + WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8); // TODO analyse WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P); WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W); WRITE_PARAM_ALL_REG(table, emc_trtm, tRTM); @@ -484,8 +484,6 @@ namespace ams::ldr::oc::pcv::mariko { WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv); WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_2, 0x24) WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_3, 0x24) - // WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt, 0x07FF003C); - // WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt2, 0x02DE002A); /* This needs some clean up. */ constexpr double MC_ARB_DIV = 4.0; @@ -574,7 +572,8 @@ namespace ams::ldr::oc::pcv::mariko { table->dram_timings.t_rp = tRFCpb; table->dram_timings.t_rfc = tRFCab; table->dram_timings.rl = RL_DBI; - table->emc_mrw2 = 0x8802003F; + + table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); table->emc_cfg_2 = 0x11083D; } @@ -776,10 +775,14 @@ namespace ams::ldr::oc::pcv::mariko { PATCH_OFFSET(ptr, emc_uv); i2cInitialize(); - I2cSet_U8(I2cDevice_Max77812_2, 0x25, (emc_uv - uv_min) / uv_step); + Result resultI2C = I2cSet_U8(I2cDevice_Max77812_2, 0x25, (emc_uv - uv_min) / uv_step); i2cExit(); - R_SUCCEED(); + if (R_SUCCEEDED(resultI2C)) { + R_SUCCEED(); + } + + return resultI2C; } void Patch(uintptr_t mapped_nso, size_t nso_size) {