Haswell NRI: Add dumping of CAPID registers

If `CONFIG(DEBUG_RAM_SETUP)`, dump the values of the CAPID0_A and
CAPID0_B registers to the log. This is useful debugging information.

Dump the CAPID registers' values before native chipset init, because
dynamic fusing changes the CAPID values.

Tested on ASRock Z97 Extreme6 with a PCIe card plugged into the PCIE4
slot (forcing PEG to be bifurcated as x8+x8). The CPU and PCH are:

    CPU id(306c3) ucode:00000028 Intel(R) Core(TM) i7-4770S CPU @ 3.10GHz
    AES supported, TXT supported, VT supported
    PCH type: Z97, device id: 8cc4, rev id 0

CAPID values before dynamic fusing are shown below:

CAPID0_A: 0x6204e861
    DDR3L 1.35V:        Yes
    DDR Write Vref:     No
    OC enabled (DSKU):  No
    DDR overclock:      No
    Compatibility RID:  0x6
    Capability DID:     Desktop
    DID override:       No
    Integrated GPU:     No
    Dual channel:       Yes
    X2APIC support:     Yes
    DIMMs per channel:  1
    Camarillo device:   No
    Full ULT info:      Yes
    DDR 1N mode:        Yes
    PCIe ratio:         No
    Max channel size:   16 GiB
    PEG Gen2 support:   Yes
    DMI Gen2 support:   Yes
    VT-d support:       Yes
    ECC forced:         No
    ECC supported:      No
    DMI width:          x4
    Width upconfig:     Yes
    PEG function 0:     Yes
    PEG function 1:     No
    PEG function 2:     No
    Disp HD audio:      Yes

CAPID0_B: 0x565400d0
    PEG for GFX single: Unlimited width
    PEG for GFX multi:  Unlimited width
    133 MHz ref clock:  Up to DDR3-1600
    Silicon mode:       Production
    HDCP capable:       Yes
    Num PEG lanes:      16
    Add. GFX capable:   Yes
    Add. GFX enable:    Yes
    CPU Package Type:   0
    PEG Gen3 support:   No
    100 MHz ref clock:  Up to DDR3-1600
    Soft Bin capable:   No
    Cache size:         3
    SMT support:        Yes
    OC enabled (SSKU):  No
    OC controlled by:   SSKU

CAPID values after dynamic fusing are shown below, with manually
added arrows to indicate which values have changed:

CAPID0_A: 0x4204a06d
    DDR3L 1.35V:        Yes
    DDR Write Vref:     No
    OC enabled (DSKU):  Yes              <-----
    DDR overclock:      Yes              <-----
    Compatibility RID:  0x6
    Capability DID:     Desktop
    DID override:       No
    Integrated GPU:     Yes              <-----
    Dual channel:       Yes
    X2APIC support:     Yes
    DIMMs per channel:  2                <-----
    Camarillo device:   No
    Full ULT info:      Yes
    DDR 1N mode:        Yes
    PCIe ratio:         No
    Max channel size:   16 GiB
    PEG Gen2 support:   Yes
    DMI Gen2 support:   Yes
    VT-d support:       Yes
    ECC forced:         No
    ECC supported:      No
    DMI width:          x4
    Width upconfig:     Yes
    PEG function 0:     Yes
    PEG function 1:     Yes              <-----
    PEG function 2:     No
    Disp HD audio:      Yes

CAPID0_B: 0x564400d0
    PEG for GFX single: Unlimited width
    PEG for GFX multi:  Unlimited width
    133 MHz ref clock:  Up to DDR3-1600
    Silicon mode:       Production
    HDCP capable:       Yes
    Num PEG lanes:      16
    Add. GFX capable:   Yes
    Add. GFX enable:    Yes
    CPU Package Type:   0
    PEG Gen3 support:   Yes              <-----
    100 MHz ref clock:  Up to DDR3-1600
    Soft Bin capable:   No
    Cache size:         3
    SMT support:        Yes
    OC enabled (SSKU):  No
    OC controlled by:   SSKU

Change-Id: I46f27c54a7ec7fd9fc79fdabaa59a44a591168b8
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91478
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
This commit is contained in:
Angel Pons 2026-02-28 20:22:49 +01:00 committed by Matt DeVillier
commit 8998999eb3
5 changed files with 183 additions and 0 deletions

View file

@ -23,3 +23,5 @@ romstage-y += train_jedec_write_leveling.c
romstage-y += train_read_mpr.c
romstage-y += train_receive_enable.c
romstage-y += train_sense_amp_offset.c
romstage-$(CONFIG_DEBUG_RAM_SETUP) += info_dumps.c

View file

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <device/pci_ops.h>
#include <northbridge/intel/haswell/haswell.h>
#include <types.h>
#include "raminit_native.h"
void dump_capid_values(void)
{
static const char *const no_yes[] = {
[0] = "No",
[1] = "Yes",
};
static const char *const cdid_decoder[] = {
[0] = "Desktop",
[1] = "Server",
[2] = "Mobile",
[3] = "Marketing Spare",
};
static const char *const ddrsz_lut[] = {
[0] = "16",
[1] = "8",
[2] = "2",
[3] = "0.5",
};
static const char *const pegfx1_lut[] = {
[0] = "Unlimited width",
[1] = "Limited to x1",
};
static const char *const dmfc_lut[] = {
[0] = "Unlimited",
[1] = "Up to DDR3-2667",
[2] = "Up to DDR3-2400",
[3] = "Up to DDR3-2133",
[4] = "Up to DDR3-1867",
[5] = "Up to DDR3-1600",
[6] = "Up to DDR3-1333",
[7] = "Up to DDR3-1067",
};
static const char *const ddd_lut[] = {
[0] = "Debug",
[1] = "Production",
};
static const char *const pll100_lut[] = {
[0] = "Not supported",
[1] = "Up to DDR3-1400",
[2] = "Up to DDR3-1600",
[3] = "Up to DDR3-1800",
[4] = "Up to DDR3-2000",
[5] = "Up to DDR3-2200",
[6] = "Up to DDR3-2400",
[7] = "Unlimited",
};
static const char *const occtl_lut[] = {
[0] = "DSKU",
[1] = "SSKU",
};
const union pci_capid0_a_reg capid0_a = {
.raw = pci_read_config32(HOST_BRIDGE, CAPID0_A)
};
const union pci_capid0_b_reg capid0_b = {
.raw = pci_read_config32(HOST_BRIDGE, CAPID0_B)
};
printk(BIOS_DEBUG, "\n");
printk(BIOS_DEBUG, "CAPID0_A: 0x%08x\n", capid0_a.raw);
printk(BIOS_DEBUG, " DDR3L 1.35V: %s\n", no_yes[capid0_a.DDR3L_EN]);
printk(BIOS_DEBUG, " DDR Write Vref: %s\n", no_yes[capid0_a.DDR_WRTVREF]);
printk(BIOS_DEBUG, " OC enabled (DSKU): %s\n", no_yes[capid0_a.OC_ENABLED_DSKU]);
printk(BIOS_DEBUG, " DDR overclock: %s\n", no_yes[capid0_a.DDR_OVERCLOCK]);
printk(BIOS_DEBUG, " Compatibility RID: 0x%01x\n", capid0_a.CRID);
printk(BIOS_DEBUG, " Capability DID: %s\n", cdid_decoder[capid0_a.CDID]);
printk(BIOS_DEBUG, " DID override: %s\n", no_yes[capid0_a.DIDOE]);
printk(BIOS_DEBUG, " Integrated GPU: %s\n", no_yes[!capid0_a.IGD]);
printk(BIOS_DEBUG, " Dual channel: %s\n", no_yes[!capid0_a.PDCD]);
printk(BIOS_DEBUG, " X2APIC support: %s\n", no_yes[capid0_a.X2APIC_EN]);
printk(BIOS_DEBUG, " DIMMs per channel: %u\n", capid0_a.DDPCD ? 1 : 2);
printk(BIOS_DEBUG, " Camarillo device: %s\n", no_yes[!capid0_a.CDD]);
printk(BIOS_DEBUG, " Full ULT info: %s\n", no_yes[!capid0_a.FUFRD]);
printk(BIOS_DEBUG, " DDR 1N mode: %s\n", no_yes[!capid0_a.D1NM]);
printk(BIOS_DEBUG, " PCIe ratio: %s\n", no_yes[!capid0_a.PCIE_RATIO_DIS]);
printk(BIOS_DEBUG, " Max channel size: %s GiB\n", ddrsz_lut[capid0_a.DDRSZ]);
printk(BIOS_DEBUG, " PEG Gen2 support: %s\n", no_yes[!capid0_a.PEGG2DIS]);
printk(BIOS_DEBUG, " DMI Gen2 support: %s\n", no_yes[!capid0_a.DMIG2DIS]);
printk(BIOS_DEBUG, " VT-d support: %s\n", no_yes[!capid0_a.VTDD]);
printk(BIOS_DEBUG, " ECC forced: %s\n", no_yes[capid0_a.FDEE]);
printk(BIOS_DEBUG, " ECC supported: %s\n", no_yes[!capid0_a.ECCDIS]);
printk(BIOS_DEBUG, " DMI width: x%u\n", capid0_a.DW ? 2 : 4);
printk(BIOS_DEBUG, " Width upconfig: %s\n", no_yes[!capid0_a.PELWUD]);
printk(BIOS_DEBUG, " PEG function 0: %s\n", no_yes[!capid0_a.PEG10D]);
printk(BIOS_DEBUG, " PEG function 1: %s\n", no_yes[!capid0_a.PEG11D]);
printk(BIOS_DEBUG, " PEG function 2: %s\n", no_yes[!capid0_a.PEG12D]);
printk(BIOS_DEBUG, " Disp HD audio: %s\n", no_yes[!capid0_a.DHDAD]);
printk(BIOS_DEBUG, "\n");
printk(BIOS_DEBUG, "CAPID0_B: 0x%08x\n", capid0_b.raw);
printk(BIOS_DEBUG, " PEG for GFX single: %s\n", pegfx1_lut[capid0_b.SPEGFX1]);
printk(BIOS_DEBUG, " PEG for GFX multi: %s\n", pegfx1_lut[capid0_b.DPEGFX1]);
printk(BIOS_DEBUG, " 133 MHz ref clock: %s\n", dmfc_lut[capid0_b.DMFC]);
printk(BIOS_DEBUG, " Silicon mode: %s\n", ddd_lut[capid0_b.DDD]);
printk(BIOS_DEBUG, " HDCP capable: %s\n", no_yes[!capid0_b.HDCPD]);
printk(BIOS_DEBUG, " Num PEG lanes: %u\n", capid0_b.PEGX16D ? 8 : 16);
printk(BIOS_DEBUG, " Add. GFX capable: %s\n", no_yes[!capid0_b.ADDGFXCAP]);
printk(BIOS_DEBUG, " Add. GFX enable: %s\n", no_yes[capid0_b.ADDGFXEN]);
printk(BIOS_DEBUG, " CPU Package Type: %u\n", capid0_b.PKGTYP);
printk(BIOS_DEBUG, " PEG Gen3 support: %s\n", no_yes[!capid0_b.PEGG3_DIS]);
printk(BIOS_DEBUG, " 100 MHz ref clock: %s\n", pll100_lut[capid0_b.PLL_REF100_CFG]);
printk(BIOS_DEBUG, " Soft Bin capable: %s\n", no_yes[capid0_b.SOFTBIN]);
printk(BIOS_DEBUG, " Cache size: %u\n", capid0_b.CACHESZ);
printk(BIOS_DEBUG, " SMT support: %s\n", no_yes[capid0_b.SMT]);
printk(BIOS_DEBUG, " OC enabled (SSKU): %s\n", no_yes[capid0_b.OC_ENABLED_SSKU]);
printk(BIOS_DEBUG, " OC controlled by: %s\n", occtl_lut[capid0_b.OC_CTL_DSKU_DIS]);
printk(BIOS_DEBUG, "\n");
}

View file

@ -171,6 +171,11 @@ void perform_raminit(const bool s3resume)
*/
const enum raminit_boot_mode orig_bootmode = get_boot_mode();
if (CONFIG(DEBUG_RAM_SETUP)) {
/* Log CAPID values before dynamic fusing takes place */
dump_capid_values();
}
const bool cpu_replaced = early_init_native(s3resume ? BOOTMODE_S3 : orig_bootmode);
wait_txt_clear();

View file

@ -703,4 +703,6 @@ uint8_t get_tCWL(uint32_t mem_clock_mhz);
uint32_t get_tREFI(uint32_t mem_clock_mhz);
uint32_t get_tXP(uint32_t mem_clock_mhz);
void dump_capid_values(void);
#endif

View file

@ -3,6 +3,65 @@
#ifndef HASWELL_RAMINIT_REG_STRUCTS_H
#define HASWELL_RAMINIT_REG_STRUCTS_H
union pci_capid0_a_reg {
struct __packed {
uint32_t DDR3L_EN : 1; // Bits 0:0
uint32_t DDR_WRTVREF : 1; // Bits 1:1
uint32_t OC_ENABLED_DSKU : 1; // Bits 2:2
uint32_t DDR_OVERCLOCK : 1; // Bits 3:3
uint32_t CRID : 4; // Bits 7:4
uint32_t CDID : 2; // Bits 9:8
uint32_t DIDOE : 1; // Bits 10:10
uint32_t IGD : 1; // Bits 11:11
uint32_t PDCD : 1; // Bits 12:12
uint32_t X2APIC_EN : 1; // Bits 13:13
uint32_t DDPCD : 1; // Bits 14:14
uint32_t CDD : 1; // Bits 15:15
uint32_t FUFRD : 1; // Bits 16:16
uint32_t D1NM : 1; // Bits 17:17
uint32_t PCIE_RATIO_DIS : 1; // Bits 18:18
uint32_t DDRSZ : 2; // Bits 20:19
uint32_t PEGG2DIS : 1; // Bits 21:21
uint32_t DMIG2DIS : 1; // Bits 22:22
uint32_t VTDD : 1; // Bits 23:23
uint32_t FDEE : 1; // Bits 24:24
uint32_t ECCDIS : 1; // Bits 25:25
uint32_t DW : 1; // Bits 26:26
uint32_t PELWUD : 1; // Bits 27:27
uint32_t PEG10D : 1; // Bits 28:28
uint32_t PEG11D : 1; // Bits 29:29
uint32_t PEG12D : 1; // Bits 30:30
uint32_t DHDAD : 1; // Bits 31:31
};
uint32_t raw;
};
union pci_capid0_b_reg {
struct __packed {
uint32_t SPEGFX1 : 1; // Bits 0:0
uint32_t DPEGFX1 : 1; // Bits 1:1
uint32_t : 2; // Bits 3:2
uint32_t DMFC : 3; // Bits 6:4
uint32_t DDD : 1; // Bits 7:7
uint32_t : 3; // Bits 10:8
uint32_t HDCPD : 1; // Bits 11:11
uint32_t : 4; // Bits 15:12
uint32_t PEGX16D : 1; // Bits 16:16
uint32_t ADDGFXCAP : 1; // Bits 17:17
uint32_t ADDGFXEN : 1; // Bits 18:18
uint32_t PKGTYP : 1; // Bits 19:19
uint32_t PEGG3_DIS : 1; // Bits 20:20
uint32_t PLL_REF100_CFG : 3; // Bits 23:21
uint32_t SOFTBIN : 1; // Bits 24:24
uint32_t CACHESZ : 3; // Bits 27:25
uint32_t SMT : 1; // Bits 28:28
uint32_t OC_ENABLED_SSKU : 1; // Bits 29:29
uint32_t OC_CTL_DSKU_DIS : 1; // Bits 30:30
uint32_t : 1; // Bits 31:31
};
uint32_t raw;
};
union ddr_data_rx_train_rank_reg {
struct __packed {
uint32_t rcven : 9; // Bits 8:0