add CPU DVFS skeleton

This commit is contained in:
souldbminersmwc committed 2026-10-04 18:37:38 -04:00
1 parent e9d01a0878
commit 930f2efe63
8 files changed
+147 -86

No files matched your search

+7 -1
View File
@@ -61,6 +61,8 @@ namespace board {
HocClkConsoleType gConsoleType = HocClkConsoleType_Icosa;
FuseData fuseData;
u8 speedoBracket;
u8 CpuSpeedoBracket;
PwmChannelSession iCon;
u32 fd = 0, fd2 = 0;
@@ -115,7 +117,7 @@ namespace board {
void FetchHardwareInfos() {
ReadFuses(fuseData, fuseVirtAddr);
SetGpuBracket(fuseData.gpuSpeedo, speedoBracket);
SetCpuBracket(fuseData.cpuSpeedo, CpuSpeedoBracket);
u32 hidrev = *(u32 *)(apbVirtAddr + APB_MISC_GP_HIDREV);
if (((hidrev >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) {
gSocType = HocClkSocType_Mariko;
@@ -339,4 +341,8 @@ namespace board {
return speedoBracket;
}
u8 GetCpuSpeedoBracket() {
return CpuSpeedoBracket;
}
} // namespace board
@@ -56,6 +56,8 @@ namespace board {
u8 GetFuseDramId();
u8 GetDramID();
u8 GetGpuSpeedoBracket();
u8 GetCpuSpeedoBracket();
bool IsDram8GB();
void SetDisplayRefreshDockedState(bool docked);
FuseData *GetFuseData();
@@ -60,6 +60,35 @@ namespace board {
}
}
void SetCpuBracket(u16 speedo, u8 &cpuBracket) {
switch (speedo) {
// Mariko
case 1451 ... 1500:
cpuBracket = 6;
break;
case 1501 ... 1550:
cpuBracket = 5;
break;
case 1551 ... 1600:
cpuBracket = 4;
break;
case 1601 ... 1650:
cpuBracket = 3;
break;
case 1651 ... 1700:
cpuBracket = 2;
break;
case 1701 ... 1750:
cpuBracket = 1;
break;
case 1751 ... 1800:
cpuBracket = 0;
break;
default:
cpuBracket = 6;
}
}
void ReadFuses(FuseData &speedo, u64 fuseVa) {
constexpr u32 FuseOffset = 0x800;
u8 *fusePtr = reinterpret_cast<u8 *>(fuseVa) + FuseOffset;
@@ -36,5 +36,6 @@ namespace board {
void ReadFuses(FuseData &speedo, u64 fuseVa);
void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket);
void SetCpuBracket(u16 speedo, u8 &cpuBracket);
} // namespace board
+105 -83
View File
@@ -30,6 +30,7 @@
#include "board.hpp"
#include "board_freq.hpp"
#include "board_volt.hpp"
#include "../i2c/max77620_wdt.hpp"
namespace board {
@@ -456,6 +457,11 @@ namespace board {
}
}
struct DvfsEntry {
u32 freq;
u32 volt;
};
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) {
u32 baseVolt = 800;
if (GetSocType() == HocClkSocType_Mariko) {
@@ -511,89 +517,38 @@ namespace board {
}
return baseVolt;
} else {
struct DvfsEntry {
u32 freq;
u32 volt;
};
static const DvfsEntry ramTable[][19] = {
{ { 1733, 725 },
{ 1800, 730 },
{ 1866, 735 },
{ 1920, 740 },
{ 1958, 745 },
{ 1996, 750 },
{ 2035, 755 },
{ 2073, 760 },
{ 2112, 765 },
{ 2131, 770 },
{ 2150, 775 },
{ 2169, 780 },
{ 2188, 785 },
{ 2227, 790 },
{ 2265, 795 },
{ 2304, 800 },
{ 2342, 805 },
{ 2380, 810 },
{ 2400, 815 } }, // Bracket 0
{ { 1733, 715 },
{ 1800, 720 },
{ 1866, 725 },
{ 1920, 730 },
{ 1958, 735 },
{ 1996, 740 },
{ 2035, 745 },
{ 2073, 750 },
{ 2112, 755 },
{ 2131, 760 },
{ 2150, 765 },
{ 2169, 770 },
{ 2188, 775 },
{ 2227, 780 },
{ 2265, 785 },
{ 2304, 790 },
{ 2342, 795 },
{ 2380, 800 },
{ 2400, 805 } }, // Bracket 1
{ { 1733, 705 },
{ 1800, 710 },
{ 1866, 715 },
{ 1920, 720 },
{ 1958, 725 },
{ 1996, 730 },
{ 2035, 735 },
{ 2073, 740 },
{ 2112, 745 },
{ 2131, 750 },
{ 2150, 755 },
{ 2169, 760 },
{ 2188, 765 },
{ 2227, 770 },
{ 2265, 775 },
{ 2304, 780 },
{ 2342, 785 },
{ 2380, 790 },
{ 2400, 795 } }, // Bracket 2
{ { 1733, 695 },
{ 1800, 700 },
{ 1866, 705 },
{ 1920, 710 },
{ 1958, 715 },
{ 1996, 720 },
{ 2035, 725 },
{ 2073, 730 },
{ 2112, 735 },
{ 2131, 740 },
{ 2150, 745 },
{ 2169, 750 },
{ 2188, 755 },
{ 2227, 760 },
{ 2265, 765 },
{ 2304, 770 },
{ 2342, 775 },
{ 2380, 780 },
{ 2400, 785 } }, // Bracket 3
};
static const DvfsEntry ramTable[][19] = {
{ // Bracket 0
{1733, 725}, {1800, 730}, {1866, 735}, {1920, 740},
{1958, 745}, {1996, 750}, {2035, 755}, {2073, 760},
{2112, 765}, {2131, 770}, {2150, 775}, {2169, 780},
{2188, 785}, {2227, 790}, {2265, 795}, {2304, 800},
{2342, 805}, {2380, 810}, {2400, 815}
},
{ // Bracket 1
{1733, 715}, {1800, 720}, {1866, 725}, {1920, 730},
{1958, 735}, {1996, 740}, {2035, 745}, {2073, 750},
{2112, 755}, {2131, 760}, {2150, 765}, {2169, 770},
{2188, 775}, {2227, 780}, {2265, 785}, {2304, 790},
{2342, 795}, {2380, 800}, {2400, 805}
},
{ // Bracket 2
{1733, 705}, {1800, 710}, {1866, 715}, {1920, 720},
{1958, 725}, {1996, 730}, {2035, 735}, {2073, 740},
{2112, 745}, {2131, 750}, {2150, 755}, {2169, 760},
{2188, 765}, {2227, 770}, {2265, 775}, {2304, 780},
{2342, 785}, {2380, 790}, {2400, 795}
},
{ // Bracket 3
{1733, 695}, {1800, 700}, {1866, 705}, {1920, 710},
{1958, 715}, {1996, 720}, {2035, 725}, {2073, 730},
{2112, 735}, {2131, 740}, {2150, 745}, {2169, 750},
{2188, 755}, {2227, 760}, {2265, 765}, {2304, 770},
{2342, 775}, {2380, 780}, {2400, 785}
},
};
if (freqMhz <= 1600)
return 0; // DVFS doesnt work below 1600MHz, it will just use vMin
if (bracket >= std::size(ramTable))
@@ -610,4 +565,71 @@ namespace board {
return baseVolt;
}
}
} // namespace board
/* TODO: Verify table on consoles */
const DvfsEntry CpuVminRamTable[/* Bracket */7][/* Entry */12] = {
{ {1866, 550}, {1996, 560}, {2133, 570}, {2400, 580}, {2533, 590}, {2666, 600}, {2800, 610}, {2933, 620}, {3066, 630}, {3200, 640}, {3333, 660}, {3466, 680} }, // Bracket 0 (Speedo 1751-1800)
{ {1866, 555}, {1996, 565}, {2133, 575}, {2400, 585}, {2533, 595}, {2666, 605}, {2800, 615}, {2933, 625}, {3066, 635}, {3200, 645}, {3333, 665}, {3466, 685} }, // Bracket 1 (Speedo 1701-1750)
{ {1866, 560}, {1996, 570}, {2133, 580}, {2400, 590}, {2533, 600}, {2666, 610}, {2800, 620}, {2933, 630}, {3066, 640}, {3200, 650}, {3333, 670}, {3466, 690} }, // Bracket 2 (Speedo 1651-1700)
{ {1866, 565}, {1996, 575}, {2133, 585}, {2400, 595}, {2533, 605}, {2666, 615}, {2800, 625}, {2933, 635}, {3066, 645}, {3200, 655}, {3333, 675}, {3466, 695} }, // Bracket 3 (Speedo 1601-1650)
{ {1866, 570}, {1996, 580}, {2133, 590}, {2400, 600}, {2533, 610}, {2666, 620}, {2800, 630}, {2933, 640}, {3066, 650}, {3200, 660}, {3333, 680}, {3466, 700} }, // Bracket 4 (Speedo 1551-1600)
{ {1866, 575}, {1996, 585}, {2133, 595}, {2400, 605}, {2533, 615}, {2666, 625}, {2800, 635}, {2933, 645}, {3066, 655}, {3200, 665}, {3333, 685}, {3466, 705} }, // Bracket 5 (Speedo 1501-1550)
{ {1866, 580}, {1996, 590}, {2133, 600}, {2400, 610}, {2533, 620}, {2666, 630}, {2800, 640}, {2933, 650}, {3066, 660}, {3200, 670}, {3333, 690}, {3466, 710} }, // Bracket 6 (Speedo 1451-1500)
};
u32 GetMinimumCpuVmin(u32 freqMhz, u32 bracket) {
if (freqMhz <= 1600)
return 0; // DVFS doesnt work below 1600MHz, it will just use vMin
if (bracket >= std::size(CpuVminRamTable))
bracket = 0;
const auto &entries = CpuVminRamTable[bracket];
u32 baseVolt = entries[std::size(entries) - 1].volt;
for (const auto &entry : entries) {
if (freqMhz <= entry.freq) {
baseVolt = entry.volt;
break;
}
}
return baseVolt;
}
constexpr u32 PmicVmin = 250;
constexpr u32 PmicStep = 5;
u32 ConvertVoltToLut(u32 mv) {
/* Refer to TRM 6.1.19 */
return (mv - PmicVmin) / PmicStep;
}
void ApplyCpuDvfs(u32 ramFreqMhz) {
/* Get the minimum DRAM OC Cpu Vmin */
u32 vmin = GetMinimumCpuVmin(ramFreqMhz, GetCpuSpeedoBracket());
/* Create the new modified CPU LUT buffer */
u32 NewCpuVoltTable[32] = { 0 };
memcpy(NewCpuVoltTable, cpuVoltTable, sizeof(NewCpuVoltTable));
/* Apply the new vmin to the reconstructed table and convert it to the appropriate format */
for(auto &vlt : NewCpuVoltTable) {
/* Will never run on freq zero so it just converts the table */
if(vlt < vmin) {
vlt = vmin;
}
/* Don't know if modifying and passing argument causes undefined behavior? */
u32 tempVlt = vlt;
vlt = ConvertVoltToLut(tempVlt);
}
/* Pet the watchdog to avoid it hanging the system during this operation */
i2c::wdt::Pet();
/* DSB to prevent a hang during setting the new LUT */
__asm__("dsb SY");
/* Copy the edited LUT into it's appropriate location */
memcpy((void*)(cldvfs + CL_DVFS_OUTPUT_LUT_0), NewCpuVoltTable, sizeof(NewCpuVoltTable));
}
} // namespace board
@@ -59,5 +59,5 @@ namespace board {
void PcvHijackGpuVolts(u32 vmin);
void PcvHijackGpuFrequency(u32 voltage, u32 hz);
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket);
void ApplyCpuDvfs(u32 ramFreqMhz);
} // namespace board