From 120367cf7ccba2b1b7c9b644877aa01aa0c7e457 Mon Sep 17 00:00:00 2001
From: KazushiM <85604869+KazushiMe@users.noreply.github.com>
Date: Tue, 24 Jan 2023 23:24:58 +0800
Subject: [PATCH] EMC voltage for Mariko; Fix #60; Show battery & voltage info
in overlay on Erista
- From previous analysis, EMC voltage is set before AMS loads on Mariko, and will not be set again or changed afterwards.
- sys-clk-OC will take care of setting emc voltage on Mariko once it loads.
- OS will not hang at boot as it always boots with EMC @ 1600 MHz.
---
.gitignore | 1 +
README.md | 74 +++++++++++--------
.../loader/source/oc/customize.cpp | 41 ++++++----
.../loader/source/oc/customize.hpp | 13 ++--
.../oc/{oc_suite_common.hpp => oc_common.hpp} | 7 +-
.../source/oc/{oc_suite.hpp => oc_loader.hpp} | 2 +-
.../oc/{oc_suite_test.cpp => oc_test.cpp} | 4 +-
.../oc/{oc_suite_test.hpp => oc_test.hpp} | 0
.../stratosphere/loader/source/oc/pcv/pcv.cpp | 3 +-
.../stratosphere/loader/source/oc/pcv/pcv.hpp | 29 +++++++-
.../loader/source/oc/pcv/pcv_erista.cpp | 15 +++-
.../loader/source/oc/pcv/pcv_erista.hpp | 8 +-
.../loader/source/oc/pcv/pcv_mariko.cpp | 29 +++++++-
.../loader/source/oc/pcv/pcv_mariko.hpp | 6 +-
.../stratosphere/loader/source/oc/ptm/ptm.hpp | 2 +-
.../{ldr_config.py => ldr_config_old.py} | 0
Source/sys-clk-OC/common/include/cpp_util.hpp | 36 +++++++++
Source/sys-clk-OC/common/include/sysclk.h | 1 +
Source/sys-clk-OC/common/include/sysclk/i2c.h | 30 ++++++--
Source/sys-clk-OC/common/src/i2c.c | 60 +++++++++++----
.../overlay/src/ui/gui/misc_gui.cpp | 27 +++----
.../sys-clk-OC/overlay/src/ui/gui/misc_gui.h | 41 ++++++----
.../sys-clk-OC/sysmodule/src/file_utils.cpp | 38 +++++-----
Source/sys-clk-OC/sysmodule/src/file_utils.h | 3 +-
24 files changed, 324 insertions(+), 146 deletions(-)
rename Source/Atmosphere/stratosphere/loader/source/oc/{oc_suite_common.hpp => oc_common.hpp} (93%)
rename Source/Atmosphere/stratosphere/loader/source/oc/{oc_suite.hpp => oc_loader.hpp} (95%)
rename Source/Atmosphere/stratosphere/loader/source/oc/{oc_suite_test.cpp => oc_test.cpp} (99%)
rename Source/Atmosphere/stratosphere/loader/source/oc/{oc_suite_test.hpp => oc_test.hpp} (100%)
rename Source/loaderConfigurator/{ldr_config.py => ldr_config_old.py} (100%)
create mode 100644 Source/sys-clk-OC/common/include/cpp_util.hpp
diff --git a/.gitignore b/.gitignore
index 5509140f..2276a02d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.DS_Store
+.vscode/
diff --git a/README.md b/README.md
index e5155327..319b0b75 100644
--- a/README.md
+++ b/README.md
@@ -7,24 +7,28 @@ Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW.
**DISCLAIMER: USE AT YOUR OWN RISK!**
-- Overclocking in general will shorten the lifespan of some hardware components.
-
-- Due to HorizonOS design, instabilities from unsafe RAM clocks may cause filesystem corruption. **Always make backup before usage.**
+- Overclocking in general will shorten the lifespan of some hardware components. **YOU ARE RESPONSIBLE for any problem or potential damage** if unsafe frequencies are ENABLED in sys-clk-OC. Issues like asking for bypassing limit will BE IGNORED OR CLOSED WITHOUT REPLY.
+- Due to HorizonOS design, instabilities from unsafe RAM clocks may cause filesystem corruption. **Always make backup before enabling DRAM OC.**
## Features
- Erista variant (HAC-001)
- - CPU Overclock
- - Safe: 1785 MHz
- - Unsafe (due to the limit of board power draw or power IC):
- - Enable "Allow Unsafe Frequencies" in overlay to unlock frequencies up to 2091 MHz
- - See [README for sys-clk-OC](https://github.com/KazushiMe/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md)
+ - CPU Overclock (Safe: 1785 MHz)
+ Unsafe
- - DRAM Overclock
- - Safe: 1862.4 MHz
- - Unsafe:
- - DRAM bus overvolting
+ - Due to the limit of board power draw or power IC
+ - Unlockable frequencies up to 2091 MHz
+ - See [README for sys-clk-OC](https://github.com/KazushiMe/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md)
+
+
+
+ - DRAM Overclock (Safe: 1862.4 MHz)
+ Unsafe
+
+ - Up to 2131 MHz with DRAM bus overvolting depending on your DRAM chip
+
+
- Modded sys-clk and ReverseNX-RT
- CPU & GPU frequency governor (Experimental)
@@ -33,16 +37,21 @@ Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW.
- Sync ReverseNX Mode
- Mariko variant (HAC-001-01, HDH-001, HEG-001)
- - CPU / GPU Overclock
- - Safe: 1963 / 998 MHz
- - Unsafe (due to the limit of board power draw or power IC):
- - Enable "Allow Unsafe Frequencies" in overlay to unlock frequencies up to 2397 / 1305 MHz
- - See [README for sys-clk-OC](https://github.com/KazushiMe/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md)
+ - CPU / GPU Overclock (Safe: 1963 / 998 MHz)
+ Unsafe
- - DRAM Overclock
- - Safe: 1996.8 MHz with built-in timing adjustment
- - Unsafe:
- - [DRAM bus overvolting](https://gist.github.com/KazushiMe/6bb0fcbefe0e03b1274079522516d56d).
+ - Due to the limit of board power draw or power IC
+ - Unlockable frequencies up to 2397 / 1305 MHz or 2295 / 1267 MHz
+ - See [README for sys-clk-OC](https://github.com/KazushiMe/Switch-OC-Suite/blob/master/Source/sys-clk-OC/README.md)
+
+
+
+ - DRAM Overclock (Safe: 1996.8 MHz)
+ Unsafe
+
+ - [DRAM bus overvolting](https://gist.github.com/KazushiMe/6bb0fcbefe0e03b1274079522516d56d).
+
+
- Modded sys-clk and ReverseNX-RT
- Auto CPU Boost
@@ -59,8 +68,7 @@ Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW.
- CPU & GPU frequency governor (Experimental)
- Adjust frequency based on load. Might decrease power draw but can introduce stutters. Can be turned off for specific titles.
-- Fast-charging (0.5A/2A) toggle, set charge limit (20% - 100%)
- - Hoag (Switch Lite) cannot use the fast-charging toggle feature for now [#56](https://github.com/KazushiMe/Switch-OC-Suite/issues/56).
+- Setting charge limit (20% - 100%)
- Long-term use of charge limit may render the battery gauge inaccurate. Performing full cycles could help recalibration, or try [battery_desync_fix_nx](https://github.com/CTCaer/battery_desync_fix_nx).
- Global profile
@@ -101,23 +109,25 @@ Overclocking suite for Horizon OS (HOS) running on Atmosphere CFW.
Deprecated: patching sysmodules manually
- This method is only served as reference as it could damage your MMC file system if not handled properly.
- Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (normally in `x.0.0`).
+ - This method is only served as reference as it could damage your MMC file system if not handled properly.
- Tools:
- - Lockpick_RCM
- - TegraExplorer
- - [hactool](https://github.com/SciresM/hactool)
- - [nx2elf](https://github.com/shuffle2/nx2elf)
- - elf2nso from [switch-tools](https://github.com/switchbrew/switch-tools/)
- - [hacpack](https://github.com/The-4n/hacPack)
+ - Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (normally in `x.0.0`).
+
+ - Tools:
+ - Lockpick_RCM
+ - TegraExplorer
+ - [hactool](https://github.com/SciresM/hactool)
+ - [nx2elf](https://github.com/shuffle2/nx2elf)
+ - elf2nso from [switch-tools](https://github.com/switchbrew/switch-tools/)
+ - [hacpack](https://github.com/The-4n/hacPack)
1. Dump `prod.keys` with Lockpick_RCM
2. Dump HOS firmware with TegraExplorer
3. Configure and run `test_patch.sh` to generate patched pcv & ptm sysmodules in nca
4. Replace nca in `SYSTEM:/Contents/registered/` with TegraExplorer
5. `ValidateAcidSignature()` should be stubbed to allow unsigned sysmodules to load (a.k.a. `loader_patch`)
+
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
index 41731e13..7caf1f54 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp
@@ -20,29 +20,34 @@ namespace ams::ldr::oc {
volatile CustomizeTable C = {
/* DRAM Timing:
- * AUTO_ADJ_MARIKO_SAFE: Auto adjust timings for LPDDR4 ≤3733 Mbps specs, 8Gb density (Default).
- * AUTO_ADJ_MARIKO_4266: Auto adjust timings for LPDDR4X 4266 Mbps specs, 8Gb density.
+ * AUTO_ADJ_MARIKO_SAFE_NO_ADJ_ERISTA: Auto adjust timings for Mariko LPDDR4X ≤3733 Mbps specs, 8Gb density; No timing adjustment for Erista. (Default)
+ * AUTO_ADJ_MARIKO_4266_NO_ADJ_ERISTA: Auto adjust timings for Mariko LPDDR4X 4266 Mbps specs, 8Gb density; No timing adjustments for Erista.
+ * NO_ADJ_ALL: No timing adjustment for both Erista and Mariko. Might achieve better performance on Mariko but lower maximum frequency is expected.
*/
-.mtcConf = AUTO_ADJ_MARIKO_SAFE,
+.mtcConf = AUTO_ADJ_MARIKO_SAFE_NO_ADJ_ERISTA,
/* Mariko CPU:
* - Max Clock in kHz:
* Default: 1785000
- * >= 2397000 will enable overvolting (> 1120 mV)
- * - Boost Clock in kHz:
- * Default: 1785000
- * Boost clock will be applied when applications request higher CPU frequency for quicker loading.
- * - Max Voltage in mV:
- * Default voltage: 1120
+ * 2397000 might be unreachable for some SoCs.
*/
.marikoCpuMaxClock = 2397000,
+/* - Boost Clock in kHz:
+ * Default: 1785000
+ * Boost clock will be applied when applications request higher CPU frequency for quicker loading.
+ * This will be set regardless of whether sys-clk is enabled.
+ */
.marikoCpuBoostClock = 1785000,
+/* - Max Voltage in mV:
+ * Default voltage: 1120
+ */
.marikoCpuMaxVolt = 1235,
/* Mariko GPU:
* - Max Clock in kHz:
* Default: 921600
* NVIDIA Maximum: 1267200
+ * 1305600 might be unreachable for some SoCs.
*/
.marikoGpuMaxClock = 1305600,
@@ -54,17 +59,22 @@ volatile CustomizeTable C = {
* - Graphical glitches
* - System instabilities
* - NAND corruption
- * Timings from auto-adjustment have been tested safe for up to 1996.8 MHz for all DRAM chips.
*/
.marikoEmcMaxClock = 1996800,
+/* - RAM Voltage in uV
+ * Range: 600'000 to 650'000 uV
+ * Value should be divided evenly by 5'000
+ * Default: 600'000
+ * Not enabled by default.
+ * This will not work without sys-clk-OC.
+ */
+.marikoEmcVolt = 0,
/* Erista CPU:
* Not tested but enabled by default.
- * - Enable Overclock
* - Max Voltage in mV
*/
-.eristaCpuOCEnabled= 1,
-.eristaCpuMaxVolt = 1257,
+.eristaCpuMaxVolt = 1235,
/* Erista EMC:
* - RAM Clock in kHz
@@ -73,13 +83,14 @@ volatile CustomizeTable C = {
* - Graphical glitches
* - System instabilities
* - NAND corruption
- * - RAM Voltage in uV
+ */
+.eristaEmcMaxClock = 1862400,
+/* - RAM Voltage in uV
* Range: 600'000 to 1250'000 uV
* Value should be divided evenly by 12'500
* Default(HOS): 1125'000
* Not enabled by default.
*/
-.eristaEmcMaxClock = 1862400,
.eristaEmcVolt = 0,
};
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
index f9f417d8..f80f87cd 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp
@@ -16,29 +16,30 @@
#pragma once
-#define CUST_REV 2
+#define CUST_REV 3
-#include "oc_suite_common.hpp"
+#include "oc_common.hpp"
namespace ams::ldr::oc {
#include "mtc_timing_table.hpp"
enum MtcConfig {
- AUTO_ADJ_MARIKO_SAFE = 0,
- AUTO_ADJ_MARIKO_4266 = 1,
+ AUTO_ADJ_MARIKO_SAFE_NO_ADJ_ERISTA = 0,
+ AUTO_ADJ_MARIKO_4266_NO_ADJ_ERISTA = 1,
+ NO_ADJ_ALL = 2,
};
typedef struct __attribute__((packed)) CustomizeTable {
u8 cust[4] = {'C', 'U', 'S', 'T'};
u16 custRev = CUST_REV;
- u16 mtcConf = AUTO_ADJ_MARIKO_SAFE;
+ u16 mtcConf = AUTO_ADJ_MARIKO_SAFE_NO_ADJ_ERISTA;
u32 marikoCpuMaxClock;
u32 marikoCpuBoostClock;
u32 marikoCpuMaxVolt;
u32 marikoGpuMaxClock;
u32 marikoEmcMaxClock;
- u32 eristaCpuOCEnabled;
+ u32 marikoEmcVolt;
u32 eristaCpuMaxVolt;
u32 eristaEmcMaxClock;
u32 eristaEmcVolt;
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp
similarity index 93%
rename from Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_common.hpp
rename to Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp
index bf14ed01..3982885b 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_common.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp
@@ -22,7 +22,7 @@
#define LOGGING(fmt, ...) ((void)0)
#define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#else
- #include "oc_suite_test.hpp"
+ #include "oc_test.hpp"
#endif
#include "customize.hpp"
@@ -39,8 +39,9 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1008);
R_DEFINE_ERROR_RESULT(InvalidGpuFreqMaxPattern, 1009);
R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1010);
- R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1011);
- R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1012);
+ R_DEFINE_ERROR_RESULT(InvalidRegulatorEntry, 1011);
+ R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1012);
+ R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1013);
}
namespace ams::ldr::oc {
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp
similarity index 95%
rename from Source/Atmosphere/stratosphere/loader/source/oc/oc_suite.hpp
rename to Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp
index 97cb5188..e0445818 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp
@@ -16,6 +16,6 @@
#pragma once
-#include "oc_suite_common.hpp"
+#include "oc_common.hpp"
#include "pcv/pcv.hpp"
#include "ptm/ptm.hpp"
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_test.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp
similarity index 99%
rename from Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_test.cpp
rename to Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp
index eb470090..61486d5f 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_test.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.cpp
@@ -15,8 +15,8 @@
*/
#ifndef ATMOSPHERE_IS_STRATOSPHERE
-#include "oc_suite_test.hpp"
-#include "oc_suite.hpp"
+#include "oc_test.hpp"
+#include "oc_loader.hpp"
void* loadExec(const char* file_loc, size_t* out_size) {
FILE* fp = fopen(file_loc, "rb");
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_test.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp
similarity index 100%
rename from Source/Atmosphere/stratosphere/loader/source/oc/oc_suite_test.hpp
rename to Source/Atmosphere/stratosphere/loader/source/oc/oc_test.hpp
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
index ce67ed13..19a6fa84 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp
@@ -33,7 +33,8 @@ void SafetyCheck() {
if (C.custRev != CUST_REV ||
C.marikoCpuMaxVolt >= 1300 ||
C.eristaCpuMaxVolt >= 1300 ||
- (C.eristaEmcVolt && (C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)))
+ (C.eristaEmcVolt && (C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)) ||
+ (C.marikoEmcVolt && (C.marikoEmcVolt < 600'000 || C.marikoEmcVolt > 650'000)))
{
CRASH("Triggered");
}
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
index 00976a80..01143df4 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp
@@ -16,7 +16,7 @@
#pragma once
-#include "../oc_suite_common.hpp"
+#include "../oc_common.hpp"
namespace ams::ldr::oc::pcv {
@@ -88,6 +88,33 @@ typedef struct __attribute__((packed)) dvfs_rail {
u32 unk_2[11];
} dvfs_rail;
+typedef struct __attribute__((packed)) regulator {
+ u64 id;
+ const char* name;
+ u32 type;
+ union {
+ struct {
+ u32 volt_reg;
+ u32 step_uv;
+ u32 min_uv;
+ u32 default_uv;
+ u32 max_uv;
+ u32 unk_0[2];
+ } type_1;
+ struct {
+ u32 unk_0;
+ u32 step_uv;
+ u32 unk_1;
+ u32 min_uv;
+ u32 max_uv;
+ u32 unk_2;
+ u32 default_uv;
+ } type_2_3;
+ };
+ u32 unk_x[60];
+} regulator;
+static_assert(sizeof(regulator) == 0x120);
+
constexpr u32 CpuClkOSLimit = 1785'000;
constexpr u32 MemClkOSLimit = 1600'000;
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp
index ea378233..acc68cf9 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.cpp
@@ -27,11 +27,20 @@ Result CpuFreqCvbTable(u32* ptr) {
bool validated = std::memcmp(cpu_cvb_table_head, CpuCvbTableDefault, sizeof(CpuCvbTableDefault)) == 0;
R_UNLESS(validated, ldr::ResultInvalidCpuDvfs());
- if (!C.eristaCpuOCEnabled)
- R_SKIP();
-
std::memcpy(reinterpret_cast(new_start), CpuCvbTableAppend, sizeof(CpuCvbTableAppend));
+ // Patch CPU max volt in existing and appended CPU dvfs table
+ if (C.eristaCpuMaxVolt) {
+ size_t table_size = sizeof(CpuCvbTableAppend) / sizeof(cpu_freq_cvb_table_t);
+ cpu_freq_cvb_table_t* entry = new_start;
+ for (size_t i = 0; i < table_size; i++) {
+ if (entry->cvb_dfll_param.c0 == CpuVoltL4T) {
+ PatchOffset(reinterpret_cast(&(entry->cvb_dfll_param.c0)), C.eristaCpuMaxVolt * 1000);
+ }
+ entry++;
+ }
+ }
+
R_SUCCEED();
}
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp
index f01fe4de..1bf329ae 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp
@@ -40,10 +40,12 @@ constexpr cpu_freq_cvb_table_t CpuCvbTableDefault[] = {
{ 1785000, { 1227500 }, { 5100873, -279186, 4747 } },
};
+constexpr u32 CpuVoltL4T = 1235'000;
+
constexpr cpu_freq_cvb_table_t CpuCvbTableAppend[] = {
- { 1887000, { 1235000 }, { 5100873, -279186, 4747 } },
- { 1963500, { 1235000 }, { 5100873, -279186, 4747 } },
- { 2091000, { 1235000 }, { 5100873, -279186, 4747 } },
+ { 1887000, { CpuVoltL4T }, { 5100873, -279186, 4747 } },
+ { 1963500, { CpuVoltL4T }, { 5100873, -279186, 4747 } },
+ { 2091000, { CpuVoltL4T }, { 5100873, -279186, 4747 } },
};
constexpr u32 CpuMinVolts[] = { 950, 850, 825, 810 };
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp
index f03da3d8..97b9ec56 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp
@@ -149,6 +149,9 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
* you'd better calculate timings yourself rather than relying on following algorithm.
*/
+ if (C.mtcConf == NO_ADJ_ALL)
+ return;
+
#define ADJUST_PROP(TARGET, REF) \
(u32)(std::ceil(REF + ((C.marikoEmcMaxClock-MemClkOSAlt)*(TARGET-REF))/(MemClkOSLimit-MemClkOSAlt)))
@@ -186,7 +189,7 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
ADJUST_PARAM_TABLE(table, la_scale_regs.mc_ptsa_grant_decrement, ref);
/* Timings that are available in or can be derived from LPDDR4X datasheet or TRM */
- const bool use_4266_spec = C.mtcConf == AUTO_ADJ_MARIKO_4266;
+ const bool use_4266_spec = C.mtcConf == AUTO_ADJ_MARIKO_4266_NO_ADJ_ERISTA;
// tCK_avg (average clock period) in ns
const double tCK_avg = 1000'000. / C.marikoEmcMaxClock;
// tRPpb (row precharge time per bank) in ns
@@ -368,6 +371,29 @@ Result MemFreqMax(u32* ptr) {
R_SUCCEED();
}
+Result MemVoltHandler(u32* ptr) {
+ u32 emc_uv = C.marikoEmcVolt;
+ if (!emc_uv)
+ R_SKIP();
+
+ regulator* entry = reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_2_3.default_uv));
+
+ constexpr u32 uv_step = 5'000;
+ constexpr u32 uv_min = 250'000;
+
+ if (entry->id != 2 || entry->type != 3 ||
+ entry->type_2_3.step_uv != uv_step ||
+ entry->type_2_3.min_uv != uv_min)
+ R_THROW(ldr::ResultInvalidRegulatorEntry());
+
+ if (emc_uv % uv_step)
+ emc_uv = emc_uv / uv_step * uv_step; // rounding
+
+ PatchOffset(ptr, emc_uv);
+
+ R_SUCCEED();
+}
+
void Patch(uintptr_t mapped_nso, size_t nso_size) {
PatcherEntry patches[] = {
{ "CPU Freq Vdd", &CpuFreqVdd, 1, nullptr, CpuClkOSLimit },
@@ -380,6 +406,7 @@ void Patch(uintptr_t mapped_nso, size_t nso_size) {
{ "MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, MemClkOSLimit },
{ "MEM Freq Max", &MemFreqMax, 0, nullptr, MemClkOSLimit },
{ "MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, MemClkPllmLimit },
+ { "MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltDefault }
};
for (uintptr_t ptr = mapped_nso;
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp
index 032a71b9..46c23175 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp
@@ -115,13 +115,9 @@ constexpr emc_dvb_dvfs_table_t EmcDvbTableDefault[] = {
{ 1600000, { 675, 650, 637, } },
};
-constexpr emc_dvb_dvfs_table_t EmcDvbTableReplaced[] = {
- { 1862400, { 675, 650, 637, } },
- { 2133000, { 700, 675, 650, } },
-};
-
constexpr u32 MemClkOSAlt = 1331'200;
constexpr u32 MemClkPllmLimit = 2133'000'000;
+constexpr u32 MemVoltDefault = 600'000;
constexpr u32 MTC_TABLE_REV = 3;
diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp
index 38d6fb8d..72360e44 100644
--- a/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp
+++ b/Source/Atmosphere/stratosphere/loader/source/oc/ptm/ptm.hpp
@@ -16,7 +16,7 @@
#pragma once
-#include "../oc_suite_common.hpp"
+#include "../oc_common.hpp"
namespace ams::ldr::oc::ptm {
diff --git a/Source/loaderConfigurator/ldr_config.py b/Source/loaderConfigurator/ldr_config_old.py
similarity index 100%
rename from Source/loaderConfigurator/ldr_config.py
rename to Source/loaderConfigurator/ldr_config_old.py
diff --git a/Source/sys-clk-OC/common/include/cpp_util.hpp b/Source/sys-clk-OC/common/include/cpp_util.hpp
new file mode 100644
index 00000000..34e5621f
--- /dev/null
+++ b/Source/sys-clk-OC/common/include/cpp_util.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+
+template
+class ScopeGuard {
+public:
+ ScopeGuard(F&& f)
+ : f(f), engaged(true) {};
+
+ ~ScopeGuard() {
+ if (engaged)
+ f();
+ };
+
+ ScopeGuard(ScopeGuard&& rhs)
+ : f(std::move(rhs.f)) {};
+
+ void dismiss() { engaged = false; }
+
+private:
+ F f;
+ bool engaged;
+};
+
+struct MakeScopeExit {
+ template
+ ScopeGuard operator+=(F&& f) {
+ return ScopeGuard(std::move(f));
+ };
+};
+
+#define STRING_CAT2(x, y) x##y
+#define STRING_CAT(x, y) STRING_CAT2(x, y)
+#define SCOPE_GUARD MakeScopeExit() += [&]() __attribute__((always_inline))
+#define SCOPE_EXIT auto STRING_CAT(scope_exit_, __LINE__) = SCOPE_GUARD
\ No newline at end of file
diff --git a/Source/sys-clk-OC/common/include/sysclk.h b/Source/sys-clk-OC/common/include/sysclk.h
index dfa7c6ec..d278083e 100644
--- a/Source/sys-clk-OC/common/include/sysclk.h
+++ b/Source/sys-clk-OC/common/include/sysclk.h
@@ -11,6 +11,7 @@
#pragma once
#ifdef __cplusplus
+#include "cpp_util.hpp"
extern "C" {
#endif
diff --git a/Source/sys-clk-OC/common/include/sysclk/i2c.h b/Source/sys-clk-OC/common/include/sysclk/i2c.h
index 8e6038f2..d5c2ea66 100644
--- a/Source/sys-clk-OC/common/include/sysclk/i2c.h
+++ b/Source/sys-clk-OC/common/include/sysclk/i2c.h
@@ -14,14 +14,34 @@ float I2c_Max17050_GetBatteryCurrent();
const u8 MAX17050_CURRENT_REG = 0x0A;
-// Max77812 Mariko-specific buck converter
-typedef enum I2c_Max77812_Volt_Type {
+// Buck Converter
+typedef enum I2c_BuckConverter_Reg {
+ I2c_Max77620_SD1VOLT_REG = 0x16,
+ I2c_Max77621_VOLT_REG = 0x00,
I2c_Max77812_CPUVOLT_REG = 0x26,
I2c_Max77812_GPUVOLT_REG = 0x23,
- I2c_Max77812_MEMVOLT_REG = 0x25,
-} I2c_Max77812_Volt_Type;
+ I2c_Max77812_MEMVOLT_REG = 0x25, // Master 3 (GPU 1 + 2, DRAM 3, CPU 4)
+} I2c_BuckConverter_Reg;
-u32 I2c_Max77812_GetMVOUT(I2c_Max77812_Volt_Type type);
+typedef struct I2c_BuckConverter_Domain {
+ I2cDevice device;
+ I2c_BuckConverter_Reg reg;
+ u8 volt_mask;
+ u32 uv_step;
+ u32 uv_min;
+ u32 uv_max;
+ u8 por_val;
+} I2c_BuckConverter_Domain;
+
+const I2c_BuckConverter_Domain I2c_Erista_CPU = { I2cDevice_Max77621Cpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
+const I2c_BuckConverter_Domain I2c_Erista_GPU = { I2cDevice_Max77621Gpu, I2c_Max77621_VOLT_REG, 0x7F, 6250, 606250, 1400000, };
+const I2c_BuckConverter_Domain I2c_Erista_DRAM = { I2cDevice_Max77620Pmic, I2c_Max77620_SD1VOLT_REG, 0x7F, 12500, 600000, 1250000, };
+const I2c_BuckConverter_Domain I2c_Mariko_CPU = { I2cDevice_Max77812_2, I2c_Max77812_CPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
+const I2c_BuckConverter_Domain I2c_Mariko_GPU = { I2cDevice_Max77812_2, I2c_Max77812_GPUVOLT_REG, 0xFF, 5000, 250000, 1525000, 0x78 };
+const I2c_BuckConverter_Domain I2c_Mariko_DRAM = { I2cDevice_Max77812_2, I2c_Max77812_MEMVOLT_REG, 0xFF, 5000, 250000, 650000, 0x78 };
+
+u32 I2c_BuckConverter_GetMvOut(const I2c_BuckConverter_Domain* domain);
+Result I2c_BuckConverter_SetMvOut(const I2c_BuckConverter_Domain* domain, u32 mvolt);
// Bq24193 Battery management
u32 I2c_Bq24193_Convert_Raw_mA(u8 raw);
diff --git a/Source/sys-clk-OC/common/src/i2c.c b/Source/sys-clk-OC/common/src/i2c.c
index cef2d94c..115c9e76 100644
--- a/Source/sys-clk-OC/common/src/i2c.c
+++ b/Source/sys-clk-OC/common/src/i2c.c
@@ -83,24 +83,58 @@ float I2c_Max17050_GetBatteryCurrent() {
return (s16)val * (1.5625 / (SenseResistor * CGain));
}
-u32 I2c_Max77812_GetMVOUT(I2c_Max77812_Volt_Type type) {
- u8 reg = (u8)type;
+u32 I2c_BuckConverter_MultiplierToMvOut(const I2c_BuckConverter_Domain* domain, u8 multiplier) {
+ return (domain->uv_min + domain->uv_step * multiplier) / 1000;
+}
- const u32 MIN_MV = 250;
- const u32 MV_STEP = 5;
- const u8 RESET_VAL = 0x78;
+u8 I2c_BuckConverter_MvOutToMultiplier(const I2c_BuckConverter_Domain* domain, u32 mvolt) {
+ u32 uvolt = mvolt * 1000;
+ if (uvolt < domain->uv_min)
+ uvolt = domain->uv_min;
+ if (uvolt > domain->uv_max)
+ uvolt = domain->uv_max;
- u8 val = RESET_VAL;
- // Retry 3 times if received RESET_VAL
+ return (uvolt - domain->uv_min) / domain->uv_step;
+}
+
+u32 I2c_BuckConverter_GetMvOut(const I2c_BuckConverter_Domain* domain) {
+ u8 val;
+ Result res;
+ // Retry 3 times if failed or received POR value
for (int i = 0; i < 3; i++) {
- if (I2cRead_OutU8(I2cDevice_Max77812_2, reg, &val))
- return 0u;
- if (val != RESET_VAL)
- break;
- svcSleepThread(10);
+ res = I2cRead_OutU8(domain->device, domain->reg, &val);
+ if (R_FAILED(res) || (domain->por_val && val == domain->por_val)) {
+ svcSleepThread(1000);
+ continue;
+ }
+ return I2c_BuckConverter_MultiplierToMvOut(domain, val & domain->volt_mask);
}
+ return 0u;
+}
- return val * MV_STEP + MIN_MV;
+Result I2c_BuckConverter_SetMvOut(const I2c_BuckConverter_Domain* domain, u32 mvolt) {
+ u8 val;
+ Result res = I2cRead_OutU8(domain->device, domain->reg, &val);
+ if (R_FAILED(res))
+ return res;
+
+ u8 multiplier = I2c_BuckConverter_MvOutToMultiplier(domain, mvolt);
+ val &= ~domain->volt_mask;
+ val |= multiplier & domain->volt_mask;
+
+ res = I2cSet_U8(domain->device, domain->reg, val);
+ if (R_FAILED(res))
+ return res;
+
+ svcSleepThread(1000);
+ u8 new_val;
+ res = I2cRead_OutU8(domain->device, domain->reg, &new_val);
+ if (R_FAILED(res))
+ return res;
+ if (new_val != val)
+ return -1;
+
+ return 0;
}
u8 I2c_Bq24193_Convert_mA_Raw(u32 ma) {
diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp
index 3c71a5db..99a1512c 100644
--- a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp
+++ b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp
@@ -65,7 +65,6 @@ void MiscGui::listUI()
addConfigToggle(SysClkConfigValue_AutoCPUBoost);
}
- addConfigToggle(SysClkConfigValue_AllowUnsafeFrequencies);
addConfigToggle(SysClkConfigValue_SyncReverseNXMode);
addConfigToggle(SysClkConfigValue_GovernorExperimental);
@@ -86,7 +85,7 @@ void MiscGui::listUI()
uint32_t current_ma = val * 100;
this->configList->values[SysClkConfigValue_ChargingCurrentLimit] = current_ma;
- snprintf(chargingCurrentBarDesc, sizeof(chargingCurrentBarDesc), "Battery Charging Current: %lu mA", this->configList->values[SysClkConfigValue_ChargingCurrentLimit]);
+ snprintf(chargingCurrentBarDesc, sizeof(chargingCurrentBarDesc), "Battery Charging Current: %lu mA (Now: %+.2f mA)", this->configList->values[SysClkConfigValue_ChargingCurrentLimit], this->i2cInfo->batCurrent);
this->chargingCurrentHeader->setText(chargingCurrentBarDesc);
Result rc = sysclkIpcSetConfigValues(this->configList);
@@ -109,7 +108,7 @@ void MiscGui::listUI()
}
this->configList->values[SysClkConfigValue_ChargingLimitPercentage] = val;
- snprintf(chargingLimitBarDesc, sizeof(chargingLimitBarDesc), "Battery Charging Limit: %lu%% (%u%%)", this->configList->values[SysClkConfigValue_ChargingLimitPercentage], this->batteryChargePerc);
+ snprintf(chargingLimitBarDesc, sizeof(chargingLimitBarDesc), "Battery Charging Limit: %lu%% (Now: %u%%)", this->configList->values[SysClkConfigValue_ChargingLimitPercentage], this->batteryChargePerc);
this->chargingLimitHeader->setText(chargingLimitBarDesc);
this->chargingLimitBar->setIcon(PsmGetBatteryStateIcon(this->chargeInfo));
@@ -144,13 +143,11 @@ void MiscGui::listUI()
this->listElement->addItem(this->backlightToggle);
// Info
- if (this->isMariko) {
- this->listElement->addItem(new tsl::elm::CategoryHeader("Info"));
- this->listElement->addItem(new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
- renderer->drawString(this->infoNames, false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR);
- renderer->drawString(this->infoVals, false, x + 120, y + 20, SMALL_TEXT_SIZE, VALUE_COLOR);
- }), SMALL_TEXT_SIZE * 12 + 20);
- }
+ this->listElement->addItem(new tsl::elm::CategoryHeader("Info"));
+ this->listElement->addItem(new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) {
+ renderer->drawString(this->infoNames, false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR);
+ renderer->drawString(this->infoVals, false, x + 120, y + 20, SMALL_TEXT_SIZE, VALUE_COLOR);
+ }), SMALL_TEXT_SIZE * 12 + 20);
}
void MiscGui::refresh() {
@@ -175,16 +172,14 @@ void MiscGui::refresh() {
this->backlightToggle->setState(lblstatus);
this->chargingCurrentBar->setProgress(this->configList->values[SysClkConfigValue_ChargingCurrentLimit] / 100);
- snprintf(chargingCurrentBarDesc, sizeof(chargingCurrentBarDesc), "Battery Charging Current: %lu mA", this->configList->values[SysClkConfigValue_ChargingCurrentLimit]);
+ snprintf(chargingCurrentBarDesc, sizeof(chargingCurrentBarDesc), "Battery Charging Current: %lu mA (Now: %+.2f mA)", this->configList->values[SysClkConfigValue_ChargingCurrentLimit], this->i2cInfo->batCurrent);
this->chargingCurrentHeader->setText(chargingCurrentBarDesc);
this->chargingLimitBar->setProgress(this->configList->values[SysClkConfigValue_ChargingLimitPercentage]);
- snprintf(chargingLimitBarDesc, sizeof(chargingLimitBarDesc), "Battery Charging Limit: %lu%% (%u%%)", this->configList->values[SysClkConfigValue_ChargingLimitPercentage], this->batteryChargePerc);
+ snprintf(chargingLimitBarDesc, sizeof(chargingLimitBarDesc), "Battery Charging Limit: %lu%% (Now: %u%%)", this->configList->values[SysClkConfigValue_ChargingLimitPercentage], this->batteryChargePerc);
this->chargingLimitHeader->setText(chargingLimitBarDesc);
- if (this->isMariko) {
- I2cGetInfo(this->i2cInfo);
- UpdateInfo(this->infoVals, sizeof(this->infoVals));
- }
+ I2cGetInfo(this->i2cInfo);
+ UpdateInfo(this->infoVals, sizeof(this->infoVals));
}
}
diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h
index c10a5346..8f106401 100644
--- a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h
+++ b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h
@@ -32,9 +32,9 @@ class MiscGui : public BaseMenuGui
protected:
typedef struct {
float batCurrent;
- u32 cpuVolt = 620;
- u32 gpuVolt = 610;
- u32 dramVolt = 600;
+ u32 cpuVolt;
+ u32 gpuVolt;
+ u32 dramVolt;
} I2cInfo;
void PsmUpdate(uint32_t dispatchId = 0)
@@ -57,11 +57,12 @@ class MiscGui : public BaseMenuGui
{
i2cInitialize();
- i2cInfo->batCurrent = I2c_Max17050_GetBatteryCurrent();
+ float batCurrent = I2c_Max17050_GetBatteryCurrent();
+ i2cInfo->batCurrent = std::abs(batCurrent) < 10. ? 0. : batCurrent;
- i2cInfo->cpuVolt = I2c_Max77812_GetMVOUT(I2c_Max77812_CPUVOLT_REG);
- i2cInfo->gpuVolt = I2c_Max77812_GetMVOUT(I2c_Max77812_GPUVOLT_REG);
- i2cInfo->dramVolt = I2c_Max77812_GetMVOUT(I2c_Max77812_MEMVOLT_REG);
+ i2cInfo->cpuVolt = I2c_BuckConverter_GetMvOut(isMariko ? &I2c_Mariko_CPU : &I2c_Erista_CPU);
+ i2cInfo->gpuVolt = I2c_BuckConverter_GetMvOut(isMariko ? &I2c_Mariko_GPU : &I2c_Erista_GPU);
+ i2cInfo->dramVolt = I2c_BuckConverter_GetMvOut(isMariko ? &I2c_Mariko_DRAM : &I2c_Erista_DRAM);
I2c_Bq24193_GetFastChargeCurrentLimit(reinterpret_cast(&(chargeInfo->ChargeCurrentLimit)));
@@ -78,16 +79,13 @@ class MiscGui : public BaseMenuGui
if (chargeInfo->ChargeVoltageLimit)
snprintf(chargeVoltLimit, sizeof(chargeVoltLimit), ", %umV", chargeInfo->ChargeVoltageLimit);
- char chargWattsInfo[50] = "";
+ char chargWattsInfo[30] = "";
if (chargeInfo->ChargerType)
snprintf(chargWattsInfo, sizeof(chargWattsInfo), " %.1fV/%.1fA (%.1fW)", chargerVoltLimit, chargerCurrLimit, chargerOutWatts);
char batCurInfo[30] = "";
- if (std::abs(i2cInfo->batCurrent) < 10)
- snprintf(batCurInfo, sizeof(batCurInfo), "0mA");
- else
- snprintf(batCurInfo, sizeof(batCurInfo), "%+.2fmA (%+.2fW)",
- i2cInfo->batCurrent, i2cInfo->batCurrent * (float)chargeInfo->VoltageAvg / 1000'000);
+ snprintf(batCurInfo, sizeof(batCurInfo), "%+.2fmA (%+.2fW)",
+ i2cInfo->batCurrent, i2cInfo->batCurrent * (float)chargeInfo->VoltageAvg / 1000'000);
snprintf(out, outsize,
"%s%s\n"
@@ -155,10 +153,21 @@ class MiscGui : public BaseMenuGui
I2cInfo* i2cInfo;
LblBacklightSwitchStatus lblstatus = LblBacklightSwitchStatus_Disabled;
- const char* infoNames = "Charger:\nBattery:\nCurrent Limit:\nCharging Limit:\nRaw Charge:\nBattery Age:\nPower Role:\nCurrent Flow:\n\nCPU Volt:\nGPU Volt:\nDRAM Volt:";
+ const char* infoNames =
+ "Charger:\n"\
+ "Battery:\n"\
+ "Current Limit:\n"\
+ "Charging Limit:\n"\
+ "Raw Charge:\n"\
+ "Battery Age:\n"\
+ "Power Role:\n"\
+ "Current Flow:\n\n"\
+ "CPU Volt:\n"\
+ "GPU Volt:\n"\
+ "DRAM Volt:";
char infoVals[300] = "";
- char chargingLimitBarDesc[40] = "";
- char chargingCurrentBarDesc[45] = "";
+ char chargingLimitBarDesc[50] = "";
+ char chargingCurrentBarDesc[60] = "";
u32 batteryChargePerc = 0;
u8 frameCounter = 60;
};
diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp
index 95338f23..7351cb11 100644
--- a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp
+++ b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp
@@ -185,11 +185,14 @@ void FileUtils::Exit()
void FileUtils::ParseLoaderKip() {
const char* dirs[] = { "/", "/atmosphere/", "/atmosphere/kips/", "/bootloader/" };
char* full_path = new char[0x200];
+ SCOPE_EXIT { delete[] full_path; };
+
for (auto const& dir : dirs) {
struct dirent *entry = NULL;
DIR *dp = opendir(dir);
if (!dp)
continue;
+ SCOPE_EXIT { closedir(dp); };
while ((entry = readdir(dp))) {
if (entry->d_type != DT_REG)
@@ -219,18 +222,15 @@ void FileUtils::ParseLoaderKip() {
continue;
if (R_SUCCEEDED(CustParser(full_path, filesize))) {
- LogLine("Parsed cust config from %s, maxMemFreq: %u MHz, boostCpuFreq: %u MHz",
+ LogLine("Parsed cust config from \"%s\", maxMemFreq: %u MHz, boostCpuFreq: %u MHz",
full_path,
Clocks::maxMemFreq / 1'000'000,
Clocks::boostCpuFreq / 1'000'000
);
- delete[] full_path;
return;
}
}
- closedir(dp);
}
- delete[] full_path;
}
Result FileUtils::CustParser(const char* filepath, size_t filesize) {
@@ -245,17 +245,17 @@ Result FileUtils::CustParser(const char* filepath, size_t filesize) {
FILE* fp = fopen(filepath, "r");
if (!fp)
return ParseError_OpenReadFailed;
+ SCOPE_EXIT { fclose(fp); };
constexpr uint8_t KIP_MAGIC[] = {'K', 'I', 'P', '1', 'L', 'o', 'a', 'd', 'e', 'r'};
constexpr size_t BLOCK_SIZE = 0x1000;
char* tmp_block = new char[BLOCK_SIZE];
+ SCOPE_EXIT { delete[] tmp_block; };
fread(tmp_block, sizeof(char), BLOCK_SIZE, fp);
- if (memcmp(KIP_MAGIC, tmp_block, sizeof(KIP_MAGIC))) {
- delete[] tmp_block;
+ if (memcmp(KIP_MAGIC, tmp_block, sizeof(KIP_MAGIC)))
return ParseError_WrongKipMagic;
- }
CustTable table {};
@@ -274,23 +274,15 @@ Result FileUtils::CustParser(const char* filepath, size_t filesize) {
}
found:
- delete[] tmp_block;
-
- if (!cust_pos) {
- fclose(fp);
+ if (!cust_pos)
return ParseError_CustNotFound;
- }
memset(reinterpret_cast(&table), 0, sizeof(CustTable));
fsetpos(fp, &cust_pos);
- if (!fread(reinterpret_cast(&table), 1, sizeof(CustTable), fp)) {
- fclose(fp);
+ if (!fread(reinterpret_cast(&table), 1, sizeof(CustTable), fp))
return ParseError_OpenReadFailed;
- }
- fclose(fp);
-
- if (table.custRev != 2)
+ if (table.custRev != CUST_REV)
return ParseError_WrongCustRev;
if (Clocks::GetIsMariko()) {
@@ -298,6 +290,11 @@ Result FileUtils::CustParser(const char* filepath, size_t filesize) {
Clocks::boostCpuFreq = table.marikoCpuBoostClock * 1000;
if (table.marikoEmcMaxClock)
Clocks::maxMemFreq = table.marikoEmcMaxClock * 1000;
+ if (table.marikoEmcVolt && table.marikoEmcVolt >= 600'000 && table.marikoEmcVolt <= 650'000) {
+ u32 mvolt = table.marikoEmcVolt / 1000;
+ Result res = I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM, mvolt);
+ LogLine("Set EMC volt to %u mV: %s", mvolt, R_FAILED(res) ? "Failed" : "OK");
+ }
} else {
if (table.eristaEmcMaxClock)
Clocks::maxMemFreq = table.eristaEmcMaxClock * 1000;
@@ -335,6 +332,7 @@ Result FileUtils::mkdir_p(const char* dirpath) {
size_t path_len = strnlen(dirpath, 0x1000);
char* path_copy = new char[path_len];
+ SCOPE_EXIT { delete[] path_copy; };
memcpy(path_copy, dirpath, path_len);
char* p = path_copy;
while (*p) {
@@ -344,7 +342,7 @@ Result FileUtils::mkdir_p(const char* dirpath) {
if (R_FAILED(mkdir_wrapper(path_copy))) {
res = -1;
- goto end;
+ return res;
}
*p = '/';
@@ -355,7 +353,5 @@ Result FileUtils::mkdir_p(const char* dirpath) {
if (R_FAILED(mkdir_wrapper(path_copy)))
res = -1;
- end:
- delete[] path_copy;
return res;
}
diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.h b/Source/sys-clk-OC/sysmodule/src/file_utils.h
index b2ec0c00..1e76832a 100644
--- a/Source/sys-clk-OC/sysmodule/src/file_utils.h
+++ b/Source/sys-clk-OC/sysmodule/src/file_utils.h
@@ -38,6 +38,7 @@ class FileUtils
static void ParseLoaderKip();
static Result mkdir_p(const char* dirpath);
protected:
+ static const uint16_t CUST_REV = 3;
typedef struct CustTable {
uint8_t cust[4] = {'C', 'U', 'S', 'T'};
uint16_t custRev;
@@ -47,7 +48,7 @@ class FileUtils
uint32_t marikoCpuMaxVolt;
uint32_t marikoGpuMaxClock;
uint32_t marikoEmcMaxClock;
- uint32_t eristaCpuOCEnable;
+ uint32_t marikoEmcVolt;
uint32_t eristaCpuMaxVolt;
uint32_t eristaEmcMaxClock;
uint32_t eristaEmcVolt;