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 d4877fe3..c6796da9 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp @@ -29,16 +29,12 @@ namespace ams::ldr::oc::pcv::mariko { /* TODO: This function is quite uggly, refactor! */ void CalculateMiscTimings() { - rdv = 0x39 + C.mem_burst_read_latency; einput_duration = 0x1C; - quse_width = 0x8; for (u32 i = 0; i < g_misc_table_size; i++) { const auto& e = g_misc_table[i]; if (C.marikoEmcMaxClock >= e.min_freq) { - rdv += e.rdv_inc; if (e.einput) einput_duration = e.einput; - if (e.quse_width) quse_width = e.quse_width; } } @@ -54,14 +50,6 @@ namespace ams::ldr::oc::pcv::mariko { } } - void CalculateObdly() { - obdly = 0x10000002 + C.mem_burst_write_latency; - - if (auto patch = FindObdlyPatch()) { - obdly += 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++; @@ -76,24 +64,6 @@ namespace ams::ldr::oc::pcv::mariko { } } - void CalculateQrst() { - qrst = 0x00070000; - u32 qrst_calc = ROUND(22.1 - (C.marikoEmcMaxClock / 1000000.0) * 8.0) + C.mem_burst_read_latency; - u32 qrst_low = MAX(static_cast(0), qrst_calc); - - if (C.marikoEmcMaxClock >= 2'533'000) { - qrst = INCREMENT_HIGH_BYTES_BY(qrst, 1); - } else if (C.marikoEmcMaxClock == 2'800'000) { - qrst = SET_HIGH_BYTES(qrst, 6); - } - - qrst = SET_LOW_BYTES(qrst, qrst_low); - - if (auto patch = FindQrstPatch()) { - qrst = INCREMENT_LOW_BYTES_BY(qrst, patch->adjust); - } - } - void CalculateQsafe() { qsafe = ROUND((C.marikoEmcMaxClock / 1000.0) / 138.0 + 37.4) + C.mem_burst_read_latency; if (auto patch = FindQsafePatch()) { @@ -132,10 +102,8 @@ namespace ams::ldr::oc::pcv::mariko { void CalculateTimings() { CalculateMiscTimings(); CalculateIbdly(); - CalculateObdly(); CalculateTWTPDEN(); CalculateTR2W(); - CalculateQrst(); CalculateQsafe(); CalculateQpop(); CalculatePdex2rw(); 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 7090a13f..492c61ef 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.cpp @@ -20,29 +20,29 @@ namespace ams::ldr::oc::pcv::mariko { const MiscTimings g_misc_table[] = { - {1'866'000, 1, 0x20, 0x9, }, - {2'133'000, 1, 0x24, 0xA, }, - {2'166'000, 1, 0, 0, }, - {2'233'000, 0, 0x25, 0, }, - {2'300'000, 0, 0x26, 0xB, }, - {2'333'000, 0, 0x27, 0, }, - {2'366'000, 1, 0x26, 0xA, }, - {2'433'000, 0, 0x27, 0, }, - {2'466'000, 0, 0x2A, 0, }, - {2'500'000, 0, 0x28, 0xB, }, - {2'533'000, 0, 0x29, 0, }, - {2'566'000, 1, 0, 0, }, - {2'633'000, 0, 0x2A, 0, }, - {2'700'000, 0, 0x2B, 0xC, }, - {2'733'000, 0, 0x2C, 0, }, - {2'766'000, 1, 0x2B, 0xB, }, - {2'833'000, 0, 0x2C, 0, }, - {2'866'000, 0, 0, 0, }, - {2'900'000, 0, 0, 0, }, - {2'933'000, 0, 0x2E, 0xC, }, - {2'966'000, 1, 0, 0, }, - {3'033'000, 0, 0x2F, 0, }, - {3'133'000, 1, 0x31, 0xD, }, + {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]); @@ -98,39 +98,6 @@ namespace ams::ldr::oc::pcv::mariko { return nullptr; } - const AdjustPatch g_obdly_patches[] = { - {2'533'000, -2}, - {2'566'000, -2}, - {2'600'000, -2}, - {2'633'000, -2}, - {2'666'000, -2}, - {2'700'000, -2}, - {2'733'000, -2}, - {2'766'000, -2}, - {2'800'000, -2}, - {2'833'000, -2}, - {2'866'000, -2}, - {2'900'000, -2}, - {2'933'000, -2}, - {2'966'000, -2}, - {3'000'000, -2}, - {3'033'000, -2}, - {3'066'000, -2}, - {3'100'000, -2}, - {3'133'000, -2}, - {3'166'000, -2}, - {3'200'000, -2}, - }; - - const u32 g_obdly_table_size = sizeof(g_obdly_patches) / sizeof(g_obdly_patches[0]); - - const AdjustPatch *FindObdlyPatch() { - for (u32 i = 0; i < g_obdly_table_size; i++) - if (g_obdly_patches[i].freq == C.marikoEmcMaxClock) - return &g_obdly_patches[i]; - return nullptr; - } - const AdjustPatch g_tr2w_patches[] = { {2'500'000, 1}, {2'533'000, 1}, @@ -149,42 +116,6 @@ namespace ams::ldr::oc::pcv::mariko { return nullptr; } - const AdjustPatch g_qrst_patches[] = { - {2'166'000, 1}, - {2'200'000, 1}, - {2'233'000, 1}, - {2'266'000, 1}, - {2'366'000, 2}, - {2'400'000, 2}, - {2'433'000, 1}, - {2'466'000, 2}, - {2'500'000, 1}, - {2'533'000, -1}, - {2'600'000, 1}, - {2'700'000, -1}, - {2'733'000, -1}, - {2'766'000, 1}, - {2'800'000, 1}, - {2'833'000, 1}, - {2'866'000, 1}, - {2'900'000, 1}, - {2'933'000, -1}, - {2'966'000, 1}, - {3'000'000, 1}, - {3'100'000, 1}, - {3'166'000, 1}, - {3'200'000, 1}, - }; - - const u32 g_qrst_table_size = sizeof(g_qrst_patches) / sizeof(g_qrst_patches[0]); - - const AdjustPatch *FindQrstPatch() { - for (u32 i = 0; i < g_qrst_table_size; i++) - if (g_qrst_patches[i].freq == C.marikoEmcMaxClock) - return &g_qrst_patches[i]; - return nullptr; - } - const AdjustPatch g_qsafe_patches[] = { {2'166'000, 1}, {2'200'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 81231c85..06176a49 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/timing_tables.hpp @@ -37,18 +37,10 @@ namespace ams::ldr::oc::pcv::mariko { extern const u32 g_ibdly_table_size; const AdjustPatch *FindIbdlyPatch(); - extern const AdjustPatch g_obdly_patches[]; - extern const u32 g_obdly_table_size; - const AdjustPatch *FindObdlyPatch(); - extern const AdjustPatch g_tr2w_patches[]; extern const u32 g_tr2w_table_size; const AdjustPatch *FindTR2WPatch(); - extern const AdjustPatch g_qrst_patches[]; - extern const u32 q_qrst_table_size; - const AdjustPatch *FindQrstPatch(); - extern const AdjustPatch g_qsafe_patches[]; extern const u32 g_qsafe_table_size; const AdjustPatch *FindQsafePatch(); @@ -63,9 +55,7 @@ namespace ams::ldr::oc::pcv::mariko { struct MiscTimings { u32 min_freq; - u32 rdv_inc; u32 einput; - u32 quse_width; }; extern const MiscTimings g_misc_table[]; 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 735510d9..aaf1bd13 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -27,37 +27,36 @@ namespace ams::ldr::oc { #define FLOOR(A) std::floor(A) #define ROUND(A) std::lround(A) - #define GET_LOW_BYTES(x) ((u16)((x) & 0xFFFF)) - #define SET_LOW_BYTES(x, val) (((x) & 0xFFFF0000) | ((u32)(val) & 0xFFFF)) - #define INCREMENT_LOW_BYTES_BY(x, n) SET_LOW_BYTES((x), (GET_LOW_BYTES(x) + (n))) - #define GET_HIGH_BYTES(x) ((u16)(((x) >> 16) & 0xFFFF)) - #define SET_HIGH_BYTES(x, val) (((x) & 0x0000FFFF) | (((u32)(val) & 0xFFFF) << 16)) - #define INCREMENT_HIGH_BYTES_BY(x, n) SET_HIGH_BYTES((x), (GET_HIGH_BYTES(x) + (n))) + #define PACK_U32(high, low) ((static_cast(high) << 16) | (static_cast(low) & 0xFFFF)) /* 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 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? */ + 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 }; const std::array tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 }; + /* Burst latency, not to be confused with base latency (tWRL). */ const u32 BL = 16; + /* Base latency for read and write (tWRL). */ const u32 RL = 28 + C.mem_burst_read_latency; const u32 WL = 14 + C.mem_burst_write_latency; + /* Switch uses RL_DBI, todo: get rid of non DBI_RL. */ const u32 RL_DBI = RL + 4; - /* Precharge to Precharge Delay. (Cycles) */ + /* Precharge to Precharge Delay. (tCK) */ const u32 tPPD = 4; /* DQS output access time from CK_t/CK_c. */ const double tDQSCK_max = 3.5; + /* Write preamble. (tCK) */ const u32 tWPRE = 2; - /* tCK Read postamble. */ + /* Read postamble. (tCK) */ const double tRPST = 0.5; /* Minimum Self-Refresh Time. (Entry to Exit) */ @@ -66,86 +65,61 @@ namespace ams::ldr::oc { /* Exit power down to next valid command delay. */ const double tXP = 7.5; + /* Write command to first DQS transition (max) (tCK) */ const double tDQSS_max = 1.25; + + /* DQ-to-DQS offset(max) (ns) */ const double tDQS2DQ_max = 0.8; + /* Write recovery time. */ const u32 tWR = 18; /* TOOD: Fix erista */ namespace pcv::erista { - // const double tCK_avg = 1000'000.0 / C.eristaEmcMaxClock; - // - // /* Primary timings. */ - // const u32 tRCD = tRCD_values[C.t1_tRCD]; - // const u32 tRPpb = tRP_values[C.t2_tRP]; - // const u32 tRAS = tRAS_values[C.t3_tRAS]; - // - // /* Secondary timings. */ - // const double tRRD = tRRD_values[C.t4_tRRD]; - // const u32 tRFCpb = tRFC_values[C.t5_tRFC]; - // const u32 tWTR = tWTR_values[C.t7_tWTR]; - // const u32 tREFpb = tREFpb_values[C.t8_tREFI]; - // - // /* Four-bank ACTIVATE Window */ - // const u32 tFAW = (u32) (tRRD * 4.0); - // - // /* Latency stuff. */ - // const int tR2W = (int)((3.5 / tCK_avg) + 32 + (BL / 2) - 14 - 6 + tWPRE + 12 - (C.t6_tRTW * 3)); - // const int tW2R = (int)((tWTR / tCK_avg) + 18 - (BL / 2)); - // const int tRW2PDEN = (int)((tDQSS_max / tCK_avg) + 46 + (tDQS2DQ_max / tCK_avg) + 6); - // - // /* Refresh Cycle time. (All Banks) */ - // const u32 tRFCab = tRFCpb * 2; - // - // /* ACTIVATE-to-ACTIVATE command period. (same bank) */ - // const u32 tRC = tRAS + tRPpb; - // - // /* SELF REFRESH exit to next valid command delay. */ - // const double tXSR = (double) (tRFCab + 7.5); - // - // /* u32ernal READ to PRECHARGE command delay. */ - // const int pdex2mrr = (tCK_avg * 3.0) + tRCD_values[C.t1_tRCD] + 1; - // - // /* Row Precharge Time. (all banks) */ - // const u32 tRPab = tRPpb + 3; + } namespace pcv::mariko { const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock; - const u32 tRCD = tRCD_values[C.t1_tRCD]; - const u32 tRPpb = tRP_values[C.t2_tRP]; - const u32 tRAS = tRAS_values[C.t3_tRAS]; + const u32 tRCD = tRCD_values[C.t1_tRCD]; + const u32 tRPpb = tRP_values[C.t2_tRP]; + const u32 tRAS = tRAS_values[C.t3_tRAS]; const double tRRD = tRRD_values[C.t4_tRRD]; - const u32 tRFCpb = tRFC_values[C.t5_tRFC]; - const u32 tWTR = 10 - tWTR_values[C.t7_tWTR]; + const u32 tRFCpb = tRFC_values[C.t5_tRFC]; + const u32 tWTR = 10 - tWTR_values[C.t7_tWTR]; - const u32 tRC = tRAS + tRPpb; - const u32 tRFCab = tRFCpb * 2; - const double tXSR = (double) (tRFCab + 7.5); - const u32 tFAW = static_cast(tRRD * 4.0); + const u32 tRC = tRAS + tRPpb; + const u32 tRFCab = tRFCpb * 2; + const double tXSR = static_cast(tRFCab + 7.5); + const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; 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? - inline u32 rdv; - const u32 quse = FLOOR((-0.0048159 * (C.marikoEmcMaxClock / 1000.0)) + RL_DBI) + (FLOOR((C.marikoEmcMaxClock / 1000.0) * 0.0050997) * 1.5134); + 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; - inline u32 obdly; - inline u32 quse_width; + + 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; - inline u32 qrst; + 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 tW2P = (CEIL(WL * 1.7303) * 2) - 5; + 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 tWTM = WL + (BL / 2) + 1 + CEIL(7.5 / tCK_avg); + 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 tWTM = WL + (BL / 2) + 1 + CEIL(7.5 / tCK_avg); const u32 tWATM = tWTM + CEIL(tWR / tCK_avg); const u32 wdv = WL; @@ -157,7 +131,7 @@ namespace ams::ldr::oc { const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * (C.marikoEmcMaxClock / 1000.0))); - const double tMMRI = tRCD + (tCK_avg * 3); + 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_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp index 80e98e1c..1110c097 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -378,13 +378,19 @@ namespace ams::ldr::oc::pcv::mariko { if (prev_freq != 128000 && prev_freq != 1300000 && prev_freq != 76800) { R_THROW(ldr::ResultInvalidGpuPllEntry()); } - + PATCH_OFFSET(ptr, 3600000); R_SUCCEED(); } void MemMtcTableAutoAdjust(MarikoMtcTable *table) { + /* Official Tegra X1 TRM, sign up for nvidia developer program (free) to download: + * https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual + * Section 18.11.1: MC Registers + * Section 18.11.2: EMC Registers + */ + #define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \ TABLE->burst_regs.PARAM = VALUE; \ TABLE->shadow_regs_ca_train.PARAM = VALUE; \ @@ -392,6 +398,10 @@ namespace ams::ldr::oc::pcv::mariko { #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 */ if (C.hpMode) { WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000); } else { @@ -492,10 +502,13 @@ namespace ams::ldr::oc::pcv::mariko { table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA; + /* Two consecutive reads between two different dram modules. */ + /* Only be above 1 for 8gb ram. */ if (table->burst_mc_regs.mc_emem_arb_timing_r2r > 1) { table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / 4) - 1 + MC_ARB_SFA; } + /* Same as r2r but for write. */ if (table->burst_mc_regs.mc_emem_arb_timing_w2w > 1) { table->burst_mc_regs.mc_emem_arb_timing_w2w = CEIL(table->burst_regs.emc_wext / MC_ARB_DIV) - 1 + MC_ARB_SFA; } @@ -565,220 +578,13 @@ namespace ams::ldr::oc::pcv::mariko { table->emc_cfg_2 = 0x11083D; } - // void MemMtcTableAutoAdjust(MarikoMtcTable *table) { - // /* Official Tegra X1 TRM, sign up for nvidia developer program (free) to download: - // * https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual - // * Section 18.11: MC Registers - // * - // * Retail Mariko: 200FBGA 16Gb DDP LPDDR4X SDRAM x 2 - // * x16/Ch, 1Ch/die, Double-die, 2Ch, 1CS(rank), 8Gb density per die - // * 64Mb x 16DQ x 8banks x 2channels = 2048MB (x32DQ) per package - // * - // * Devkit Mariko: 200FBGA 32Gb DDP LPDDR4X SDRAM x 2 - // * x16/Ch, 1Ch/die, Quad-die, 2Ch, 2CS(rank), 8Gb density per die - // * X1+ EMC can R/W to both ranks at the same time, resulting in doubled DQ - // * 64Mb x 32DQ x 8banks x 2channels = 4096MB (x64DQ) per package - // * - // * If you have access to LPDDR4(X) specs or datasheets (from manufacturers or Google), - // * you'd better calculate timings yourself rather than relying on following algorithm. - // */ - // - /* #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(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) - -/* This condition is insane but it's done in eos. */ - /* Need to clean up at some point. */ - // u32 rext; - // u32 wext; - // if (C.marikoEmcMaxClock < 3200001) { - // if (C.marikoEmcMaxClock < 2133001) { - // rext = 26; - // wext = 22; - // } else { - // rext = 28; - // wext = 22; - // - // if (2400000 < C.marikoEmcMaxClock) { - // wext = 25; - // } - // } - // } else { - // rext = 30; - // wext = 25; - // } - // - // u32 refresh_raw = 0xFFFF; - // u32 trefbw = 0; - // - // if (C.t8_tREFI != 6) { - // refresh_raw = static_cast(std::floor(static_cast(tREFpb_values[C.t8_tREFI]) / tCK_avg)) - 0x40; - // refresh_raw = MIN(refresh_raw, static_cast(0xFFFF)); - // } - // - // trefbw = refresh_raw + 0x40; - // trefbw = MIN(trefbw, static_cast(0x3FFF)); - // - // /* Primary timings. */ - // WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE(tRCD)); - // WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE(tRCD)); - // WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE(tRAS)); - // WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE(tRPpb)); - // - // /* Secondary timings. */ - // WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE(tRRD)); - // WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE(tRFCab)); - // WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE(tRFCpb)); - // WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W); - // WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R); - // WRITE_PARAM_ALL_REG(table, emc_r2p, (u32) 0xC); - // WRITE_PARAM_ALL_REG(table, emc_w2p, (u32) 0x2D); - // - // WRITE_PARAM_ALL_REG(table, emc_rext, rext); - // WRITE_PARAM_ALL_REG(table, emc_wext, wext); - // - // WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE(tRPab)); - // WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE(tFAW)); - // WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE(tRC)); - // - // WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE(tSR)); - // WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE(tXP) + 2); - // WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE(tXP)); - // WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE(tXP) + 8); - // - // WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE(tXSR), (u32) 1022)); - // WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE(tXSR), (u32) 1022)); - // - // const u32 dyn_self_ref_control = (((u32)(7605.0 / tCK_avg)) + 260U) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000U); - // WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control); - // - // WRITE_PARAM_ALL_REG(table, emc_rw2pden, ams::ldr::oc::pcv::erista::tRW2PDEN); - // WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE(10.0)); - // WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE(10.0)); - // - // WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE(1.75)); - // WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE(1.75)); - // WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE(1.75)); - // WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE(14.0)); - // WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE(5.0)); - // WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE(ams::ldr::oc::pcv::erista::pdex2mrr)); - // - // WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw); - // WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, (u32) (refresh_raw / 4)); - // WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw); - // - // const u32 mc_tRCD = (int)((double)(GET_CYCLE(tRCD) >> 2) - 2.0); - // const u32 mc_tRPpb = (int)(((double)(GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0); - // const u32 mc_tRC = (uint)((double)(GET_CYCLE(tRC) >> 2) - 1.0); - // const u32 mc_tR2W = (uint)(((double)((uint)tR2W >> 2) - 1.0) + 2.0); - // const u32 mc_tW2R = (uint)(((double)(tW2R >> 2) - 1.0) + 2.0); - // const u32 mc_tRAS = MIN(GET_CYCLE(tRAS), (u32) 0x7F); - // const u32 mc_tRRD = MIN(GET_CYCLE(tRRD), (u32) 31); - // - // table->burst_mc_regs.mc_emem_arb_cfg = (int)(((double) C.marikoEmcMaxClock / 33300.0) * 0.25); - // table->burst_mc_regs.mc_emem_arb_timing_ras = (int) ((double) (mc_tRAS >> 2) - 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_rcd = (int) ((double) (GET_CYCLE(tRCD) >> 2) - 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_rp = (int) (((double) (GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_rc = (int) ((double) (GET_CYCLE(tRC) >> 2) - 1.0); - // table->burst_mc_regs.mc_emem_arb_timing_faw = (int) ((double)(GET_CYCLE(tFAW) >> 2) - 1.0); - // table->burst_mc_regs.mc_emem_arb_timing_rrd = (int)((double)(mc_tRRD >> 2) - 1.0); - // table->burst_mc_regs.mc_emem_arb_timing_rap2pre = 3; - // table->burst_mc_regs.mc_emem_arb_timing_wap2pre = 11; - // table->burst_mc_regs.mc_emem_arb_timing_r2w = (uint)(((double)((uint)tR2W >> 2) - 1.0) + 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_w2r = (uint)(((double)(tW2R >> 2) - 1.0) + 2.0); - // - // u32 mc_r2r = table->burst_mc_regs.mc_emem_arb_timing_r2r; - // if (mc_r2r > 1) { - // mc_r2r = (uint)(((double)(long)((double)rext * 0.25) - 1.0) + 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_r2r = mc_r2r; - // } - // - // u32 mc_w2w = table->burst_mc_regs.mc_emem_arb_timing_w2w; - // if (mc_w2w > 1) { - // mc_w2w = (uint)(((double)(long)((double)wext / 4.0) - 1.0) + 2.0); - // table->burst_mc_regs.mc_emem_arb_timing_w2w = mc_w2w; - // } - // - // table->burst_mc_regs.mc_emem_arb_da_turns = ((mc_tW2R >> 1) << 0x18) | ((mc_tR2W >> 1) << 0x10) | ((mc_r2r >> 1) << 8) | ((mc_w2w >> 1)); - // table->burst_mc_regs.mc_emem_arb_da_covers = (((uint)(mc_tRCD + 3 + mc_tRPpb) >> 1 & 0xff) << 8) | (((uint)(mc_tRCD + 11 + mc_tRPpb) >> 1 & 0xff) << 0x10) | ((mc_tRC >> 1) & 0xff); - // table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xffe08000U) | ((mc_tRC + 1) & 0xff); - // table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = MIN((u32)((C.marikoEmcMaxClock / 1600000) * 0xd0U), (u32)0x115); - // table->la_scale_regs.mc_ftop_ptsa_rate = MIN((u32)((C.marikoEmcMaxClock / 1600000) * 0x18U), (u32)0x1f); - // table->la_scale_regs.mc_ptsa_grant_decrement = MIN((u32)((C.marikoEmcMaxClock / 1600000) * 0x1203U), (u32)0x17ff); - // - // u32 mc_latency_allowance = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance = 204800 / (C.marikoEmcMaxClock / 1000); - // } - // - // const u32 mc_latency_allowance2 = mc_latency_allowance & 0xFF; - // const u32 mc_latency_allowance3 = (mc_latency_allowance & 0xFF) << 0x10; - // table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & 0xff00ffffU) | mc_latency_allowance3; - // - // u32 mc_latency_allowance_hc_0 = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance_hc_0 = 35200 / (C.marikoEmcMaxClock / 1000); - // } - // - // table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & 0xff00ffffU) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & 0xffffff00U) | mc_latency_allowance_hc_0; - // - // table->la_scale_regs.mc_latency_allowance_isp2_1 = (table->la_scale_regs.mc_latency_allowance_isp2_1 & 0xff00ff00U) | mc_latency_allowance3 | mc_latency_allowance2; - // table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & 0xffffff00U) | mc_latency_allowance2; - // - // u32 mc_latency_allowance_gpu_0 = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance_gpu_0 = 40000 / (C.marikoEmcMaxClock / 1000); - // } - // - // table->la_scale_regs.mc_latency_allowance_gpu_0 = ((mc_latency_allowance_gpu_0 | table->la_scale_regs.mc_latency_allowance_gpu_0) & 0xff00ff00U) | mc_latency_allowance3; - // - // u32 mc_latency_allowance_gpu2_0 = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance_gpu2_0 = 40000 / (C.marikoEmcMaxClock / 1000); - // } - // - // table->la_scale_regs.mc_latency_allowance_gpu2_0 = ((mc_latency_allowance_gpu2_0 | table->la_scale_regs.mc_latency_allowance_gpu2_0) & 0xff00ff00U) | mc_latency_allowance3; - // - // u32 mc_latency_allowance_nvenc_0 = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance_nvenc_0 = 38400 / (C.marikoEmcMaxClock / 1000); - // } - // - // table->la_scale_regs.mc_latency_allowance_nvenc_0 = ((mc_latency_allowance_nvenc_0 | table->la_scale_regs.mc_latency_allowance_nvenc_0) & 0xff00ff00U) | mc_latency_allowance3; - // - // u32 mc_latency_allowance_vic_0 = 0; - // if (C.marikoEmcMaxClock / 1000 != 0) { - // mc_latency_allowance_vic_0 = 0xb540 / (C.marikoEmcMaxClock / 1000); - // } - // - // table->la_scale_regs.mc_latency_allowance_vic_0 = ((mc_latency_allowance_vic_0 | table->la_scale_regs.mc_latency_allowance_vic_0) & 0xff00ff00U) | mc_latency_allowance3; - // table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & 0xffffff00U) | mc_latency_allowance2; - // - // table->burst_mc_regs.mc_emem_arb_timing_rfcpb = GET_CYCLE(tRFCpb) >> 2; - // - // if (C.hpMode) { - // WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000); - // } - // - // table->dram_timings.t_rp = tRFCpb; - // table->dram_timings.t_rfc = tRFCab; - // table->emc_cfg_2 = 0x11083d; - - // (void) table; - // } + // WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE(10.0)); + // WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE(10.0)); + // WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE(1.75)); + // WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE(1.75)); + // WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE(1.75)); + // WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE(14.0)); + // WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE(5.0)); void MemMtcPllmbDivisor(MarikoMtcTable *table) { constexpr u32 PllOscInKHz = 38400;