From fa206bb865c0d7d69d50df5d75379830b0cf446f Mon Sep 17 00:00:00 2001 From: Sam Demeulemeester Date: Mon, 21 Mar 2022 02:33:12 +0100 Subject: [PATCH] Added DDR2 SPD decoding (#2) --- system/smbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/system/smbus.c b/system/smbus.c index 10719b3..50eb809 100644 --- a/system/smbus.c +++ b/system/smbus.c @@ -20,6 +20,7 @@ unsigned short smbusbase; static bool isPage1 = false; +static spd_info parse_spd_ddr2(uint8_t smb_idx, uint8_t slot_idx); static spd_info parse_spd_ddr3(uint8_t smb_idx, uint8_t slot_idx); static spd_info parse_spd_ddr4(uint8_t smb_idx, uint8_t slot_idx); static void print_spdi(spd_info spdi, uint8_t lidx); @@ -121,12 +122,11 @@ void print_smbus_startup_info(void) { curspd = parse_spd_ddr3(index, spdidx); break; case 0x08: // DDR2 - + curspd = parse_spd_ddr2(index, spdidx); break; } if(curspd.isValid) { - if(spd_line_idx == 0) { prints(LINE_SPD-2, 0, "Memory SPD Informations"); prints(LINE_SPD-1, 0, "-----------------------"); @@ -372,6 +372,91 @@ static spd_info parse_spd_ddr3(uint8_t smb_idx, uint8_t slot_idx) return spdi; } +static spd_info parse_spd_ddr2(uint8_t smb_idx, uint8_t slot_idx) { + spd_info spdi; + + uint8_t bcd; + int8_t j; + + spdi.type = "DDR2"; + spdi.slot_num = slot_idx; + spdi.sku_len = 0; + spdi.XMP = 0; + + // Compute module size with shifts + switch (get_spd(smb_idx, slot_idx, 31)) { + case 1: + spdi.module_size = 1024; + break; + case 2: + spdi.module_size = 2048; + break; + case 4: + spdi.module_size = 4096; + break; + case 8: + spdi.module_size = 8192; + break; + case 16: + spdi.module_size = 16384; + break; + case 32: + spdi.module_size = 128; + break; + case 64: + spdi.module_size = 256; + break; + default: + case 128: + spdi.module_size = 512; + break; + } + + spdi.module_size *= (get_spd(smb_idx, slot_idx, 5) & 7) + 1; + spdi.module_size *= 1024; + + spdi.hasECC = ((get_spd(smb_idx, slot_idx, 11) >> 1) == 1); + + // Module speed + uint8_t spd_byte9 = get_spd(smb_idx, slot_idx, 9); + spdi.freq = (float)(1.0f / (((spd_byte9 >> 4) * 10.0f) + (spd_byte9 & 0xF)) * 10000.0f * 2.0f); + + // Module manufacturer + uint8_t contcode; + for (contcode = 64; contcode < 72; contcode++) { + if (get_spd(smb_idx, slot_idx, contcode) != 0x7F) { + break; + } + } + + spdi.jedec_code = (contcode - 64) << 8; + spdi.jedec_code |= get_spd(smb_idx, slot_idx, contcode) & 0x7F; + + // Module SKU + uint8_t sku_byte; + for (j = 0; j < 18; j++) { + sku_byte = get_spd(smb_idx, slot_idx, 73 + j); + + if (sku_byte <= 0x20 && j > 0 && spdi.sku[j - 1] <= 0x20) { + spdi.sku_len--; + break; + } else { + spdi.sku[j] = sku_byte; + spdi.sku_len++; + } + } + + bcd = get_spd(smb_idx, slot_idx, 94); + spdi.fab_year = bcd - 6 * (bcd >> 4); + + bcd = get_spd(smb_idx, slot_idx, 93); + spdi.fab_week = bcd - 6 * (bcd >> 4); + + spdi.isValid = true; + + return spdi; +} + // -------------------------- // Smbus Controller Functions // --------------------------