diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
index 6116ac6f..64cc695a 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
@@ -36,6 +36,8 @@ volatile CustomizeTable C = {
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
+.eristaEmcMaxClock1 = 1600000,
+.eristaEmcMaxClock2 = 1600000,
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
index 65051d39..fbbd51d4 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
@@ -80,6 +80,8 @@ typedef struct CustomizeTable {
u32 commonEmcMemVolt;
u32 eristaEmcMaxClock;
+ u32 eristaEmcMaxClock1;
+ u32 eristaEmcMaxClock2;
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
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
new file mode 100644
index 00000000..e9385ef0
--- /dev/null
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) Lightos_
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "../oc_common.hpp"
+#include "../mtc_timing_value.hpp"
+
+namespace ams::ldr::hoc::pcv::erista {
+
+ void CalculateTimings(double tCK_avg) {
+ tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3) + finetRTW;
+ tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (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_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
+
+ pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
+ tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
+
+ const double tMMRI = tRCD + (tCK_avg * 3);
+ pdex2mrr = tMMRI + 10;
+ }
+
+}
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
new file mode 100644
index 00000000..3a58c83a
--- /dev/null
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.hpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) Lightos_
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+namespace ams::ldr::hoc::pcv::erista {
+
+ void CalculateTimings(double tCK_avg);
+
+}
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 ff769475..3bbe4f84 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp
@@ -30,14 +30,7 @@ namespace ams::ldr::hoc {
#define PACK_U32(high, low) ((static_cast(high) << 16) | (static_cast(low) & 0xFFFF))
#define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast(high & 0xF) << 28) | (static_cast(low) & 0xFF))
- /* Primary timings. */
- const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
- const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
- const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
- const std::array 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;
@@ -75,9 +68,14 @@ namespace ams::ldr::hoc {
/* Write recovery time. */
const u32 tWR = 18;
- /* TOOD: Fix erista */
namespace pcv::erista {
- const double tCK_avg = 1000'000.0 / C.eristaEmcMaxClock;
+ 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 };
+ 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 };
const u32 tRCD = tRCD_values[C.t1_tRCD];
const u32 tRPpb = tRP_values[C.t2_tRP];
@@ -95,43 +93,29 @@ namespace ams::ldr::hoc {
const double tRPab = tRPpb + 3;
const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0);
- const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3) + finetRTW;
+ inline u32 tR2W;
inline u32 rext;
- const u32 rdv = RL_DBI + FLOOR((5.105 / tCK_avg) + 17.017);
- const u32 qpop = rdv - 14;
- const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
- const u32 quse = FLOOR(RL_DBI + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
- const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
- const u32 einput = quse - CEIL(9.928 / tCK_avg);
- const u32 qrst_duration = FLOOR(8.399 - tCK_avg);
- const u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0));
- const u32 qrst = PACK_U32(qrst_duration, qrstLow);
- const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
- const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
- const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
- const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast(tW2P))) + (BL / 2));
- const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
+ const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
+ inline u32 tWTPDEN;
+ inline u32 tW2R;
- const u32 wdv = WL;
- const u32 wsv = WL - 2;
- const u32 wev = 0xA + (WL - 14);
+ inline u32 pdex2rw;
- const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7)));
- const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
- const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
+ inline u32 tCLKSTOP;
- const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
-
- const u32 tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
-
- const double tMMRI = tRCD + (tCK_avg * 3);
- const double pdex2mrr = tMMRI + 10; /* Do this properly? */
-
- inline u8 mrw2;
+ inline double pdex2mrr;
}
namespace pcv::mariko {
+ const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
+ const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
+ const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
+ const std::array tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
+ const std::array tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
+ const std::array tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
+ const std::array tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
+
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock;
const u32 tRCD = tRCD_values[C.t1_tRCD];
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
index 35d3ebae..b969179a 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
@@ -138,19 +138,20 @@ void SafetyCheck() {
break;
}
+ using namespace ams::ldr::hoc::pcv;
sValidator validators[] = {
{ C.eristaCpuBoostClock, 1020'000, 2295'000, true },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true },
- { C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV
- { C.eristaCpuMaxVolt, 1000, 1257 },
- { C.eristaEmcMaxClock, 1600'000, 2600'000 },
- { C.marikoCpuMaxVolt, 1000, 1235 },
- { C.marikoEmcMaxClock, 1600'000, 3500'000 },
- { C.marikoEmcVddqVolt, 250'000, 700'000 },
- { eristaCpuDvfsMaxFreq, 1785'000, 2295'000 },
- { marikoCpuDvfsMaxFreq, 1785'000, 2703'000 },
- { eristaGpuDvfsMaxFreq, 768'000, 1152'000 },
- { marikoGpuDvfsMaxFreq, 768'000, 1536'000 },
+ { C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV
+ { C.eristaCpuMaxVolt, 1000, 1257 },
+ { GET_MAX_OF_ARR(erista::maxClocks), 1600'000, 2600'000 },
+ { C.marikoCpuMaxVolt, 1000, 1235 },
+ { C.marikoEmcMaxClock, 1600'000, 3500'000 },
+ { C.marikoEmcVddqVolt, 250'000, 700'000 },
+ { eristaCpuDvfsMaxFreq, 1785'000, 2295'000 },
+ { marikoCpuDvfsMaxFreq, 1785'000, 2703'000 },
+ { eristaGpuDvfsMaxFreq, 768'000, 1152'000 },
+ { marikoGpuDvfsMaxFreq, 768'000, 1536'000 },
};
for (auto& i : validators) {
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
index ab52f759..0da748c4 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
@@ -178,6 +178,9 @@ namespace ams::ldr::hoc::pcv {
}
namespace erista {
+ const u32 maxClocks[] = { 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}, { } },
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 e8e0e93c..282ceadd 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp
@@ -20,6 +20,7 @@
#include "pcv.hpp"
#include "../mtc_timing_value.hpp"
+#include "../erista/calculate_timings_erista.hpp"
namespace ams::ldr::hoc::pcv::erista {
@@ -184,12 +185,15 @@ namespace ams::ldr::hoc::pcv::erista {
/* However, it may still achieve a slightly higher frequency, but not as much as it could be. */
/* I'm certainly not insane enough to attempt this pain again, so this will have to do *for now*. */
void MemMtcTableAutoAdjust(EristaMtcTable *table) {
+ const double tCK_avg = 1000'000.0 / table->rate_khz;
+
#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))
+
/* Ram power down */
/* B31: DRAM_CLKSTOP_PD */
/* B30: DRAM_CLKSTOP_SR */
@@ -206,10 +210,9 @@ namespace ams::ldr::hoc::pcv::erista {
refresh_raw = MIN(refresh_raw, static_cast(0xFFFF));
}
- u32 rext;
- if (C.eristaEmcMaxClock > 3200000) {
+ if (table->rate_khz > 3200000) {
rext = 30;
- } else if (C.eristaEmcMaxClock >= 2133001) {
+ } else if (table->rate_khz >= 2133001) {
rext = 28;
} else {
rext = 26;
@@ -218,6 +221,8 @@ namespace ams::ldr::hoc::pcv::erista {
u32 trefbw = refresh_raw + 0x40;
trefbw = MIN(trefbw, static_cast(0x3FFF));
+ 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));
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast(0xB8)));
@@ -239,7 +244,7 @@ namespace ams::ldr::hoc::pcv::erista {
WRITE_PARAM_ALL_REG(table, emc_w2p, tW2P);
WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R);
WRITE_PARAM_ALL_REG(table, emc_rext, rext);
- WRITE_PARAM_ALL_REG(table, emc_wext, (C.eristaEmcMaxClock >= 2533000) ? 0x19 : 0x16);
+ WRITE_PARAM_ALL_REG(table, emc_wext, (table->rate_khz >= 2533000) ? 0x19 : 0x16);
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
@@ -286,7 +291,7 @@ namespace ams::ldr::hoc::pcv::erista {
constexpr double MC_ARB_DIV = 4.0;
constexpr u32 MC_ARB_SFA = 2;
- table->burst_mc_regs.mc_emem_arb_cfg = C.eristaEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV;
+ table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
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;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
@@ -319,24 +324,24 @@ namespace ams::ldr::hoc::pcv::erista {
table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xFFE08000) | (table->burst_mc_regs.mc_emem_arb_timing_rc + 1);
- u32 mpcorer_ptsa_rate = MAX(static_cast(227), (C.eristaEmcMaxClock / 1600000) * 208);
+ u32 mpcorer_ptsa_rate = MAX(static_cast(227), (table->rate_khz / 1600000) * 208);
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = mpcorer_ptsa_rate;
- u32 ftop_ptsa_rate = MAX(static_cast(31), (C.eristaEmcMaxClock / 1600000) * 24);
+ u32 ftop_ptsa_rate = MAX(static_cast(31), (table->rate_khz / 1600000) * 24);
table->la_scale_regs.mc_ftop_ptsa_rate = ftop_ptsa_rate;
- u32 grant_decrement = MAX(static_cast(6143), (C.eristaEmcMaxClock / 1600000) * 4611);
+ u32 grant_decrement = MAX(static_cast(6143), (table->rate_khz / 1600000) * 4611);
table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement;
constexpr u32 MaskHigh = 0xFF00FFFF;
constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00;
- const u32 allowance1 = static_cast(0x32000 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
- const u32 allowance2 = static_cast(0x9C40 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
- const u32 allowance3 = static_cast(0xB540 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
- const u32 allowance4 = static_cast(0x9600 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
- const u32 allowance5 = static_cast(0x8980 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
+ const u32 allowance1 = static_cast(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF;
+ const u32 allowance2 = static_cast(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF;
+ const u32 allowance3 = static_cast(0xB540 / (table->rate_khz / 0x3E8)) & 0xFF;
+ const u32 allowance4 = static_cast(0x9600 / (table->rate_khz / 0x3E8)) & 0xFF;
+ const u32 allowance5 = static_cast(0x8980 / (table->rate_khz / 0x3E8)) & 0xFF;
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
@@ -377,25 +382,32 @@ namespace ams::ldr::hoc::pcv::erista {
R_UNLESS(table_list[i]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
}
- if (C.eristaEmcMaxClock <= EmcClkOSLimit)
+ if (GET_MAX_OF_ARR(maxClocks) <= EmcClkOSLimit) {
R_SKIP();
+ }
- // Make room for new mtc table, discarding useless 40.8 MHz table
- // 40800 overwritten by 68000, ..., 1331200 overwritten by 1600000, leaving table_list[0] not overwritten
- 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));
+ // Make room for new mtc table, discarding useless 40.8, 68000 and 102000 MHz table
+ // 40800 overwritten by 68000, ..., 1331200 overwritten by 1600000, leaving table_list[0], table_list[1] and table_list[2] not overwritten
+ for (u32 i = khz_list_size - 1; i > 2; --i) {
+ std::memcpy(static_cast(table_list[i]), static_cast(table_list[i - 3]), sizeof(EristaMtcTable));
+ }
- MemMtcTableAutoAdjust(table_list[0]);
+ for (u32 i = 0; i < std::size(maxClocks); ++i) {
+ if (maxClocks[i] > EmcClkOSLimit) {
+ table_list[i]->rate_khz = maxClocks[i];
+ MemMtcTableAutoAdjust(table_list[i]);
+ }
+ }
- PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
R_SUCCEED();
}
Result MemFreqMax(u32 *ptr) {
- if (C.eristaEmcMaxClock <= EmcClkOSLimit)
+ if (GET_MAX_OF_ARR(maxClocks) <= EmcClkOSLimit) {
R_SKIP();
+ }
- PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
+ PATCH_OFFSET(ptr, GET_MAX_OF_ARR(maxClocks));
R_SUCCEED();
}
diff --git a/Source/sys-clk/common/include/sysclk/config.h b/Source/sys-clk/common/include/sysclk/config.h
index d5f14773..d9db7297 100644
--- a/Source/sys-clk/common/include/sysclk/config.h
+++ b/Source/sys-clk/common/include/sysclk/config.h
@@ -69,6 +69,8 @@ typedef enum {
KipConfigValue_commonEmcMemVolt,
KipConfigValue_eristaEmcMaxClock,
+ KipConfigValue_eristaEmcMaxClock1,
+ KipConfigValue_eristaEmcMaxClock2,
KipConfigValue_marikoEmcMaxClock,
KipConfigValue_marikoEmcVddqVolt,
KipConfigValue_emcDvbShift,
@@ -248,7 +250,11 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue 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_clock";
+ 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_marikoEmcMaxClock:
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
case KipConfigValue_marikoEmcVddqVolt:
@@ -464,6 +470,8 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case KipConfigValue_hpMode:
case KipConfigValue_commonEmcMemVolt:
case KipConfigValue_eristaEmcMaxClock:
+ case KipConfigValue_eristaEmcMaxClock1:
+ case KipConfigValue_eristaEmcMaxClock2:
case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift:
diff --git a/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp
index 33a70377..7148ef84 100644
--- a/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp
+++ b/Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp
@@ -285,7 +285,6 @@ void MiscGui::listUI()
);
}
-
ValueThresholds throttleThresholds(70, 80);
addConfigButton(
HocClkConfigValue_ThermalThrottleThreshold,
@@ -617,16 +616,9 @@ protected:
};
if(IsErista()) {
- addConfigButton(
- KipConfigValue_eristaEmcMaxClock,
- "RAM Max Clock",
- ValueRange(0, 1, 1, "", 1),
- "RAM Max Clock",
- &eristaRamThresholds,
- {},
- eristaMaxEmcClock,
- false
- );
+ addConfigButton(KipConfigValue_eristaEmcMaxClock, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
+ addConfigButton(KipConfigValue_eristaEmcMaxClock1, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
+ addConfigButton(KipConfigValue_eristaEmcMaxClock2, "RAM Max Clock", ValueRange(0, 1, 1, "", 1), "RAM Max Clock", &eristaRamThresholds, {}, eristaMaxEmcClock, false);
} else {
addConfigButton(
KipConfigValue_marikoEmcMaxClock,
diff --git a/Source/sys-clk/sysmodule/src/clock_manager.cpp b/Source/sys-clk/sysmodule/src/clock_manager.cpp
index d11d348f..febd0cd9 100644
--- a/Source/sys-clk/sysmodule/src/clock_manager.cpp
+++ b/Source/sys-clk/sysmodule/src/clock_manager.cpp
@@ -797,6 +797,8 @@ void ClockManager::SetKipData() {
CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, this->config->GetConfigValue(KipConfigValue_commonEmcMemVolt));
CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock));
+ CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock1, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock1));
+ CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock2));
CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock));
CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, this->config->GetConfigValue(KipConfigValue_marikoEmcVddqVolt));
CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, this->config->GetConfigValue(KipConfigValue_emcDvbShift));
@@ -920,6 +922,8 @@ void ClockManager::GetKipData() {
initialConfigValues[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table);
initialConfigValues[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table);
+ initialConfigValues[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table);
+ initialConfigValues[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table);
initialConfigValues[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table);
initialConfigValues[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table);
initialConfigValues[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table);
@@ -966,6 +970,8 @@ void ClockManager::GetKipData() {
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);
diff --git a/Source/sys-clk/sysmodule/src/kip.h b/Source/sys-clk/sysmodule/src/kip.h
index 85f4222f..818b4937 100644
--- a/Source/sys-clk/sysmodule/src/kip.h
+++ b/Source/sys-clk/sysmodule/src/kip.h
@@ -32,6 +32,8 @@ typedef struct {
u32 hpMode;
u32 commonEmcMemVolt;
u32 eristaEmcMaxClock;
+ u32 eristaEmcMaxClock1;
+ u32 eristaEmcMaxClock2;
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
@@ -192,6 +194,8 @@ static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p,
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_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); }
static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); }
@@ -261,6 +265,8 @@ static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FI
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_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); }
static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); }