fix freq list generation and dvb

This commit is contained in:
Lightos1
2026-04-17 16:36:12 +02:00
parent 51f935c252
commit 119f49a3a4
5 changed files with 86 additions and 50 deletions

View File

@@ -31,6 +31,7 @@
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
volatile CustomizeTable C = { volatile CustomizeTable C = {
/* Disables RAM powerdown */ /* Disables RAM powerdown */
.hpMode = DISABLED, .hpMode = DISABLED,
@@ -39,8 +40,12 @@ volatile CustomizeTable C = {
.eristaEmcMaxClock1 = 1600000, .eristaEmcMaxClock1 = 1600000,
.eristaEmcMaxClock2 = 1600000, .eristaEmcMaxClock2 = 1600000,
.marikoEmcMaxClock = 1633000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ /* Available: 66MHz step rate, 100MHz step rate and jedec. */
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */ /* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
.stepMode = StepMode_66MHz,
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000,
.emcDvbShift = 0, .emcDvbShift = 0,
// Primary // Primary

View File

@@ -36,6 +36,12 @@ enum TableConfig: u32 {
EXTREME_TABLE = 4, EXTREME_TABLE = 4,
}; };
enum StepMode:u32 {
StepMode_66MHz = 0,
StepMode_100MHz = 1,
StepMode_Jedec = 2,
};
/* /*
* Read: * Read:
* 2133RL = 40 * 2133RL = 40
@@ -82,6 +88,8 @@ typedef struct CustomizeTable {
u32 eristaEmcMaxClock; u32 eristaEmcMaxClock;
u32 eristaEmcMaxClock1; u32 eristaEmcMaxClock1;
u32 eristaEmcMaxClock2; u32 eristaEmcMaxClock2;
StepMode stepMode;
u32 marikoEmcMaxClock; u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt; u32 marikoEmcVddqVolt;
u32 emcDvbShift; u32 emcDvbShift;

View File

@@ -46,11 +46,6 @@ namespace ams::ldr::hoc::pcv {
unsigned long dvco_calibration_max; unsigned long dvco_calibration_max;
} cvb_cpu_dfll_data; } cvb_cpu_dfll_data;
typedef struct emc_dvb_dvfs_table_t {
u64 freq;
s32 volt[4] = {0};
} emc_dvb_dvfs_table_t;
typedef struct __attribute__((packed)) div_nmp { typedef struct __attribute__((packed)) div_nmp {
u8 divn_shift; u8 divn_shift;
u8 divn_width; u8 divn_width;

View File

@@ -500,11 +500,11 @@ namespace ams::ldr::hoc::pcv::mariko {
constexpr u32 Mask2 = 0xFFFFFF00; constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00; constexpr u32 Mask3 = 0xFF00FF00;
const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 1000)) & 0xFF;
const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 1000)) & 0xFF;
const u32 allowance3 = static_cast<u32>(0xB540 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance3 = static_cast<u32>(0xB540 / (table->rate_khz / 1000)) & 0xFF;
const u32 allowance4 = static_cast<u32>(0x9600 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance4 = static_cast<u32>(0x9600 / (table->rate_khz / 1000)) & 0xFF;
const u32 allowance5 = static_cast<u32>(0x8980 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance5 = static_cast<u32>(0x8980 / (table->rate_khz / 1000)) & 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_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); table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
@@ -645,19 +645,31 @@ namespace ams::ldr::hoc::pcv::mariko {
/* Clear all other tables */ /* Clear all other tables */
/* 1 erista table is excluded because it's always before firstTable. */ /* 1 erista table is excluded because it's always before firstTable. */
/* We also exclude the used table obviously. */ /* We also exclude the used table obviously. */
constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * 16 + (erista::MtcFullTableSize * 2); constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * (mariko::MtcFullTableCount - 1) + (erista::MtcFullTableSize * (erista::MtcFullTableCount - 1));
memset(firstTable + mariko::MtcFullTableSize, 0, RemainingRegionSize); memset(firstTable + mariko::MtcFullTableSize, 0, RemainingRegionSize);
} }
std::vector<u32> newEmcList; std::vector<u32> newEmcList;
void MtcGenerateFreqTables() { void MtcGenerateFreqTables() {
constexpr u32 OverwrittenEristaTables = erista::MtcFullTableCount - 1; /* We don't overwrite the first table */ constexpr u32 RoundHz = 1000;
constexpr size_t MaxFreqSize = (OverwrittenEristaTables * erista::MtcTableCountDefault) + (mariko::MtcFullTableCount * mariko::MtcTableCountDefault);
constexpr u32 StepHz = 100000; u32 stepRate = 0;
constexpr u32 RoundHz = 1000; switch (C.stepMode) {
case StepMode_66MHz:
stepRate = 66667;
break;
case StepMode_100MHz:
stepRate = 100000;
break;
case StepMode_Jedec:
break;
default:
stepRate = 66667;
break;
}
newEmcList.clear(); newEmcList.clear();
newEmcList.reserve(MaxFreqSize); newEmcList.reserve(DvfsTableEntryCount);
newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault)); newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault));
if (C.marikoEmcMaxClock <= EmcClkOSLimit) { if (C.marikoEmcMaxClock <= EmcClkOSLimit) {
@@ -665,17 +677,27 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
for (u32 stepIndex = 1;; ++stepIndex) { for (u32 stepIndex = 1;; ++stepIndex) {
u32 newFreq = EmcClkOSLimit + (stepIndex * StepHz + 1) / 3; u32 newFreq = EmcClkOSLimit + stepIndex * stepRate;
newFreq = (newFreq / RoundHz) * RoundHz; newFreq = (newFreq / RoundHz) * RoundHz;
if (newFreq > C.marikoEmcMaxClock) { if (newFreq > C.marikoEmcMaxClock) {
if (newEmcList.back() != C.marikoEmcMaxClock) {
newEmcList.push_back(static_cast<u32>(C.marikoEmcMaxClock));
}
break; break;
} }
newEmcList.push_back(newFreq); newEmcList.push_back(newFreq);
} }
newEmcList.resize(std::min(newEmcList.size(), MaxFreqSize)); Log("Size = %u\n", newEmcList.size());
for (u32 i = 0; i < newEmcList.size(); ++i) {
Log("Freq: %u\n", newEmcList[i]);
}
Log("C.marikoEmcMaxClock: %u", C.marikoEmcMaxClock);
/* TODO: Test */
//ViewLog();
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryCount));
} }
void MtcExtendTables(MarikoMtcTable *table) { void MtcExtendTables(MarikoMtcTable *table) {
@@ -700,7 +722,7 @@ namespace ams::ldr::hoc::pcv::mariko {
static const MtcTableIndex mtcIndex = [] { static const MtcTableIndex mtcIndex = [] {
MtcTableIndex idx = GetMtcDramIndex(dramId); MtcTableIndex idx = GetMtcDramIndex(dramId);
/* If for some reason this happens, there is chance of recovering this. */ /* If for some reason this happens, there is no chance of recovering this. */
if (idx == MtcTableIndex_Invalid) { if (idx == MtcTableIndex_Invalid) {
AbortInvalidDramId(); AbortInvalidDramId();
} }
@@ -742,8 +764,8 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
Result MemFreqDvbTable(u32 *ptr) { Result MemFreqDvbTable(u32 *ptr) {
emc_dvb_dvfs_table_t *default_end = reinterpret_cast<emc_dvb_dvfs_table_t *>(ptr); DvbEntry *default_end = reinterpret_cast<DvbEntry *>(ptr);
emc_dvb_dvfs_table_t *new_start = default_end + 1; DvbEntry *new_start = default_end + 1;
// Validate existing table // Validate existing table
void *mem_dvb_table_head = reinterpret_cast<u8 *>(new_start) - sizeof(EmcDvbTableDefault); void *mem_dvb_table_head = reinterpret_cast<u8 *>(new_start) - sizeof(EmcDvbTableDefault);
@@ -754,33 +776,34 @@ namespace ams::ldr::hoc::pcv::mariko {
R_SKIP(); R_SKIP();
} }
int32_t voltAdd = 25 * C.emcDvbShift; s32 voltAdd = 25 * C.emcDvbShift;
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000), #define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
DvbEntry emcDvbTableNew[] = {
{ 204000, { 637, 637, 637, } },
{ 1331200, { 650, 637, 637, } },
{ 1600000, { 675, 650, 637, } },
{ 1866000, { DVB_VOLT(700, 675, 650) } },
{ 2133000, { DVB_VOLT(725, 700, 675) } },
{ 2400000, { DVB_VOLT(750, 725, 700) } },
{ 2666000, { DVB_VOLT(775, 750, 725) } },
{ 2933000, { DVB_VOLT(800, 775, 750) } },
{ 3200000, { DVB_VOLT(800, 800, 775) } },
{ 0xFFFFFFFF, { } },
};
/* TODO: More fine tuned values? */ u32 j = MtcTableCountDefault;
if (C.marikoEmcMaxClock < 1862400) { for (u32 i = MtcTableCountDefault; i < newEmcList.size(); ++i) {
std::memcpy(new_start, default_end, sizeof(emc_dvb_dvfs_table_t)); if (newEmcList[i] >= emcDvbTableNew[j].freq && newEmcList[i] < emcDvbTableNew[j + 1].freq) {
} else if (C.marikoEmcMaxClock < 2131200) { emcDvbTableNew[j].freq = newEmcList[i];
emc_dvb_dvfs_table_t oc_table = {1862400, {700, 675, 650, }}; ++j;
std::memcpy(new_start, &oc_table, sizeof(emc_dvb_dvfs_table_t)); } else {
} else if (C.marikoEmcMaxClock < 2400000) { break;
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) {
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) {
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) {
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 {
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));
} }
new_start->freq = C.marikoEmcMaxClock;
std::memset(mem_dvb_table_head, 0, sizeof(EmcDvbTableDefault));
std::memcpy(mem_dvb_table_head, &emcDvbTableNew, sizeof(emcDvbTableNew));
/* Max dvfs entry is 32, but HOS doesn't seem to boot if exact freq doesn't exist in dvb table, /* Max dvfs entry is 32, but HOS doesn't seem to boot if exact freq doesn't exist in dvb table,
reason why it's like this reason why it's like this
*/ */

View File

@@ -110,7 +110,12 @@ namespace ams::ldr::hoc::pcv::mariko {
return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]); return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]);
} }
constexpr emc_dvb_dvfs_table_t EmcDvbTableDefault[] = { struct DvbEntry {
u64 freq;
s32 volt[4] = {};
};
constexpr DvbEntry EmcDvbTableDefault[] = {
{ 204000, { 637, 637, 637, } }, { 204000, { 637, 637, 637, } },
{ 408000, { 637, 637, 637, } }, { 408000, { 637, 637, 637, } },
{ 800000, { 637, 637, 637, } }, { 800000, { 637, 637, 637, } },