DDR5 DIMM Temperature Reporting (#497)

* Initial commit for DDR5 Temperature report

* Change smbus.h to i2c_x86.h

* Change I2C includes defines name to avoid conflict

* Add dummy get_ram_temp() function on LA64

* Add menu option for RAM/DDR5 Temperature polling
This commit is contained in:
Sam Demeulemeester authored and GitHub committed 2025-10-06 23:01:33 +02:00
1 parent 2b51351ab7
commit ced9529bea
18 files changed
+229 -96

No files matched your search

+13 -7
View File
@@ -92,9 +92,11 @@ bool exclude_ecores = true;
bool smp_enabled = true;
bool enable_big_status = true;
bool enable_temperature = true;
bool enable_trace = false;
bool enable_temp_cpu = true;
bool enable_temp_ram = false; // DDR5+ temperature polling
bool enable_sm = true;
bool enable_bench = true;
bool enable_mch_read = true;
@@ -901,11 +903,10 @@ void config_menu(bool initial)
if (!smp_enabled) set_foreground_colour(BOLD+BLACK);
prints(POP_R+7, POP_LI, "<F5> CPU selection");
if (!smp_enabled) set_foreground_colour(WHITE);
//if (no_temperature) set_foreground_colour(BOLD+BLACK);
printf(POP_R+8, POP_LI, "<F6> Temperature %s", enable_temperature ? "disable" : "enable ");
//if (no_temperature) set_foreground_colour(WHITE);
printf(POP_R+9, POP_LI, "<F7> Boot trace %s", enable_trace ? "disable" : "enable ");
prints(POP_R+10, POP_LI, "<F10> Exit menu");
printf(POP_R+8, POP_LI, "<F6> CPU Temperature %s", enable_temp_cpu ? "disable" : "enable ");
printf(POP_R+9, POP_LI, "<F7> RAM Temperature %s", enable_temp_ram ? "disable" : "enable ");
printf(POP_R+10, POP_LI, "<F8> Boot trace %s", enable_trace ? "disable" : "enable ");
prints(POP_R+11, POP_LI, "<F10> Exit menu");
} else {
prints(POP_R+7, POP_LI, "<F5> Skip current test");
prints(POP_R+8 , POP_LI, "<F10> Exit menu");
@@ -942,10 +943,15 @@ void config_menu(bool initial)
break;
case '6':
if (initial) {
enable_temperature = !enable_temperature;
enable_temp_cpu = !enable_temp_cpu;
}
break;
case '7':
if (initial) {
enable_temp_ram = !enable_temp_ram;
}
break;
case '8':
if (initial) {
enable_trace = !enable_trace;
}
+3 -1
View File
@@ -54,9 +54,11 @@ extern bool exclude_ecores;
extern bool smp_enabled;
extern bool enable_big_status;
extern bool enable_temperature;
extern bool enable_trace;
extern bool enable_temp_cpu;
extern bool enable_temp_ram;
extern bool enable_sm;
extern bool enable_tty;
extern bool enable_bench;
+32 -17
View File
@@ -8,13 +8,13 @@
#include "cpuid.h"
#include "cpuinfo.h"
#include "hwctrl.h"
#include "i2c_x86.h"
#include "io.h"
#include "keyboard.h"
#include "memctrl.h"
#include "serial.h"
#include "pmem.h"
#include "smbios.h"
#include "smbus.h"
#include "spd.h"
#include "temperature.h"
#include "tsc.h"
@@ -402,27 +402,42 @@ void display_error_count(void)
void display_temperature(void)
{
if (!enable_temperature) {
return;
}
if (enable_temp_cpu) {
// Display CPU Temperature
int actual_cpu_temp = get_cpu_temp();
int actual_cpu_temp = get_cpu_temperature();
if (actual_cpu_temp == 0) {
if (max_cpu_temp == 0) {
enable_temperature = false;
if (actual_cpu_temp == 0) {
if (max_cpu_temp == 0) {
enable_temp_cpu = false;
}
return;
}
return;
if (max_cpu_temp < actual_cpu_temp ) {
max_cpu_temp = actual_cpu_temp;
}
int offset = actual_cpu_temp / 100 + max_cpu_temp / 100;
display_cpu_temperature(actual_cpu_temp, max_cpu_temp, offset);
}
if (max_cpu_temp < actual_cpu_temp ) {
max_cpu_temp = actual_cpu_temp;
if (enable_temp_ram) {
// Display RAM Temperature (DDR5+ Only) - LA64 unsupported yet
if (dmi_memory_device->type == DMI_DDR5 && !strstr(cpuid_info.vendor_id.str, "Loongson")) {
for (int i = 0; i < MAX_SPD_SLOT; i++) {
if (!ram_slot_info[i].isPopulated || !ram_slot_info[i].hasTempSensor)
continue;
int ram_temp = get_ram_temp(i);
if (ram_temp > 0) {
display_ram_temperature(ram_temp, ram_slot_info[i].display_idx)
}
}
}
}
int offset = actual_cpu_temp / 100 + max_cpu_temp / 100;
clear_screen_region(1, 18, 1, 22);
printf(1, 20-offset, "%2i/%2i%cC", actual_cpu_temp, max_cpu_temp, 0xF8);
}
void display_big_status(bool pass)
+9
View File
@@ -47,6 +47,12 @@ typedef enum {
#define display_cpu_clk(freq) \
printf(1, 10, "%iMHz", freq)
#define display_cpu_temperature(actual_cpu_temp, max_cpu_temp, offset) \
{ \
clear_screen_region(1, 18, 1, 22); \
printf(1, 20-offset, "%2i/%2i%cC", actual_cpu_temp, max_cpu_temp, 0xF8); \
}
#define display_cpu_addr_mode(str) \
prints(4, 75, str)
@@ -74,6 +80,9 @@ typedef enum {
#define display_ram_speed(speed) \
printf(5, 18, "%S6kB/s", (uintptr_t)(speed))
#define display_ram_temperature(ram_temp, idx) \
printf(idx+ROW_SPD, SCREEN_WIDTH-4, "%i%cC", ram_temp, 0xF8);
#define display_status(status) \
prints(7, 68, status)
+1 -1
View File
@@ -260,7 +260,7 @@ static void global_init(void)
error_init();
temperature_init();
cpu_temp_init();
initial_config();
+3 -2
View File
@@ -99,7 +99,7 @@ static void get_vt82c597_mb_cache_size(void)
static void disable_temp_reporting(void)
{
enable_temperature = false;
enable_temp_cpu = false;
}
static void amd_k8_revfg_temp(void)
@@ -168,7 +168,8 @@ static void unhide_asus_smbus(void)
if ((smb_ctrl_reg & 1) == 0) { return; }
// Read MMIO at offset 0x3418
uint32_t *ptr = (uint32_t *)((smb_ctrl_reg & 0xFFFFC000) + 0x3418);
uintptr_t base = (uintptr_t)(smb_ctrl_reg & ~0x3FFFu);
uint32_t *ptr = (uint32_t *)(base + 0x3418u);
// Set Bit 3 to 0 to enable SMBUS Controler
*ptr &= ~(1u << 3);
+4 -5
View File
@@ -1,5 +1,5 @@
#ifndef _SMBUS_H_
#define _SMBUS_H_
#ifndef _I2C_X86_H_
#define _I2C_X86_H_
/**
* SPDX-License-Identifier: GPL-2.0
*
@@ -13,8 +13,6 @@
#define I2C_WRITE 0
#define I2C_READ 1
#define SPD5_MR11 11
/* i801 Hosts Addresses */
#define SMBHSTSTS smbusbase
#define SMBHSTCNT smbusbase + 2
@@ -116,5 +114,6 @@ struct pci_smbus_controller {
void print_spd_startup_info(void);
uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr);
uint8_t get_spd_hub_register(uint8_t slot_idx, uint8_t spd_hub_adr);
#endif // SMBUS_H
#endif // I2C_X86_H
+4 -3
View File
@@ -45,9 +45,6 @@ void get_imc_config_amd_zen(void)
uint32_t smn_reg, offset;
uint32_t reg_cha, reg_chb;
/* Select UMC MCA MSR base */
uint32_t mca_ctrl_base = (imc.family >= IMC_K1A_GRG) ? MSR_AMD64_K1A_UMC_MCA_CTRL : MSR_AMD64_K17_UMC_MCA_CTRL;
imc.tCL_dec = 0;
// Get Memory Mapped Register Base Address (Enable MMIO if needed)
@@ -95,6 +92,10 @@ void get_imc_config_amd_zen(void)
// Detect ECC (x64 only)
#if TESTWORD_WIDTH > 32
/* Select UMC MCA MSR base */
uint32_t mca_ctrl_base = (imc.family >= IMC_K1A_GRG) ? MSR_AMD64_K1A_UMC_MCA_CTRL : MSR_AMD64_K17_UMC_MCA_CTRL;
if (enable_ecc_polling) {
uint32_t regl, regh;
+1 -1
View File
@@ -9,7 +9,7 @@
#include "cpuid.h"
#include "memrw.h"
#include "vmem.h"
#include "smbus.h"
#include "i2c_x86.h"
#include "i2c.h"
#include "spd.h"
+3 -3
View File
@@ -8,8 +8,8 @@
*
*/
#ifndef _I2C_H_
#define _I2C_H_
#ifndef _I2C_LA64_H_
#define _I2C_LA64_H_
#define PRER_LO_REG 0x0
#define PRER_HI_REG 0x1
@@ -66,4 +66,4 @@ typedef struct {
i2c_slot_param i2c_mc[4];
} i2c_param;
#endif // I2C_H
#endif // I2C_LA64_H
+8 -3
View File
@@ -23,9 +23,9 @@ float cpu_temp_offset = 0;
// Public Functions
//------------------------------------------------------------------------------
void temperature_init(void)
void cpu_temp_init(void)
{
if (!enable_temperature) {
if (!enable_temp_cpu) {
return;
}
@@ -35,7 +35,12 @@ void temperature_init(void)
}
}
int get_cpu_temperature(void)
int get_cpu_temp(void)
{
return (int)(__iocsrrd_w(0x428));
}
int get_ram_temp(uint8_t slot)
{
return 0;
}
+1 -1
View File
@@ -156,7 +156,7 @@ struct serial_port {
#define tty_partial_redraw() \
tty_send_region(1, 34, 5, 79); \
tty_send_region(7, 0, 8, 79); \
if(enable_temperature) tty_send_region(1, 16, 1, 26);
if(enable_temp_cpu) tty_send_region(1, 16, 1, 26);
#define tty_error_redraw() \
tty_send_region(10, 0, 23, 79);
+18 -2
View File
@@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2004-2023 Sam Demeulemeester
// Copyright (C) 2004-2025 Sam Demeulemeester
#include "stdbool.h"
#include "stdint.h"
#include "string.h"
#include "smbus.h"
#include "i2c_x86.h"
#include "spd.h"
#include "jedec_id.h"
#include "print.h"
@@ -20,6 +20,7 @@
#define ROUNDING_FACTOR 0.9f
ram_info_t ram = { 0, 0, 0, 0, 0, 0, "N/A"};
ram_slot_info_t ram_slot_info[MAX_SPD_SLOT];
static inline uint8_t bcd_to_ui8(uint8_t bcd)
{
@@ -296,6 +297,9 @@ static void parse_spd_ddr5(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 515));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 516));
// All DDR5s should have temperature sensor. Add a check if proved wrong.
spdi->hasTempSensor = true;
spdi->isValid = true;
}
@@ -415,6 +419,8 @@ static void parse_spd_ddr4(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 323));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 324));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
@@ -572,6 +578,8 @@ static void parse_spd_ddr3(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 120));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 121));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
@@ -709,6 +717,8 @@ static void parse_spd_ddr2(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 93));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 94));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
@@ -798,6 +808,8 @@ static void parse_spd_ddr(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 93));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 94));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
@@ -871,6 +883,8 @@ static void parse_spd_rdram(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 93));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 94));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
@@ -937,6 +951,8 @@ static void parse_spd_sdram(spd_info *spdi, uint8_t slot_idx)
spdi->fab_year = bcd_to_ui8(get_spd(slot_idx, 93));
spdi->fab_week = bcd_to_ui8(get_spd(slot_idx, 94));
spdi->hasTempSensor = false;
spdi->isValid = true;
}
+26 -2
View File
@@ -7,10 +7,25 @@
*
* Provides access to SPD parsing and printing functions.
*
* Copyright (C) 2004-2023 Sam Demeulemeester.
* Copyright (C) 2004-2025 Sam Demeulemeester.
*/
#define SPD_SKU_LEN 32
#define MAX_SPD_SLOT 8
#define SPD_SKU_LEN 32
/* DDR5 SPD Hub Configuration Registers */
#define SPD5_HUB_ID_MSB 0x00 // MR0 - Device Type MSB
#define SPD5_HUB_ID_LSB 0x01 // MR1 - Device Type LSB (0x18 = w/ Temp Sensor)
#define SPD5_HUB_CAP 0x05 // MR5 - Device Capability (Bit 1 = Temp Sensor Support)
#define SPD5_HUB_I2C_CONF 0x0B // MR11 - I²C Legacy Mode Device Configuration
#define SPD5_HUB_CONF 0x12 // MR18 - General Device Configuration
#define SPD5_HUB_TS_CONF 0x1A // MR26 - Temperature Sensor Configuration (Bit 0 = 1 for Disable)
#define SPD5_HUB_TS_RES 0x24 // MR36 - TS Resolution (from 9- to 12-bit)
#define SPD5_HUB_STATUS 0x30 // MR48 - Device Status
#define SPD5_HUB_TS_LSB 0x31 // MR49 - TS Current Sensed Temperature - Low Byte
#define SPD5_HUB_TS_MSB 0x32 // MR50 - TS Current Sensed Temperature - High Byte
#define SPD5_HUB_TS_STATUS 0x33 // MR51 - Temperature Sensor Status
typedef struct spd_infos {
bool isValid;
@@ -22,6 +37,7 @@ typedef struct spd_infos {
uint8_t XMP;
uint16_t freq;
bool hasECC;
bool hasTempSensor;
uint8_t fab_year;
uint8_t fab_week;
uint16_t tCL;
@@ -42,7 +58,15 @@ typedef struct ram_infos {
char *type;
} ram_info_t;
typedef struct {
uint8_t slot_idx;
uint8_t display_idx;
bool isPopulated;
bool hasTempSensor;
} ram_slot_info_t;
extern ram_info_t ram;
extern ram_slot_info_t ram_slot_info[MAX_SPD_SLOT];
void print_spdi(spd_info spdi, uint8_t lidx);
void parse_spd(spd_info *spdi, uint8_t slot_idx);
+9 -3
View File
@@ -8,7 +8,7 @@
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
* Copyright (C) 2003-2023 Sam Demeulemeester.
* Copyright (C) 2003-2025 Sam Demeulemeester.
*/
#define AMD_TEMP_REG_K8 0xE4
@@ -30,12 +30,18 @@ extern float cpu_temp_offset;
/**
* Init temperature sensor and compute offsets if needed
*/
void temperature_init(void);
void cpu_temp_init(void);
/**
* Returns the current temperature of the CPU. Returns 0 if
* the temperature cannot be read.
*/
int get_cpu_temperature(void);
int get_cpu_temp(void);
/**
* Returns the current temperature of the RAM. Returns 0 if
* the temperature cannot be read. Only for DDR5
*/
int get_ram_temp(uint8_t slot);
#endif // TEMPERATURE_H
+4 -4
View File
@@ -396,7 +396,7 @@ static void determine_imc(void)
break;
case 0x3:
imc.family = IMC_CLT;
enable_temperature = false; // Atom Clover Trail
enable_temp_cpu = false; // Atom Clover Trail
break;
case 0x4:
imc.family = IMC_HSW_ULT; // Core 4th Gen (Haswell-ULT)
@@ -413,11 +413,11 @@ static void determine_imc(void)
switch (cpuid_info.version.extendedModel) {
case 0x2:
imc.family = IMC_TNC; // Atom Tunnel Creek / Lincroft
enable_temperature = false;
enable_temp_cpu = false;
break;
case 0x3:
imc.family = IMC_CDT; // Atom Cedar Trail
enable_temperature = false;
enable_temp_cpu = false;
break;
case 0x4:
imc.family = IMC_HSW; // Core 4th Gen (Haswell w/ GT3e)
@@ -491,7 +491,7 @@ static void determine_imc(void)
} else {
imc.family = IMC_SLT; // Atom Silverthorne / Diamondvile
}
enable_temperature = false;
enable_temp_cpu = false;
break;
case 0x2:
imc.family = IMC_WMR; // Core i7 1st Gen 32 nm (Westmere)
+62 -37
View File
@@ -11,13 +11,11 @@
#include "macros.h"
#include "cpuinfo.h"
#include "hwquirks.h"
#include "i2c_x86.h"
#include "memctrl.h"
#include "smbus.h"
#include "smbios.h"
#include "spd.h"
#include "hwquirks.h"
#define MAX_SPD_SLOT 8
int smbbus, smbdev, smbfun;
unsigned short smbusbase = 0;
@@ -60,9 +58,16 @@ void print_spd_startup_info(void)
for (spdidx = 0; spdidx < MAX_SPD_SLOT; spdidx++) {
parse_spd(&curspd, spdidx);
ram_slot_info[spdidx].slot_idx = spdidx;
ram_slot_info[spdidx].isPopulated = curspd.isValid;
ram_slot_info[spdidx].hasTempSensor = false;
if (!curspd.isValid)
continue;
ram_slot_info[spdidx].display_idx = spd_line_idx;
ram_slot_info[spdidx].hasTempSensor = curspd.hasTempSensor;
if (spd_line_idx == 0) {
prints(ROW_SPD-2, 0, "Memory SPD Information");
prints(ROW_SPD-1, 0, "----------------------");
@@ -523,9 +528,9 @@ static bool ali_get_smb(uint8_t address)
return false;
}
// ------------------
// get_spd() function
// ------------------
// --------------------
// SPD Read functions
// --------------------
uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr)
{
@@ -542,6 +547,15 @@ uint8_t get_spd(uint8_t slot_idx, uint16_t spd_adr)
}
}
uint8_t get_spd_hub_register(uint8_t slot_idx, uint8_t spd_hub_adr)
{
if(dmi_memory_device->type == DMI_DDR5) {
return ich5_read_spd_byte(slot_idx, spd_hub_adr | 0xFF00);
}
return 0;
}
/*************************************************************************************
/ ***************************** WARNING *****************************
/ ************************************************************************************
@@ -575,44 +589,55 @@ static uint8_t ich5_read_spd_byte(uint8_t smbus_adr, uint16_t spd_adr)
spd_adr -= 0x100;
}
} else if (dmi_memory_device->type == DMI_DDR5) {
// Switch page if needed (DDR5)
uint8_t adr_page = spd_adr / 128;
// For DDR5, choose between reading from the SPD EEPROM (which may require a bank switch)
// and reading from the DDR5 SPD Hub Register (where we added a 0xFF00 offset).
if (adr_page != spd_page || last_adr != smbus_adr) {
if (spd_adr >> 8 != 0xFF) {
// DDR5 SPD Read (7-bit address translated to 0x80-0xFF)
// Switch page if needed (pages are 7-bit/128 bytes wide)
uint8_t adr_page = spd_adr / 128;
// DDR5 SPD Bank switch can be achieved using 2 methods
if(((smbus_id >> 16) & 0xFFFF) == PCI_VID_INTEL) {
// On Intel, we use the process call method because the SMBUS write command
// is sometimes disabled by BIOS to avoid unexpected SPD corruption
__outb((smbus_adr << 1) | I2C_READ, SMBHSTADD);
__outb(SPD5_MR11 & 0x7F, SMBHSTCMD);
__outb(adr_page & 7, SMBHSTDAT0);
__outb(0, SMBHSTDAT1);
__outb(SMBHSTCNT_PROC_CALL, SMBHSTCNT);
if (adr_page != spd_page || last_adr != smbus_adr) {
ich5_process();
// DDR5 SPD Bank switch can be achieved using 2 methods
if(((smbus_id >> 16) & 0xFFFF) == PCI_VID_INTEL) {
// On Intel, we use the process call method because the SMBUS write command
// is sometimes disabled by BIOS to avoid unexpected SPD corruption
__outb((smbus_adr << 1) | I2C_READ, SMBHSTADD);
__outb(SPD5_HUB_I2C_CONF & 0x7F, SMBHSTCMD);
__outb(adr_page & 7, SMBHSTDAT0);
__outb(0, SMBHSTDAT1);
__outb(SMBHSTCNT_PROC_CALL, SMBHSTCNT);
// These dummy read are mandatory to terminate a Proc Call
__inb(SMBHSTDAT0);
__inb(SMBHSTDAT1);
ich5_process();
} else {
// On AMD, we continue to use the standard smbus write command as it seems
// more reliable than the process call method. This may be reevaluated later.
__outb((smbus_adr << 1) | I2C_WRITE, SMBHSTADD);
__outb(SPD5_MR11 & 0x7F, SMBHSTCMD);
__outb(adr_page & 7, SMBHSTDAT0);
__outb(SMBHSTCNT_BYTE_DATA, SMBHSTCNT);
// These dummy read are mandatory to terminate a Proc Call
__inb(SMBHSTDAT0);
__inb(SMBHSTDAT1);
ich5_process();
}
} else {
// On AMD, we continue to use the standard smbus write command as it seems
// more reliable than the process call method. This may be reevaluated later.
__outb((smbus_adr << 1) | I2C_WRITE, SMBHSTADD);
__outb(SPD5_HUB_I2C_CONF & 0x7F, SMBHSTCMD);
__outb(adr_page & 7, SMBHSTDAT0);
__outb(SMBHSTCNT_BYTE_DATA, SMBHSTCNT);
spd_page = adr_page;
last_adr = smbus_adr;
}
ich5_process();
}
spd_adr -= adr_page * 128;
spd_adr |= 0x80;
spd_page = adr_page;
last_adr = smbus_adr;
}
// Get final I2C byte address on the current page (0x00-0x7F -> 0x80-0xFF).
spd_adr -= adr_page * 128;
spd_adr |= 0x80;
} else {
// SPD5 Hub Register Read (7-bit address at 0x00 - 0x7F)
spd_adr &= 0x7F;
}
}
__outb((smbus_adr << 1) | I2C_READ, SMBHSTADD);
+28 -4
View File
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2022 Martin Whitaker.
// Copyright (C) 2004-2023 Sam Demeulemeester.
// Copyright (C) 2004-2025 Sam Demeulemeester.
#include <stdint.h>
@@ -8,9 +8,12 @@
#include "cpuid.h"
#include "cpuinfo.h"
#include "hwquirks.h"
#include "i2c_x86.h"
#include "memctrl.h"
#include "msr.h"
#include "pci.h"
#include "smbios.h"
#include "spd.h"
#include "temperature.h"
@@ -47,11 +50,11 @@ void get_specific_TjMax(void)
}
}
void temperature_init(void)
void cpu_temp_init(void)
{
uint32_t regl, regh;
if (!enable_temperature) {
if (!enable_temp_cpu) {
return;
}
@@ -77,7 +80,7 @@ void temperature_init(void)
}
}
int get_cpu_temperature(void)
int get_cpu_temp(void)
{
uint32_t regl, regh;
@@ -147,3 +150,24 @@ int get_cpu_temperature(void)
return 0;
}
int get_ram_temp(uint8_t slot)
{
uint16_t temp_reg;
float ram_temp;
// RAM Temperature is only supported on DDR5
if (dmi_memory_device->type != DMI_DDR5 || slot >= MAX_SPD_SLOT)
return 0;
// Check if slot has a temp sensor
if (ram_slot_info[slot].isPopulated == false || ram_slot_info[slot].hasTempSensor == false)
return 0;
temp_reg = get_spd_hub_register(slot, SPD5_HUB_TS_LSB);
temp_reg |= get_spd_hub_register(slot, SPD5_HUB_TS_MSB) << 8;
ram_temp = (temp_reg >> 2) / 4.0f;
return ram_temp;
}