diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index ea7dfaa6..ee0b3c7a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -35,8 +35,10 @@ volatile CustomizeTable C = { /* Disables RAM powerdown */ .hpMode = DISABLED, -.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ -.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ +.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ +.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ +.eristaEmcMaxClock1 = 1600000, +.eristaEmcMaxClock2 = 1600000, /* Available: 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */ /* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */ @@ -82,6 +84,24 @@ volatile CustomizeTable C = { /* 2133 */ 0, }, +/* You can mix and match different latencies if needed */ +/* + * Read: + * 2133RL = 40 + * 1866RL = 36 + * 1600RL = 32 + * 1331RL = 28 + * Write: + * 2133WL = 18 + * 1866WL = 16 + * 1600WL = 14 + * 1331WL = 12 + */ + +/* Erista only. */ +.mem_burst_read_latency = RL_1600, +.mem_burst_write_latency = WL_1600, + .eristaCpuUV = 0, .eristaCpuVmin = 800, .eristaCpuMaxVolt = 1200, @@ -121,6 +141,9 @@ volatile CustomizeTable C = { .commonGpuVoltOffset = 0, +/* Speedo is automatically set by hoc-clk on first boot */ +.gpuSpeedo = 1450, + /* Setting DEACTIVATED_GPU_FREQ on any freq will disable it and all freqs greater than it. (the latter is a bug :/) */ /* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */ /* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */ diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp index 1724249f..5cfb87ca 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp @@ -70,6 +70,8 @@ struct CustomizeTable { u32 commonEmcMemVolt; u32 eristaEmcMaxClock; + u32 eristaEmcMaxClock1; + u32 eristaEmcMaxClock2; StepMode stepMode; u32 marikoEmcMaxClock; @@ -95,6 +97,9 @@ struct CustomizeTable { u32 readLatency[4]; u32 writeLatency[4]; + u32 mem_burst_read_latency; + u32 mem_burst_write_latency; + u32 eristaCpuUV; u32 eristaCpuVmin; u32 eristaCpuMaxVolt; @@ -121,6 +126,8 @@ struct CustomizeTable { u32 commonGpuVoltOffset; + u32 gpuSpeedo; + u32 eristaGpuVoltArray[27]; u32 marikoGpuVoltArray[24]; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp index 74e0cb91..f83186ee 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp @@ -18,80 +18,8 @@ namespace ams::ldr::hoc::pcv::erista { - void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) { - latency += index * latencyStep; - } - - static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) { - s32 maxIndex = -1; - for (u32 i = 0; i < latencySize; ++i) { - if (latencyArray[i]) { - maxIndex = i; - } - } - - return maxIndex; - } - - void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) { - if (freq > 1600'000 && freq <= 1866'000) { /* 1866tRWL */ - latency += latencyStep * 2; - } else { /* 2133tRWL */ - latency += latencyStep * 3; - } - } - - void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) { - for (u32 i = 0; i <= indexMax; ++i) { - if (latencyArray[i] != 0 && freq <= latencyArray[i]) { - SwitchLatency(latency, i, latencyStep); - return; - } - } - - SwitchLatency(latency, indexMax, latencyStep); - } - - void HandleLatency(u32 freq) { - static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency)); - static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency)); - constexpr u32 ReadLatencyStep = 4; - constexpr u32 WriteLatencyStep = 2; - bool autoLatencyRead = false, autoLatencyWrite = false; - - if (rlIndexMax == -1) { - AutoLatency(RL, freq, ReadLatencyStep); - autoLatencyRead = true; - } - - if (wlIndexMax == -1) { - AutoLatency(WL, freq, WriteLatencyStep); - autoLatencyWrite = true; - } - - if (autoLatencyRead && autoLatencyWrite) { - return; - } - - if (!autoLatencyRead) { - HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep); - } - - if (!autoLatencyWrite) { - HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep); - } - } - - void CalculateTimings(double tCK_avg, u32 freq) { - RL = RL_1331; - WL = WL_1331; - - HandleLatency(freq); - - tR2P = CEIL((RL * 0.426) - 2.0); - tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; - - tW2P = (CEIL(WL * 1.7303) * 2) - 5; + void CalculateTimings(double tCK_avg) { + tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast(tW2P))) + (BL / 2)); tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.hpp index 7a61386d..3a58c83a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.hpp @@ -18,6 +18,6 @@ namespace ams::ldr::hoc::pcv::erista { - void CalculateTimings(double tCK_avg, u32 freq); + void CalculateTimings(double tCK_avg); } 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 d03feafa..fca368d8 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp @@ -46,7 +46,7 @@ namespace ams::ldr::hoc::pcv::mariko { } void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) { - if (freq > 1600'000 && freq <= 1862'400) { /* 1866tRWL */ + if (freq > 1600'000 && freq <= 1866'000) { /* 1866tRWL */ latency += latencyStep * 2; } else { /* 2133tRWL */ latency += latencyStep * 3; 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 15da084e..1b592f0e 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -33,6 +33,10 @@ namespace ams::ldr::hoc { /* Burst latency, not to be confused with base latency (tWRL). */ const u32 BL = 16; + /* Base latency for read and write (tWRL). */ + const u32 RL = C.mem_burst_read_latency; + const u32 WL = C.mem_burst_write_latency; + /* Precharge to Precharge Delay. (tCK) */ const u32 tPPD = 4; @@ -83,14 +87,11 @@ namespace ams::ldr::hoc { const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; - inline u32 RL; - inline u32 WL; - - inline u32 tR2P; + const u32 tR2P = CEIL((RL * 0.426) - 2.0); inline u32 tR2W; inline u32 rext; - inline u32 tW2P; + const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5; inline u32 tWTPDEN; inline u32 tW2R; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index 8e8ae163..a34c2dd6 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -147,7 +147,7 @@ namespace ams::ldr::hoc::pcv { { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, }, { marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, }, { C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */ - { C.eristaEmcMaxClock, 1600'000, 2600'000, panic::Emc, }, + { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, panic::Emc, }, { C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, }, { C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, }, { C.marikoSocVmax, 1000, 1200, panic::Emc, }, 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 4c0e9a0e..85ef4de2 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -18,7 +18,6 @@ * along with this program. If not, see . */ -#include #include "pcv.hpp" #include "../mtc_timing_value.hpp" #include "../erista/calculate_timings_erista.hpp" @@ -216,7 +215,7 @@ namespace ams::ldr::hoc::pcv::erista { const u32 dyn_self_ref_control = (static_cast(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000); - CalculateTimings(tCK_avg, table->rate_khz); + CalculateTimings(tCK_avg); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); @@ -361,176 +360,65 @@ namespace ams::ldr::hoc::pcv::erista { table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050); } - namespace { - std::vector newEmcList; - u32 *nsoStart; - } - - /* The silicon instructs; the children obey... */ - void MtcGenerateFreqTables() { - newEmcList.clear(); - newEmcList.reserve(DvfsTableEntryCount); - newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault)); - - if (C.eristaEmcMaxClock <= EmcClkOSLimit) { - return; - } - - /* This is scuffed, but Eristas step rate is... weird? */ - /* 1766MHz seems to cause crashes with other freqs near it... why is anyones guess... */ - u32 freqsLow[] = { 1633000, 1666000, 1700000, 1733000, 1800000, 1833000, 1862400, }; - constexpr size_t freqsLowSize = std::size(freqsLow); - - for (size_t i = 0; i < freqsLowSize; ++i) { - if (freqsLow[i] <= C.eristaEmcMaxClock) { - newEmcList.push_back(freqsLow[i]); - } else { - break; - } - } - - if (C.eristaEmcMaxClock <= freqsLow[freqsLowSize - 1]) { - return; - } - - /* High range. */ - constexpr u32 StepRate = 38400; - while (newEmcList.back() + StepRate < C.eristaEmcMaxClock) { - newEmcList.push_back(newEmcList.back() + StepRate); - } - - if (newEmcList.back() != C.eristaEmcMaxClock) { - newEmcList.push_back(static_cast(C.eristaEmcMaxClock)); - } - - constexpr u32 PllmToggleFrequency = 19200; - - /* A step of 19.2khz will cause hangs, crashes and other weirdness. */ - /* Why? ¯\_(ツ)_/¯ */ - if (C.eristaEmcMaxClock - newEmcList[newEmcList.size() - 2] <= PllmToggleFrequency) { - newEmcList.erase(newEmcList.begin() + newEmcList.size() - 2); - } - - newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit)); - } - - /* TODO: Template this */ - Result VerifyMtcTable(EristaMtcTable *tableStart, u32 expectedFreq) { - R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable()); - R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); - - R_SUCCEED(); - } - - /* TODO: Template this */ - Result MtcValidateAllTables(EristaMtcTable *tableStart, const u32 *validationList, u32 tableCount) { - for (u32 i = 0; i < tableCount; ++i) { - R_TRY(VerifyMtcTable(&tableStart[i], validationList[i])); - } - - R_SUCCEED(); - } - - /* TODO: Put this into common. */ - DramId GetDramId() { - u64 id64; - splGetConfig(SplConfigItem_DramId, &id64); - return static_cast(id64); - } - - MtcTableIndex GetMtcDramIndex(DramId dramId) { - for (u32 i = 0; i < std::size(mtcIndexTable); ++i) { - if (mtcIndexTable[i].dramId == dramId) { - return mtcIndexTable[i].index; - } - } - - return MtcTableIndex_Invalid; - } - - NORETURN void AbortInvalidMtc(const char *crashMsg) { - panic::SmcError(panic::Emc); - CRASH(crashMsg); - } - - u32 GetMtcOffset(MtcTableIndex index) { - if (index < T210SdevEmcDvfsTableS6gb01) { - return index * erista::MtcFullTableSize; - } - - /* Account for the weird in between mariko table. */ - return index * erista::MtcFullTableSize + mariko::MtcFullTableSize; - } - - void PrepareMtcMemoryRegion(u8 *firstTable, EristaMtcTable *usedTable) { - memmove(firstTable, usedTable, erista::MtcFullTableSize); - - /* Clear all other tables. */ - /* The used table is excluded. */ - constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * (mariko::MtcFullTableCount) + (erista::MtcFullTableSize * (erista::MtcFullTableCount - 1)); - memset(firstTable + erista::MtcFullTableSize, 0, RemainingRegionSize); - } - - void MtcExtendTables(EristaMtcTable *table) { - for (u32 i = erista::MtcTableCountDefault; i < newEmcList.size(); ++i) { - std::memcpy(&table[i], &table[i - 1], sizeof(EristaMtcTable)); - table[i].rate_khz = newEmcList[i]; - } - } - + /* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */ Result MemFreqMtcTable(u32 *ptr) { - static const DramId dramId = [] { - DramId id = GetDramId(); - return id; - }(); + u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 }; + std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks)); + u32 khz_list_size = std::size(khz_list); - static const MtcTableIndex mtcIndex = [] { - MtcTableIndex idx = GetMtcDramIndex(dramId); - /* If for some reason this happens, there is no chance of recovering this. */ - if (idx == MtcTableIndex_Invalid) { - AbortInvalidMtc("Invalid dramId"); - } - return idx; - }(); - - static const u32 mtcOffset = GetMtcOffset(mtcIndex); - - constexpr u32 StartAdjustment = offsetof(EristaMtcTable, rate_khz) + sizeof(EristaMtcTable) * (erista::MtcTableCountDefault - 1); - u8 *startPtr = reinterpret_cast(ptr) - StartAdjustment; - - EristaMtcTable *table = reinterpret_cast(startPtr + mtcOffset); - R_TRY(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault)); - - PrepareMtcMemoryRegion(startPtr, table); - table = reinterpret_cast(startPtr); - - if (R_FAILED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault))) { - AbortInvalidMtc("Failed mtc validation"); + // Generate list for mtc table pointers + EristaMtcTable *table_list[khz_list_size]; + for (u32 i = 0; i < khz_list_size; i++) { + u32 mtcIndex = khz_list_size - 1 - i; + u8 *table = reinterpret_cast(ptr) - offsetof(EristaMtcTable, rate_khz) - i * sizeof(EristaMtcTable); + table_list[mtcIndex] = reinterpret_cast(table); + R_UNLESS(table_list[mtcIndex]->rate_khz == khz_list[mtcIndex], ldr::ResultInvalidMtcTable()); + R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); } - if (C.eristaEmcMaxClock <= EmcClkOSLimit) { + if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) { R_SKIP(); } - MtcExtendTables(table); - - if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) { - AbortInvalidMtc("Failed mtc validation"); + /* If we oc ram at all, tables are always shifted by at least 1. */ + u32 tableShifts = 1; + for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) { + /* Duplicated mtc tables may cause pcv to not select frequencies properly, causing issues. */ + if (maxEmcClocks[i] != maxEmcClocks[i + 1] && maxEmcClocks[i] > EmcClkOSLimit) { + ++tableShifts; + } else { + maxEmcClocks[i] = 0; + } } - for (u32 i = erista::MtcTableCountDefault; i < newEmcList.size(); ++i) { - MemMtcTableAutoAdjust(&table[i]); + /* Erista has extra, useless mtc tables, such as 40.8 Mhz, overwrite them to make room for oc freqs. */ + /* More than 3 tables can be overwritten, but 3 is plenty. */ + std::memmove(table_list[0], table_list[tableShifts], sizeof(EristaMtcTable) * (khz_list_size - tableShifts)); + + /* Since we're not scaling r/w latency properly on Erista, we first overwrite the tables with the 1600 MHz table before scaling it. */ + for (u32 i = 0; i < tableShifts; ++i) { + std::memcpy(table_list[khz_list_size - i - 1], table_list[khz_list_size - tableShifts - 1], sizeof(EristaMtcTable)); + } + + for (u32 i = tableShifts, j = 0; i > 0 && j < std::size(maxEmcClocks); ++j) { + if (!maxEmcClocks[j]) { + continue; + } + + table_list[khz_list_size - i]->rate_khz = maxEmcClocks[j]; + MemMtcTableAutoAdjust(table_list[khz_list_size - i]); + --i; } R_SUCCEED(); } Result MemFreqMax(u32 *ptr) { - if (C.eristaEmcMaxClock <= EmcClkOSLimit) { + if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) { R_SKIP(); } - PATCH_OFFSET(ptr, C.eristaEmcMaxClock); + PATCH_OFFSET(ptr, GET_MAX_OF_ARR(maxEmcClocks)); R_SUCCEED(); } @@ -562,42 +450,7 @@ namespace ams::ldr::hoc::pcv::erista { // R_SUCCEED(); // } - - Result MemMtcTableAsm(u32 *ptr) { - constexpr u32 AddpOffset = 1; - constexpr u32 BrOffset = 9; - constexpr u32 MovOffset = 7; - - /* Ensure we don't dereference memory before nso start. */ - R_UNLESS(ptr - BrOffset >= nsoStart, ldr::ResultInvalidMtcTablePattern()); - - u32 adrp = *(ptr - AddpOffset); - R_UNLESS(AsmCompareAdrpNoImm(adrp, MtcAdrpAsm), ldr::ResultInvalidMtcTablePattern()); - - /* We don't check for matching register because both registers must be x0 in order to pass the previous checks. */ - /* The correct instructions will always be x0 since the mtcTable pointer is returned. */ - - /* Pray this does not break. */ - u32 br = *(ptr - BrOffset); - R_UNLESS(AsmCompareBrNoRd(br, MtcBrAsm), ldr::ResultInvalidMtcTablePattern()); - - /* Pray this does not break either. */ - u32 mov = *(ptr - MovOffset); - R_UNLESS(asm_compare_no_rd(mov, MtcMovAsm), ldr::ResultInvalidMtcTablePattern()); - - u8 movRd = asm_get_rd(mov); - u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd); - - PATCH_OFFSET(ptr - BrOffset, NopIns); - PATCH_OFFSET(ptr - MovOffset, movCountPatch); - - R_SUCCEED(); - } - void Patch(uintptr_t mapped_nso, size_t nso_size) { - nsoStart = reinterpret_cast(mapped_nso); - MtcGenerateFreqTables(); - u32 CpuCvbDefaultMaxFreq = static_cast(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq); u32 GpuCvbDefaultMaxFreq = static_cast(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq); @@ -612,11 +465,10 @@ namespace ams::ldr::hoc::pcv::erista { {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn }, {"GPU PLL Max", & GpuFreqPllMax, 1, nullptr, GpuClkPllMax }, // {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit }, - {"MEM Freq Mtc", &MemFreqMtcTable, 1, nullptr, EmcClkOSLimit }, + {"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit }, {"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit }, {"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit }, {"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS }, - {"MEM Table Asm", &MemMtcTableAsm, 1, &MemMtcGetGetTablePatternFn }, }; for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) { @@ -629,7 +481,7 @@ namespace ams::ldr::hoc::pcv::erista { } for (auto &entry : patches) { - LOGGING("%s Count: %zu\n", entry.description, entry.patched_count); + LOGGING("%s Count: %zu", entry.description, entry.patched_count); if (R_FAILED(entry.CheckResult())) { panic::SmcError(panic::Patch); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp index 7e2a7e5b..11f9041d 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp @@ -26,6 +26,9 @@ namespace ams::ldr::hoc::pcv::erista { + static u32 maxEmcClocks[] = { C.eristaEmcMaxClock2, C.eristaEmcMaxClock1, C.eristaEmcMaxClock, }; + #define GET_MAX_OF_ARR(ARR) (*std::max_element(ARR, ARR + std::size(ARR))) + constexpr cvb_entry_t CpuCvbTableDefault[] = { // CPU_PLL_CVB_TABLE_ODN { 204000, {721094}, { } }, @@ -106,11 +109,8 @@ namespace ams::ldr::hoc::pcv::erista { { }, }; - constexpr u32 EmcListDefault[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000, }; - constexpr u32 EmcListSizeDefault = std::size(EmcListDefault); - constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1; - constexpr u32 MemVoltHOS = 1125'000; + constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */ constexpr u32 EmcClkPllmLimit = 1866'000'000; constexpr u32 MTC_TABLE_REV = 7; @@ -147,16 +147,6 @@ namespace ams::ldr::hoc::pcv::erista { { ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, }, }; - constexpr u32 MtcBrAsm = 0xD61F0140; - constexpr u32 MtcMovAsm = 0x52800148; - constexpr u32 MtcAdrpAsm = 0xD0000081; - constexpr u32 MtcAddAsm = 0x91131821; - - ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) { - /* This builds an address that gets returned, so the register must be x0 by convention. */ - return AsmCompareAddNoImm12(*ptr, MtcAddAsm); - } - void Patch(uintptr_t mapped_nso, size_t nso_size); } 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 130174a1..d5787206 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -638,14 +638,14 @@ namespace ams::ldr::hoc::pcv::mariko { } void MtcGenerateFreqTables() { - newEmcList.clear(); - newEmcList.reserve(DvfsTableEntryCount); - newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault)); - if (C.marikoEmcMaxClock <= EmcClkOSLimit) { return; } + newEmcList.clear(); + newEmcList.reserve(DvfsTableEntryCount); + newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault)); + u32 stepRate = 0; switch (C.stepMode) { case StepMode_66MHz: @@ -767,6 +767,10 @@ namespace ams::ldr::hoc::pcv::mariko { MarikoMtcTable *table = reinterpret_cast(startPtr + mtcOffset); R_TRY(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault)); + if (C.marikoEmcMaxClock <= EmcClkOSLimit) { + R_SKIP(); + } + PrepareMtcMemoryRegion(startPtr, table); table = reinterpret_cast(startPtr); @@ -774,10 +778,6 @@ namespace ams::ldr::hoc::pcv::mariko { AbortInvalidMtc("Failed mtc validation"); } - if (C.marikoEmcMaxClock <= EmcClkOSLimit) { - R_SKIP(); - } - MtcExtendTables(table); if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) { @@ -837,18 +837,18 @@ namespace ams::ldr::hoc::pcv::mariko { DvbEntry emcDvbOcTableBrackets[] = { { 204000, { 637, 637, 637, }, }, { 1331200, { 650, 637, 637, }, }, - { 1600000, { 675, 650, 637, }, }, - { 1866000, { DVB(DvbVolt( 700, 675, 650)) }, }, - { 2133000, { DVB(DvbVolt( 725, 700, 675)) }, }, - { 2246000, { DVB(DvbVolt( 750, 725, 700)) }, }, - { 2400000, { DVB(DvbVolt( 775, 750, 725)) }, }, - { 2466000, { DVB(DvbVolt( 800, 775, 750)) }, }, - { 2533000, { DVB(DvbVolt( 810, 785, 760)) }, }, - { 2566000, { DVB(DvbVolt( 820, 795, 770)) }, }, - { 2600000, { DVB(DvbVolt( 830, 805, 780)) }, }, - { 2633000, { DVB(DvbVolt( 840, 815, 790)) }, }, - { 2666000, { DVB(DvbVolt( 850, 825, 800)) }, }, - { 2700000, { DVB(DvbVolt( 860, 835, 810)) }, }, + { 1600000, { 675, 650, 637, }, }, + { 1866000, { DVB(DvbVolt( 700, 675, 650)) }, }, + { 2133000, { DVB(DvbVolt( 725, 700, 675)) }, }, + { 2246000, { DVB(DvbVolt( 750, 725, 700)) }, }, + { 2400000, { DVB(DvbVolt( 775, 750, 725)) }, }, + { 2466000, { DVB(DvbVolt( 800, 775, 750)) }, }, + { 2533000, { DVB(DvbVolt( 810, 785, 760)) }, }, + { 2566000, { DVB(DvbVolt( 820, 795, 770)) }, }, + { 2600000, { DVB(DvbVolt( 830, 805, 780)) }, }, + { 2633000, { DVB(DvbVolt( 840, 815, 790)) }, }, + { 2666000, { DVB(DvbVolt( 850, 825, 800)) }, }, + { 2700000, { DVB(DvbVolt( 860, 835, 810)) }, }, { 2733000, { DVB(DvbVolt( 870, 845, 820)) }, }, { 2766000, { DVB(DvbVolt( 880, 855, 830)) }, }, { 2800000, { DVB(DvbVolt( 895, 865, 840)) }, }, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp index 65955f1a..43258993 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp @@ -148,6 +148,8 @@ namespace ams::ldr::hoc::pcv::mariko { constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, }; constexpr u32 EmcListSizeDefault = std::size(EmcListDefault); constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1; + constexpr u32 EmcRateStep = 33'000; + constexpr u32 EmcRateStepScale = 33'200; constexpr u32 EmcClkOSAlt = 1331'200; constexpr u32 EmcClkPllmLimit = 2133'000'000; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp index 15917d0e..7ae9183a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.cpp @@ -84,7 +84,7 @@ namespace ams::ldr::hoc::ptm { switch (entry->cpu_freq_1) { case cpuPtmBoost: - R_DISCARD(cpuPtmBoostPatch.Apply(entry)); + cpuPtmBoostPatch.Apply(entry); break; case cpuPtmDefault: case cpuPtmDevOC: @@ -99,7 +99,7 @@ namespace ams::ldr::hoc::ptm { case memPtmAlt: case memPtmClamp: if (isMariko) { - R_DISCARD(memPtmPatch.Apply(entry)); + memPtmPatch.Apply(entry); } break; default: @@ -109,15 +109,13 @@ namespace ams::ldr::hoc::ptm { } LOGGING("%s Count: %zu", cpuPtmBoostPatch.description, cpuPtmBoostPatch.patched_count); - if (R_FAILED(cpuPtmBoostPatch.CheckResult())) { + if (R_FAILED(cpuPtmBoostPatch.CheckResult())) CRASH(cpuPtmBoostPatch.description); - } if (isMariko) { LOGGING("%s Count: %zu", memPtmPatch.description, memPtmPatch.patched_count); - if (R_FAILED(memPtmPatch.CheckResult())) { + if (R_FAILED(memPtmPatch.CheckResult())) CRASH(memPtmPatch.description); - } } } diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index d402b11a..afb333d9 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -82,6 +82,8 @@ typedef enum { KipConfigValue_commonEmcMemVolt, KipConfigValue_eristaEmcMaxClock, + KipConfigValue_eristaEmcMaxClock1, + KipConfigValue_eristaEmcMaxClock2, KipConfigValue_stepMode, KipConfigValue_marikoEmcMaxClock, @@ -114,6 +116,9 @@ typedef enum { KipConfigValue_write_latency_1866, KipConfigValue_write_latency_2133, + KipConfigValue_mem_burst_read_latency, + KipConfigValue_mem_burst_write_latency, + KipConfigValue_eristaCpuUV, KipConfigValue_eristaCpuVmin, KipConfigValue_eristaCpuMaxVolt, @@ -138,6 +143,7 @@ typedef enum { KipConfigValue_marikoGpuVmax, KipConfigValue_commonGpuVoltOffset, + KipConfigValue_gpuSpeedo, KipConfigValue_g_volt_76800, KipConfigValue_g_volt_153600, @@ -302,7 +308,11 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case KipConfigValue_commonEmcMemVolt: return pretty ? "Common EMC/MEM Voltage" : "common_emc_mem_volt"; case KipConfigValue_eristaEmcMaxClock: - return pretty ? "Erista EMC Max Clock" : "erista_emc_max_clock2"; + return pretty ? "Erista EMC Max Clock 1" : "erista_emc_max_clock"; + case KipConfigValue_eristaEmcMaxClock1: + return pretty ? "Erista EMC Max Clock 2" : "erista_emc_max_clock1"; + case KipConfigValue_eristaEmcMaxClock2: + return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2"; case KipConfigValue_stepMode: return pretty ? "Step Mode:" : "step_mode"; case KipConfigValue_marikoEmcMaxClock: @@ -359,6 +369,11 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case KipConfigValue_write_latency_2133: return pretty ? "2133 Write Latency" : "write_latency_2133"; + case KipConfigValue_mem_burst_read_latency: + return pretty ? "Memory Burst Read Latency" : "mem_burst_read_latency"; + case KipConfigValue_mem_burst_write_latency: + return pretty ? "Memory Burst Write Latency" : "mem_burst_write_latency"; + // CPU – Erista case KipConfigValue_eristaCpuUV: return pretty ? "Erista CPU Undervolt" : "erista_cpu_uv"; @@ -409,6 +424,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case KipConfigValue_commonGpuVoltOffset: return pretty ? "Common GPU Voltage Offset" : "common_gpu_volt_offset"; + case KipConfigValue_gpuSpeedo: + return pretty ? "GPU Speedo" : "gpu_speedo"; // Mariko GPU voltages (24) case KipConfigValue_g_volt_76800: return pretty ? "Mariko GPU Volt 76 MHz" : "g_volt_76800"; @@ -561,6 +578,8 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_hpMode: case KipConfigValue_commonEmcMemVolt: case KipConfigValue_eristaEmcMaxClock: + case KipConfigValue_eristaEmcMaxClock1: + case KipConfigValue_eristaEmcMaxClock2: case KipConfigValue_stepMode: case KipConfigValue_marikoEmcMaxClock: case KipConfigValue_marikoEmcVddqVolt: @@ -586,6 +605,8 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_write_latency_1600: case KipConfigValue_write_latency_1866: case KipConfigValue_write_latency_2133: + case KipConfigValue_mem_burst_read_latency: + case KipConfigValue_mem_burst_write_latency: case KipConfigValue_eristaCpuUV: case KipConfigValue_eristaCpuMaxVolt: case KipConfigValue_marikoCpuUVLow: @@ -604,6 +625,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_marikoGpuBootVolt: case KipConfigValue_marikoGpuVmax: case KipConfigValue_commonGpuVoltOffset: + case KipConfigValue_gpuSpeedo: case KipConfigValue_g_volt_76800: case KipConfigValue_g_volt_153600: case KipConfigValue_g_volt_230400: diff --git a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp index 6409eabb..fb53a489 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp @@ -98,8 +98,8 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "- Washed: Washed out colors.", "- Basic: Real natural profile.", "- Natural: Not actually natural.. Extra saturation.", - "- Vivid: Saturated.", - "Default: Do not override" + "- Vivid: Saturated.", + "Default: Do not override" }; case HocClkConfigValue_CpuGovernorMinimumFreq: @@ -227,7 +227,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: 600 mV" }; - case KipConfigValue_stepMode: + case KipConfigValue_stepMode: return { "The step that RAM clocks take.", "Options (with examples):", @@ -250,6 +250,8 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, }; case KipConfigValue_eristaEmcMaxClock: + case KipConfigValue_eristaEmcMaxClock1: + case KipConfigValue_eristaEmcMaxClock2: return { "The RAM frequency used in the particular slot. Higher frequencies may cause instability, so increase this gradually and test for stability.", "Default: Disabled (1600 MHz)" @@ -361,6 +363,19 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "These properties apply for both write and read latencies, and you can mix-and-match the brackets if necessary", "Default: -" }; + + case KipConfigValue_mem_burst_read_latency: + return { + "The read latency for the ram", + "Default: 1600 RL" + }; + + case KipConfigValue_mem_burst_write_latency: + return { + "The write latency for the ram", + "Default: 1600 WL" + }; + case KipConfigValue_marikoCpuUVLow: return { "The CPU UV level used before tBreak", diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index e3185252..0ff44c7e 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -61,6 +61,7 @@ class RamLatenciesSubmenuGui; class CpuSubmenuGui; class GpuSubmenuGui; class GpuCustomTableSubmenuGui; +class RamTableEditor; class ExperimentalSettingsSubMenuGui; MiscGui::MiscGui() @@ -687,7 +688,7 @@ protected: false ); - + addConfigButton( HocClkConfigValue_PollingIntervalMs, "Polling Interval", @@ -1012,7 +1013,7 @@ protected: this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Settings")); - + addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift", {0xFFFFFFFCu, 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u}, {"-4", "-3", "-2", "-1", " 0", "1", "2", "3", "4", "5", "6", "7", "8"}); @@ -1054,7 +1055,7 @@ protected: true ); } - + addConfigToggle(KipConfigValue_hpMode, "HP Mode", true); std::map emc_voltage_label = { @@ -1105,51 +1106,20 @@ protected: addConfigButton(KipConfigValue_stepMode, "Step Mode", ValueRange(0, 0, 2, "", 0), "Step Mode", &thresholdsDisabled, {}, stepMode, false, true); } - std::vector emcMaxClock = { }; - RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; - if (IsErista()) { - emcMaxClock = { - NamedValue("Disabled", 1600000), - NamedValue("1633 MHz", 1633000), - NamedValue("1666 MHz", 1666000), - NamedValue("1700 MHz", 1700000), - NamedValue("1733 MHz", 1733000), - NamedValue("1766 MHz", 1766000), - NamedValue("1800 MHz", 1800000), - NamedValue("1833 MHz", 1833000), - NamedValue("1862 MHz", 1862400, "JEDEC."), - NamedValue("1881 MHz", 1881600), - NamedValue("1900 MHz", 1900800), - NamedValue("1920 MHz", 1920000), - NamedValue("1939 MHz", 1939200), - NamedValue("1958 MHz", 1958400), - NamedValue("1977 MHz", 1977600), - NamedValue("1996 MHz", 1996800, "JEDEC."), - NamedValue("2016 MHz", 2016000), - NamedValue("2035 MHz", 2035200), - NamedValue("2054 MHz", 2054400), - NamedValue("2073 MHz", 2073600), - NamedValue("2092 MHz", 2092800), - NamedValue("2112 MHz", 2112000), - NamedValue("2131 MHz", 2131200, "JEDEC."), - NamedValue("2150 MHz", 2150400), - NamedValue("2169 MHz", 2169600), - NamedValue("2188 MHz", 2188800), - NamedValue("2208 MHz", 2208000), - NamedValue("2227 MHz", 2227200), - NamedValue("2246 MHz", 2246400), - NamedValue("2265 MHz", 2265600), - NamedValue("2284 MHz", 2284800), - NamedValue("2304 MHz", 2304000), - NamedValue("2323 MHz", 2323200), - NamedValue("2342 MHz", 2342400), - NamedValue("2361 MHz", 2361600), - NamedValue("2380 MHz", 2380800), - NamedValue("2400 MHz", 2400000, "JEDEC."), - }; + tsl::elm::ListItem* freqSubmenu = new tsl::elm::ListItem("RAM Frequency Editor"); + freqSubmenu->setClickListener([](u64 keys) { + if (keys & HidNpadButton_A) { + tsl::changeTo(); + return true; + } + return false; + }); + freqSubmenu->setValue(R_ARROW); + this->listElement->addItem(freqSubmenu); } else { - emcMaxClock = { + RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; + std::vector marikoMaxEmcClock = { NamedValue("1600 MHz", 1600000), NamedValue("1633 MHz", 1633000), NamedValue("1666 MHz", 1666000), @@ -1203,20 +1173,19 @@ protected: NamedValue("3233 MHz", 3233000, "High speedo needed!"), NamedValue("3266 MHz", 3266000, "High speedo needed!"), NamedValue("3300 MHz", 3300000, "High speedo needed!"), + // NamedValue("3333MHz (Needs extreme Speedo/PLL)", 3333000), + // NamedValue("3366MHz (Needs extreme Speedo/PLL)", 3366000), + // NamedValue("3400MHz (Needs extreme Speedo/PLL)", 3400000), + // NamedValue("3433MHz (Needs ridiculous Speedo/PLL)", 3433000), + // NamedValue("3466MHz (Needs ridiculous Speedo/PLL)", 3466000), + // NamedValue("3500MHz (Needs ridiculous Speedo/PLL)", 3500000), }; - } - - for (auto& nv : emcMaxClock) { - if (nv.name != "Disabled") { + for (auto& nv : marikoMaxEmcClock) nv.name = formatMemClockKhzLabel(nv.value, unit); - } + + addConfigButton(KipConfigValue_marikoEmcMaxClock, "Ram Max Clock", ValueRange(0, 1, 1, "", 1), "Ram Max Clock", &thresholdsDisabled, {}, marikoMaxEmcClock, false, true); } - if (IsMariko()) { - addConfigButton(KipConfigValue_marikoEmcMaxClock, "Ram Max Clock", ValueRange(0, 1, 1, "", 1), "Ram Max Clock", &thresholdsDisabled, {}, emcMaxClock, false, true); - } else { - addConfigButton(KipConfigValue_eristaEmcMaxClock, "Ram Max Clock", ValueRange(0, 1, 1, "", 1), "Ram Max Clock", &thresholdsDisabled, {}, emcMaxClock, false, true); - } tsl::elm::ListItem* latenciesSubmenu = new tsl::elm::ListItem("RAM Latency Editor"); latenciesSubmenu->setClickListener([](u64 keys) { @@ -1355,7 +1324,7 @@ public: protected: void normalizeLatencies(const HocClkConfigValue keysArr[4]) { - uint32_t maxClock = IsMariko() ? (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock] : (uint32_t)this->configList->values[KipConfigValue_eristaEmcMaxClock]; + uint32_t maxClock = (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock]; uint32_t vals[4]; for (int i = 0; i < 4; i++) { @@ -1390,37 +1359,35 @@ protected: void listUI() override { ValueThresholds thresholdsDisabled(0, 0); + + if (IsErista()) { + std::vector rlLabels = { NamedValue("1333 RL", 28), NamedValue("1600 RL", 32), NamedValue("1866 RL", 36), NamedValue("2133 RL", 40) }; + std::vector wlLabels = { NamedValue("1333 WL", 12), NamedValue("1600 WL", 14), NamedValue("1866 WL", 16), NamedValue("2133 WL", 18) }; + + addConfigButton(KipConfigValue_mem_burst_read_latency, "Read Latency", ValueRange(0, 6, 1, "", 0), "Read Latency", &thresholdsDisabled, {}, rlLabels, false, true); + addConfigButton(KipConfigValue_mem_burst_write_latency, "Write Latency", ValueRange(0, 6, 1, "", 0), "Write Latency", &thresholdsDisabled, {}, wlLabels, false, true); + return; + } + Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - uint32_t maxClock = IsMariko() ? (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock] : (uint32_t)this->configList->values[KipConfigValue_eristaEmcMaxClock]; + uint32_t maxClock = (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock]; RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; - static std::vector kFreqOptions = { }; - if (IsMariko()) { - kFreqOptions = { - 1633000, 1666000, 1700000, 1733000, 1766000, 1800000, - 1833000, 1866000, 1900000, 1933000, 1966000, 1996800, 2000000, - 2033000, 2066000, 2100000, 2133000, 2166000, 2200000, 2233000, - 2266000, 2300000, 2333000, 2366000, 2400000, 2433000, 2466000, - 2500000, 2533000, 2566000, 2600000, 2633000, 2666000, 2700000, - 2733000, 2766000, 2800000, 2833000, 2866000, 2900000, 2933000, - 2966000, 3000000, 3033000, 3066000, 3100000, 3133000, 3166000, - 3200000, 3233000, 3266000, 3300000, - }; - } else { - kFreqOptions = { - 1633000, 1666000, 1700000, 1733000, 1800000, - 1833000, 1862400, 1881600, 1900800, 1920000, 1939200, - 1958400, 1977600, 1996800, 2016000, 2035200, 2054400, - 2073600, 2092800, 2112000, 2131200, 2150400, 2169600, - 2188800, 2208000, 2227200, 2246400, 2265600, 2284800, - 2304000, 2323200, 2342400, 2361600, 2380800, 2400000, - }; - } + static const std::vector kFreqOptions = { + 1633000, 1666000, 1700000, 1733000, 1766000, 1800000, + 1833000, 1866000, 1900000, 1933000, 1966000, 1996800, 2000000, + 2033000, 2066000, 2100000, 2133000, 2166000, 2200000, 2233000, + 2266000, 2300000, 2333000, 2366000, 2400000, 2433000, 2466000, + 2500000, 2533000, 2566000, 2600000, 2633000, 2666000, 2700000, + 2733000, 2766000, 2800000, 2833000, 2866000, 2900000, 2933000, + 2966000, 3000000, 3033000, 3066000, 3100000, 3133000, 3166000, + 3200000, 3233000, 3266000, 3300000, + }; static const HocClkConfigValue kLatencyRKeys[4] = { KipConfigValue_read_latency_1333, @@ -1480,7 +1447,7 @@ protected: for (int i = 0; i < 4; i++) vals[i] = (uint32_t)this->configList->values[keysArr[i]]; - uint32_t maxClock = IsMariko() ? (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock] : (uint32_t)this->configList->values[KipConfigValue_eristaEmcMaxClock]; + uint32_t maxClock = (uint32_t)this->configList->values[KipConfigValue_marikoEmcMaxClock]; RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; auto resolveVal = [maxClock](uint32_t v) -> uint32_t { @@ -1688,7 +1655,7 @@ protected: true ); - + std::vector maxClkOptions = { NamedValue("1963 MHz", 1963500), NamedValue("2091 MHz", 2091000), @@ -1810,6 +1777,78 @@ protected: } }; +class RamTableEditor : public MiscGui { +public: + RamTableEditor() { } + +protected: + void listUI() override { + Result rc = hocclkIpcGetConfigValues(this->configList); + if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } + this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Frequency Editor")); + + ValueThresholds thresholdsDisabled(0, 0); + // 1600000, 1331200, 1065600, 800000, 665600, 408000, 204000 + RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; + + this->listElement->addItem(new tsl::elm::ListItem(formatMemClockKhzLabel(665600, unit))); + this->listElement->addItem(new tsl::elm::ListItem(formatMemClockKhzLabel(800000, unit))); + this->listElement->addItem(new tsl::elm::ListItem(formatMemClockKhzLabel(1065600, unit))); + this->listElement->addItem(new tsl::elm::ListItem(formatMemClockKhzLabel(1331200, unit))); + this->listElement->addItem(new tsl::elm::ListItem(formatMemClockKhzLabel(1600000, unit))); + + ValueThresholds eristaRamThresholds(2208000, 2304000); + + std::vector eristaMaxEmcClock = { + NamedValue("Disabled", 1600000), + NamedValue("1633 MHz", 1633000), + NamedValue("1666 MHz", 1666000), + NamedValue("1700 MHz", 1700000), + NamedValue("1733 MHz", 1733000), + NamedValue("1766 MHz", 1766000), + NamedValue("1800 MHz", 1800000), + NamedValue("1833 MHz", 1833000), + NamedValue("1862 MHz", 1862400, "JEDEC."), + NamedValue("1881 MHz", 1881600), + NamedValue("1900 MHz", 1900800), + NamedValue("1920 MHz", 1920000), + NamedValue("1939 MHz", 1939200), + NamedValue("1958 MHz", 1958400), + NamedValue("1977 MHz", 1977600), + NamedValue("1996 MHz", 1996800, "JEDEC."), + NamedValue("2016 MHz", 2016000), + NamedValue("2035 MHz", 2035200), + NamedValue("2054 MHz", 2054400), + NamedValue("2073 MHz", 2073600), + NamedValue("2092 MHz", 2092800), + NamedValue("2112 MHz", 2112000), + NamedValue("2131 MHz", 2131200, "JEDEC."), + NamedValue("2150 MHz", 2150400), + NamedValue("2169 MHz", 2169600), + NamedValue("2188 MHz", 2188800), + NamedValue("2208 MHz", 2208000), + NamedValue("2227 MHz", 2227200), + NamedValue("2246 MHz", 2246400), + NamedValue("2265 MHz", 2265600), + NamedValue("2284 MHz", 2284800), + NamedValue("2304 MHz", 2304000), + NamedValue("2323 MHz", 2323200), + NamedValue("2342 MHz", 2342400), + NamedValue("2361 MHz", 2361600), + NamedValue("2380 MHz", 2380800), + NamedValue("2400 MHz", 2400000, "JEDEC."), + }; + + for (auto& nv : eristaMaxEmcClock) + if (nv.name != "Disabled") + nv.name = formatMemClockKhzLabel(nv.value, unit); + + addConfigButtonS(KipConfigValue_eristaEmcMaxClock, "", ValueRange(0, 1, 1, "", 1), "", &eristaRamThresholds, {}, eristaMaxEmcClock, false, A_BTN, true); + addConfigButtonS(KipConfigValue_eristaEmcMaxClock1, "", ValueRange(0, 1, 1, "", 1), "", &eristaRamThresholds, {}, eristaMaxEmcClock, false, A_BTN, true); + addConfigButtonS(KipConfigValue_eristaEmcMaxClock2, "", ValueRange(0, 1, 1, "", 1), "", &eristaRamThresholds, {}, eristaMaxEmcClock, false, A_BTN, true); + }; +}; + class GpuSubmenuGui : public MiscGui { public: GpuSubmenuGui() { } @@ -2293,6 +2332,8 @@ void MiscGui::refresh() { constexpr HocClkConfigValue emcKeys[] = { KipConfigValue_marikoEmcMaxClock, KipConfigValue_eristaEmcMaxClock, + KipConfigValue_eristaEmcMaxClock1, + KipConfigValue_eristaEmcMaxClock2, }; for (auto key : emcKeys) { auto it = this->configNamedValues.find(key); diff --git a/Source/hoc-clk/sysmodule/src/file/kip.cpp b/Source/hoc-clk/sysmodule/src/file/kip.cpp index ecf0595e..19adfe32 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.cpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.cpp @@ -71,6 +71,8 @@ namespace kip { CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, config::GetConfigValue(KipConfigValue_commonEmcMemVolt)); CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock1, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock1)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock2)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift)); @@ -101,6 +103,8 @@ namespace kip { CUST_WRITE_FIELD_BATCH(&table, writeLatency1866, config::GetConfigValue(KipConfigValue_write_latency_1866)); CUST_WRITE_FIELD_BATCH(&table, writeLatency2133, config::GetConfigValue(KipConfigValue_write_latency_2133)); + CUST_WRITE_FIELD_BATCH(&table, mem_burst_read_latency, config::GetConfigValue(KipConfigValue_mem_burst_read_latency)); + CUST_WRITE_FIELD_BATCH(&table, mem_burst_write_latency, config::GetConfigValue(KipConfigValue_mem_burst_write_latency)); CUST_WRITE_FIELD_BATCH(&table, eristaCpuUV, config::GetConfigValue(KipConfigValue_eristaCpuUV)); CUST_WRITE_FIELD_BATCH(&table, eristaCpuVmin, config::GetConfigValue(KipConfigValue_eristaCpuVmin)); CUST_WRITE_FIELD_BATCH(&table, eristaCpuMaxVolt, config::GetConfigValue(KipConfigValue_eristaCpuMaxVolt)); @@ -126,6 +130,7 @@ namespace kip { CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, config::GetConfigValue(KipConfigValue_marikoGpuVmax)); CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, config::GetConfigValue(KipConfigValue_commonGpuVoltOffset)); + CUST_WRITE_FIELD_BATCH(&table, gpuSpeedo, config::GetConfigValue(KipConfigValue_gpuSpeedo)); for (int i = 0; i < 24; i++) { table.marikoGpuVoltArray[i] = config::GetConfigValue((HocClkConfigValue)(KipConfigValue_g_volt_76800 + i)); @@ -226,6 +231,8 @@ namespace kip { configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table); + configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table); + configValues.values[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); configValues.values[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); configValues.values[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); @@ -256,6 +263,9 @@ namespace kip { configValues.values[KipConfigValue_write_latency_1866] = cust_get_write_latency_1866(&table); configValues.values[KipConfigValue_write_latency_2133] = cust_get_write_latency_2133(&table); + configValues.values[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table); + configValues.values[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table); + configValues.values[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table); configValues.values[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table); configValues.values[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table); @@ -278,6 +288,7 @@ namespace kip { configValues.values[KipConfigValue_marikoGpuBootVolt] = cust_get_mariko_gpu_boot_volt(&table); configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); + configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table); for (int i = 0; i < 24; i++) { configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); diff --git a/Source/hoc-clk/sysmodule/src/file/kip.hpp b/Source/hoc-clk/sysmodule/src/file/kip.hpp index 7e7b2430..47fcfe8d 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.hpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.hpp @@ -36,6 +36,8 @@ namespace kip { u32 hpMode; u32 commonEmcMemVolt; u32 eristaEmcMaxClock; + u32 eristaEmcMaxClock1; + u32 eristaEmcMaxClock2; u32 stepMode; u32 marikoEmcMaxClock; u32 marikoEmcVddqVolt; @@ -62,6 +64,9 @@ namespace kip { u32 readLatency1333, readLatency1600, readLatency1866, readLatency2133; u32 writeLatency1333, writeLatency1600, writeLatency1866, writeLatency2133; + u32 mem_burst_read_latency; + u32 mem_burst_write_latency; + u32 eristaCpuUV; u32 eristaCpuVmin; u32 eristaCpuMaxVolt; @@ -88,6 +93,8 @@ namespace kip { u32 commonGpuVoltOffset; + u32 gpuSpeedo; + u32 eristaGpuVoltArray[27]; u32 marikoGpuVoltArray[24]; @@ -202,6 +209,8 @@ namespace kip { static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); } static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); } + static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); } + static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); } static inline bool cust_set_step_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, stepMode, v); } static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); } static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); } @@ -232,6 +241,9 @@ namespace kip { static inline bool cust_set_write_latency_1866(const char* p, u32 v) { CUST_WRITE_FIELD(p, writeLatency1866, v); } static inline bool cust_set_write_latency_2133(const char* p, u32 v) { CUST_WRITE_FIELD(p, writeLatency2133, v); } + static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); } + static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); } + static inline bool cust_set_erista_cpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUV, v); } static inline bool cust_set_eristaCpuVmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuVmin, v); } static inline bool cust_set_erista_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuMaxVolt, v); } @@ -252,6 +264,7 @@ namespace kip { static inline bool cust_set_mariko_gpu_boot_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuBootVolt, v); } static inline bool cust_set_mariko_gpu_vmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmax, v); } static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); } + static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); } static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); } static inline bool cust_set_marikoSocVmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoSocVmax, v); } @@ -286,6 +299,8 @@ namespace kip { static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); } static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); } + static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); } + static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); } static inline u32 cust_get_step_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, stepMode); } static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); } static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); } @@ -316,6 +331,9 @@ namespace kip { static inline u32 cust_get_write_latency_1866(const CustomizeTable* t) { return CUST_GET_FIELD(t, writeLatency1866); } static inline u32 cust_get_write_latency_2133(const CustomizeTable* t) { return CUST_GET_FIELD(t, writeLatency2133); } + static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); } + static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); } + static inline u32 cust_get_erista_cpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUV); } static inline u32 cust_get_eristaCpuVmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuVmin); } static inline u32 cust_get_erista_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuMaxVolt); } @@ -337,6 +355,7 @@ namespace kip { static inline u32 cust_get_mariko_gpu_boot_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuBootVolt); } static inline u32 cust_get_mariko_gpu_vmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmax); } static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); } + static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); } static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); } static inline u32 cust_get_marikoSocVmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoSocVmax); } diff --git a/dist/atmosphere/exosphere.bin b/dist/atmosphere/exosphere.bin index 147372e1..9315328e 100644 Binary files a/dist/atmosphere/exosphere.bin and b/dist/atmosphere/exosphere.bin differ