diff --git a/Source/hoc-clk/common/include/hocclk/board.h b/Source/hoc-clk/common/include/hocclk/board.h index 389ba513..0b424f9d 100644 --- a/Source/hoc-clk/common/include/hocclk/board.h +++ b/Source/hoc-clk/common/include/hocclk/board.h @@ -95,6 +95,7 @@ typedef enum HocClkThermalSensor_PLLX, // PLLX temperature in millicelcius HocClkThermalSensor_AO, // AOTAG HocClkThermalSensor_BQ24193, // BQ24193 temperature. Refer to BQ24193Temp for returned values + HocClkThermalSensor_DRAM, // DRAM die temperature from LPDDR4(X) MR4. Use in combination with PCB and AO to get accurate reading HocClkThermalSensor_EnumMax } HocClkThermalSensor; @@ -292,6 +293,8 @@ static inline const char* hocclkFormatThermalSensor(HocClkThermalSensor thermSen return pretty ? "AO" : "ao"; case HocClkThermalSensor_BQ24193: return pretty ? "BQ24193" : "bq24193"; + case HocClkThermalSensor_DRAM: + return pretty ? "DRAM" : "dram"; default: return "unknown"; } diff --git a/Source/hoc-clk/common/include/hocclk/clock_manager.h b/Source/hoc-clk/common/include/hocclk/clock_manager.h index 794e0c1e..bbe70207 100644 --- a/Source/hoc-clk/common/include/hocclk/clock_manager.h +++ b/Source/hoc-clk/common/include/hocclk/clock_manager.h @@ -89,7 +89,7 @@ typedef struct { HocClkBpmpSharedInfo bpmpInfo; // Reserved for future use - u8 reserved[0x30C]; + u8 reserved[0x308]; } HocClkContext; typedef struct 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 a0dd851a..a72db69a 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp @@ -41,6 +41,7 @@ tsl::elm::ListItem* ramBWItemGpu = NULL; tsl::elm::ListItem* ramBWItemMax = NULL; tsl::elm::ListItem* bqtempitem = NULL; tsl::elm::ListItem* aotagTempItem = NULL; +tsl::elm::ListItem* dramTempItem = NULL; tsl::elm::ListItem* cTypeItem = NULL; tsl::elm::ListItem* creditsItem = NULL; tsl::elm::ListItem* bpmpStatusItem = NULL; @@ -96,6 +97,10 @@ void AboutGui::listUI() new tsl::elm::ListItem("BQ24193 Temp:"); this->listElement->addItem(bqtempitem); + dramTempItem = + new tsl::elm::ListItem("DRAM Temp:"); + this->listElement->addItem(dramTempItem); + this->listElement->addItem( new tsl::elm::CategoryHeader("RAM Bandwidth") ); @@ -275,6 +280,10 @@ void AboutGui::refresh() bqtempitem->setValue(strings[10]); + millis = context->temps[HocClkThermalSensor_DRAM]; + sprintf(strings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); + dramTempItem->setValue(strings[12]); + cTypeItem->setValue(hocClkFormatConsoleType(this->context->consoleType, true)); bpmpStatusItem->setValue(this->context->bpmpInfo.magic == HOCCLK_BPMP_MAGIC ? "Enabled" : "Halted"); } diff --git a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp index 1a274050..23add9ab 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp @@ -36,6 +36,7 @@ #include "../file/config.hpp" #include "../hos/apm_ext.h" #include "../i2c/i2cDrv.h" +#include "../soc/dram_mrr.hpp" #include "../tsensor/aotag.hpp" #include "../tsensor/bq24193.hpp" #include "../tsensor/soctherm.hpp" @@ -46,6 +47,32 @@ namespace board { + namespace { + /* Only poll every 10 ticks to avoid stalling EMC too much */ + constexpr u32 DramMr4PollDivisor = 20; // 1 - 20 seconds depending on polling interval + u32 gDramMr4Tick = DramMr4PollDivisor; + s32 gDramMr4Millis = 30000; /* 4x refresh default */ + + s32 PollDramMr4TempMilli() { + u8 mr4 = 0; + if (!soc::mrr::ReadRamMr4(&mr4)) + return 0; /* stock exosphere */ + + /* TODO: verify this table manually*/ + switch (mr4 & 0x7) + { + case 0x0: return 0; /* below operating range */ + case 0x1: return 30000; /* 4x refresh */ + case 0x2: return 50000; /* 2x refresh */ + case 0x3: return 85000; /* 1x refresh */ + case 0x4: return 95000; /* 0.5x refresh */ + case 0x5: return 100000; /* 0.25x refresh */ + case 0x6: return 105000; /* 0.25x refresh, de-rated */ + default: return 110000; /* above operating range */ + } + } + } + s32 GetTemperatureMilli(HocClkThermalSensor sensor) { s32 millis = 0; BatteryChargeInfo info; @@ -90,9 +117,9 @@ namespace board { case HocClkThermalSensor_MEM: { if (board::GetSocType() == HocClkSocType_Mariko && tsensor::IsInitialized() && tsensor::ReadAotag() > 0) { if(board::GetConsoleType() == HocClkConsoleType_Aula) { // Aula has a misplaced thermal sensor that makes tBoard report too high - millis = tsensor::ReadAotag(); + millis = (tsensor::ReadAotag() * 0.40f) + (gDramMr4Millis * 0.60f); } else { // On other consoles it's placed correctly so avoid relying on AOTAG - millis = (tsensor::ReadAotag() * 0.40f) + (tmp451TempPcb() * 0.6f); + millis = (tsensor::ReadAotag() * 0.20f) + (tmp451TempPcb() * 0.40f) + (gDramMr4Millis * 0.40f); } } else { millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem; @@ -111,6 +138,14 @@ namespace board { millis = tsensor::ReadAotag(); break; } + case HocClkThermalSensor_DRAM: { + if (++gDramMr4Tick >= DramMr4PollDivisor) { + gDramMr4Tick = 0; + gDramMr4Millis = PollDramMr4TempMilli(); + } + millis = gDramMr4Millis; + break; + } default: { ASSERT_ENUM_VALID(HocClkThermalSensor, sensor); } diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp index 5c8b396a..0bea9f15 100644 --- a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp +++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp @@ -251,6 +251,21 @@ namespace soc::mrr { return data; } + bool ReadRamMr4(u8 *mr4) { + EmcTopology topo = {}; + if (!QueryTopology(&topo)) + return false; + + ClearMrrLeftovers(); + + emc_mr_data_t data = {}; + if (!ReadMrxRank(MR4_TEMP, topo.ranks > 1, topo.channels > 1, &data)) + return false; + + *mr4 = data.chip0.rank0_ch0; + return true; + } + /* MR8 density field (bits 5:2) to MB */ static bool DecodeDensityMb(u8 mr8, u32 *mb) { switch ((mr8 & 0x3C) >> 2) diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp index 98eab47c..c37f540a 100644 --- a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp +++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp @@ -99,9 +99,7 @@ namespace soc::mrr { emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); bool IsMrrAvailable(); - /* Fuse-style DRAM ID (hekate numbering, as in board::GetDramID): - derived from MRR when the patched exosphere grants EMC access, - otherwise falls back to the fuse ODM4 ID. MRR-detected 8GB WT:B/NEE - (no dedicated fuse numbering) alias to Aula AA-MGCL 8GB (28). */ + bool ReadRamMr4(u8 *mr4); + u8 IdentifyDramId(); } \ No newline at end of file