2133BL for mariko (AA); TODO: proper scaling and adjustments
This commit is contained in:
@@ -36,19 +36,19 @@ volatile CustomizeTable C = {
|
||||
|
||||
.commonCpuBoostClock = 1785000, // Default boost clock
|
||||
|
||||
.commonEmcMemVolt = 1212500, // LPDDR4X JEDEC Specification
|
||||
.commonEmcMemVolt = 1175000, // LPDDR4X JEDEC Specification
|
||||
|
||||
.eristaCpuMaxVolt = 1235,
|
||||
|
||||
.eristaEmcMaxClock = 2300000, // Maximum HB-MGCH ram rating
|
||||
.eristaEmcMaxClock = 1600001, // Maximum HB-MGCH ram rating
|
||||
|
||||
.marikoCpuMaxVolt = 1120,
|
||||
|
||||
.marikoEmcMaxClock = 1866000, // Hynix NME and Samsung AM-MGCJ Rating (others are 4766MT, 2133MHz)
|
||||
.marikoEmcMaxClock = 3000000, // Hynix NME and Samsung AM-MGCJ Rating (others are 4766MT, 2133MHz)
|
||||
|
||||
.marikoEmcVddqVolt = 640000,
|
||||
|
||||
.marikoCpuUV = 5, // No undervolt
|
||||
.marikoCpuUV = 0, // No undervolt
|
||||
|
||||
.marikoGpuUV = 3,
|
||||
|
||||
@@ -71,15 +71,15 @@ volatile CustomizeTable C = {
|
||||
// Defaults - (3-3-2) 0-1-4-3-6
|
||||
|
||||
// Primary
|
||||
.t1_tRCD = 5,
|
||||
.t2_tRP = 7,
|
||||
.t3_tRAS = 8,
|
||||
.t1_tRCD = 0,
|
||||
.t2_tRP = 0,
|
||||
.t3_tRAS = 0,
|
||||
// Secondary
|
||||
.t4_tRRD = 1,
|
||||
.t5_tRFC = 2,
|
||||
.t6_tRTW = 5,
|
||||
.t7_tWTR = 4,
|
||||
.t8_tREFI= 6,
|
||||
.t4_tRRD = 0,
|
||||
.t5_tRFC = 0,
|
||||
.t6_tRTW = 0,
|
||||
.t7_tWTR = 0,
|
||||
.t8_tREFI= 0,
|
||||
|
||||
// .mem_burst_latency = 0, // 0 - 1600l, 1 = 1866bl, 2 = 2133bl /* TODO: Remove/fix. */
|
||||
|
||||
@@ -110,12 +110,12 @@ volatile CustomizeTable C = {
|
||||
710 /* 1075 */,
|
||||
735 /* 1152 */,
|
||||
785 /* 1228 */,
|
||||
780 /* 1267 (Disabled by default) */,
|
||||
805 /* 1305 (Disabled by default) */,
|
||||
870 /* 1344 (Disabled by default) */,
|
||||
870 /* 1382 (Disabled by default) */,
|
||||
870 /* 1420 (Disabled by default) */,
|
||||
0 /* 1459 (Disabled by default) */,
|
||||
785 /* 1267 (Disabled by default) */,
|
||||
960 /* 1305 (Disabled by default) */,
|
||||
960 /* 1344 (Disabled by default) */,
|
||||
960 /* 1382 (Disabled by default) */,
|
||||
960 /* 1420 (Disabled by default) */,
|
||||
960 /* 1459 (Disabled by default) */,
|
||||
0 /* 1497 (Disabled by default) */,
|
||||
0 /* 1536 (Disabled by default) */,
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
||||
u32 custRev = CUST_REV;
|
||||
u32 mtcConf = AUTO_ADJ;
|
||||
bool hpMode;
|
||||
u32 hpMode;
|
||||
u32 commonCpuBoostClock;
|
||||
u32 commonEmcMemVolt;
|
||||
u32 eristaCpuMaxVolt;
|
||||
|
||||
@@ -28,37 +28,44 @@ namespace ams::ldr::oc {
|
||||
const std::array<u32, 8> tRCD_values = {18, 17, 16, 15, 14, 13, 12, 11};
|
||||
const std::array<u32, 8> tRP_values = {18, 17, 16, 15, 14, 13, 12, 11};
|
||||
const std::array<u32, 10> tRAS_values = {42, 36, 34, 32, 30, 28, 26, 24, 22, 20};
|
||||
|
||||
/* Secondary timings. */
|
||||
const std::array<double, 8> tRRD_values = {10.0, 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0};
|
||||
const std::array<u32, 6> tRFC_values = {90, 80, 70, 60, 50, 40};
|
||||
const std::array<u32, 11> tRFC_values = {140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40};
|
||||
const std::array<u32, 10> tWTR_values = {10, 9, 8, 7, 6, 5, 4, 3, 3, 1};
|
||||
const std::array<u32, 6> tREFpb_values = {3900, 5850, 7800, 11700, 15600, 99999};
|
||||
|
||||
const u32 BL = 16;
|
||||
|
||||
/* Set to 4 read and 2 write for 1866bl. */
|
||||
/* For 2131bl: 8 read and 4 write. */
|
||||
const u32 latency_offset_read = 0;
|
||||
const u32 latency_offset_write = 0;
|
||||
|
||||
const u32 BL = 16;
|
||||
const u32 RL = 28 + latency_offset_read;
|
||||
const u32 WL = 14 + latency_offset_write;
|
||||
|
||||
/* Precharge to Precharge Delay. (Cycles) */
|
||||
/* Don't touch! */
|
||||
const u32 tPPD = 4;
|
||||
|
||||
/* DQS output access time from CK_t/CK_c. */
|
||||
const double tDQSCK_max = 3.5;
|
||||
const double tWPRE = 2.0;
|
||||
const double tWPRE = 1.8;
|
||||
|
||||
/* tCK Read postamble. */
|
||||
const double tRPST = 0.5;
|
||||
|
||||
/* Minimum Self-Refresh Time. (Entry to Exit) */
|
||||
const double tSR = 15.0;
|
||||
|
||||
/* Exit power down to next valid command delay. */
|
||||
const double tXP = 7.5;
|
||||
|
||||
const double tDQSS_max = 1.25;
|
||||
const double tDQS2DQ_max = 0.8;
|
||||
|
||||
/* TOOD: Fix erista */
|
||||
namespace pcv::erista {
|
||||
/* tCK_avg may have to be improved... */
|
||||
const double tCK_avg = 1000'000.0 / C.eristaEmcMaxClock;
|
||||
|
||||
const u32 RL = 28 + latency_offset_read;
|
||||
const u32 WL = 14 + latency_offset_write;
|
||||
|
||||
/* Primary timings. */
|
||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||
@@ -76,33 +83,57 @@ namespace ams::ldr::oc {
|
||||
/* 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)((1.25 / tCK_avg) + 46 + (0.8 / tCK_avg) + 6);
|
||||
const int tRW2PDEN = (int)((tDQSS_max / tCK_avg) + 46 + (tDQS2DQ_max / tCK_avg) + 6);
|
||||
|
||||
/* Refresh Cycle time. (All Banks) */
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
|
||||
/* Do not touch stuff. */
|
||||
/* ACTIVATE-to-ACTIVATE command period. (same bank) */
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
|
||||
/* Minimum Self-Refresh Time. (Entry to Exit) */
|
||||
const double tSR = 15.0;
|
||||
/* SELF REFRESH exit to next valid command delay. */
|
||||
const double tXSR = (double) (tRFCab + 7.5);
|
||||
|
||||
/* Exit power down to next valid command delay. */
|
||||
const double tXP = 7.5; // I assume this is correct.
|
||||
|
||||
/* 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 double tRPab = tRPpb + 3;
|
||||
const u32 tRPab = tRPpb + 3;
|
||||
}
|
||||
|
||||
/* TODO. */
|
||||
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 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 RL = 36;
|
||||
const u32 WL = 18;
|
||||
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
const double tXSR = (double) (tRFCab + 7.5);
|
||||
const u32 tFAW = (u32) (tRRD * 4.0);
|
||||
const double tRPab = tRPpb + 3;
|
||||
|
||||
const double tR2P = 7.5; /* Tighten up? */
|
||||
const u32 tR2W = CEIL(RL + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST)); /* TODO */
|
||||
const u32 tRTM = RL + 9 + (tDQSCK_max / tCK_avg) + FLOOR(tRPST) + CEIL(7.5 / tCK_avg);
|
||||
const u32 tRATM = tRTM + CEIL(tR2P / tCK_avg) - (BL / 2);
|
||||
|
||||
/* Note: Dividing WL is probably incorect but it works out by pure chance :) */
|
||||
const u32 tW2P = WL + (BL / 2) + 1 + CEIL(WL / tCK_avg); /* Tighten? */
|
||||
const u32 tW2R = WL + (BL / 2) + 1 + CEIL(tWTR / tCK_avg);
|
||||
const u32 tWTM = WL + (BL / 2) + 1 + CEIL(7.5 / tCK_avg);
|
||||
const u32 tWATM = tWTM + CEIL(WL / tCK_avg);
|
||||
|
||||
const double tMMRI = tRCD + (tCK_avg * 3);
|
||||
const double tPDEX2MRR = tMMRI + 10;
|
||||
const u32 tWTPDEN = tW2P + 1 + CEIL(tDQSS_max / tCK_avg) + CEIL(tDQS2DQ_max / tCK_avg) + 6.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
namespace ams::ldr::oc::pcv
|
||||
{
|
||||
|
||||
namespace mariko
|
||||
{
|
||||
namespace mariko {
|
||||
constexpr cvb_entry_t CpuCvbTableDefault[] = {
|
||||
// CPUB01_CVB_TABLE
|
||||
{204000, {721589, -12695, 27}, {}},
|
||||
@@ -119,8 +118,7 @@ namespace ams::ldr::oc::pcv
|
||||
inline auto asm_set_imm16 = [](u32 ins, u16 imm)
|
||||
{ return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); };
|
||||
|
||||
inline bool GpuMaxClockPatternFn(u32 *ptr32)
|
||||
{
|
||||
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
|
||||
return asm_compare_no_rd(*ptr32, asm_pattern[0]);
|
||||
}
|
||||
|
||||
@@ -168,8 +166,7 @@ namespace ams::ldr::oc::pcv
|
||||
|
||||
}
|
||||
|
||||
namespace erista
|
||||
{
|
||||
namespace erista {
|
||||
constexpr cvb_entry_t CpuCvbTableDefault[] = {
|
||||
// CPU_PLL_CVB_TABLE_ODN
|
||||
{204000, {721094}, {}},
|
||||
@@ -199,8 +196,7 @@ namespace ams::ldr::oc::pcv
|
||||
|
||||
constexpr u16 CpuMinVolts[] = {950, 850, 825, 810};
|
||||
|
||||
inline bool CpuMaxVoltPatternFn(u32 *ptr32)
|
||||
{
|
||||
inline bool CpuMaxVoltPatternFn(u32 *ptr32) {
|
||||
u32 val = *ptr32;
|
||||
return (val == 1132 || val == 1170 || val == 1227);
|
||||
}
|
||||
@@ -229,8 +225,7 @@ namespace ams::ldr::oc::pcv
|
||||
inline auto asm_set_imm16 = [](u32 ins, u16 imm)
|
||||
{ return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); };
|
||||
|
||||
inline bool GpuMaxClockPatternFn(u32 *ptr32)
|
||||
{
|
||||
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
|
||||
return asm_compare_no_rd(*ptr32, asm_pattern[0]);
|
||||
}
|
||||
|
||||
@@ -260,8 +255,7 @@ namespace ams::ldr::oc::pcv
|
||||
}
|
||||
|
||||
template <bool isMariko>
|
||||
Result CpuFreqCvbTable(u32 *ptr)
|
||||
{
|
||||
Result CpuFreqCvbTable(u32 *ptr) {
|
||||
cvb_entry_t *default_table = isMariko ? (cvb_entry_t *)(&mariko::CpuCvbTableDefault) : (cvb_entry_t *)(&erista::CpuCvbTableDefault);
|
||||
cvb_entry_t *customize_table = nullptr; // impossible to reach, there will always be a way to set a pointer
|
||||
|
||||
@@ -284,12 +278,9 @@ namespace ams::ldr::oc::pcv
|
||||
}
|
||||
u32 cpu_max_volt = isMariko ? C.marikoCpuMaxVolt : C.eristaCpuMaxVolt;
|
||||
u32 cpu_freq_threshold = 1020'000;
|
||||
if (isMariko)
|
||||
{
|
||||
if (isMariko) {
|
||||
cpu_freq_threshold = C.marikoCpuUV ? 2193'000 : 2091'000;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cpu_freq_threshold = cpu_max_volt >= 1300 ? 1887'000 : 1428'000;
|
||||
}
|
||||
|
||||
@@ -307,19 +298,13 @@ namespace ams::ldr::oc::pcv
|
||||
std::memcpy(cpu_cvb_table_head, static_cast<void *>(customize_table), customize_table_size);
|
||||
|
||||
// Patch CPU max volt
|
||||
if (cpu_max_volt)
|
||||
{
|
||||
if (cpu_max_volt) {
|
||||
cvb_entry_t *entry = static_cast<cvb_entry_t *>(cpu_cvb_table_head);
|
||||
for (size_t i = 0; i < customize_entry_count; i++)
|
||||
{
|
||||
if (entry->freq >= cpu_freq_threshold)
|
||||
{
|
||||
if (isMariko)
|
||||
{
|
||||
for (size_t i = 0; i < customize_entry_count; i++) {
|
||||
if (entry->freq >= cpu_freq_threshold) {
|
||||
if (isMariko) {
|
||||
PATCH_OFFSET(&(entry->cvb_pll_param.c0), cpu_max_volt * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
PATCH_OFFSET(&(entry->cvb_dfll_param.c0), cpu_max_volt * 1000);
|
||||
}
|
||||
}
|
||||
@@ -331,14 +316,11 @@ namespace ams::ldr::oc::pcv
|
||||
}
|
||||
|
||||
template <bool isMariko>
|
||||
Result GpuFreqCvbTable(u32 *ptr)
|
||||
{
|
||||
Result GpuFreqCvbTable(u32 *ptr) {
|
||||
cvb_entry_t *default_table = isMariko ? (cvb_entry_t *)(&mariko::GpuCvbTableDefault) : (cvb_entry_t *)(&erista::GpuCvbTableDefault);
|
||||
cvb_entry_t *customize_table;
|
||||
if (isMariko)
|
||||
{
|
||||
switch (C.marikoGpuUV)
|
||||
{
|
||||
if (isMariko) {
|
||||
switch (C.marikoGpuUV) {
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
@@ -349,24 +331,18 @@ namespace ams::ldr::oc::pcv
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
|
||||
break;
|
||||
case 3:
|
||||
if(C.enableMarikoGpuUnsafeFreqs)
|
||||
{
|
||||
if(C.enableMarikoGpuUnsafeFreqs) {
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableUv3UnsafeFreqs);
|
||||
}
|
||||
else
|
||||
{
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
} else {
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (C.eristaGpuUV)
|
||||
{
|
||||
} else {
|
||||
switch (C.eristaGpuUV) {
|
||||
case 0:
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
break;
|
||||
@@ -377,13 +353,10 @@ namespace ams::ldr::oc::pcv
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHigh);
|
||||
break;
|
||||
case 3:
|
||||
if(C.enableEristaGpuUnsafeFreqs)
|
||||
{
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableUv3UnsafeFreqs);
|
||||
}
|
||||
else
|
||||
{
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
if(C.enableEristaGpuUnsafeFreqs) {
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableUv3UnsafeFreqs);
|
||||
} else {
|
||||
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -406,23 +379,16 @@ namespace ams::ldr::oc::pcv
|
||||
std::memcpy(gpu_cvb_table_head, (void *)customize_table, customize_table_size);
|
||||
|
||||
// Patch GPU volt
|
||||
if (C.marikoGpuUV == 3 || C.eristaGpuUV == 3)
|
||||
{
|
||||
if (C.marikoGpuUV == 3 || C.eristaGpuUV == 3) {
|
||||
cvb_entry_t *entry = static_cast<cvb_entry_t *>(gpu_cvb_table_head);
|
||||
for (size_t i = 0; i < customize_entry_count; i++)
|
||||
{
|
||||
if (isMariko)
|
||||
{
|
||||
if (C.marikoGpuVoltArray[i] == 0)
|
||||
{
|
||||
for (size_t i = 0; i < customize_entry_count; i++) {
|
||||
if (isMariko) {
|
||||
if (C.marikoGpuVoltArray[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
PATCH_OFFSET(&(entry->cvb_pll_param.c0), C.marikoGpuVoltArray[i] * 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (C.eristaGpuVoltArray[i] == 0)
|
||||
{
|
||||
} else {
|
||||
if (C.eristaGpuVoltArray[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
PATCH_OFFSET(&(entry->cvb_pll_param.c0), C.eristaGpuVoltArray[i] * 1000);
|
||||
@@ -434,12 +400,9 @@ namespace ams::ldr::oc::pcv
|
||||
PATCH_OFFSET(&(entry->cvb_pll_param.c5), 0);
|
||||
entry++;
|
||||
}
|
||||
}
|
||||
else if (C.commonGpuVoltOffset)
|
||||
{
|
||||
} else if (C.commonGpuVoltOffset) {
|
||||
cvb_entry_t *entry = static_cast<cvb_entry_t *>(gpu_cvb_table_head);
|
||||
for (size_t i = 0; i < customize_entry_count; i++)
|
||||
{
|
||||
for (size_t i = 0; i < customize_entry_count; i++) {
|
||||
PATCH_OFFSET(&(entry->cvb_pll_param.c0), (entry->cvb_pll_param.c0 - C.commonGpuVoltOffset * 1000));
|
||||
entry++;
|
||||
}
|
||||
@@ -452,21 +415,18 @@ namespace ams::ldr::oc::pcv
|
||||
Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2
|
||||
|
||||
template <typename T>
|
||||
Result MemMtcCustomizeTable(T *dst, T *src)
|
||||
{
|
||||
Result MemMtcCustomizeTable(T *dst, T *src) {
|
||||
constexpr u32 mtc_magic = std::is_same_v<T, MarikoMtcTable> ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC;
|
||||
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
|
||||
|
||||
constexpr u32 ZERO_VAL = UINT32_MAX;
|
||||
// Skip params from dvfs_ver to clock_src;
|
||||
for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32))
|
||||
{
|
||||
for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) {
|
||||
u32 *src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
|
||||
u32 *dst_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(dst) + offset);
|
||||
u32 src_val = *src_ent;
|
||||
|
||||
if (src_val)
|
||||
{
|
||||
if (src_val){
|
||||
PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,47 +21,38 @@
|
||||
#include "pcv.hpp"
|
||||
#include "../mtc_timing_value.hpp"
|
||||
|
||||
namespace ams::ldr::oc::pcv::mariko
|
||||
{
|
||||
namespace ams::ldr::oc::pcv::mariko {
|
||||
|
||||
Result GpuVmin(u32 *ptr)
|
||||
{
|
||||
Result GpuVmin(u32 *ptr) {
|
||||
if (!C.marikoGpuVmin)
|
||||
R_SKIP();
|
||||
PATCH_OFFSET(ptr, (int)C.marikoGpuVmin);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GpuVmax(u32 *ptr)
|
||||
{
|
||||
Result GpuVmax(u32 *ptr) {
|
||||
if (!C.marikoGpuVmax)
|
||||
R_SKIP();
|
||||
PATCH_OFFSET(ptr, (int)C.marikoGpuVmax);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CpuFreqVdd(u32 *ptr)
|
||||
{
|
||||
Result CpuFreqVdd(u32 *ptr) {
|
||||
dvfs_rail *entry = reinterpret_cast<dvfs_rail *>(reinterpret_cast<u8 *>(ptr) - offsetof(dvfs_rail, freq));
|
||||
|
||||
R_UNLESS(entry->id == 1, ldr::ResultInvalidCpuFreqVddEntry());
|
||||
R_UNLESS(entry->min_mv == 250'000, ldr::ResultInvalidCpuFreqVddEntry());
|
||||
R_UNLESS(entry->step_mv == 5000, ldr::ResultInvalidCpuFreqVddEntry());
|
||||
R_UNLESS(entry->max_mv == 1525'000, ldr::ResultInvalidCpuFreqVddEntry());
|
||||
if (C.enableMarikoCpuUnsafeFreqs)
|
||||
{
|
||||
if (C.enableMarikoCpuUnsafeFreqs) {
|
||||
PATCH_OFFSET(ptr, GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (C.marikoCpuUV)
|
||||
{
|
||||
if (!C.enableMarikoCpuUnsafeFreqs)
|
||||
{
|
||||
else {
|
||||
if (C.marikoCpuUV) {
|
||||
if (!C.enableMarikoCpuUnsafeFreqs) {
|
||||
PATCH_OFFSET(ptr, GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
PATCH_OFFSET(ptr, GetDvfsTableLastEntry(C.marikoCpuDvfsTableUnsafeFreqs)->freq);
|
||||
}
|
||||
}
|
||||
@@ -69,11 +60,9 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CpuVoltRange(u32 *ptr)
|
||||
{
|
||||
Result CpuVoltRange(u32 *ptr) {
|
||||
u32 min_volt_got = *(ptr - 1);
|
||||
for (const auto &mv : CpuMinVolts)
|
||||
{
|
||||
for (const auto &mv : CpuMinVolts) {
|
||||
if (min_volt_got != mv)
|
||||
continue;
|
||||
|
||||
@@ -82,14 +71,11 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
|
||||
PATCH_OFFSET(ptr, C.marikoCpuMaxVolt);
|
||||
// Patch vmin for slt
|
||||
if (C.marikoCpuUV)
|
||||
{
|
||||
if (*(ptr - 5) == 620)
|
||||
{
|
||||
if (C.marikoCpuUV) {
|
||||
if (*(ptr - 5) == 620) {
|
||||
PATCH_OFFSET((ptr - 5), C.marikoCpuVmin);
|
||||
}
|
||||
if (*(ptr - 1) == 620)
|
||||
{
|
||||
if (*(ptr - 1) == 620) {
|
||||
PATCH_OFFSET((ptr - 1), 600);
|
||||
}
|
||||
}
|
||||
@@ -98,16 +84,14 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||
}
|
||||
|
||||
Result CpuVoltDfll(u32 *ptr)
|
||||
{
|
||||
Result CpuVoltDfll(u32 *ptr) {
|
||||
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
|
||||
|
||||
R_UNLESS(entry->tune0_low == 0x0000FFCF, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||
R_UNLESS(entry->tune0_high == 0x00000000, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||
R_UNLESS(entry->tune1_low == 0x012207FF, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||
R_UNLESS(entry->tune1_high == 0x03FFF7FF, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||
switch (C.marikoCpuUV)
|
||||
{
|
||||
switch (C.marikoCpuUV) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
@@ -164,8 +148,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GpuFreqMaxAsm(u32 *ptr32)
|
||||
{
|
||||
Result GpuFreqMaxAsm(u32 *ptr32) {
|
||||
// Check if both two instructions match the pattern
|
||||
u32 ins1 = *ptr32, ins2 = *(ptr32 + 1);
|
||||
if (!(asm_compare_no_rd(ins1, asm_pattern[0]) && asm_compare_no_rd(ins2, asm_pattern[1])))
|
||||
@@ -177,8 +160,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
|
||||
|
||||
u32 max_clock;
|
||||
switch (C.marikoGpuUV)
|
||||
{
|
||||
switch (C.marikoGpuUV) {
|
||||
case 0:
|
||||
max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq;
|
||||
break;
|
||||
@@ -189,12 +171,10 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq;
|
||||
break;
|
||||
case 3:
|
||||
if (C.enableMarikoGpuUnsafeFreqs)
|
||||
{
|
||||
if (C.enableMarikoGpuUnsafeFreqs) {
|
||||
max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTableUv3UnsafeFreqs)->freq;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
max_clock = GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq;
|
||||
}
|
||||
break;
|
||||
@@ -204,20 +184,20 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
}
|
||||
u32 asm_patch[2] = {
|
||||
asm_set_rd(asm_set_imm16(asm_pattern[0], max_clock), rd),
|
||||
asm_set_rd(asm_set_imm16(asm_pattern[1], max_clock >> 16), rd)};
|
||||
asm_set_rd(asm_set_imm16(asm_pattern[1], max_clock >> 16), rd)
|
||||
};
|
||||
|
||||
PATCH_OFFSET(ptr32, asm_patch[0]);
|
||||
PATCH_OFFSET(ptr32 + 1, asm_patch[1]);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GpuFreqPllLimit(u32 *ptr)
|
||||
{
|
||||
Result GpuFreqPllLimit(u32 *ptr) {
|
||||
clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||
|
||||
// All zero except for freq
|
||||
for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++)
|
||||
{
|
||||
for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++) {
|
||||
R_UNLESS(*(ptr + i) == 0, ldr::ResultInvalidGpuPllEntry());
|
||||
}
|
||||
|
||||
@@ -227,183 +207,193 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* Get RAM vendor data, ty b0rd2death! */
|
||||
/* Note: I know this is horrible but I don't care atm. */
|
||||
bool IsMicron()
|
||||
{
|
||||
u64 packed_version;
|
||||
splGetConfig((SplConfigItem)2, &packed_version);
|
||||
|
||||
switch (packed_version)
|
||||
{
|
||||
case 11:
|
||||
case 15:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
/* RAM is Micron. */
|
||||
return true;
|
||||
default:
|
||||
/* Not Micron. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MemMtcTableAutoAdjustBaseLatency(MarikoMtcTable *table) {
|
||||
#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;
|
||||
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg, 0xf3200000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rc, 0x00000070);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rfc, 0x0000020b);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ras, 0x0000004f);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rp, 0x00000022);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2w, 0x0000002e);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2r, 0x00000025);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2p, 0x0000000e);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2p, 0x00000033);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, 0x00000022);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, 0x00000022);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rrd, 0x00000013);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rext, 0x0000001a);
|
||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||
|
||||
WRITE_PARAM_ALL_REG(table, emc_qsafe, 0x00000038);
|
||||
WRITE_PARAM_ALL_REG(table, emc_refresh, 0x00001c2d);
|
||||
WRITE_PARAM_ALL_REG(table, emc_burst_refresh_num, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, 0x00000013);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, 0x00000013);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, 0x00000004);
|
||||
WRITE_PARAM_ALL_REG(table, emc_act2pden, 0x0000001b);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ar2pden, 0x00000004);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rw2pden, 0x0000003f);
|
||||
WRITE_PARAM_ALL_REG(table, emc_txsr, 0x00000219);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tcke, 0x00000010);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tfaw, 0x0000004b);
|
||||
WRITE_PARAM_ALL_REG(table, emc_trpab, 0x00000028);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tclkstable, 0x00000004);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tclkstop, 0x00000017);
|
||||
WRITE_PARAM_ALL_REG(table, emc_trefbw, 0x00001c6d);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tppd, 0x00000004);
|
||||
WRITE_PARAM_ALL_REG(table, emc_odt_write, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, 0x00000037);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wext, 0x00000016);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rfc_slr, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt2, 0x01d3001b);
|
||||
WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt, 0x074a0034);
|
||||
table->emc_mrs = 0x00000000;
|
||||
table->emc_emrs = 0x00000000;
|
||||
table->emc_mrw = 0x00170040;
|
||||
WRITE_PARAM_ALL_REG(table, emc_fbio_spare, 0x00000012);
|
||||
WRITE_PARAM_ALL_REG(table, emc_fbio_cfg5, 0x9160a00d);
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, 0x00000002);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cke2pden, 0x00000010);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2r, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_einput, 0x00000015);
|
||||
WRITE_PARAM_ALL_REG(table, emc_einput_duration, 0x00000020);
|
||||
WRITE_PARAM_ALL_REG(table, emc_puterm_extra, 0x00000001);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tckesr, 0x0000001c);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tpd, 0x0000000e);
|
||||
table->emc_cfg_2 = 0x0011083d;
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll, 0x002c03a9);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll_period, 0x00008000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_mask, 0x00000040);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wdv_mask, 0x00000010);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, 0x0000003e);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_early, 0x0000003c);
|
||||
WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_dq, 0x8020221f);
|
||||
WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_cmd, 0x0220f40f);
|
||||
table->emc_sel_dpd_ctrl = 0x0004000c;
|
||||
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, 0x0000070b);
|
||||
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, 0x80003873);
|
||||
WRITE_PARAM_ALL_REG(table, emc_txsrdll, 0x00000219);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ibdly, 0x1000001f);
|
||||
WRITE_PARAM_ALL_REG(table, emc_obdly, 0x10000004);
|
||||
WRITE_PARAM_ALL_REG(table, emc_txdsrvttgen, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_we_duration, 0x0000000e);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ws_duration, 0x00000008);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wev, 0x0000000c);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_3, 0x00000040);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wdv_chk, 0x00000006);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_2, 0x00000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_1, 0x0fff0000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg_pipe, 0x0fff0000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_quse_width, 0x00000009);
|
||||
WRITE_PARAM_ALL_REG(table, emc_puterm_width, 0x80000000);
|
||||
WRITE_PARAM_ALL_REG(table, emc_fbio_cfg7, 0x00003bff);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rfcpb, 0x00000106);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ccdmw, 0x00000020);
|
||||
WRITE_PARAM_ALL_REG(table, emc_config_sample_delay, 0x00000020);
|
||||
table->dram_timings.t_rp = 0x00000106;
|
||||
table->dram_timings.t_rfc = 0x0000020b;
|
||||
if (C.hpMode) {
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000);
|
||||
} else {
|
||||
WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000);
|
||||
}
|
||||
|
||||
table->dram_timings.rl = 32; /* */
|
||||
WRITE_PARAM_ALL_REG(table, emc_wdv, 0x00000010); /* */
|
||||
WRITE_PARAM_ALL_REG(table, emc_quse, 0x00000028); /* */
|
||||
WRITE_PARAM_ALL_REG(table, emc_qrst, 0x0007000c); /* These timings cause issues and I have no idea why. */
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv, 0x0000003e); /* */
|
||||
WRITE_PARAM_ALL_REG(table, emc_wsv, 0x0000000e); /* */
|
||||
WRITE_PARAM_ALL_REG(table, emc_qpop, 0x00000030); /* */
|
||||
u32 refresh_raw = 0xFFFF;
|
||||
if (C.t8_tREFI != 6) {
|
||||
refresh_raw = std::floor(tREFpb_values[C.t8_tREFI] / tCK_avg) - 0x40;
|
||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||
}
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = 0x0000000E;
|
||||
table->burst_mc_regs.mc_emem_arb_outstanding_req = 0x80000080;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = 0x00000007;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rp = 0x00000008;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rc = 0x0000001C;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_ras = 0x00000012;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_faw = 0x00000012;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rrd = 0x00000004;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = 0x00000004;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = 0x0000000F;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_r2r = 0x00000001;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_w2w = 0x00000001;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_r2w = 0x0000000D;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_w2r = 0x0000000B;
|
||||
table->burst_mc_regs.mc_emem_arb_da_turns = 0x05060000;
|
||||
table->burst_mc_regs.mc_emem_arb_da_covers = 0x000F0A0E;
|
||||
table->burst_mc_regs.mc_emem_arb_misc0 = 0x726E2A1D;
|
||||
table->burst_mc_regs.mc_emem_arb_misc1 = 0x70000F0F;
|
||||
table->burst_mc_regs.mc_emem_arb_misc2 = 0x00000000;
|
||||
table->burst_mc_regs.mc_emem_arb_ring1_throttle = 0x001F0000;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = 0x00000041;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_ccdmw = 0x00000008;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_ctrl = 0x00000002;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_0 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_1 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_2 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_3 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_4 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_5 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_6 = 0x0000001A;
|
||||
table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_7 = 0x0000001A;
|
||||
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x000000F2;
|
||||
table->la_scale_regs.mc_ftop_ptsa_rate = 0x0000001B;
|
||||
table->la_scale_regs.mc_ptsa_grant_decrement = 0x00001501;
|
||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = 0x006D0004;
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = 0x006D0005;
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = 0x006D0014;
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_0 = 0x0000002C;
|
||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = 0x006D006D;
|
||||
table->la_scale_regs.mc_latency_allowance_vic_0 = 0x006D0019;
|
||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = 0x006D0095;
|
||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = 0x006D0041;
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = 0x006D0080;
|
||||
table->la_scale_regs.mc_latency_allowance_xusb_0 = 0x006D003D;
|
||||
table->la_scale_regs.mc_latency_allowance_ppcs_0 = 0x00340049;
|
||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = 0x006D0016;
|
||||
table->la_scale_regs.mc_latency_allowance_hc_1 = 0x0000006D;
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = 0x006D0090;
|
||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = 0x006D0004;
|
||||
table->la_scale_regs.mc_latency_allowance_vi2_0 = 0x0000006D;
|
||||
table->la_scale_regs.mc_latency_allowance_hc_0 = 0x00080013;
|
||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = 0x006D0016;
|
||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = 0x006D0005;
|
||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = 0x006D0018;
|
||||
u32 trefbw = refresh_raw + 0x40;
|
||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||
|
||||
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, GET_CYCLE_CEIL(tRC));
|
||||
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb));
|
||||
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
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_tckesr, GET_CYCLE_CEIL(tSR));
|
||||
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tXP) + 1);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP));
|
||||
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8);
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tR2P));
|
||||
WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W);
|
||||
WRITE_PARAM_ALL_REG(table, emc_trtm, tRTM);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tratm, tRATM);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2p, tW2P);
|
||||
WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R);
|
||||
WRITE_PARAM_ALL_REG(table, emc_twtm, tWTM);
|
||||
WRITE_PARAM_ALL_REG(table, emc_twatm, tWATM);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rext, 26);
|
||||
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);
|
||||
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_pdex2wr, GET_CYCLE_CEIL(10.0));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(10.0));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.75));
|
||||
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75));
|
||||
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0));
|
||||
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(5.0));
|
||||
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
|
||||
WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN);
|
||||
WRITE_PARAM_ALL_REG(table, emc_einput, 0xF);
|
||||
WRITE_PARAM_ALL_REG(table, emc_einput_duration, 0x31);
|
||||
WRITE_PARAM_ALL_REG(table, emc_obdly, 0x10000002);
|
||||
WRITE_PARAM_ALL_REG(table, emc_ibdly, 0x1000001C);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wdv_mask, 0x12);
|
||||
WRITE_PARAM_ALL_REG(table, emc_quse_width, 0xD);
|
||||
WRITE_PARAM_ALL_REG(table, emc_quse, 0x2F);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wdv, 0x12);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wsv, 0x10);
|
||||
WRITE_PARAM_ALL_REG(table, emc_wev, 0xE);
|
||||
WRITE_PARAM_ALL_REG(table, emc_qrst, 0x00080005);
|
||||
WRITE_PARAM_ALL_REG(table, emc_qsafe, 0x44);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tr_qpop, 0x3B);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv, 0x49);
|
||||
WRITE_PARAM_ALL_REG(table, emc_qpop, 0x3B);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tr_rdv_mask, 0x4B);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_early, 0x47);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, 0x49);
|
||||
WRITE_PARAM_ALL_REG(table, emc_rdv_mask, 0x4B);
|
||||
WRITE_PARAM_ALL_REG(table, emc_tr_rdv, 0x49);
|
||||
|
||||
constexpr u32 MC_ARB_DIV = 4;
|
||||
constexpr u32 MC_ARB_SFA = 2;
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_cfg = C.marikoEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = (u32) (GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rp = (u32) (GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rc = (u32) (GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_ras = (u32) (GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_faw = (u32) (GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rrd = (u32) (GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = (u32) (GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
|
||||
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = (u32) (GET_CYCLE_CEIL(tR2P) / MC_ARB_DIV);
|
||||
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = (u32) (tW2P / MC_ARB_DIV);
|
||||
table->burst_mc_regs.mc_emem_arb_timing_r2r = (u32) (table->burst_regs.emc_rext / 4) - 1 + MC_ARB_SFA;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_r2w = (u32) (tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
|
||||
table->burst_mc_regs.mc_emem_arb_timing_w2r = (u32) (tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
|
||||
|
||||
u32 da_turns = 0;
|
||||
da_turns |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16;
|
||||
da_turns |= u8(table->burst_mc_regs.mc_emem_arb_timing_w2r / 2) << 24;
|
||||
table->burst_mc_regs.mc_emem_arb_da_turns = da_turns;
|
||||
|
||||
u32 da_covers = 0;
|
||||
u8 r_cover = (table->burst_mc_regs.mc_emem_arb_timing_rap2pre + table->burst_mc_regs.mc_emem_arb_timing_rp + table->burst_mc_regs.mc_emem_arb_timing_rcd) / 2;
|
||||
u8 w_cover = (table->burst_mc_regs.mc_emem_arb_timing_wap2pre + table->burst_mc_regs.mc_emem_arb_timing_rp + table->burst_mc_regs.mc_emem_arb_timing_rcd) / 2;
|
||||
da_covers |= (u8) (table->burst_mc_regs.mc_emem_arb_timing_rc / 2);
|
||||
da_covers |= (r_cover << 8);
|
||||
da_covers |= (w_cover << 16);
|
||||
table->burst_mc_regs.mc_emem_arb_da_covers = da_covers;
|
||||
|
||||
table->burst_mc_regs.mc_emem_arb_misc0 &= 0xFFE08000U;
|
||||
table->burst_mc_regs.mc_emem_arb_misc0 |= ((table->burst_mc_regs.mc_emem_arb_timing_rc + 1) & 0xFF); /* TODO, check this */
|
||||
|
||||
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->pllm_ss_ctrl1 = 0xb55fe01;
|
||||
table->pllm_ss_ctrl2 = 0x10170b55;
|
||||
table->pllmb_ss_ctrl1 = 0xb55fe01;
|
||||
table->pllmb_ss_ctrl2 = 0x10170b55;
|
||||
|
||||
table->dram_timings.t_rp = tRFCpb;
|
||||
table->dram_timings.t_rfc = tRFCab;
|
||||
table->dram_timings.rl = RL - 10;
|
||||
table->emc_mrw2 = 0x8802003F;
|
||||
table->emc_cfg_2 = 0x11083D;
|
||||
}
|
||||
|
||||
void MemMtcTableAutoAdjust(MarikoMtcTable *table) {
|
||||
@@ -429,7 +419,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
||||
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
||||
|
||||
#define GET_CYCLE(PARAM) ((u32)((double)(PARAM) / tCK_avg))
|
||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||
|
||||
WRITE_PARAM_ALL_REG(table, emc_rc, 0x60);
|
||||
// WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
|
||||
@@ -483,28 +473,25 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
// WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rfcpb, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV))
|
||||
}
|
||||
|
||||
void MemMtcPllmbDivisor(MarikoMtcTable *table)
|
||||
{
|
||||
void MemMtcPllmbDivisor(MarikoMtcTable *table) {
|
||||
// Calculate DIVM and DIVN (clock divisors)
|
||||
// Common PLL oscillator is 38.4 MHz
|
||||
// PLLMB_OUT = 38.4 MHz / PLLLMB_DIVM * PLLMB_DIVN
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
u8 numerator : 4;
|
||||
u8 denominator : 4;
|
||||
} pllmb_div;
|
||||
|
||||
constexpr pllmb_div div[] = {
|
||||
{3, 4}, {2, 3}, {1, 2}, {1, 3}, {1, 4}, {0, 2}};
|
||||
{3, 4}, {2, 3}, {1, 2}, {1, 3}, {1, 4}, {0, 2}
|
||||
};
|
||||
|
||||
constexpr u32 pll_osc_in = 38'400;
|
||||
u32 divm{}, divn{};
|
||||
const u32 remainder = C.marikoEmcMaxClock % pll_osc_in;
|
||||
for (const auto &index : div)
|
||||
{
|
||||
for (const auto &index : div) {
|
||||
// Round down
|
||||
if (remainder >= pll_osc_in * index.numerator / index.denominator)
|
||||
{
|
||||
if (remainder >= pll_osc_in * index.numerator / index.denominator) {
|
||||
divm = index.denominator;
|
||||
divn = C.marikoEmcMaxClock / pll_osc_in * divm + index.numerator;
|
||||
break;
|
||||
@@ -515,15 +502,13 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
table->pllmb_divn = divn;
|
||||
}
|
||||
|
||||
Result MemFreqMtcTable(u32 *ptr)
|
||||
{
|
||||
Result MemFreqMtcTable(u32 *ptr) {
|
||||
u32 khz_list[] = {1600000, 1331200, 204000};
|
||||
u32 khz_list_size = sizeof(khz_list) / sizeof(u32);
|
||||
|
||||
// Generate list for mtc table pointers
|
||||
MarikoMtcTable *table_list[khz_list_size];
|
||||
for (u32 i = 0; i < khz_list_size; i++)
|
||||
{
|
||||
for (u32 i = 0; i < khz_list_size; i++) {
|
||||
u8 *table = reinterpret_cast<u8 *>(ptr) - offsetof(MarikoMtcTable, rate_khz) - i * sizeof(MarikoMtcTable);
|
||||
table_list[i] = reinterpret_cast<MarikoMtcTable *>(table);
|
||||
R_UNLESS(table_list[i]->rate_khz == khz_list[i], ldr::ResultInvalidMtcTable());
|
||||
@@ -546,6 +531,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
} else {
|
||||
MemMtcTableAutoAdjustBaseLatency(table_max);
|
||||
}
|
||||
|
||||
MemMtcPllmbDivisor(table_max);
|
||||
// Overwrite 13312000 table with unmodified 1600000 table copied back
|
||||
std::memcpy(reinterpret_cast<void *>(table_alt), reinterpret_cast<void *>(tmp), sizeof(MarikoMtcTable));
|
||||
@@ -553,17 +539,10 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
delete tmp;
|
||||
|
||||
PATCH_OFFSET(ptr, C.marikoEmcMaxClock);
|
||||
|
||||
// Handle customize table replacement
|
||||
// if (C.mtcConf == CUSTOMIZED_ALL) {
|
||||
// MemMtcCustomizeTable(table_list[0], reinterpret_cast<MarikoMtcTable *>(reinterpret_cast<u8 *>(C.marikoMtcTable)));
|
||||
// }
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemFreqDvbTable(u32 *ptr)
|
||||
{
|
||||
Result MemFreqDvbTable(u32 *ptr) {
|
||||
emc_dvb_dvfs_table_t *default_end = reinterpret_cast<emc_dvb_dvfs_table_t *>(ptr);
|
||||
emc_dvb_dvfs_table_t *new_start = default_end + 1;
|
||||
|
||||
@@ -579,45 +558,25 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
|
||||
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
|
||||
|
||||
if (C.marikoEmcMaxClock < 1862400)
|
||||
{
|
||||
if (C.marikoEmcMaxClock < 1862400) {
|
||||
std::memcpy(new_start, default_end, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2131200)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {1862400, {
|
||||
700,
|
||||
675,
|
||||
650,
|
||||
}};
|
||||
} else if (C.marikoEmcMaxClock < 2131200) {
|
||||
emc_dvb_dvfs_table_t oc_table = {1862400, {700, 675, 650, }};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2400000)
|
||||
{
|
||||
emc_dvb_dvfs_table_t oc_table = {2131200, {
|
||||
725,
|
||||
700,
|
||||
675,
|
||||
}};
|
||||
} else if (C.marikoEmcMaxClock < 2400000) {
|
||||
emc_dvb_dvfs_table_t oc_table = {2131200, { 725, 700, 675} };
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2665600)
|
||||
{
|
||||
} else if (C.marikoEmcMaxClock < 2665600) {
|
||||
emc_dvb_dvfs_table_t oc_table = {2400000, {DVB_VOLT(750, 725, 700)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 2931200)
|
||||
{
|
||||
} else if (C.marikoEmcMaxClock < 2931200) {
|
||||
emc_dvb_dvfs_table_t oc_table = {2665600, {DVB_VOLT(775, 750, 725)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else if (C.marikoEmcMaxClock < 3200000)
|
||||
{
|
||||
else if (C.marikoEmcMaxClock < 3200000) {
|
||||
emc_dvb_dvfs_table_t oc_table = {2931200, {DVB_VOLT(800, 775, 750)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
emc_dvb_dvfs_table_t oc_table = {3200000, {DVB_VOLT(800, 800, 775)}};
|
||||
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t));
|
||||
}
|
||||
@@ -629,8 +588,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemFreqMax(u32 *ptr)
|
||||
{
|
||||
Result MemFreqMax(u32 *ptr) {
|
||||
if (C.marikoEmcMaxClock <= EmcClkOSLimit)
|
||||
R_SKIP();
|
||||
|
||||
@@ -638,10 +596,8 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val)
|
||||
{
|
||||
struct
|
||||
{
|
||||
Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val) {
|
||||
struct {
|
||||
u8 reg;
|
||||
u8 val;
|
||||
} __attribute__((packed)) cmd;
|
||||
@@ -658,15 +614,13 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
return res;
|
||||
}
|
||||
|
||||
Result EmcVddqVolt(u32 *ptr)
|
||||
{
|
||||
Result EmcVddqVolt(u32 *ptr) {
|
||||
regulator *entry = reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_2_3.default_uv));
|
||||
|
||||
constexpr u32 uv_step = 5'000;
|
||||
constexpr u32 uv_min = 250'000;
|
||||
|
||||
auto validator = [entry]()
|
||||
{
|
||||
auto validator = [entry]() {
|
||||
R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type == 3, ldr::ResultInvalidRegulatorEntry());
|
||||
R_UNLESS(entry->type_2_3.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
|
||||
@@ -692,8 +646,7 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size)
|
||||
{
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
|
||||
u32 GpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq);
|
||||
|
||||
@@ -715,23 +668,20 @@ namespace ams::ldr::oc::pcv::mariko
|
||||
{"GPU Vmax", &GpuVmax, 0, nullptr, gpuVmax},
|
||||
};
|
||||
|
||||
for (uintptr_t ptr = mapped_nso;
|
||||
ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable);
|
||||
ptr += sizeof(u32))
|
||||
{
|
||||
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable); ptr += sizeof(u32)) {
|
||||
u32 *ptr32 = reinterpret_cast<u32 *>(ptr);
|
||||
for (auto &entry : patches)
|
||||
{
|
||||
if (R_SUCCEEDED(entry.SearchAndApply(ptr32)))
|
||||
for (auto &entry : patches) {
|
||||
if (R_SUCCEEDED(entry.SearchAndApply(ptr32))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &entry : patches)
|
||||
{
|
||||
for (auto &entry : patches) {
|
||||
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
|
||||
if (R_FAILED(entry.CheckResult()))
|
||||
if (R_FAILED(entry.CheckResult())) {
|
||||
CRASH(entry.description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user