mirror of
https://github.com/memtest86plus/memtest86plus
synced 2025-03-12 08:53:02 +03:00
Add support for Intel MTL & ARL CPUs (#441)
* Add CPUID detection for MTL & ARL CPUs * Add support for ARL SMBus Controler Add PCI Device polling on Bus 0x80 (instead of fixed 0x00) Solve issue with DDR5 SPD Bank switching when SPD Write is disabled (using Proc Call) * Add Live Freq/Timings IMC Polling for Intel MTL & ADL CPUs * Correct K8 Rev G detection Fix #361 (PR hijacking)
This commit is contained in:
parent
0a543a41f2
commit
f34a85ce07
@ -375,17 +375,17 @@ static void determine_imc(void)
|
||||
switch (cpuid_info.version.model) {
|
||||
case 0x5:
|
||||
switch (cpuid_info.version.extendedModel) {
|
||||
case 2:
|
||||
case 0x2:
|
||||
imc.family = IMC_NHM; // Core i3/i5 1st Gen 45 nm (Nehalem/Bloomfield)
|
||||
break;
|
||||
case 3:
|
||||
case 0x3:
|
||||
imc.family = IMC_CLT;
|
||||
enable_temperature = false; // Atom Clover Trail
|
||||
break;
|
||||
case 4:
|
||||
case 0x4:
|
||||
imc.family = IMC_HSW_ULT; // Core 4th Gen (Haswell-ULT)
|
||||
break;
|
||||
case 5:
|
||||
case 0x5:
|
||||
imc.family = IMC_SKL_SP; // Skylake/Cascade Lake/Cooper Lake (Server)
|
||||
break;
|
||||
default:
|
||||
@ -395,23 +395,26 @@ static void determine_imc(void)
|
||||
|
||||
case 0x6:
|
||||
switch (cpuid_info.version.extendedModel) {
|
||||
case 2:
|
||||
case 0x2:
|
||||
imc.family = IMC_TNC; // Atom Tunnel Creek / Lincroft
|
||||
enable_temperature = false;
|
||||
break;
|
||||
case 3:
|
||||
case 0x3:
|
||||
imc.family = IMC_CDT; // Atom Cedar Trail
|
||||
enable_temperature = false;
|
||||
break;
|
||||
case 4:
|
||||
case 0x4:
|
||||
imc.family = IMC_HSW; // Core 4th Gen (Haswell w/ GT3e)
|
||||
break;
|
||||
case 5:
|
||||
case 0x5:
|
||||
imc.family = IMC_BDW_DE; // Broadwell-DE (Server)
|
||||
break;
|
||||
case 6:
|
||||
case 0x6:
|
||||
imc.family = IMC_CNL; // Cannon Lake
|
||||
break;
|
||||
case 0xC:
|
||||
imc.family = IMC_ARL; // Core 15th Gen (Arrow Lake)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -456,6 +459,9 @@ static void determine_imc(void)
|
||||
case 0x9:
|
||||
imc.family = IMC_ADL; // Core 12th Gen (Alder Lake-S)
|
||||
break;
|
||||
case 0xA:
|
||||
imc.family = IMC_MTL; // Core 14th Gen (Meteor Lake)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define IMC_ADL 0x1100 // Core 12th Gen (Alder Lake-S)
|
||||
#define IMC_RPL 0x1110 // Core 13th Gen (Raptor Lake)
|
||||
#define IMC_MTL 0x1120 // Core 14th Gen (Meteor Lake)
|
||||
#define IMC_ARL 0x1130 // Core 15th Gen (Arrow Lake)
|
||||
|
||||
#define IMC_NHM_E 0x2010 // Core i7 1st Gen 45 nm (Nehalem-E)
|
||||
#define IMC_SNB_E 0x2020 // Core 2nd Gen (Sandy Bridge-E)
|
||||
|
@ -84,10 +84,10 @@ static void amd_k8_revfg_temp(void)
|
||||
}
|
||||
|
||||
// K8 Rev G Desktop requires an additional offset.
|
||||
if (cpuid_info.version.extendedModel < 6 && cpuid_info.version.extendedModel > 7) // Not Rev G
|
||||
if (cpuid_info.version.extendedModel < 6 || cpuid_info.version.extendedModel > 7) // Not Rev G
|
||||
return;
|
||||
|
||||
if (cpuid_info.version.extendedModel == 6 && cpuid_info.version.extendedModel < 9) // Not Desktop
|
||||
if (cpuid_info.version.extendedModel == 6 && cpuid_info.version.model < 9) // Not Desktop
|
||||
return;
|
||||
|
||||
uint16_t brandID = (cpuid_info.version.extendedBrandID >> 9) & 0x1f;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2023 Sam Demeulemeester
|
||||
// Copyright (C) 2004-2024 Sam Demeulemeester
|
||||
|
||||
#include "display.h"
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
#define MAX_SPD_SLOT 8
|
||||
|
||||
int smbdev, smbfun;
|
||||
int smbbus, smbdev, smbfun;
|
||||
unsigned short smbusbase = 0;
|
||||
uint32_t smbus_id = 0;
|
||||
static uint16_t extra_initial_sleep_for_smb_transaction = 0;
|
||||
@ -81,14 +81,16 @@ static bool setup_smb_controller(void)
|
||||
{
|
||||
uint16_t vid, did;
|
||||
|
||||
for (smbdev = 0; smbdev < 32; smbdev++) {
|
||||
for (smbfun = 0; smbfun < 8; smbfun++) {
|
||||
vid = pci_config_read16(0, smbdev, smbfun, 0);
|
||||
if (vid != 0xFFFF) {
|
||||
did = pci_config_read16(0, smbdev, smbfun, 2);
|
||||
if (did != 0xFFFF) {
|
||||
if (find_smb_controller(vid, did)) {
|
||||
return true;
|
||||
for(smbbus = 0; smbbus < 0xFF; smbbus += 0x80) {
|
||||
for (smbdev = 0; smbdev < 32; smbdev++) {
|
||||
for (smbfun = 0; smbfun < 8; smbfun++) {
|
||||
vid = pci_config_read16(smbbus, smbdev, smbfun, 0);
|
||||
if (vid != 0xFFFF) {
|
||||
did = pci_config_read16(smbbus, smbdev, smbfun, 2);
|
||||
if (did != 0xFFFF) {
|
||||
if (find_smb_controller(vid, did)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,6 +172,9 @@ static const uint16_t intel_ich5_dids[] =
|
||||
0x51A3, // Alder Lake-P (PCH)
|
||||
0x54A3, // Alder Lake-M (PCH)
|
||||
0x7A23, // Raptor Lake-S (PCH)
|
||||
//0x7E22, // Meteor Lake-P (SOC)
|
||||
0x7F23, // Arrow Lake-S (PCH)
|
||||
//0xA822, // Lunar Lake
|
||||
};
|
||||
|
||||
static bool find_in_did_array(uint16_t did, const uint16_t * ids, unsigned int size)
|
||||
@ -185,6 +190,7 @@ static bool find_in_did_array(uint16_t did, const uint16_t * ids, unsigned int s
|
||||
static bool find_smb_controller(uint16_t vid, uint16_t did)
|
||||
{
|
||||
smbus_id = (((uint32_t)vid) << 16) | did;
|
||||
|
||||
switch(vid)
|
||||
{
|
||||
case PCI_VID_INTEL:
|
||||
@ -373,20 +379,21 @@ static bool ich5_get_smb(void)
|
||||
uint16_t x;
|
||||
|
||||
// Enable SMBus IO Space if disabled
|
||||
x = pci_config_read16(0, smbdev, smbfun, 0x4);
|
||||
x = pci_config_read16(smbbus, smbdev, smbfun, 0x4);
|
||||
|
||||
if (!(x & 1)) {
|
||||
pci_config_write16(0, smbdev, smbfun, 0x4, x | 1);
|
||||
pci_config_write16(smbbus, smbdev, smbfun, 0x4, x | 1);
|
||||
}
|
||||
|
||||
// Read Base Address
|
||||
x = pci_config_read16(0, smbdev, smbfun, 0x20);
|
||||
x = pci_config_read16(smbbus, smbdev, smbfun, 0x20);
|
||||
smbusbase = x & 0xFFF0;
|
||||
|
||||
// Enable I2C Host Controller Interface if disabled
|
||||
uint8_t temp = pci_config_read8(0, smbdev, smbfun, 0x40);
|
||||
if ((temp & 4) == 0) {
|
||||
pci_config_write8(0, smbdev, smbfun, 0x40, temp | 0x04);
|
||||
// Use SMBUS Mode for DDR5 to allow bank switch using Proc Call
|
||||
uint8_t temp = pci_config_read8(smbbus, smbdev, smbfun, 0x40);
|
||||
if ((temp & 4) == 0 && dmi_memory_device->type != DMI_DDR5) {
|
||||
pci_config_write8(smbbus, smbdev, smbfun, 0x40, temp | 0x04);
|
||||
}
|
||||
|
||||
// Reset SMBUS Controller
|
||||
@ -405,7 +412,7 @@ static bool amd_sb_get_smb(void)
|
||||
uint8_t rev_id;
|
||||
uint16_t pm_reg;
|
||||
|
||||
rev_id = pci_config_read8(0, smbdev, smbfun, 0x08);
|
||||
rev_id = pci_config_read8(smbbus, smbdev, smbfun, 0x08);
|
||||
|
||||
if ((smbus_id & 0xFFFF) == 0x4385 && rev_id <= 0x3D) {
|
||||
// Older AMD SouthBridge (SB700 & older) use PIIX4 registers
|
||||
@ -567,13 +574,19 @@ static uint8_t ich5_read_spd_byte(uint8_t smbus_adr, uint16_t spd_adr)
|
||||
uint8_t adr_page = spd_adr / 128;
|
||||
|
||||
if (adr_page != spd_page || last_adr != smbus_adr) {
|
||||
__outb((smbus_adr << 1) | I2C_WRITE, SMBHSTADD);
|
||||
|
||||
__outb((smbus_adr << 1) | I2C_READ, SMBHSTADD);
|
||||
__outb(SPD5_MR11 & 0x7F, SMBHSTCMD);
|
||||
__outb(adr_page, SMBHSTDAT0);
|
||||
__outb(SMBHSTCNT_BYTE_DATA, SMBHSTCNT);
|
||||
__outb(adr_page & 7, SMBHSTDAT0);
|
||||
__outb(0, SMBHSTDAT1);
|
||||
__outb(SMBHSTCNT_PROC_CALL, SMBHSTCNT);
|
||||
|
||||
ich5_process();
|
||||
|
||||
// These dummy read are mandatory to finish a Proc Call
|
||||
__inb(SMBHSTDAT0);
|
||||
__inb(SMBHSTDAT1);
|
||||
|
||||
spd_page = adr_page;
|
||||
last_adr = smbus_adr;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2023 Sam Demeulemeester
|
||||
// Copyright (C) 2004-2024 Sam Demeulemeester
|
||||
#ifndef _IMC_H_
|
||||
#define _IMC_H_
|
||||
|
||||
@ -25,6 +25,9 @@ void get_imc_config_intel_icl(void);
|
||||
/* Memory configuration Detection for Intel Alder Lake */
|
||||
void get_imc_config_intel_adl(void);
|
||||
|
||||
/* Memory configuration Detection for Intel Metor Lake */
|
||||
void get_imc_config_intel_mtl(void);
|
||||
|
||||
/* Memory configuration Detection for Loongson LoongArch DDR4 CPU family */
|
||||
void get_imc_config_loongson_ddr4(void);
|
||||
|
||||
|
113
system/imc/intel_mtl.c
Normal file
113
system/imc/intel_mtl.c
Normal file
@ -0,0 +1,113 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2004-2024 Sam Demeulemeester
|
||||
//
|
||||
// ------------------------
|
||||
//
|
||||
// Platform-specific code for Intel Meteor Lake (MTL) and
|
||||
// Arrow-Lake (ARL) CPUs
|
||||
//
|
||||
|
||||
#include "cpuinfo.h"
|
||||
#include "memctrl.h"
|
||||
#include "msr.h"
|
||||
#include "pci.h"
|
||||
#include "vmem.h"
|
||||
|
||||
#include "imc.h"
|
||||
|
||||
#define MTL_MMR_BASE_REG_LOW 0x48
|
||||
#define MTL_MMR_BASE_REG_HIGH 0x4C
|
||||
|
||||
#define MTL_MMR_WINDOW_RANGE (1UL << 17)
|
||||
#define MTL_MMR_BASE_MASK 0x3FFFFFE0000
|
||||
|
||||
#define MTL_MMR_MC1_OFFSET 0x10000
|
||||
#define MTL_MMR_CH1_OFFSET 0x800
|
||||
|
||||
#define MTL_MMR_IC_DECODE 0xD800
|
||||
#define MTL_MMR_CH0_DIMM_REG 0xD80C
|
||||
|
||||
#define MTL_MMR_CH0_PRE_REG 0xE000
|
||||
#define MTL_MMR_CH0_CAS_REG 0xE070
|
||||
#define MTL_MMR_CH0_ACT_REG 0xE138
|
||||
|
||||
#define MTL_MMR_PTGRAM_REG 0x13D98
|
||||
|
||||
void get_imc_config_intel_mtl(void)
|
||||
{
|
||||
uint64_t mmio_reg;
|
||||
uint32_t cha, chb, offset;
|
||||
uint32_t tmp;
|
||||
uintptr_t *ptr;
|
||||
uint32_t *ptr32;
|
||||
|
||||
// Get Memory Mapped Register Base Address (Enable MMIO if needed)
|
||||
mmio_reg = pci_config_read32(0, 0, 0, MTL_MMR_BASE_REG_LOW);
|
||||
if (!(mmio_reg & 0x1)) {
|
||||
pci_config_write32( 0, 0, 0, MTL_MMR_BASE_REG_LOW, mmio_reg | 1);
|
||||
mmio_reg = pci_config_read32(0, 0, 0, MTL_MMR_BASE_REG_LOW);
|
||||
if (!(mmio_reg & 0x1)) return;
|
||||
}
|
||||
|
||||
mmio_reg |= (uint64_t)pci_config_read32(0, 0, 0, MTL_MMR_BASE_REG_HIGH) << 32;
|
||||
mmio_reg &= MTL_MMR_BASE_MASK;
|
||||
|
||||
#ifndef __x86_64__
|
||||
if (mmio_reg >= (1ULL << 32)) return; // MMIO is outside reachable range (> 32bit)
|
||||
#endif
|
||||
|
||||
uintptr_t mchbar_addr = map_region(mmio_reg, MTL_MMR_WINDOW_RANGE, false);
|
||||
|
||||
// Get channel configuration & IMC width
|
||||
cha = *(uintptr_t*)(mchbar_addr + MTL_MMR_CH0_DIMM_REG);
|
||||
tmp = *(uintptr_t*)(mchbar_addr + MTL_MMR_IC_DECODE);
|
||||
cha = ~cha ? 1 << (((tmp >> 27) & 3) + 4) : 0;
|
||||
|
||||
chb = *(uintptr_t*)(mchbar_addr + MTL_MMR_CH0_DIMM_REG + MTL_MMR_MC1_OFFSET);
|
||||
tmp = *(uintptr_t*)(mchbar_addr + MTL_MMR_IC_DECODE + MTL_MMR_MC1_OFFSET);
|
||||
chb = ~chb ? 1 << (((tmp >> 27) & 3) + 4) : 0;
|
||||
|
||||
offset = cha ? 0x0 : MTL_MMR_MC1_OFFSET;
|
||||
imc.width = (cha + chb) * 2;
|
||||
|
||||
// MTL+ only supports DDR5
|
||||
imc.type = "DDR5";
|
||||
|
||||
// Get Memory Clock
|
||||
ptr32 = (uint32_t*)(mchbar_addr + MTL_MMR_PTGRAM_REG);
|
||||
|
||||
switch((*ptr32 >> 20) & 0xF) {
|
||||
default:
|
||||
case 0x1:
|
||||
imc.freq = 200;
|
||||
break;
|
||||
case 0x2:
|
||||
imc.freq = 100;
|
||||
break;
|
||||
case 0xA:
|
||||
imc.freq = 133;
|
||||
break;
|
||||
case 0xB:
|
||||
imc.freq = 66;
|
||||
break;
|
||||
case 0xC:
|
||||
imc.freq = 33;
|
||||
break;
|
||||
}
|
||||
|
||||
imc.freq *= (*ptr32 >> 12) & 0xFF; // * Divider
|
||||
imc.freq *= (((*ptr32 >> 24) & 1) + 1) * 2; // * Gear * DDR
|
||||
|
||||
// Get DRAM Timings
|
||||
ptr = (uintptr_t*)(mchbar_addr + offset + MTL_MMR_CH0_CAS_REG);
|
||||
imc.tCL = (*ptr >> 16) & 0x7F;
|
||||
|
||||
ptr = (uintptr_t*)(mchbar_addr + offset + MTL_MMR_CH0_ACT_REG);
|
||||
imc.tRCD = (*ptr >> 22) & 0xFF;
|
||||
|
||||
ptr = (uintptr_t*)(mchbar_addr + offset + MTL_MMR_CH0_PRE_REG);
|
||||
imc.tRP = (*ptr >> 10) & 0xFF;
|
||||
|
||||
ptr32 = (uint32_t*)((uintptr_t)mchbar_addr + offset + MTL_MMR_CH0_PRE_REG + 4);
|
||||
imc.tRAS = (*ptr32 >> 13) & 0x1FF;
|
||||
}
|
@ -57,6 +57,9 @@ void memctrl_init(void)
|
||||
case IMC_ADL:
|
||||
get_imc_config_intel_adl();
|
||||
break;
|
||||
case IMC_ARL:
|
||||
case IMC_MTL:
|
||||
get_imc_config_intel_mtl();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -37,10 +37,12 @@
|
||||
#define SMBHSTSTS_INTR 0x02
|
||||
#define SMBHSTSTS_HOST_BUSY 0x01
|
||||
|
||||
/* i801 Hosts Control register bits */
|
||||
#define SMBHSTCNT_QUICK 0x00
|
||||
#define SMBHSTCNT_BYTE 0x04
|
||||
#define SMBHSTCNT_BYTE_DATA 0x08
|
||||
#define SMBHSTCNT_WORD_DATA 0x0C
|
||||
#define SMBHSTCNT_PROC_CALL 0x10
|
||||
#define SMBHSTCNT_BLOCK_DATA 0x14
|
||||
#define SMBHSTCNT_I2C_BLOCK_DATA 0x18
|
||||
#define SMBHSTCNT_LAST_BYTE 0x20
|
||||
|
Loading…
x
Reference in New Issue
Block a user