add latency switching
This commit is contained in:
@@ -44,9 +44,9 @@ volatile CustomizeTable C = {
|
|||||||
/* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
|
/* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
|
||||||
.stepMode = StepMode_66MHz,
|
.stepMode = StepMode_66MHz,
|
||||||
|
|
||||||
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
.marikoEmcMaxClock = 2933000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
||||||
.marikoEmcVddqVolt = 600000,
|
.marikoEmcVddqVolt = 600000,
|
||||||
.emcDvbShift = 0,
|
.emcDvbShift = 10,
|
||||||
|
|
||||||
// Primary
|
// Primary
|
||||||
.t1_tRCD = 0,
|
.t1_tRCD = 0,
|
||||||
@@ -59,6 +59,20 @@ volatile CustomizeTable C = {
|
|||||||
.t7_tWTR = 0,
|
.t7_tWTR = 0,
|
||||||
.t8_tREFI = 0,
|
.t8_tREFI = 0,
|
||||||
|
|
||||||
|
.readLatency = {
|
||||||
|
2133000,
|
||||||
|
2400000,
|
||||||
|
2600000,
|
||||||
|
C.marikoEmcMaxClock,
|
||||||
|
},
|
||||||
|
|
||||||
|
.writeLatency = {
|
||||||
|
2133000,
|
||||||
|
2400000,
|
||||||
|
2600000,
|
||||||
|
C.marikoEmcMaxClock,
|
||||||
|
},
|
||||||
|
|
||||||
/* You can mix and match different latencies if needed */
|
/* You can mix and match different latencies if needed */
|
||||||
/*
|
/*
|
||||||
* Read:
|
* Read:
|
||||||
@@ -79,7 +93,7 @@ volatile CustomizeTable C = {
|
|||||||
.eristaCpuUV = 0,
|
.eristaCpuUV = 0,
|
||||||
.eristaCpuVmin = 800,
|
.eristaCpuVmin = 800,
|
||||||
.eristaCpuMaxVolt = 1200,
|
.eristaCpuMaxVolt = 1200,
|
||||||
/* Unlocks up to 2295 Mhz CPU, usage is not recommended. */
|
/* Unlocks up to 2397 Mhz CPU, usage is not recommended. */
|
||||||
.eristaCpuUnlock = DISABLED,
|
.eristaCpuUnlock = DISABLED,
|
||||||
|
|
||||||
.marikoCpuUVLow = 0, // No undervolt
|
.marikoCpuUVLow = 0, // No undervolt
|
||||||
|
|||||||
@@ -103,6 +103,9 @@ typedef struct CustomizeTable {
|
|||||||
u32 t7_tWTR;
|
u32 t7_tWTR;
|
||||||
u32 t8_tREFI;
|
u32 t8_tREFI;
|
||||||
|
|
||||||
|
u32 readLatency[4];
|
||||||
|
u32 writeLatency[4];
|
||||||
|
|
||||||
u32 mem_burst_read_latency;
|
u32 mem_burst_read_latency;
|
||||||
u32 mem_burst_write_latency;
|
u32 mem_burst_write_latency;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,73 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
rext = 0x1A;
|
rext = 0x1A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) {
|
||||||
|
latency += index * latencyStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) {
|
||||||
|
u32 maxIndex = 0;
|
||||||
|
for (u32 i = 0; i < latencySize; ++i) {
|
||||||
|
if (latencyArray[i]) {
|
||||||
|
maxIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) {
|
||||||
|
if (freq >= 1866'000 && freq < 2133000) {
|
||||||
|
latency += latencyStep * 2;
|
||||||
|
} else if (freq >= 2133'000) {
|
||||||
|
latency += latencyStep * 3;
|
||||||
|
} else {
|
||||||
|
latency += latencyStep;
|
||||||
|
}
|
||||||
|
/* 1333 latency is not possible with this config. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) {
|
||||||
|
for (u32 i = 0; i <= indexMax; ++i) {
|
||||||
|
if (latencyArray[i] != 0 && freq <= latencyArray[i]) {
|
||||||
|
SwitchLatency(latency, i, latencyStep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchLatency(latency, indexMax, latencyStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleLatency(u32 freq) {
|
||||||
|
static u32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency));
|
||||||
|
static u32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency));
|
||||||
|
constexpr u32 ReadLatencyStep = 4;
|
||||||
|
constexpr u32 WriteLatencyStep = 2;
|
||||||
|
bool autoLatencyRead = false, autoLatencyWrite = false;
|
||||||
|
|
||||||
|
if (rlIndexMax == 0) {
|
||||||
|
AutoLatency(RL, freq, ReadLatencyStep);
|
||||||
|
autoLatencyRead = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlIndexMax == 0) {
|
||||||
|
AutoLatency(WL, freq, WriteLatencyStep);
|
||||||
|
autoLatencyWrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoLatencyRead && autoLatencyWrite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!autoLatencyRead) {
|
||||||
|
HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!autoLatencyWrite) {
|
||||||
|
HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CalculateMrw2() {
|
void CalculateMrw2() {
|
||||||
static const u8 rlMapDBI[8] = {
|
static const u8 rlMapDBI[8] = {
|
||||||
6, 12, 16, 22, 28, 32, 36, 40
|
6, 12, 16, 22, 28, 32, 36, 40
|
||||||
@@ -59,7 +126,12 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6)));
|
mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalculateTimings(double tCK_avg) {
|
void CalculateTimings(double tCK_avg, u32 freq) {
|
||||||
|
RL = 28;
|
||||||
|
WL = 12;
|
||||||
|
|
||||||
|
HandleLatency(freq);
|
||||||
|
|
||||||
GetRext();
|
GetRext();
|
||||||
|
|
||||||
tR2P = CEIL((RL * 0.426) - 2.0);
|
tR2P = CEIL((RL * 0.426) - 2.0);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace ams::ldr::hoc::pcv::mariko {
|
namespace ams::ldr::hoc::pcv::mariko {
|
||||||
|
|
||||||
void CalculateTimings(double tCK_avg);
|
void CalculateTimings(double tCK_avg, u32 freq);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ namespace ams::ldr::hoc {
|
|||||||
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||||
const double tRPab = tRPpb + 3;
|
const double tRPab = tRPpb + 3;
|
||||||
|
|
||||||
|
inline u32 RL;
|
||||||
|
inline u32 WL;
|
||||||
|
|
||||||
inline u32 tR2P;
|
inline u32 tR2P;
|
||||||
inline u32 tR2W;
|
inline u32 tR2W;
|
||||||
inline u32 tRTM;
|
inline u32 tRTM;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
|
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
|
||||||
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
|
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
|
||||||
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
|
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
|
||||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
|
{ C.marikoEmcMaxClock, 1600'000, 3700'000, false, panic::Emc },
|
||||||
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc },
|
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc },
|
||||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
|
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
|
||||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
|
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
|
|
||||||
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
|
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
|
||||||
|
|
||||||
CalculateTimings(tCK_avg);
|
CalculateTimings(tCK_avg, table->rate_khz);
|
||||||
|
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
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_wr_rcd, GET_CYCLE_CEIL(tRCD));
|
||||||
@@ -592,7 +592,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result VerifyMtcTable(MarikoMtcTable *tableStart, u32 expectedFreq) {
|
Result VerifyMtcTable(MarikoMtcTable *tableStart, u32 expectedFreq) {
|
||||||
Log("Rate_khz: %u, revision: %u\n", tableStart->rate_khz, tableStart->rev);
|
// Log("Rate_khz: %u, revision: %u\n", tableStart->rate_khz, tableStart->rev);
|
||||||
R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable());
|
R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable());
|
||||||
R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
|
R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
|
||||||
|
|
||||||
@@ -624,8 +624,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void AbortInvalidDramId() {
|
NORETURN void AbortInvalidDramId() {
|
||||||
// Log("Invalid dram id\n");
|
Log("Invalid dram id\n");
|
||||||
// ViewLog();
|
ViewLog();
|
||||||
panic::SmcError(panic::Emc);
|
panic::SmcError(panic::Emc);
|
||||||
CRASH("Invalid dram id\n");
|
CRASH("Invalid dram id\n");
|
||||||
}
|
}
|
||||||
@@ -688,16 +688,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
newEmcList.push_back(newFreq);
|
newEmcList.push_back(newFreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log("Size = %u\n", newEmcList.size());
|
newEmcList.resize(std::min(newEmcList.size(), DvfsTableEntryLimit));
|
||||||
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) {
|
||||||
@@ -716,7 +707,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
static const DramId dramId = [] {
|
static const DramId dramId = [] {
|
||||||
DramId id = GetDramId();
|
DramId id = GetDramId();
|
||||||
id = IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL;
|
id = IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL;
|
||||||
//Log("Dram id: %u\n", id);
|
// Log("Dram id: %u\n", id);
|
||||||
return id;
|
return id;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
@@ -747,7 +738,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
|
|
||||||
MtcExtendTables(table);
|
MtcExtendTables(table);
|
||||||
for (u32 i = 0; i < newEmcList.size(); ++i) {
|
for (u32 i = 0; i < newEmcList.size(); ++i) {
|
||||||
Log("freqList[%u] = %u\n", i, newEmcList[i]);
|
// Log("freqList[%u] = %u\n", i, newEmcList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) {
|
if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) {
|
||||||
@@ -946,7 +937,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
CRASH(entry.description);
|
CRASH(entry.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ViewLog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user