From 4b9310e0ab11a6c529a5e37b2c95a74cbe959a34 Mon Sep 17 00:00:00 2001 From: hanabbi Date: Tue, 20 Jun 2023 13:30:38 +0900 Subject: [PATCH] timing adjustment for erista --- .../loader/source/oc/customize.cpp | 6 +- .../loader/source/oc/customize.hpp | 4 +- .../loader/source/oc/pcv/pcv_erista.cpp | 143 ++++++++++++++++++ .../loader/source/oc/pcv/pcv_mariko.cpp | 4 +- pages/src/main.ts | 4 +- 5 files changed, 152 insertions(+), 9 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 1e80ef16..9eb8956f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -23,12 +23,12 @@ namespace ams::ldr::oc { volatile CustomizeTable C = { /* DRAM Timing: - * AUTO_ADJ_SAFE_MARIKO_ONLY: Auto adjust timings for Mariko LPDDR4X ≤3733 Mbps specs, 8Gb density. (Default) - * AUTO_ADJ_4266_MARIKO_ONLY: Auto adjust timings for Mariko LPDDR4X 4266 Mbps specs, 8Gb density. + * AUTO_ADJ_ALL: Auto adjust timings for Mariko LPDDR4X ≤3733 Mbps specs, 8Gb density. (Default) + * CUSTOM_ADJ_ALL: Basically same as NO_ADJ_ALL, with core timing adjustments * NO_ADJ_ALL: No timing adjustment for both Erista and Mariko. * CUSTOMIZED_ALL: Replace with values in customized table for both Erista and Mariko. */ -.mtcConf = AUTO_ADJ_SAFE_MARIKO, +.mtcConf = AUTO_ADJ_ALL, /* Common: * - Boost Clock in kHz: diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp index 57aa52b8..697c0647 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp @@ -26,8 +26,8 @@ namespace ams::ldr::oc { #include "mtc_timing_table.hpp" enum MtcConfig: u32 { - AUTO_ADJ_SAFE_MARIKO = 0, - CUSTOM_ADJ_MARIKO = 1, + AUTO_ADJ_ALL = 0, + CUSTOM_ADJ_ALL = 1, NO_ADJ_ALL = 2, CUSTOMIZED_ALL = 4, 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 505f8f0a..5e81b06f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp @@ -15,6 +15,7 @@ */ #include "pcv.hpp" +#include "../mtc_timing_value.hpp" namespace ams::ldr::oc::pcv::erista { @@ -33,6 +34,147 @@ Result CpuVoltRange(u32* ptr) { R_THROW(ldr::ResultInvalidCpuMinVolt()); } +void MemMtcTableAutoAdjust(EristaMtcTable* table) { + if (C.mtcConf != AUTO_ADJ_ALL) + return; + + #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; + + #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) + + WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); + WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab)); + WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); + WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); + WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); + WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); + WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); + WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP)); + WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); + WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); + WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); + WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); + 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_pdex2wr, GET_CYCLE_CEIL(tXP)); + WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(tXP)); + WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(tCMDCKE)); + WRITE_PARAM_ALL_REG(table, emc_act2pden,GET_CYCLE_CEIL(tMRWCKEL)); + WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(tCMDCKE)); + WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); + WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(tCKELCS)); + WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(tCSCKEH)); + WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR)); + WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); + WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); + WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tCKE)); + WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR)); + WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tCKE)); + WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW)); + WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); + WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(tCKCKEH)); + WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tCKE)+8); + WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW); + + constexpr u32 MC_ARB_DIV = 4; + constexpr u32 MC_ARB_SFA = 2; + table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; + table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA; + table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(MAX(GET_CYCLE_CEIL(tRC), GET_CYCLE_CEIL(tRAS)+GET_CYCLE_CEIL(tRPpb)) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; + table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV); + table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); + //table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA; + //table->burst_mc_regs.mc_emem_arb_timing_w2w = CEIL(table->burst_regs.emc_wext / MC_ARB_DIV) - 1 + MC_ARB_SFA; + 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; + table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV); + //table->burst_mc_regs.mc_emem_arb_timing_ccdmw = CEIL(tCCDMW / MC_ARB_DIV) -1 + MC_ARB_SFA; +} + +void MemMtcTableCustomAdjust(EristaMtcTable* table) { + if (C.mtcConf != CUSTOM_ADJ_ALL) + return; + + constexpr u32 MC_ARB_DIV = 4; + constexpr u32 SFA = 2; + + if (TIMING_PRESET_ONE) { + WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC)); + WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS)); + WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb)); + WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab)); + WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); + WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); + WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR)); + + table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV - 2); + table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV - 1); + table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV - 1 + SFA); + table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV - 2); + + } + if (TIMING_PRESET_TWO) { + WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW)); + WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); + + table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; + table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; + } + + if (TIMING_PRESET_THREE) { + WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(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(tRTP) / MC_ARB_DIV); + table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV); + } + + if (TIMING_PRESET_FOUR) { + WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab)); + WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); + WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); + WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe)); + + table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV); + } + if (TIMING_PRESET_FIVE) { + WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); + + table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + SFA; + } + + if (TIMING_PRESET_SIX) { + 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, REFRESH + 64); + } + + if (TIMING_PRESET_SEVEN) { + WRITE_PARAM_ALL_REG(table, emc_w2r, W2R); + WRITE_PARAM_ALL_REG(table, emc_w2p, WTP); + WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN); + WRITE_PARAM_ALL_REG(table, emc_r2w, R2W); + 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); + + 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 + SFA; + table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + SFA; + } + +} + Result MemFreqMtcTable(u32* ptr) { u32 khz_list[] = { 1600000, 1331200, 1065600, 800000, 665600, 408000, 204000, 102000, 68000, 40800 }; u32 khz_list_size = sizeof(khz_list) / sizeof(u32); @@ -54,6 +196,7 @@ Result MemFreqMtcTable(u32* ptr) { for (u32 i = khz_list_size - 1; i > 0; i--) std::memcpy(static_cast(table_list[i]), static_cast(table_list[i - 1]), sizeof(EristaMtcTable)); + MemMtcTableAutoAdjust(table_list[0]); PATCH_OFFSET(ptr, C.eristaEmcMaxClock); // Handle customize table replacement 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 c2190317..45ff402f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -101,7 +101,7 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) { * you'd better calculate timings yourself rather than relying on following algorithm. */ - if (C.mtcConf != AUTO_ADJ_SAFE_MARIKO) + if (C.mtcConf != AUTO_ADJ_SAFE_ALL) return; #define ADJUST_PROP(TARGET, REF) \ @@ -185,7 +185,7 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) { } void MemMtcTableCustomAdjust(MarikoMtcTable* table) { - if (C.mtcConf != CUSTOM_ADJ_MARIKO) + if (C.mtcConf != CUSTOM_ADJ_ALL) return; constexpr u32 MC_ARB_DIV = 4; diff --git a/pages/src/main.ts b/pages/src/main.ts index 77a40099..f5625f93 100644 --- a/pages/src/main.ts +++ b/pages/src/main.ts @@ -162,8 +162,8 @@ var CustTable: Array = [ "DRAM Timing", CustPlatform.Mariko, 4, - ["0: AUTO_ADJ_SAFE_MARIKO: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density. (Default)", - "1: CUSTOM_ADJ_MARIKO: Basically same as NO_ADJ_ALL, with core timing adjustments (Use advanced config)", + ["0: AUTO_ADJ_ALL: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density. (Default)", + "1: CUSTOM_ADJ_ALL: Basically same as NO_ADJ_ALL, with core timing adjustments (Use advanced config)", "2: NO_ADJ_ALL: No timing adjustment for both Erista and Mariko. Might achieve better performance on Mariko but lower maximum frequency is expected."], 0, [0, 2],