Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e80c9a75f | ||
|
|
42bdfb55f2 | ||
|
|
e0967a9fd6 | ||
|
|
2406ce4f86 | ||
|
|
3b40a4a3e5 | ||
|
|
38c408dde6 | ||
|
|
5e62eb3f5d | ||
|
|
b4b5599ed2 | ||
|
|
b4917f3e1a | ||
|
|
e6b4cb6612 | ||
|
|
b1ca62ce61 | ||
|
|
243f614887 | ||
|
|
a8577378f6 | ||
|
|
564703b7c5 | ||
|
|
5ef56bed25 | ||
|
|
afddb963a9 | ||
|
|
aa72176196 | ||
|
|
7af0721847 | ||
|
|
2a6320e646 | ||
|
|
fc212bb419 | ||
|
|
14e0053335 | ||
|
|
8f28daceef | ||
|
|
f1044673d0 | ||
|
|
61a0ebffee | ||
|
|
8de8f4013e | ||
|
|
dd447553d4 | ||
|
|
11c456e00c | ||
|
|
5efb4bdd6b | ||
|
|
e331f1249b | ||
|
|
786467d7ea | ||
|
|
496e77301b | ||
|
|
d657f1d156 | ||
|
|
7ab5c2f540 | ||
|
|
71900721cf | ||
|
|
0bc9547701 | ||
|
|
96ac254022 | ||
|
|
92f378a80f | ||
|
|
589af01ad8 |
@@ -22,7 +22,6 @@
|
||||
|
||||
/* Never edit these. */
|
||||
#define AUTO 0
|
||||
#define AUTO_RAM 0
|
||||
#define ENABLED 1
|
||||
#define DISABLED 0
|
||||
#define DEACTIVATED_GPU_FREQ 2000
|
||||
@@ -105,7 +104,7 @@ volatile CustomizeTable C = {
|
||||
/* For automatic vmin detection, set this to AUTO. */
|
||||
/* vmin past 795mV won't work due to HOS limitation */
|
||||
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
|
||||
.marikoGpuVmin = AUTO,
|
||||
.marikoGpuVmin = AUTO,
|
||||
|
||||
.marikoGpuVmax = 800,
|
||||
|
||||
@@ -176,6 +175,10 @@ volatile CustomizeTable C = {
|
||||
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
|
||||
},
|
||||
|
||||
/* Advanced. */
|
||||
.fineTune_t6_tRTW = 0,
|
||||
.fineTune_t7_tWTR = 0,
|
||||
|
||||
/* You shouldn't have to anything past here. */
|
||||
.eristaCpuDvfsTable = {
|
||||
{ 204000, { 721094, }, { } },
|
||||
@@ -460,7 +463,7 @@ volatile CustomizeTable C = {
|
||||
{ 921600, { }, { 970060,-10108, -614,-179, 1508, -13 } },
|
||||
{ 998400, { }, { 1065665,-16075, -497,-179, 3213, 9 } },
|
||||
{ 1075200, { }, { 1132576,-16093, -648, 0, 1077, 40 } },
|
||||
{ 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
||||
// { 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
||||
// { 1228800, { }, { 1248293,-16383, -859, 0, 3722, 313 } },
|
||||
// { 1267200, { }, { 1286399,-17475, -867, 0, 3681, 559 } },
|
||||
},
|
||||
|
||||
@@ -121,12 +121,16 @@ typedef struct CustomizeTable {
|
||||
|
||||
u32 commonGpuVoltOffset;
|
||||
|
||||
/* TODO: Automatically detect speedo. */
|
||||
u32 gpuSpeedo;
|
||||
|
||||
u32 eristaGpuVoltArray[27];
|
||||
u32 marikoGpuVoltArray[24];
|
||||
u32 reserved[64];
|
||||
|
||||
u32 fineTune_t6_tRTW;
|
||||
u32 fineTune_t7_tWTR;
|
||||
|
||||
u32 reserved[60];
|
||||
|
||||
CustomizeCpuDvfsTable eristaCpuDvfsTable;
|
||||
CustomizeCpuDvfsTable eristaCpuDvfsTableSLT;
|
||||
|
||||
|
||||
@@ -132,6 +132,8 @@ namespace ams::ldr::hoc {
|
||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||
const s32 finetRTW = C.fineTune_t6_tRTW;
|
||||
const s32 finetWTR = C.fineTune_t7_tWTR;
|
||||
|
||||
const u32 tRC = tRAS + tRPpb;
|
||||
const u32 tRFCab = tRFCpb * 2;
|
||||
@@ -140,7 +142,7 @@ 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);
|
||||
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;
|
||||
const u32 tRTM = FLOOR((10.0 + RL_DBI) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
|
||||
const u32 tRATM = CEIL((tRTM - 10.0) + (RL_DBI * 0.426));
|
||||
inline u32 rext;
|
||||
@@ -158,7 +160,7 @@ namespace ams::ldr::hoc {
|
||||
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<double>(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);
|
||||
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 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
|
||||
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
|
||||
|
||||
|
||||
@@ -122,16 +122,6 @@ namespace ams::ldr::hoc::pcv {
|
||||
{0xFFFFFFFF, 35},
|
||||
};
|
||||
|
||||
static const u32 ramBrackets[][22] = {
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||
};
|
||||
|
||||
static const u32 gpuBudgetDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
|
||||
/* GPU Max Clock asm Pattern:
|
||||
*
|
||||
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
||||
|
||||
@@ -50,30 +50,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
return ramScale;
|
||||
}
|
||||
|
||||
u32 GetSpeedoBracket() {
|
||||
u32 speedoBracket = 3;
|
||||
if ((C.gpuSpeedo < 1754) && (speedoBracket = 2, C.gpuSpeedo < 1690)) {
|
||||
speedoBracket = !!(1625 < C.gpuSpeedo);
|
||||
}
|
||||
|
||||
return speedoBracket;
|
||||
}
|
||||
|
||||
u32 GetGpuBudgetDvfsVoltage() {
|
||||
u32 bracket = GetSpeedoBracket();
|
||||
|
||||
if (ramFreqMhz <= 1600)
|
||||
return 0;
|
||||
|
||||
for (u32 voltageIndex = 0; voltageIndex < 22; voltageIndex++) {
|
||||
if (ramFreqMhz <= ramBrackets[bracket][voltageIndex]) {
|
||||
return gpuBudgetDvfsArray[voltageIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return 800;
|
||||
}
|
||||
|
||||
/* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */
|
||||
u32 GetAutoVoltage() {
|
||||
u32 voltage = GetGpuVminVoltage();
|
||||
@@ -102,14 +78,13 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
}
|
||||
|
||||
/* C.marikoGpuVmin is non zero, user sets manual voltage. */
|
||||
if (C.marikoGpuVmin != 0 && C.marikoGpuVmin != 1) {
|
||||
if (C.marikoGpuVmin) {
|
||||
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* C.marikoGpuVmin is zero OR one, auto voltage is applied. */
|
||||
/* Get vmin depending on speedo and ram clock. */
|
||||
u32 autoVmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
||||
/* C.marikoGpuVmin is zero, auto voltage is applied. */
|
||||
u32 autoVmin = GetAutoVoltage();
|
||||
PATCH_OFFSET(ptr, autoVmin);
|
||||
R_SUCCEED();
|
||||
}
|
||||
@@ -122,8 +97,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
u32 vmin = C.marikoGpuVmin;
|
||||
|
||||
/* Automatic voltage. */
|
||||
if (!C.marikoGpuVmin || C.marikoGpuVmin == 1) {
|
||||
vmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
||||
if (!C.marikoGpuVmin) {
|
||||
vmin = GetAutoVoltage();
|
||||
PATCH_OFFSET(ptr, vmin);
|
||||
PATCH_OFFSET(ptr + 3, vmin);
|
||||
PATCH_OFFSET(ptr + 6, vmin);
|
||||
|
||||
@@ -169,15 +169,4 @@ Result hocClkIpcGetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||
}
|
||||
|
||||
Result hocClkIpcUpdateEmcRegs()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
||||
}
|
||||
Result hocClkIpcCalculateGpuVmin()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
||||
}
|
||||
41
Source/sys-clk/common/include/memmem.h
Normal file
41
Source/sys-clk/common/include/memmem.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Roy Merkel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MEMMEM_IMPL_H
|
||||
#define MEMMEM_IMPL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *memmem_impl(void *haystack, size_t haystacklen,
|
||||
const void *needle, size_t needlelen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -132,6 +132,14 @@ typedef enum {
|
||||
GPUUVLevel_EnumMax,
|
||||
} GPUUndervoltLevel;
|
||||
|
||||
enum {
|
||||
DVFSMode_Disabled,
|
||||
DVFSMode_Hijack,
|
||||
// DVFSMode_OfficialService,
|
||||
// DVFSMode_Hack,
|
||||
DVFSMode_EnumMax,
|
||||
};
|
||||
|
||||
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
|
||||
|
||||
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -51,13 +51,13 @@ typedef enum {
|
||||
|
||||
HocClkConfigValue_LiteTDPLimit,
|
||||
|
||||
HocClkConfigValue_EnforceBoardLimit,
|
||||
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
|
||||
HorizonOCConfigValue_OverwriteRefreshRate,
|
||||
HorizonOCConfigValue_EnableUnsafeDisplayFreqs,
|
||||
HocClkConfigValue_FixCpuVoltBug,
|
||||
|
||||
HorizonOCConfigValue_DVFSMode,
|
||||
HorizonOCConfigValue_DVFSOffset,
|
||||
|
||||
KipConfigValue_custRev,
|
||||
// KipConfigValue_mtcConf,
|
||||
@@ -158,6 +158,9 @@ typedef enum {
|
||||
KipConfigValue_g_volt_e_1036800,
|
||||
KipConfigValue_g_volt_e_1075200,
|
||||
|
||||
KipConfigValue_t6_tRTW_fine_tune,
|
||||
KipConfigValue_t7_tWTR_fine_tune,
|
||||
|
||||
KipCrc32,
|
||||
HocClkConfigValue_IsFirstLoad,
|
||||
SysClkConfigValue_EnumMax,
|
||||
@@ -208,21 +211,21 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
||||
case HocClkConfigValue_LiteTDPLimit:
|
||||
return pretty ? "Handheld TDP Limit" : "tdp_limit_l";
|
||||
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
return pretty ? "Enforce Board Limit" : "enforce_board_limit";
|
||||
|
||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||
return pretty ? "Battery Charge Current" : "bat_charge_current";
|
||||
|
||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||
return pretty ? "Display Refresh Rate Changing" : "drr_changing";
|
||||
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
return pretty ? "Fix CPU Volt Bug" : "cpu_volt_bugfix";
|
||||
|
||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||
return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe";
|
||||
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
return pretty ? "DVFS Mode" : "dvfs_mode";
|
||||
|
||||
case HorizonOCConfigValue_DVFSOffset:
|
||||
return pretty ? "DVFS Offset" : "dvfs_offset";
|
||||
|
||||
// KIP config values
|
||||
case KipConfigValue_custRev:
|
||||
return pretty ? "Custom Revision" : "kip_cust_rev";
|
||||
@@ -370,6 +373,8 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
||||
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
|
||||
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
|
||||
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
|
||||
case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_fune";
|
||||
case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune";
|
||||
case KipCrc32:
|
||||
return pretty ? "CRC32" : "crc32";
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
@@ -403,9 +408,8 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
||||
|
||||
case HocClkConfigValue_ThermalThrottle:
|
||||
case HocClkConfigValue_HandheldTDP:
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
return 1ULL;
|
||||
case HocClkConfigValue_ThermalThrottleThreshold:
|
||||
return 70ULL;
|
||||
@@ -429,7 +433,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case HocClkConfigValue_LiteTDPLimit:
|
||||
case SysClkConfigValue_PollingIntervalMs:
|
||||
return input > 0;
|
||||
|
||||
|
||||
case SysClkConfigValue_TempLogIntervalMs:
|
||||
case SysClkConfigValue_FreqLogIntervalMs:
|
||||
case SysClkConfigValue_PowerLogIntervalMs:
|
||||
@@ -438,13 +442,11 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case HocClkConfigValue_OverwriteBoostMode:
|
||||
case HocClkConfigValue_ThermalThrottle:
|
||||
case HocClkConfigValue_HandheldTDP:
|
||||
case HocClkConfigValue_EnforceBoardLimit:
|
||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||
case HocClkConfigValue_FixCpuVoltBug:
|
||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||
case HocClkConfigValue_IsFirstLoad:
|
||||
return (input & 0x1) == input;
|
||||
|
||||
|
||||
case KipConfigValue_custRev:
|
||||
// case KipConfigValue_mtcConf:
|
||||
case KipConfigValue_hpMode:
|
||||
@@ -534,7 +536,11 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
||||
case KipConfigValue_g_volt_e_1075200:
|
||||
case KipConfigValue_eristaCpuVmin:
|
||||
case KipConfigValue_eristaCpuUnlock:
|
||||
case KipConfigValue_t6_tRTW_fine_tune:
|
||||
case KipConfigValue_t7_tWTR_fine_tune:
|
||||
case KipCrc32:
|
||||
case HorizonOCConfigValue_DVFSMode:
|
||||
case HorizonOCConfigValue_DVFSOffset:
|
||||
return true;
|
||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||
return ((input >= 1024) && (input <= 3072)) || !input;
|
||||
|
||||
@@ -51,8 +51,6 @@ enum SysClkIpcCmd
|
||||
SysClkIpcCmd_SetReverseNXRTMode = 12,
|
||||
HocClkIpcCmd_SetKipData = 13,
|
||||
HocClkIpcCmd_GetKipData = 14,
|
||||
HocClkIpcCmd_UpdateEmcRegs = 15,
|
||||
HocClkIpcCmd_CalculateGpuVmin = 16,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -169,15 +169,4 @@ Result hocClkIpcGetKipData()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||
}
|
||||
|
||||
Result hocClkIpcUpdateEmcRegs()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
||||
}
|
||||
Result hocClkIpcCalculateGpuVmin()
|
||||
{
|
||||
u32 temp = 0;
|
||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
||||
}
|
||||
83
Source/sys-clk/common/src/memmem.c
Normal file
83
Source/sys-clk/common/src/memmem.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Roy Merkel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "memmem.h"
|
||||
|
||||
void *memmem_impl(void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
|
||||
{
|
||||
const unsigned char *cmpp;
|
||||
const unsigned char *p;
|
||||
const unsigned char *endp;
|
||||
const unsigned char *q;
|
||||
const unsigned char *endq;
|
||||
unsigned char found;
|
||||
|
||||
if(haystack == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(needle == NULL)
|
||||
{
|
||||
return haystack;
|
||||
}
|
||||
if(haystacklen == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if(needlelen == 0)
|
||||
{
|
||||
return haystack;
|
||||
}
|
||||
|
||||
if(needlelen > haystacklen)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
endp = haystack + haystacklen - needlelen;
|
||||
endq = needle + needlelen;
|
||||
for(p = haystack; p <= endp; p++)
|
||||
{
|
||||
found = 1;
|
||||
cmpp = p;
|
||||
for(q = needle; q < endq; q++)
|
||||
{
|
||||
if(*cmpp != *q)
|
||||
{
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmpp++;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
{
|
||||
return (void*)p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
|
||||
# version control constants
|
||||
#---------------------------------------------------------------------------------
|
||||
#TARGET_VERSION := $(shell git describe --dirty --always --tags)
|
||||
APP_VERSION := 0.35
|
||||
APP_VERSION := 0.38
|
||||
TARGET_VERSION := $(APP_VERSION)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
@@ -281,7 +281,7 @@ void AppProfileGui::addProfileUI(SysClkProfile profile)
|
||||
FatalGui::openWithResultCode("sysclkIpcGetConfigValues", rc);
|
||||
return;
|
||||
}
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||
this->addModuleListItem(profile, SysClkModule_CPU);
|
||||
this->addModuleListItem(profile, SysClkModule_GPU);
|
||||
this->addModuleListItem(profile, SysClkModule_MEM);
|
||||
|
||||
@@ -155,7 +155,7 @@ void FreqChoiceGui::listUI()
|
||||
|
||||
if (IsMariko())
|
||||
{
|
||||
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1963;
|
||||
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1964;
|
||||
if(this->configList->values[KipConfigValue_marikoGpuUV] == 0) {
|
||||
unsafe_gpu = 1076;
|
||||
} else if (this->configList->values[KipConfigValue_marikoGpuUV] == 1) {
|
||||
|
||||
@@ -285,7 +285,7 @@ void GlobalOverrideGui::listUI()
|
||||
}
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(
|
||||
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||
this->addModuleListItem(SysClkModule_CPU);
|
||||
this->addModuleListItem(SysClkModule_GPU);
|
||||
this->addModuleListItem(SysClkModule_MEM);
|
||||
|
||||
@@ -47,7 +47,7 @@ std::map<uint32_t, std::string> gpu_freq_label_e = {
|
||||
{768000000, "Docked"},
|
||||
{921600000, "Safe Max"},
|
||||
{960000000, "Unsafe Max"},
|
||||
{1075200000, "Aboslute Max"},
|
||||
{1075200000, "Absolute Max"},
|
||||
};
|
||||
|
||||
std::map<uint32_t, std::string> gpu_freq_label_m = {
|
||||
@@ -59,5 +59,6 @@ std::map<uint32_t, std::string> gpu_freq_label_m = {
|
||||
{768000000, "Docked"},
|
||||
{1075200000, "Safe Max"},
|
||||
{1305600000, "Unsafe Max"},
|
||||
{1536000000, "Aboslute Max"},
|
||||
};
|
||||
{1536000000, "Absolute Max"},
|
||||
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#if IS_MINIMAL == 1
|
||||
#pragma message("Compiling with minimal features")
|
||||
#endif
|
||||
|
||||
class RamSubmenuGui;
|
||||
class RamTimingsSubmenuGui;
|
||||
class RamLatenciesSubmenuGui;
|
||||
@@ -247,12 +248,9 @@ void MiscGui::listUI()
|
||||
|
||||
addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_OverwriteBoostMode, nullptr);
|
||||
#if IS_MINIMAL == 0
|
||||
addConfigToggle(HocClkConfigValue_FixCpuVoltBug, nullptr);
|
||||
#endif
|
||||
addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_HandheldTDP, nullptr);
|
||||
addConfigToggle(HocClkConfigValue_EnforceBoardLimit, nullptr);
|
||||
// addConfigToggle(HocClkConfigValue_EnforceBoardLimit, nullptr);
|
||||
|
||||
#if IS_MINIMAL == 0
|
||||
std::map<uint32_t, std::string> labels_pwr_l = {
|
||||
@@ -297,6 +295,45 @@ void MiscGui::listUI()
|
||||
addFreqButton(HocClkConfigValue_EristaMaxCpuClock, nullptr, SysClkModule_CPU, cpu_freq_label_e);
|
||||
}
|
||||
|
||||
if (IsMariko()) {
|
||||
std::vector<NamedValue> dvfsValues = {
|
||||
NamedValue("Disabled", DVFSMode_Disabled),
|
||||
NamedValue("PCV Hijack", DVFSMode_Hijack),
|
||||
// NamedValue("Official Service", DVFSMode_OfficialService),
|
||||
// NamedValue("Hack", DVFSMode_Hack),
|
||||
};
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_DVFSMode,
|
||||
"GPU DVFS Mode",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"GPU DVFS Mode",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
dvfsValues,
|
||||
false
|
||||
);
|
||||
|
||||
std::vector<NamedValue> dvfsOffset = {
|
||||
NamedValue("-50 mV", 0xFFFFFFCE),
|
||||
NamedValue("-45 mV", 0xFFFFFFD3),
|
||||
NamedValue("-40 mV", 0xFFFFFFD8),
|
||||
NamedValue("-30 mV", 0xFFFFFFE2),
|
||||
NamedValue("-25 mV", 0xFFFFFFE7),
|
||||
NamedValue("-20 mV", 0xFFFFFFEC),
|
||||
NamedValue("-10 mV", 0xFFFFFFF6),
|
||||
NamedValue(" -5 mV", 0xFFFFFFFB),
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue(" +5 mV", 5),
|
||||
NamedValue("+10 mV", 10),
|
||||
NamedValue("+15 mV", 15),
|
||||
NamedValue("+20 mV", 20),
|
||||
};
|
||||
|
||||
addConfigButton(HorizonOCConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, dvfsOffset, false);
|
||||
|
||||
}
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("KIP"));
|
||||
|
||||
tsl::elm::ListItem* saveBtn = new tsl::elm::ListItem("Save KIP Settings");
|
||||
@@ -343,46 +380,47 @@ void MiscGui::listUI()
|
||||
});
|
||||
this->listElement->addItem(gpuSubmenu);
|
||||
|
||||
|
||||
#if IS_MINIMAL == 0
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
NamedValue("2816mA", 2816),
|
||||
NamedValue("3072mA", 3072),
|
||||
};
|
||||
// std::vector<NamedValue> chargerCurrents = {
|
||||
// NamedValue("Disabled", 0),
|
||||
// NamedValue("1024mA", 1024),
|
||||
// NamedValue("1280mA", 1280),
|
||||
// NamedValue("1536mA", 1536),
|
||||
// NamedValue("1792mA", 1792),
|
||||
// NamedValue("2048mA", 2048),
|
||||
// NamedValue("2304mA", 2304),
|
||||
// NamedValue("2560mA", 2560),
|
||||
// NamedValue("2816mA", 2816),
|
||||
// NamedValue("3072mA", 3072),
|
||||
// };
|
||||
if(!IsHoag()) {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
NamedValue("2816mA", 2816),
|
||||
NamedValue("3072mA", 3072),
|
||||
};
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
// std::vector<NamedValue> chargerCurrents = {
|
||||
// NamedValue("Disabled", 0),
|
||||
// NamedValue("1024mA", 1024),
|
||||
// NamedValue("1280mA", 1280),
|
||||
// NamedValue("1536mA", 1536),
|
||||
// NamedValue("1792mA", 1792),
|
||||
// NamedValue("2048mA", 2048),
|
||||
// NamedValue("2304mA", 2304),
|
||||
// NamedValue("2560mA", 2560),
|
||||
// NamedValue("2816mA", 2816),
|
||||
// NamedValue("3072mA", 3072),
|
||||
// };
|
||||
|
||||
ValueThresholds chargerThresholds(2048, 2560);
|
||||
// ValueThresholds chargerThresholds(2048, 2560);
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
{},
|
||||
chargerCurrents,
|
||||
false
|
||||
);
|
||||
// addConfigButton(
|
||||
// HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
// "Charge Current Override",
|
||||
// ValueRange(0, 0, 1, "", 0),
|
||||
// "Charge Current Override",
|
||||
// &chargerThresholds,
|
||||
// {},
|
||||
// chargerCurrents,
|
||||
// false
|
||||
// );
|
||||
addConfigToggle(HorizonOCConfigValue_OverwriteRefreshRate, nullptr);
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 Enabling unsafe display", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
@@ -393,32 +431,33 @@ void MiscGui::listUI()
|
||||
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110);
|
||||
this->listElement->addItem(warningText);
|
||||
addConfigToggle(HorizonOCConfigValue_EnableUnsafeDisplayFreqs, nullptr);
|
||||
} else {
|
||||
std::vector<NamedValue> chargerCurrents = {
|
||||
NamedValue("Disabled", 0),
|
||||
NamedValue("1024mA", 1024),
|
||||
NamedValue("1280mA", 1280),
|
||||
NamedValue("1536mA", 1536),
|
||||
NamedValue("1792mA", 1792),
|
||||
NamedValue("2048mA", 2048),
|
||||
NamedValue("2304mA", 2304),
|
||||
NamedValue("2560mA", 2560),
|
||||
};
|
||||
|
||||
ValueThresholds chargerThresholds(1792, 2048);
|
||||
|
||||
addConfigButton(
|
||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
"Charge Current Override",
|
||||
ValueRange(0, 0, 1, "", 0),
|
||||
"Charge Current Override",
|
||||
&chargerThresholds,
|
||||
{},
|
||||
chargerCurrents,
|
||||
false
|
||||
);
|
||||
|
||||
}
|
||||
// else {
|
||||
// std::vector<NamedValue> chargerCurrents = {
|
||||
// NamedValue("Disabled", 0),
|
||||
// NamedValue("1024mA", 1024),
|
||||
// NamedValue("1280mA", 1280),
|
||||
// NamedValue("1536mA", 1536),
|
||||
// NamedValue("1792mA", 1792),
|
||||
// NamedValue("2048mA", 2048),
|
||||
// NamedValue("2304mA", 2304),
|
||||
// NamedValue("2560mA", 2560),
|
||||
// };
|
||||
|
||||
// ValueThresholds chargerThresholds(1792, 2048);
|
||||
|
||||
// addConfigButton(
|
||||
// HorizonOCConfigValue_BatteryChargeCurrent,
|
||||
// "Charge Current Override",
|
||||
// ValueRange(0, 0, 1, "", 0),
|
||||
// "Charge Current Override",
|
||||
// &chargerThresholds,
|
||||
// {},
|
||||
// chargerCurrents,
|
||||
// false
|
||||
// );
|
||||
|
||||
// }
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -590,7 +629,7 @@ protected:
|
||||
addConfigButton(
|
||||
KipConfigValue_marikoEmcVddqVolt,
|
||||
"RAM VDDQ Voltage",
|
||||
ValueRange(550000, 700000, 5000, "mV", 1000),
|
||||
ValueRange(400000, 700000, 5000, "mV", 1000),
|
||||
"RAM VDDQ Voltage",
|
||||
&thresholdsDisabled,
|
||||
{},
|
||||
@@ -650,36 +689,28 @@ protected:
|
||||
addConfigButton(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 10, 1, "", 1), "tRTW", &thresholdsDisabled, {}, {}, false);
|
||||
addConfigButton(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 10, 1, "", 1), "tWTR", &thresholdsDisabled, {}, {}, false);
|
||||
addConfigButton(KipConfigValue_t8_tREFI, "t8 tREFI", ValueRange(0, 6, 1, "", 1), "tREFI", &thresholdsDisabled, {}, {}, false);
|
||||
#if IS_MINIMAL == 0
|
||||
if(IsMariko()) {
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental"));
|
||||
|
||||
tsl::elm::ListItem* emcUpdBtn = new tsl::elm::ListItem("Update RAM Timings");
|
||||
emcUpdBtn->setClickListener([this](u64 keys) {
|
||||
if (keys & HidNpadButton_A) {
|
||||
if(this->context->freqs[SysClkModule_MEM] > 1600000000) {
|
||||
Result rc = hocClkIpcUpdateEmcRegs();
|
||||
if (R_FAILED(rc)) {
|
||||
FatalGui::openWithResultCode("hocClkIpcUpdateEmcRegs", rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
writeNotification("Horizon OC\nSet your ram frequency to max\nbefore applying timings!");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
this->listElement->addItem(emcUpdBtn);
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 This feature is EXPERIMENTAL", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("and should only be used for testing!", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
});
|
||||
warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70);
|
||||
this->listElement->addItem(warningText);
|
||||
}
|
||||
#endif
|
||||
std::vector<NamedValue> t6_tRTW_fine_tune = {
|
||||
NamedValue("-2", 0xFFFFFFFE),
|
||||
NamedValue("-1", 0xFFFFFFFF),
|
||||
NamedValue(" 0", 0),
|
||||
NamedValue("+1", 1),
|
||||
NamedValue("+2", 2),
|
||||
};
|
||||
|
||||
std::vector<NamedValue> t7_tWTR_fine_tune = {
|
||||
NamedValue("-3", 0xFFFFFFFD),
|
||||
NamedValue("-2", 0xFFFFFFFE),
|
||||
NamedValue("-1", 0xFFFFFFFF),
|
||||
NamedValue(" 0", 0),
|
||||
NamedValue("+1", 1),
|
||||
NamedValue("+2", 2),
|
||||
NamedValue("+3", 3),
|
||||
};
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced"));
|
||||
addConfigButton(KipConfigValue_t6_tRTW_fine_tune, "t6 tRTW Fine Tune", ValueRange(0, 4, 1, "", 0), "tRTW Fine Tune", &thresholdsDisabled, {}, t6_tRTW_fine_tune, false);
|
||||
addConfigButton(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune", ValueRange(0, 6, 1, "", 0), "tWTR Fine Tune", &thresholdsDisabled, {}, t7_tWTR_fine_tune, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -937,7 +968,7 @@ protected:
|
||||
};
|
||||
|
||||
std::vector<NamedValue> mGpuVoltsVmin = {
|
||||
NamedValue("Auto", 0), NamedValue("Auto (RAM)", 1),
|
||||
NamedValue("Auto", 0),
|
||||
NamedValue("480mV", 480), NamedValue("485mV", 485), NamedValue("490mV", 490),
|
||||
NamedValue("495mV", 495), NamedValue("500mV", 500), NamedValue("505mV", 505),
|
||||
NamedValue("510mV", 510), NamedValue("515mV", 515), NamedValue("520mV", 520),
|
||||
@@ -1188,7 +1219,7 @@ protected:
|
||||
};
|
||||
|
||||
if (IsMariko()) {
|
||||
|
||||
|
||||
tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
|
||||
renderer->drawString("\uE150 Setting GPU Clocks past", false, x + 20, y + 30, 18, tsl::style::color::ColorText);
|
||||
renderer->drawString("1075MHz without UV, 1152MHz on SLT", false, x + 20, y + 50, 18, tsl::style::color::ColorText);
|
||||
|
||||
@@ -39,7 +39,7 @@ DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_V
|
||||
|
||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
CFLAGS := -g -Wall -Os -ffunction-sections \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2023 CTCaer
|
||||
* Copyright (c) 2023 p-sam
|
||||
* Copyright (c) 2026 Souldbminer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -47,7 +48,7 @@
|
||||
|
||||
#define PTO_CLK_CNT_BUSY BIT(31)
|
||||
#define PTO_CLK_CNT 0xFFFFFF
|
||||
#define CLK_PTO_CCLK_G 0x12
|
||||
#define CLK_PTO_CCLK_G_DIV2 0x13
|
||||
#define CLK_PTO_EMC 0x24
|
||||
|
||||
#define CLOCK(x) (*(volatile u32 *)(g_clk_base + (x)))
|
||||
@@ -117,7 +118,7 @@ static u32 g_mem_freq = 0;
|
||||
static u32 g_emc_lall = 0;
|
||||
static u32 g_emc_lcpu = 0;
|
||||
|
||||
static u32 _clock_get_dev_freq(u32 id)
|
||||
static u32 _clock_get_dev_freq(u32 id, u32 multiplier)
|
||||
{
|
||||
const u32 pto_win = 16;
|
||||
const u32 pto_osc = 32768;
|
||||
@@ -148,7 +149,7 @@ static u32 _clock_get_dev_freq(u32 id)
|
||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||
usleep(2);
|
||||
|
||||
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
|
||||
u32 freq_khz = (u64)cnt * multiplier * pto_osc / pto_win;
|
||||
|
||||
return freq_khz;
|
||||
}
|
||||
@@ -203,8 +204,8 @@ static void _clock_update_freqs(void)
|
||||
return;
|
||||
}
|
||||
|
||||
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC) * 1000;
|
||||
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G) * 1000;
|
||||
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC, 1);
|
||||
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G_DIV2, 2);
|
||||
|
||||
if (!g_gpu_base)
|
||||
{
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <cstring>
|
||||
#include <registers.h>
|
||||
#include <notification.h>
|
||||
#include <memmem.h>
|
||||
|
||||
#define MAX(A, B) std::max(A, B)
|
||||
#define MIN(A, B) std::min(A, B)
|
||||
@@ -96,9 +97,23 @@ std::atomic<uint64_t> idletick2{systemtickfrequency};
|
||||
std::atomic<uint64_t> idletick3{systemtickfrequency};
|
||||
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
||||
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
||||
u32 speedoBracket;
|
||||
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
||||
u8 g_dramID = 0;
|
||||
|
||||
static const u32 ramBrackets[][22] = {
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||
};
|
||||
|
||||
static const u32 gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
u32 dvfsTable[6][32] = {};
|
||||
u64 dvfsAddress;
|
||||
u32 ramVmin;
|
||||
|
||||
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
||||
{
|
||||
ASSERT_ENUM_VALID(SysClkModule, module);
|
||||
@@ -311,7 +326,7 @@ void Board::fuseReadSpeedos() {
|
||||
cpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_CPU_IDDQ_CALIB);
|
||||
gpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_SOC_IDDQ_CALIB);
|
||||
socIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_GPU_IDDQ_CALIB);
|
||||
|
||||
|
||||
svcCloseHandle(debug);
|
||||
return;
|
||||
}
|
||||
@@ -436,13 +451,22 @@ void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
||||
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
||||
rc = clkrstSetClockRate(&session, hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||
|
||||
if (module == SysClkModule_CPU) {
|
||||
svcSleepThread(300'000);
|
||||
rc = clkrstSetClockRate(&session, hz);
|
||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||
}
|
||||
clkrstCloseSession(&session);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||
if (module == SysClkModule_CPU) {
|
||||
svcSleepThread(300'000);
|
||||
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +482,7 @@ std::uint32_t Board::GetHz(SysClkModule module)
|
||||
hz = 60;
|
||||
return hz;
|
||||
}
|
||||
|
||||
|
||||
if(HOSSVC_HAS_CLKRST)
|
||||
{
|
||||
ClkrstSession session = {0};
|
||||
@@ -753,7 +777,7 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor)
|
||||
}
|
||||
|
||||
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
||||
{
|
||||
{
|
||||
switch(loadSource)
|
||||
{
|
||||
case SysClkPartLoad_EMC:
|
||||
@@ -792,6 +816,7 @@ u8 Board::GetDramID() {
|
||||
void Board::FetchHardwareInfos()
|
||||
{
|
||||
fuseReadSpeedos();
|
||||
SetSpeedoBracket();
|
||||
u64 sku = 0, dramID = 0;
|
||||
Result rc = splInitialize();
|
||||
ASSERT_RESULT_OK(rc, "splInitialize");
|
||||
@@ -801,7 +826,7 @@ void Board::FetchHardwareInfos()
|
||||
|
||||
rc = splGetConfig(SplConfigItem_DramId, &dramID);
|
||||
ASSERT_RESULT_OK(rc, "splGetConfig");
|
||||
|
||||
|
||||
splExit();
|
||||
|
||||
switch(sku)
|
||||
@@ -816,9 +841,12 @@ void Board::FetchHardwareInfos()
|
||||
g_socType = SysClkSocType_Erista;
|
||||
}
|
||||
|
||||
if (g_socType == SysClkSocType_Mariko) {
|
||||
CacheDvfsTable();
|
||||
}
|
||||
|
||||
g_consoleType = (HorizonOCConsoleType)sku;
|
||||
g_dramID = (u8)dramID;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -926,174 +954,181 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
||||
return out > 0 ? out : 0;
|
||||
}
|
||||
|
||||
#define MC_REGISTER_BASE 0x70019000
|
||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||
void Board::SetSpeedoBracket() {
|
||||
if (cpuSpeedo2 >= 1754) {
|
||||
speedoBracket = 3;
|
||||
} else if (cpuSpeedo2 >= 1690) {
|
||||
speedoBracket = 2;
|
||||
} else if (cpuSpeedo2 > 1625) {
|
||||
speedoBracket = 1;
|
||||
} else {
|
||||
speedoBracket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define EMC_REGISTER_BASE 0x7001b000
|
||||
#define EMC_REGISTER_REGION_SIZE 0x1000
|
||||
u32 Board::GetMinimumGpuVoltage(u32 freqMhz) {
|
||||
if (freqMhz <= 1600)
|
||||
return 0;
|
||||
|
||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||
|
||||
#define WRITE_REGISTER_EMC(TIMING_OFFSET, VALUE) \
|
||||
do { \
|
||||
args = {}; \
|
||||
args.X[0] = 0xF0000002; \
|
||||
args.X[1] = EMC_REGISTER_BASE + (TIMING_OFFSET); \
|
||||
args.X[2] = 0xFFFFFFFF; \
|
||||
args.X[3] = (VALUE); \
|
||||
svcCallSecureMonitor(&args); \
|
||||
} while (false)
|
||||
|
||||
#define WRITE_REGISTER_MC(TIMING_OFFSET, VALUE) \
|
||||
do { \
|
||||
args = {}; \
|
||||
args.X[0] = 0xF0000002; \
|
||||
args.X[1] = MC_REGISTER_BASE + (TIMING_OFFSET); \
|
||||
args.X[2] = 0xFFFFFFFF; \
|
||||
args.X[3] = (VALUE); \
|
||||
svcCallSecureMonitor(&args); \
|
||||
} while (false)
|
||||
|
||||
|
||||
// NOTE: needs patch to exosphere to expose emc region to secmon. MC does NOT need this patch
|
||||
|
||||
u32 tRCD_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
u32 tRP_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||
u32 tRAS_values[] = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||
double 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? */
|
||||
u32 tRFC_values[] = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||
u32 tWTR_values[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
u32 tREFpb_values[] = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||
|
||||
// Credit to Lightos for these timings!
|
||||
|
||||
|
||||
void Board::UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode) {
|
||||
// timing stuff
|
||||
|
||||
SecmonArgs args = {};
|
||||
|
||||
constexpr double MC_ARB_DIV = 4.0;
|
||||
constexpr u32 MC_ARB_SFA = 2;
|
||||
|
||||
double tCK_avg = 1000'000.0 / ramFreq;
|
||||
u32 BL = 16;
|
||||
u32 RL = 28 + rlAdd;
|
||||
u32 WL = 14 + wlAdd;
|
||||
u32 RL_DBI = RL + 4;
|
||||
|
||||
u32 tRCD = tRCD_values[tRCD_i];
|
||||
u32 tRPpb = tRP_values[tRP_i];
|
||||
u32 tRAS = tRAS_values[tRAS_i];
|
||||
double tRRD = tRRD_values[tRRD_i];
|
||||
u32 tRFCpb = tRFC_values[tRFC_i];
|
||||
u32 tWTR = 10 - tWTR_values[tWTR_i];
|
||||
u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||
|
||||
double tDQSCK_max = 3.5;
|
||||
u32 tWPRE = 2;
|
||||
|
||||
double tRPST = 0.5;
|
||||
|
||||
u32 tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (tRTW_i * 3);
|
||||
|
||||
u32 tRC = tRAS + tRPpb;
|
||||
u32 tRFCab = tRFCpb * 2;
|
||||
u32 tRPab = tRPpb + 3;
|
||||
|
||||
u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (ramFreq / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
|
||||
|
||||
double tMMRI = tRCD + (tCK_avg * 3);
|
||||
double pdex2mrr = tMMRI + 10;
|
||||
u32 emc_cfg = hpMode ? 0x13200000 : 0xF3200000;
|
||||
|
||||
u32 refresh_raw = 0xFFFF;
|
||||
if (tREFpb_i != 6) {
|
||||
refresh_raw = CEIL(tREFpb_values[tREFpb_i] / tCK_avg) - 0x40;
|
||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||
for (u32 voltageIndex = 0; voltageIndex < 22; ++voltageIndex) {
|
||||
if (freqMhz <= ramBrackets[speedoBracket][voltageIndex]) {
|
||||
return gpuDvfsArray[voltageIndex];
|
||||
}
|
||||
}
|
||||
|
||||
u32 trefbw = refresh_raw + 0x40;
|
||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||
return 800;
|
||||
}
|
||||
|
||||
u32 tR2P = 12 + (rlAdd / 2);
|
||||
u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||
Handle Board::GetPcvHandle() {
|
||||
constexpr u64 PcvID = 0x10000000000001a;
|
||||
u64 processIDList[80]{};
|
||||
s32 processCount = 0;
|
||||
Handle handle = INVALID_HANDLE;
|
||||
|
||||
double tXSR = (double) (tRFCab + 7.5);
|
||||
DebugEventInfo debugEvent{};
|
||||
|
||||
args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = EMC_REGISTER_BASE + EMC_INTSTATUS_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
/* Get all running processes. */
|
||||
Result resultGetProcessList = svcGetProcessList(&processCount, processIDList, std::size(processIDList));
|
||||
if (R_FAILED(resultGetProcessList)) {
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if(args.X[1] == (EMC_REGISTER_BASE + EMC_INTSTATUS_0)) { // if param 1 is identical read failed, exosphere needs patch!
|
||||
writeNotification("Horizon OC\nExosphere not patched\nfor EMC r/w");
|
||||
/* Try to find pcv. */
|
||||
for (int i = 0; i < processCount; ++i) {
|
||||
if (handle != INVALID_HANDLE) {
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Try to debug process, if it fails, try next process. */
|
||||
Result resultSvcDebugProcess = svcDebugActiveProcess(&handle, processIDList[i]);
|
||||
if (R_FAILED(resultSvcDebugProcess)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try to get a debug event. */
|
||||
Result resultDebugEvent = svcGetDebugEvent(&debugEvent, handle);
|
||||
if (R_SUCCEEDED(resultDebugEvent)) {
|
||||
if (debugEvent.info.create_process.program_id == PcvID) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed to get handle. */
|
||||
return INVALID_HANDLE;
|
||||
}
|
||||
|
||||
void Board::CacheDvfsTable() {
|
||||
const u32 voltagePattern[] = { 600000, 12500, 1400000, };
|
||||
|
||||
Handle handle = GetPcvHandle();
|
||||
if (handle == INVALID_HANDLE) {
|
||||
FileUtils::LogLine("[Board] Invalid handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
// actually write the timings
|
||||
WRITE_REGISTER_EMC(EMC_CFG_0, emc_cfg);
|
||||
WRITE_REGISTER_EMC(EMC_RD_RCD_0, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_REGISTER_EMC(EMC_WR_RCD_0, GET_CYCLE_CEIL(tRCD));
|
||||
WRITE_REGISTER_EMC(EMC_RC_0, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
||||
WRITE_REGISTER_EMC(EMC_RAS_0, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
|
||||
WRITE_REGISTER_EMC(EMC_RRD_0, GET_CYCLE_CEIL(tRRD));
|
||||
WRITE_REGISTER_EMC(EMC_RFCPB_0, GET_CYCLE_CEIL(tRFCpb));
|
||||
WRITE_REGISTER_EMC(EMC_RFC_0, GET_CYCLE_CEIL(tRFCab));
|
||||
WRITE_REGISTER_EMC(EMC_RP_0, GET_CYCLE_CEIL(tRPpb));
|
||||
WRITE_REGISTER_EMC(EMC_TRPAB_0, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
||||
WRITE_REGISTER_EMC(EMC_R2W_0, tR2W);
|
||||
WRITE_REGISTER_EMC(EMC_W2R_0, tW2R);
|
||||
WRITE_REGISTER_EMC(EMC_REFRESH_0, refresh_raw);
|
||||
WRITE_REGISTER_EMC(EMC_PRE_REFRESH_REQ_CNT_0, refresh_raw / 4);
|
||||
WRITE_REGISTER_EMC(EMC_TREFBW_0, trefbw);
|
||||
WRITE_REGISTER_EMC(EMC_PDEX2MRR_0, GET_CYCLE_CEIL(pdex2mrr));
|
||||
WRITE_REGISTER_EMC(EMC_TXSR_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
WRITE_REGISTER_EMC(EMC_TXSRDLL_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
||||
MemoryInfo memoryInfo = {};
|
||||
u64 address = 0;
|
||||
u32 pageInfo = 0;
|
||||
constexpr u32 PageSize = 0x1000;
|
||||
u8 buffer[PageSize];
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RCD_0, CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RP_0, CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RC_0, CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAS_0, CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_FAW_0, CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RRD_0, CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RFCPB_0, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1);
|
||||
/* Loop until failure. */
|
||||
while (true) {
|
||||
/* Find pcv heap. */
|
||||
while (true) {
|
||||
Result resultProcessMemory = svcQueryDebugProcessMemory(&memoryInfo, &pageInfo, handle, address);
|
||||
address = memoryInfo.addr + memoryInfo.size;
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_R2W_0, CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_W2R_0, CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
||||
if (R_FAILED(resultProcessMemory) || !address) {
|
||||
svcCloseHandle(handle);
|
||||
FileUtils::LogLine("[Board] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory));
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAP2PRE_0, CEIL(tR2P / MC_ARB_DIV));
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_WAP2PRE_0, CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA);
|
||||
if (memoryInfo.size && (memoryInfo.perm & 3) == 3 && static_cast<char>(memoryInfo.type) == 0x04) {
|
||||
/* Found valid memory. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 da_turns = 0;
|
||||
da_turns |= u8((CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 16;
|
||||
da_turns |= u8((CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 24;
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_TURNS_0, da_turns);
|
||||
for (u64 base = 0; base < memoryInfo.size; base += PageSize) {
|
||||
u32 memorySize = std::min(memoryInfo.size, static_cast<u64>(PageSize));
|
||||
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, base + memoryInfo.addr, memorySize))) {
|
||||
break;
|
||||
}
|
||||
|
||||
u32 da_covers = 0;
|
||||
u8 r_cover = ((CEIL(tR2P / MC_ARB_DIV)) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
||||
u8 w_cover = ((CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
||||
da_covers |= ((u32)(CEIL(GET_CYCLE_CEIL(tRC) / (u32)MC_ARB_DIV) - 1) / 2);
|
||||
da_covers |= (r_cover << 8);
|
||||
da_covers |= (w_cover << 16);
|
||||
u8 *resultPattern = static_cast<u8 *>(memmem_impl(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
|
||||
u32 index = resultPattern - buffer;
|
||||
|
||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_COVERS_0, da_covers);
|
||||
// TODO: modify mc_emem_arb_misc0
|
||||
|
||||
WRITE_REGISTER_MC(MC_TIMING_CONTROL_0, 0x1); // update timing regs as they are shadowed
|
||||
WRITE_REGISTER_EMC(EMC_TIMING_CONTROL_0, 0x1);
|
||||
if (!resultPattern) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Assuming mariko. */
|
||||
const u32 vmax = 800;
|
||||
constexpr u32 DvfsTableOffset = 312;
|
||||
if (!std::memcmp(&buffer[index + DvfsTableOffset], &vmax, sizeof(vmax))) {
|
||||
std::memcpy(dvfsTable, &buffer[index + DvfsTableOffset], sizeof(dvfsTable));
|
||||
dvfsAddress = base + memoryInfo.addr + DvfsTableOffset + index;
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
handle = INVALID_HANDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
void Board::PcvHijackDvfs(u32 vmin) {
|
||||
u32 table[192];
|
||||
static_assert(sizeof(table) == sizeof(dvfsTable));
|
||||
std::memcpy(table, dvfsTable, sizeof(dvfsTable));
|
||||
|
||||
if (ramVmin == vmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < std::size(table); ++i) {
|
||||
if (table[i] && table[i] <= vmin) {
|
||||
table[i] = vmin;
|
||||
}
|
||||
}
|
||||
|
||||
Handle handle = GetPcvHandle();
|
||||
if (handle == INVALID_HANDLE) {
|
||||
FileUtils::LogLine("Invalid handle!");
|
||||
return;
|
||||
}
|
||||
|
||||
Result rc = svcWriteDebugProcessMemory(handle, table, dvfsAddress, sizeof(table));
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ramVmin = vmin;
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin);
|
||||
}
|
||||
|
||||
#define MC_REGISTER_BASE 0x70019000
|
||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||
|
||||
bool Board::IsDram8GB() {
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
SecmonArgs args = {};
|
||||
args.X[0] = 0xF0000002;
|
||||
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
||||
svcCallSecureMonitor(&args);
|
||||
|
||||
if(args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
|
||||
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
||||
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
||||
return false;
|
||||
} else
|
||||
return args.X[1] == 0x00002000 ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -33,6 +33,8 @@
|
||||
class Board
|
||||
{
|
||||
public:
|
||||
static void PcvHijackDvfs(u32 vmin);
|
||||
static u32 GetMinimumGpuVoltage(u32 freqMhz);
|
||||
static void fuseReadSpeedos();
|
||||
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
||||
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
||||
@@ -61,10 +63,13 @@ class Board
|
||||
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
||||
static u8 GetFanRotationLevel();
|
||||
static u8 GetDramID();
|
||||
static void UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode);
|
||||
static bool IsDram8GB();
|
||||
protected:
|
||||
static void FetchHardwareInfos();
|
||||
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
||||
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
||||
private:
|
||||
static void SetSpeedoBracket();
|
||||
static void CacheDvfsTable();
|
||||
static Handle GetPcvHandle();
|
||||
};
|
||||
|
||||
@@ -47,8 +47,9 @@ bool hasChanged = true;
|
||||
ClockManager *ClockManager::instance = NULL;
|
||||
Thread governorTHREAD;
|
||||
u32 initialConfigValues[SysClkConfigValue_EnumMax]; // initial config. used for safety checks
|
||||
|
||||
u64 previousRamHz;
|
||||
bool kipAvailable = false;
|
||||
|
||||
ClockManager *ClockManager::GetInstance()
|
||||
{
|
||||
return instance;
|
||||
@@ -110,37 +111,7 @@ ClockManager::ClockManager()
|
||||
|
||||
this->context->dramID = Board::GetDramID();
|
||||
this->context->isDram8GB = Board::IsDram8GB();
|
||||
}
|
||||
|
||||
|
||||
void ClockManager::FixCpuBug() {
|
||||
if(this->config->Refresh() && this->RefreshContext()) {
|
||||
u32 targetHz = 0;
|
||||
u32 maxHz = 0;
|
||||
u32 nearestHz = 0;
|
||||
|
||||
// ResetToStockClocks();
|
||||
|
||||
targetHz = this->context->overrideFreqs[SysClkModule_CPU];
|
||||
if (!targetHz) {
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_CPU, this->context->profile, false);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_CPU, this->context->profile, false);
|
||||
}
|
||||
|
||||
if (targetHz) {
|
||||
maxHz = this->GetMaxAllowedHz(SysClkModule_CPU, this->context->profile);
|
||||
nearestHz = this->GetNearestHz(SysClkModule_CPU, targetHz, maxHz);
|
||||
|
||||
while ((nearestHz = this->GetNearestHz(SysClkModule_CPU, targetHz, maxHz)) != targetHz) {
|
||||
Board::SetHz(SysClkModule_CPU, 1020000000);
|
||||
svcSleepThread(1'000'000);
|
||||
Board::SetHz(SysClkModule_CPU, maxHz);
|
||||
this->context->freqs[SysClkModule_CPU] = maxHz;
|
||||
}
|
||||
Board::SetHz(SysClkModule_CPU, targetHz);
|
||||
}
|
||||
}
|
||||
previousRamHz = Board::GetHz(SysClkModule_MEM);
|
||||
}
|
||||
|
||||
ClockManager::~ClockManager()
|
||||
@@ -196,7 +167,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
{
|
||||
if (this->config->GetConfigValue(HocClkConfigValue_UncappedClocks))
|
||||
{
|
||||
return 4294967294; // Integer limit, uncapped clocks ON
|
||||
return ~0; // Integer limit, uncapped clocks ON
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -213,10 +184,10 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
return 614400000;
|
||||
case 1:
|
||||
return 691200000;
|
||||
case 2:
|
||||
case 2:
|
||||
return 768000000;
|
||||
default:
|
||||
return 614400000;
|
||||
return 614400000;
|
||||
}
|
||||
default:
|
||||
return 460800000;
|
||||
@@ -233,10 +204,10 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
return 844800000;
|
||||
case 1:
|
||||
return 921600000;
|
||||
case 2:
|
||||
case 2:
|
||||
return 998400000;
|
||||
default:
|
||||
return 844800000;
|
||||
return 844800000;
|
||||
}
|
||||
default:
|
||||
return 768000000;
|
||||
@@ -246,7 +217,7 @@ std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile p
|
||||
if(profile < SysClkProfile_HandheldCharging && Board::GetSocType() == SysClkSocType_Erista) {
|
||||
return 1581000000;
|
||||
} else {
|
||||
return 4294967294;
|
||||
return ~0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,7 +333,7 @@ void ClockManager::GovernorThread(void* arg)
|
||||
svcSleepThread(50'000'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
std::scoped_lock lock{mgr->contextMutex};
|
||||
|
||||
u32 currentHz = Board::GetHz(SysClkModule_GPU);
|
||||
@@ -463,12 +434,12 @@ void ClockManager::Tick()
|
||||
}
|
||||
}
|
||||
|
||||
if(this->config->GetConfigValue(HocClkConfigValue_EnforceBoardLimit) && opMode == AppletOperationMode_Console ) {
|
||||
if(Board::GetPowerMw(SysClkPowerSensor_Now) < 0) {
|
||||
ResetToStockClocks();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if(this->config->GetConfigValue(HocClkConfigValue_EnforceBoardLimit) && opMode == AppletOperationMode_Console ) {
|
||||
// if(Board::GetPowerMw(SysClkPowerSensor_Now) < 0) {
|
||||
// ResetToStockClocks();
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
if(((tmp451TempSoc() / 1000) > (int)this->config->GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && this->config->GetConfigValue(HocClkConfigValue_ThermalThrottle)) {
|
||||
ResetToStockClocks();
|
||||
@@ -484,6 +455,7 @@ void ClockManager::Tick()
|
||||
|
||||
if (this->RefreshContext() || this->config->Refresh())
|
||||
{
|
||||
|
||||
if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) {
|
||||
I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent));
|
||||
}
|
||||
@@ -495,10 +467,13 @@ void ClockManager::Tick()
|
||||
// ResetToStockClocks();
|
||||
return;
|
||||
}
|
||||
previousRamHz = Board::GetHz(SysClkModule_MEM);
|
||||
|
||||
bool returnRaw = false;
|
||||
for (unsigned int module = 0; module < SysClkModule_EnumMax; module++)
|
||||
{
|
||||
u32 oldHz = Board::GetHz((SysClkModule)module);
|
||||
|
||||
if(module > SysClkModule_MEM)
|
||||
returnRaw = true;
|
||||
else
|
||||
@@ -559,11 +534,44 @@ void ClockManager::Tick()
|
||||
targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10
|
||||
);
|
||||
|
||||
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
|
||||
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
|
||||
|
||||
Board::PcvHijackDvfs(vmin);
|
||||
|
||||
/* Update the voltage. */
|
||||
if (I2c_BuckConverter_GetMvOut(&I2c_Mariko_GPU) < vmin) {
|
||||
I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, vmin);
|
||||
}
|
||||
|
||||
this->context->voltages[HocClkVoltage_GPU] = vmin * 1000;
|
||||
}
|
||||
|
||||
Board::SetHz((SysClkModule)module, nearestHz);
|
||||
this->context->freqs[module] = nearestHz;
|
||||
}
|
||||
if(module == SysClkModule_CPU && this->config->GetConfigValue(HocClkConfigValue_FixCpuVoltBug)) {
|
||||
FixCpuBug();
|
||||
|
||||
if(module == SysClkModule_MEM && Board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset);
|
||||
dvfsOffset = std::max(dvfsOffset, -50);
|
||||
u32 vmin = Board::GetMinimumGpuVoltage(targetHz / 1000000) + dvfsOffset;
|
||||
Board::PcvHijackDvfs(vmin);
|
||||
|
||||
targetHz = this->context->overrideFreqs[SysClkModule_GPU];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false);
|
||||
}
|
||||
if(targetHz) {
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::SetHz(SysClkModule_GPU, targetHz);
|
||||
} else {
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -586,7 +594,7 @@ void ClockManager::WaitForNextTick()
|
||||
bool ClockManager::RefreshContext()
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
|
||||
std::uint32_t mode = 0;
|
||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||
@@ -613,6 +621,11 @@ bool ClockManager::RefreshContext()
|
||||
{
|
||||
// this->rnxSync->ToggleSync(this->GetConfig()->GetConfigValue(HocClkConfigValue_SyncReverseNXMode));
|
||||
Board::ResetToStock();
|
||||
if (Board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
Board::PcvHijackDvfs(0);
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
this->WaitForNextTick();
|
||||
}
|
||||
|
||||
@@ -648,6 +661,26 @@ bool ClockManager::RefreshContext()
|
||||
break;
|
||||
case SysClkModule_MEM:
|
||||
Board::ResetToStockMem();
|
||||
|
||||
if (Board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) {
|
||||
Board::PcvHijackDvfs(0);
|
||||
|
||||
u32 targetHz = this->context->overrideFreqs[SysClkModule_GPU];
|
||||
if (!targetHz)
|
||||
{
|
||||
targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false);
|
||||
if(!targetHz)
|
||||
targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false);
|
||||
}
|
||||
if(targetHz) {
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::SetHz(SysClkModule_GPU, targetHz);
|
||||
} else {
|
||||
Board::SetHz(SysClkModule_GPU, ~0);
|
||||
Board::ResetToStockGpu();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -816,6 +849,9 @@ void ClockManager::SetKipData() {
|
||||
table.eristaGpuVoltArray[i] = this->config->GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_e_76800 + i));
|
||||
}
|
||||
|
||||
CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, this->config->GetConfigValue(KipConfigValue_t6_tRTW_fine_tune));
|
||||
CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, this->config->GetConfigValue(KipConfigValue_t7_tWTR_fine_tune));
|
||||
|
||||
if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) {
|
||||
FileUtils::LogLine("[clock_manager] Failed to write KIP file");
|
||||
writeNotification("Horizon OC\nKip write failed");
|
||||
@@ -908,7 +944,6 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table);
|
||||
initialConfigValues[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table);
|
||||
|
||||
|
||||
initialConfigValues[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table);
|
||||
initialConfigValues[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table);
|
||||
initialConfigValues[KipConfigValue_tableConf] = cust_get_table_conf(&table);
|
||||
@@ -926,6 +961,8 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table);
|
||||
initialConfigValues[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table);
|
||||
initialConfigValues[KipConfigValue_gpuSpeedo] = cust_get_gpu_speedo(&table);
|
||||
initialConfigValues[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
|
||||
initialConfigValues[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
|
||||
}
|
||||
|
||||
// configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table);
|
||||
@@ -982,6 +1019,9 @@ void ClockManager::GetKipData() {
|
||||
initialConfigValues[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i);
|
||||
}
|
||||
|
||||
configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table);
|
||||
configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table);
|
||||
|
||||
// if(cust_get_cust_rev(&table) == KIP_CUST_REV)
|
||||
// return;
|
||||
|
||||
@@ -1001,74 +1041,3 @@ void ClockManager::GetKipData() {
|
||||
writeNotification("Horizon OC\nConfig refresh failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ClockManager::UpdateRamTimings() {
|
||||
u32 t1_tRCD = this->config->GetConfigValue(KipConfigValue_t1_tRCD);
|
||||
u32 t2_tRP = this->config->GetConfigValue(KipConfigValue_t2_tRP);
|
||||
u32 t3_tRAS = this->config->GetConfigValue(KipConfigValue_t3_tRAS);
|
||||
u32 t4_tRRD = this->config->GetConfigValue(KipConfigValue_t4_tRRD);
|
||||
u32 t5_tRFC = this->config->GetConfigValue(KipConfigValue_t5_tRFC);
|
||||
u32 t6_tRTW = this->config->GetConfigValue(KipConfigValue_t6_tRTW);
|
||||
u32 t7_tWTR = this->config->GetConfigValue(KipConfigValue_t7_tWTR);
|
||||
u32 t8_tREFI = this->config->GetConfigValue(KipConfigValue_t8_tREFI);
|
||||
bool hpMode = (bool)this->config->GetConfigValue(KipConfigValue_hpMode);
|
||||
|
||||
u64 ramFreq = initialConfigValues[KipConfigValue_marikoEmcMaxClock];
|
||||
u32 rlAdd = initialConfigValues[KipConfigValue_mem_burst_read_latency];
|
||||
u32 wlAdd = initialConfigValues[KipConfigValue_mem_burst_write_latency];
|
||||
|
||||
|
||||
Board::UpdateShadowRegs(t1_tRCD, t2_tRP, t3_tRAS, t4_tRRD, t5_tRFC, t6_tRTW, t7_tWTR, t8_tREFI, ramFreq, rlAdd, wlAdd, hpMode);
|
||||
}
|
||||
|
||||
unsigned int ramBrackets[][22] =
|
||||
{
|
||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }
|
||||
};
|
||||
|
||||
unsigned int gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||
|
||||
int ClockManager::GetSpeedoBracket (int speedo)
|
||||
{
|
||||
int speedoBracket = 3;
|
||||
if ((speedo < 1754) && (speedoBracket = 2, speedo < 1690)) {
|
||||
speedoBracket = !!(1625 < speedo);
|
||||
}
|
||||
|
||||
return speedoBracket;
|
||||
}
|
||||
|
||||
unsigned int ClockManager::GetGpuVoltage (unsigned int freq, int speedo)
|
||||
{
|
||||
long int loop;
|
||||
int bracket = GetSpeedoBracket(speedo);
|
||||
|
||||
if (freq < 1601)
|
||||
return 610;
|
||||
|
||||
loop = 0;
|
||||
do
|
||||
{
|
||||
if (freq <= ramBrackets[bracket][loop])
|
||||
return gpuDvfsArray[loop];
|
||||
|
||||
loop++;
|
||||
} while (loop != 22);
|
||||
|
||||
return 800;
|
||||
}
|
||||
|
||||
void ClockManager::calculateGpuVmin (void)
|
||||
{
|
||||
if(this->config->Refresh()) {
|
||||
SysClkConfigValueList configValues;
|
||||
this->config->GetConfigValues(&configValues);
|
||||
|
||||
int speedo = Board::getSpeedo(HorizonOCSpeedo_CPU), freq = this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock);
|
||||
configValues.values[KipConfigValue_marikoGpuVmin] = GetGpuVoltage(freq, speedo);
|
||||
this->config->SetConfigValues(&configValues, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class ClockManager
|
||||
|
||||
ClockManager();
|
||||
virtual ~ClockManager();
|
||||
void FixCpuBug();
|
||||
|
||||
SysClkContext GetCurrentContext();
|
||||
Config* GetConfig();
|
||||
@@ -63,7 +62,6 @@ class ClockManager
|
||||
void SetKipData();
|
||||
void GetKipData();
|
||||
static void GovernorThread(void* arg);
|
||||
void UpdateRamTimings();
|
||||
struct {
|
||||
std::uint32_t count;
|
||||
std::uint32_t list[SYSCLK_FREQ_LIST_MAX];
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -43,7 +43,7 @@ IpcService::IpcService(ClockManager* clockMgr)
|
||||
|
||||
this->running = false;
|
||||
this->clockMgr = clockMgr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void IpcService::SetRunning(bool running)
|
||||
@@ -209,16 +209,6 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
|
||||
return ipcSrv->SetKipData();
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_UpdateEmcRegs:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->UpdateEmcRegs();
|
||||
}
|
||||
break;
|
||||
case HocClkIpcCmd_CalculateGpuVmin:
|
||||
if (r->data.size >= 0) {
|
||||
return ipcSrv->CalculateGPUVmin();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SYSCLK_ERROR(Generic);
|
||||
@@ -377,23 +367,12 @@ Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) {
|
||||
|
||||
Result IpcService::SetKipData() {
|
||||
this->clockMgr->SetKipData();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::GetKipData() {
|
||||
this->clockMgr->GetKipData();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::UpdateEmcRegs() {
|
||||
this->clockMgr->UpdateRamTimings();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result IpcService::CalculateGPUVmin() {
|
||||
this->clockMgr->calculateGpuVmin();
|
||||
return 0;
|
||||
}
|
||||
@@ -57,8 +57,6 @@ class IpcService
|
||||
Result SetReverseNXRTMode(ReverseNXMode mode);
|
||||
Result SetKipData();
|
||||
Result GetKipData();
|
||||
Result UpdateEmcRegs();
|
||||
Result CalculateGPUVmin();
|
||||
bool running;
|
||||
Thread thread;
|
||||
LockableMutex threadMutex;
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
@@ -77,7 +77,11 @@ typedef struct {
|
||||
|
||||
u32 eristaGpuVoltArray[27];
|
||||
u32 marikoGpuVoltArray[24];
|
||||
u32 reserved[64];
|
||||
|
||||
u32 t6_tRTW_fine_tune;
|
||||
u32 t7_tWTR_fine_tune;
|
||||
|
||||
u32 reserved[60];
|
||||
} CustomizeTable;
|
||||
|
||||
#pragma pack(pop)
|
||||
@@ -200,6 +204,8 @@ static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_
|
||||
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
|
||||
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
|
||||
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
|
||||
static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); }
|
||||
static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); }
|
||||
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
|
||||
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
|
||||
|
||||
@@ -267,6 +273,8 @@ static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD
|
||||
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
|
||||
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
|
||||
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
|
||||
static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); }
|
||||
static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); }
|
||||
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
|
||||
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }
|
||||
|
||||
|
||||
18
build.sh
18
build.sh
@@ -21,20 +21,4 @@ cd ../../
|
||||
|
||||
cd Source/Horizon-OC-Monitor/
|
||||
make -j"$(nproc)"
|
||||
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
||||
|
||||
cd ../../
|
||||
|
||||
ROOT="build"
|
||||
PATCHES="Source/Atmosphere-Patches"
|
||||
|
||||
cp "$PATCHES/secmon_memory_layout.hpp" "$ROOT/libraries/libexosphere/include/exosphere/secmon/"
|
||||
cp "$PATCHES/secmon_emc_access_table_data.inc" "$ROOT/exosphere/program/source/smc/"
|
||||
cp "$PATCHES/secmon_define_emc_access_table.inc" "$ROOT/exosphere/program/source/smc/"
|
||||
cp "$PATCHES/secmon_smc_register_access.cpp" "$ROOT/exosphere/program/source/smc/"
|
||||
cd build/exosphere
|
||||
|
||||
make -j"$(nproc)"
|
||||
|
||||
cd out/nintendo_nx_arm64_armv8a/release
|
||||
cp "exosphere.bin" "../../../../../dist/"
|
||||
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
||||
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
Binary file not shown.
BIN
dist/atmosphere/kips/hoc.kip
vendored
BIN
dist/atmosphere/kips/hoc.kip
vendored
Binary file not shown.
BIN
dist/exosphere.bin
vendored
BIN
dist/exosphere.bin
vendored
Binary file not shown.
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
Binary file not shown.
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
Binary file not shown.
Reference in New Issue
Block a user