diff --git a/Source/hoc-clk/common/include/hocclk/clock_manager.h b/Source/hoc-clk/common/include/hocclk/clock_manager.h index eaf89b55..73978ec2 100644 --- a/Source/hoc-clk/common/include/hocclk/clock_manager.h +++ b/Source/hoc-clk/common/include/hocclk/clock_manager.h @@ -83,7 +83,8 @@ typedef struct { bool isKipLoaded; bool rebootRequired; bool isFirstLoad; - + + bool isWdtEnabled; // Reserved for future use u8 reserved[0x358]; } HocClkContext; diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index 3bc27fa4..89d5baae 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -79,6 +79,8 @@ typedef enum { HocClkConfigValue_AutoRamCpuCpuOCFreq, HocClkConfigValue_AutoRamCpuRamOCThreshold, + HocClkConfigValue_Watchdog, + KipConfigValue_custRev, KipConfigValue_KipVersion, // KipConfigValue_mtcConf, @@ -337,7 +339,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr return pretty ? "Auto High RAM CPU OC Freq" : "auto_ram_cpu_cpu_oc_freq"; case HocClkConfigValue_AutoRamCpuRamOCThreshold: return pretty ? "Auto High RAM CPU OC RAM Threshold" : "auto_ram_cpu_ram_oc_threshold"; - + case HocClkConfigValue_Watchdog: + return pretty ? "Watchcat" : "watchdog"; // More dignified // KIP config values case KipConfigValue_custRev: return pretty ? "Custom Revision" : "kip_cust_rev"; @@ -656,6 +659,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case HocClkConfigValue_MarikoMiddleFreqs: case HocClkConfigValue_LiveGpuVoltage: case HocClkConfigValue_AutoRAMCPUOverclock: + case HocClkConfigValue_Watchdog: return (input & 0x1) == input; case KipConfigValue_KipVersion: diff --git a/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp index 322cb480..a728757a 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp @@ -44,6 +44,7 @@ tsl::elm::ListItem* aotagTempItem = NULL; tsl::elm::ListItem* dramTempItem = NULL; tsl::elm::ListItem* cTypeItem = NULL; tsl::elm::ListItem* creditsItem = NULL; +tsl::elm::ListItem* wdtItem = NULL; #define R_ARROW "\u2192" @@ -159,6 +160,9 @@ void AboutGui::listUI() kipLoadedItem = new tsl::elm::ListItem("KIP status:"); this->listElement->addItem(kipLoadedItem); + wdtItem = new tsl::elm::ListItem("Watchcat:"); + this->listElement->addItem(wdtItem); + if(!IsHoag()) { sysdockStatusItem = new tsl::elm::ListItem("sys-dock status:"); @@ -282,6 +286,7 @@ void AboutGui::refresh() dramTempItem->setValue(strings[12]); cTypeItem->setValue(hocClkFormatConsoleType(this->context->consoleType, true)); + wdtItem->setValue(context->isWdtEnabled ? "Enabled" : "Disabled"); } class CreditsSubMenu : public AboutGui { diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index 2d433860..e02cfc88 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -1191,6 +1191,7 @@ class SafetySubMenuGui : public MiscGui { this->listElement->addItem(new CompactCategoryHeader("Safety Settings")); addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr); addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr); + addConfigToggle(HocClkConfigValue_Watchdog, nullptr); #if IS_MINIMAL == 0 ValueThresholds throttleThresholds(70, 80); diff --git a/Source/hoc-clk/sysmodule/src/board/board.cpp b/Source/hoc-clk/sysmodule/src/board/board.cpp index 9146adf7..69bd3d5d 100644 --- a/Source/hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board.cpp @@ -95,7 +95,8 @@ namespace board { rc = pscPmModuleGetRequest(&s_pscModule, &state, &flags); if (R_SUCCEEDED(rc)) { if (state == PscPmState_Awake) { - i2c::wdt::Arm(i2c::wdt::MAX77620_WDT_2S); + i2c::wdt::ResetWdtEnableState(); + i2c::wdt::Pet(); s_isAwake = true; } else if (state == PscPmState_ReadySleep) { i2c::wdt::Disarm(); @@ -251,9 +252,6 @@ namespace board { rc = threadStart(&s_pscThread); ASSERT_RESULT_OK(rc, "threadStart"); - - /* Arm the watchdog */ - i2c::wdt::Arm(i2c::wdt::MAX77620_WDT_2S); } void Exit() { diff --git a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp index 803741b5..c6dca098 100644 --- a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp +++ b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp @@ -1,5 +1,5 @@ /* - * + * * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors * * This program is free software; you can redistribute it and/or modify it @@ -17,6 +17,9 @@ */ #include "max77620_wdt.hpp" +#include "../file/config.hpp" +#include +#include /* PMIC Registers */ #define MAX77620_REG_CNFGGLBL2 ((u8)0x01) @@ -46,6 +49,9 @@ namespace i2c::wdt { + static LockableMutex g_wdt_mutex; + static bool isWdtEnabled = false; + static Result update_bits(u8 reg, u8 mask, u8 val) { u8 cur; Result rc; @@ -58,7 +64,11 @@ namespace i2c::wdt { return I2cSet_U8(I2cDevice_Max77620Pmic, reg, cur); } - void Arm(max77620_wdt_time_t timeout) { + static void ArmLocked(max77620_wdt_time_t timeout) { + if (isWdtEnabled) { + return; + } + Result rc; u8 twd; @@ -91,16 +101,48 @@ namespace i2c::wdt { /* Enable. */ rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_WDTEN, MAX77620_WDTEN); ASSERT_RESULT_OK(rc, "update_bits"); + + isWdtEnabled = true; } void Disarm() { + if (!isWdtEnabled) { + return; + } + Result rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_WDTEN, (u8)0x00); ASSERT_RESULT_OK(rc, "update_bits"); + + isWdtEnabled = false; + } + + void ResetWdtEnableState() { + std::scoped_lock lock{g_wdt_mutex}; + + isWdtEnabled = false; + } + + void Arm(max77620_wdt_time_t timeout) { + std::scoped_lock lock{g_wdt_mutex}; + + ArmLocked(timeout); + } + + bool IsWdtEnabled() { + return isWdtEnabled; } void Pet() { - Result rc = update_bits(MAX77620_REG_CNFGGLBL3, MAX77620_WDTC_MASK, MAX77620_WDTC_KICK); - ASSERT_RESULT_OK(rc, "update_bits"); + const bool watchdogEnabled = file::config::GetConfigValue(HocClkConfigValue_Watchdog); + std::scoped_lock lock{g_wdt_mutex}; + + if (watchdogEnabled) { + ArmLocked(i2c::wdt::MAX77620_WDT_2S); + Result rc = update_bits(MAX77620_REG_CNFGGLBL3, MAX77620_WDTC_MASK, MAX77620_WDTC_KICK); + ASSERT_RESULT_OK(rc, "update_bits"); + } else { + Disarm(); + } } -} // namespace pwr::wdt +} // namespace i2c::wdt diff --git a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp index 25baa408..005ef6e0 100644 --- a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp +++ b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp @@ -15,6 +15,8 @@ * */ +#pragma once + #include #include #include "i2cDrv.h" @@ -34,4 +36,6 @@ namespace i2c::wdt { void Pet(); -} // namespace pwr::wdt + void ResetWdtEnableState(); + bool IsWdtEnabled(); +} // namespace i2c::wdt diff --git a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp index a2d2b1da..c2fb455e 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp +++ b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp @@ -779,6 +779,8 @@ namespace mgr { else gContext.resolutionHeight = 0; // N/A + gContext.isWdtEnabled = i2c::wdt::IsWdtEnabled(); + return hasChanged; }