diff --git a/src/vendorcode/amd/agesa/Kconfig b/src/vendorcode/amd/agesa/Kconfig index bfec0457d8..67055ea5dc 100644 --- a/src/vendorcode/amd/agesa/Kconfig +++ b/src/vendorcode/amd/agesa/Kconfig @@ -25,4 +25,117 @@ config CPU_AMD_AGESA_OPENSOURCE_MEM_XMP_2 help XMP 2 memory profile. Check that it exists on ALL of your RAM sticks! +config CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM + bool "CUSTOM" + help + Custom memory profile. Use the XMP SPD values as the base, if available. + +if CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM + +config CUSTOM_SPD_DIVIDENT + int "[10]: Medium Timebase (MTB) Dividend" + default 1 + range 1 255 + +config CUSTOM_SPD_DIVISOR + int "[11]: Medium Timebase (MTB) Divisor" + default 14 + range 1 255 + +config CUSTOM_SPD_TCK + int "[12]: SDRAM Minimum Cycle Time, tCK" + default 15 + range 1 255 + +config CUSTOM_SPD_CASLO + int "[14]: CAS Latencies Supported, Lower Byte" + default 124 + range 0 255 + +config CUSTOM_SPD_CASHI + int "[15]: CAS Latencies Supported, Higher Byte" + default 0 + range 0 255 + +config CUSTOM_SPD_TAA + int "[16]: Min CAS Latency Time, tAA" + default 132 + range 1 255 + +config CUSTOM_SPD_TWR + int "[17]: Min Write Recovery Time, tWR" + default 210 + range 1 255 + +config CUSTOM_SPD_TRCD + int "[18]: Min RAS# to CAS# Delay Time, tRCD" + default 132 + range 1 255 + +config CUSTOM_SPD_TRRD + int "[19]: Min Row Active to Row Active Delay Time, tRRD" + default 84 + range 1 255 + +config CUSTOM_SPD_TRP + int "[20]: Min Row Precharge Delay Time, tRP" + default 132 + range 1 255 + +config CUSTOM_SPD_UPPER_TRC + int "[21][7:4]: Min Active to Active/Refresh Delay, UPPER tRC" + default 2 + range 0 16 + +config CUSTOM_SPD_UPPER_TRAS + int "[21][3:0]: Min Active to Precharge Delay Time, UPPER tRAS" + default 1 + range 0 16 + +config CUSTOM_SPD_TRAS + int "[22]: Min Active to Precharge Delay Time, LOWER tRAS" + default 138 + range 1 255 + +config CUSTOM_SPD_TRC + int "[23]: Min Active to Active/Refresh Delay, LOWER tRC" + default 181 + range 1 255 + +if CPU_AMD_AGESA_FAMILY16_KB + +config CUSTOM_SPD_TRFC_LO + int "[24]: Min Refresh Recovery Delay Time, LOWER tRFC" + default 56 + range 1 255 + +config CUSTOM_SPD_TRFC_HI + int "[25]: Min Refresh Recovery Delay Time, UPPER tRFC" + default 14 + range 0 255 + +endif + +config CUSTOM_SPD_TWTR + int "[26]: Min Internal Write to Read Command Delay, tWTR" + default 105 + range 1 255 + +config CUSTOM_SPD_TRTP + int "[27]: Min Internal Read to Precharge Command Delay, tRTP" + default 105 + range 1 255 + +config CUSTOM_SPD_UPPER_TFAW + int "[28][3:0]: Min Four Activate Window Delay, UPPER tFAW" + default 1 + range 0 16 + +config CUSTOM_SPD_TFAW + int "[29]: Min Four Activate Window Delay Time, tFAW" + default 164 + range 1 255 + +endif + endchoice diff --git a/src/vendorcode/amd/agesa/f14/Config/PlatformInstall.h b/src/vendorcode/amd/agesa/f14/Config/PlatformInstall.h index 31472b2c2e..4103961f64 100644 --- a/src/vendorcode/amd/agesa/f14/Config/PlatformInstall.h +++ b/src/vendorcode/amd/agesa/f14/Config/PlatformInstall.h @@ -817,6 +817,11 @@ CONST UINT32 ROMDATA AmdPlatformTypeCgf = CFG_AMD_PLATFORM_TYPE; #define CFG_DQS_TRAINING_CONTROL TRUE #endif +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) + #undef BLDCFG_IGNORE_SPD_CHECKSUM + #define BLDCFG_IGNORE_SPD_CHECKSUM TRUE +#endif + #ifdef BLDCFG_IGNORE_SPD_CHECKSUM #define CFG_IGNORE_SPD_CHECKSUM BLDCFG_IGNORE_SPD_CHECKSUM #else diff --git a/src/vendorcode/amd/agesa/f14/Proc/Mem/Main/mmflow.c b/src/vendorcode/amd/agesa/f14/Proc/Mem/Main/mmflow.c index 392b7fc87c..cf3942b08e 100644 --- a/src/vendorcode/amd/agesa/f14/Proc/Mem/Main/mmflow.c +++ b/src/vendorcode/amd/agesa/f14/Proc/Mem/Main/mmflow.c @@ -64,6 +64,7 @@ #include "mm.h" #include "mn.h" #include "mt.h" +#include "mtspd3.h" #include "mu.h" #include "heapManager.h" #include "Filecode.h" @@ -101,6 +102,16 @@ MemSPDDataProcess ( IN OUT MEM_DATA_STRUCT *MemPtr ); +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ); + +#endif + /*---------------------------------------------------------------------------- * EXPORTED FUNCTIONS * @@ -293,6 +304,60 @@ AmdMemAuto ( return Retval; } +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +/* -----------------------------------------------------------------------------*/ +/** + * + * + * This function modifies a SPD buffer with the custom SPD values set up in coreboot's config. + * + * @param[in,out] *Buffer - Pointer to the UINT8 + * + */ + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ) +{ + UINT16 Offset; + // + // Modify a SPD buffer. + // + Buffer[SPD_DIVIDENT] = CONFIG_CUSTOM_SPD_DIVIDENT; + Buffer[SPD_DIVISOR] = CONFIG_CUSTOM_SPD_DIVISOR; + Buffer[SPD_TCK] = CONFIG_CUSTOM_SPD_TCK; + Buffer[SPD_CASLO] = CONFIG_CUSTOM_SPD_CASLO; + Buffer[SPD_CASHI] = CONFIG_CUSTOM_SPD_CASHI; + Buffer[SPD_TAA] = CONFIG_CUSTOM_SPD_TAA; + Buffer[SPD_TWR] = CONFIG_CUSTOM_SPD_TWR; + Buffer[SPD_TRCD] = CONFIG_CUSTOM_SPD_TRCD; + Buffer[SPD_TRRD] = CONFIG_CUSTOM_SPD_TRRD; + Buffer[SPD_TRP] = CONFIG_CUSTOM_SPD_TRP; + // + // SPD_UPPER_TRC and SPD_UPPER_TRAS are the same index but different bits: + // SPD_UPPER_TRC - [7:4], SPD_UPPER_TRAS - [3:0]. + // + Buffer[SPD_UPPER_TRAS] = (CONFIG_CUSTOM_SPD_UPPER_TRC << 4) + CONFIG_CUSTOM_SPD_UPPER_TRAS; + Buffer[SPD_TRAS] = CONFIG_CUSTOM_SPD_TRAS; + Buffer[SPD_TRC] = CONFIG_CUSTOM_SPD_TRC; + Buffer[SPD_TWTR] = CONFIG_CUSTOM_SPD_TWTR; + Buffer[SPD_TRTP] = CONFIG_CUSTOM_SPD_TRTP; + Buffer[SPD_UPPER_TFAW] = CONFIG_CUSTOM_SPD_UPPER_TFAW; + Buffer[SPD_TFAW] = CONFIG_CUSTOM_SPD_TFAW; + // + // Print a SPD buffer. + // + printk(BIOS_SPEW, "***** SPD BUFFER *****\n"); + for (Offset = 0; Offset < 256; Offset++) { + printk(BIOS_SPEW, "Buffer[%d] = 0x%02X\n", Offset, Buffer[Offset]); + } + printk(BIOS_SPEW, "**********************\n"); +} + +#endif /* -----------------------------------------------------------------------------*/ /** @@ -369,6 +434,9 @@ MemSPDDataProcess ( if (AgesaStatus == AGESA_SUCCESS) { DimmSPDPtr->DimmPresent = TRUE; IDS_HDT_CONSOLE (MEM_FLOW, "SPD Socket %d Channel %d Dimm %d: %08x\n", Socket, Channel, Dimm, SpdParam.Buffer); + #if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + AgesaCustomMemoryProfileSPD(SpdParam.Buffer); + #endif } else { DimmSPDPtr->DimmPresent = FALSE; } diff --git a/src/vendorcode/amd/agesa/f14/Proc/Mem/Tech/DDR3/mtspd3.h b/src/vendorcode/amd/agesa/f14/Proc/Mem/Tech/DDR3/mtspd3.h index c7f490df2d..2797f80f9a 100644 --- a/src/vendorcode/amd/agesa/f14/Proc/Mem/Tech/DDR3/mtspd3.h +++ b/src/vendorcode/amd/agesa/f14/Proc/Mem/Tech/DDR3/mtspd3.h @@ -95,7 +95,7 @@ #define SPD_FTB 9 -#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) || CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) #define SPD_DIVIDENT 10 #define SPD_DIVISOR 11 diff --git a/src/vendorcode/amd/agesa/f15tn/Config/PlatformInstall.h b/src/vendorcode/amd/agesa/f15tn/Config/PlatformInstall.h index 8bdbb92165..4a6d5984c0 100644 --- a/src/vendorcode/amd/agesa/f15tn/Config/PlatformInstall.h +++ b/src/vendorcode/amd/agesa/f15tn/Config/PlatformInstall.h @@ -2047,6 +2047,11 @@ CONST UINT32 ROMDATA AmdPlatformTypeCgf = CFG_AMD_PLATFORM_TYPE; #define CFG_DQS_TRAINING_CONTROL TRUE #endif +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) + #undef BLDCFG_IGNORE_SPD_CHECKSUM + #define BLDCFG_IGNORE_SPD_CHECKSUM TRUE +#endif + #ifdef BLDCFG_IGNORE_SPD_CHECKSUM #define CFG_IGNORE_SPD_CHECKSUM BLDCFG_IGNORE_SPD_CHECKSUM #else diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Main/mmflow.c b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Main/mmflow.c index f2e5848bfe..1030d7ae9b 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Main/mmflow.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Main/mmflow.c @@ -62,6 +62,7 @@ #include "mm.h" #include "mn.h" #include "mt.h" +#include "mtspd3.h" #include "mu.h" #include "heapManager.h" #include "Filecode.h" @@ -99,6 +100,16 @@ MemSPDDataProcess ( IN OUT MEM_DATA_STRUCT *MemPtr ); +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ); + +#endif + /*---------------------------------------------------------------------------- * EXPORTED FUNCTIONS * @@ -302,6 +313,60 @@ AmdMemAuto ( return Retval; } +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +/* -----------------------------------------------------------------------------*/ +/** + * + * + * This function modifies a SPD buffer with the custom SPD values set up in coreboot's config. + * + * @param[in,out] *Buffer - Pointer to the UINT8 + * + */ + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ) +{ + UINT16 Offset; + // + // Modify a SPD buffer. + // + Buffer[SPD_DIVIDENT] = CONFIG_CUSTOM_SPD_DIVIDENT; + Buffer[SPD_DIVISOR] = CONFIG_CUSTOM_SPD_DIVISOR; + Buffer[SPD_TCK] = CONFIG_CUSTOM_SPD_TCK; + Buffer[SPD_CASLO] = CONFIG_CUSTOM_SPD_CASLO; + Buffer[SPD_CASHI] = CONFIG_CUSTOM_SPD_CASHI; + Buffer[SPD_TAA] = CONFIG_CUSTOM_SPD_TAA; + Buffer[SPD_TWR] = CONFIG_CUSTOM_SPD_TWR; + Buffer[SPD_TRCD] = CONFIG_CUSTOM_SPD_TRCD; + Buffer[SPD_TRRD] = CONFIG_CUSTOM_SPD_TRRD; + Buffer[SPD_TRP] = CONFIG_CUSTOM_SPD_TRP; + // + // SPD_UPPER_TRC and SPD_UPPER_TRAS are the same index but different bits: + // SPD_UPPER_TRC - [7:4], SPD_UPPER_TRAS - [3:0]. + // + Buffer[SPD_UPPER_TRAS] = (CONFIG_CUSTOM_SPD_UPPER_TRC << 4) + CONFIG_CUSTOM_SPD_UPPER_TRAS; + Buffer[SPD_TRAS] = CONFIG_CUSTOM_SPD_TRAS; + Buffer[SPD_TRC] = CONFIG_CUSTOM_SPD_TRC; + Buffer[SPD_TWTR] = CONFIG_CUSTOM_SPD_TWTR; + Buffer[SPD_TRTP] = CONFIG_CUSTOM_SPD_TRTP; + Buffer[SPD_UPPER_TFAW] = CONFIG_CUSTOM_SPD_UPPER_TFAW; + Buffer[SPD_TFAW] = CONFIG_CUSTOM_SPD_TFAW; + // + // Print a SPD buffer. + // + printk(BIOS_SPEW, "***** SPD BUFFER *****\n"); + for (Offset = 0; Offset < 256; Offset++) { + printk(BIOS_SPEW, "Buffer[%d] = 0x%02X\n", Offset, Buffer[Offset]); + } + printk(BIOS_SPEW, "**********************\n"); +} + +#endif /* -----------------------------------------------------------------------------*/ /** @@ -378,6 +443,9 @@ MemSPDDataProcess ( if (AgesaStatus == AGESA_SUCCESS) { DimmSPDPtr->DimmPresent = TRUE; IDS_HDT_CONSOLE (MEM_FLOW, "SPD Socket %d Channel %d Dimm %d: %08x\n", Socket, Channel, Dimm, SpdParam.Buffer); + #if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + AgesaCustomMemoryProfileSPD(SpdParam.Buffer); + #endif } else { DimmSPDPtr->DimmPresent = FALSE; } diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h index bbe5c1238c..ede7067464 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h +++ b/src/vendorcode/amd/agesa/f15tn/Proc/Mem/Tech/DDR3/mtspd3.h @@ -94,7 +94,7 @@ #define SPD_FTB 9 -#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) || CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) #define SPD_DIVIDENT 10 #define SPD_DIVISOR 11 diff --git a/src/vendorcode/amd/agesa/f16kb/Config/PlatformInstall.h b/src/vendorcode/amd/agesa/f16kb/Config/PlatformInstall.h index 4606443632..2a588698b5 100644 --- a/src/vendorcode/amd/agesa/f16kb/Config/PlatformInstall.h +++ b/src/vendorcode/amd/agesa/f16kb/Config/PlatformInstall.h @@ -1016,6 +1016,11 @@ CONST UINT32 ROMDATA AmdPlatformTypeCgf = CFG_AMD_PLATFORM_TYPE; #define CFG_DQS_TRAINING_CONTROL TRUE #endif +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) + #undef BLDCFG_IGNORE_SPD_CHECKSUM + #define BLDCFG_IGNORE_SPD_CHECKSUM TRUE +#endif + #ifdef BLDCFG_IGNORE_SPD_CHECKSUM #define CFG_IGNORE_SPD_CHECKSUM BLDCFG_IGNORE_SPD_CHECKSUM #else diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Main/mmflow.c b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Main/mmflow.c index d497aec68d..dfc1e357f1 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Main/mmflow.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Main/mmflow.c @@ -62,6 +62,7 @@ #include "mm.h" #include "mn.h" #include "mt.h" +#include "mtspd3.h" #include "mu.h" #include "heapManager.h" #include "Filecode.h" @@ -99,6 +100,16 @@ MemSPDDataProcess ( IN OUT MEM_DATA_STRUCT *MemPtr ); +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ); + +#endif + /*---------------------------------------------------------------------------- * EXPORTED FUNCTIONS * @@ -314,6 +325,62 @@ AmdMemAuto ( return Retval; } +#if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + +/* -----------------------------------------------------------------------------*/ +/** + * + * + * This function modifies a SPD buffer with the custom SPD values set up in coreboot's config. + * + * @param[in,out] *Buffer - Pointer to the UINT8 + * + */ + +VOID +STATIC +AgesaCustomMemoryProfileSPD ( + IN OUT UINT8 *Buffer + ) +{ + UINT16 Offset; + // + // Modify a SPD buffer. + // + Buffer[SPD_DIVIDENT] = CONFIG_CUSTOM_SPD_DIVIDENT; + Buffer[SPD_DIVISOR] = CONFIG_CUSTOM_SPD_DIVISOR; + Buffer[SPD_TCK] = CONFIG_CUSTOM_SPD_TCK; + Buffer[SPD_CASLO] = CONFIG_CUSTOM_SPD_CASLO; + Buffer[SPD_CASHI] = CONFIG_CUSTOM_SPD_CASHI; + Buffer[SPD_TAA] = CONFIG_CUSTOM_SPD_TAA; + Buffer[SPD_TWR] = CONFIG_CUSTOM_SPD_TWR; + Buffer[SPD_TRCD] = CONFIG_CUSTOM_SPD_TRCD; + Buffer[SPD_TRRD] = CONFIG_CUSTOM_SPD_TRRD; + Buffer[SPD_TRP] = CONFIG_CUSTOM_SPD_TRP; + // + // SPD_UPPER_TRC and SPD_UPPER_TRAS are the same index but different bits: + // SPD_UPPER_TRC - [7:4], SPD_UPPER_TRAS - [3:0]. + // + Buffer[SPD_UPPER_TRAS] = (CONFIG_CUSTOM_SPD_UPPER_TRC << 4) + CONFIG_CUSTOM_SPD_UPPER_TRAS; + Buffer[SPD_TRAS] = CONFIG_CUSTOM_SPD_TRAS; + Buffer[SPD_TRC] = CONFIG_CUSTOM_SPD_TRC; + Buffer[SPD_TRFC_LO] = CONFIG_CUSTOM_SPD_TRFC_LO; + Buffer[SPD_TRFC_HI] = CONFIG_CUSTOM_SPD_TRFC_HI; + Buffer[SPD_TWTR] = CONFIG_CUSTOM_SPD_TWTR; + Buffer[SPD_TRTP] = CONFIG_CUSTOM_SPD_TRTP; + Buffer[SPD_UPPER_TFAW] = CONFIG_CUSTOM_SPD_UPPER_TFAW; + Buffer[SPD_TFAW] = CONFIG_CUSTOM_SPD_TFAW; + // + // Print a SPD buffer. + // + printk(BIOS_SPEW, "***** SPD BUFFER *****\n"); + for (Offset = 0; Offset < 256; Offset++) { + printk(BIOS_SPEW, "Buffer[%d] = 0x%02X\n", Offset, Buffer[Offset]); + } + printk(BIOS_SPEW, "**********************\n"); +} + +#endif /* -----------------------------------------------------------------------------*/ /** @@ -390,6 +457,9 @@ MemSPDDataProcess ( if (AgesaStatus == AGESA_SUCCESS) { DimmSPDPtr->DimmPresent = TRUE; IDS_HDT_CONSOLE (MEM_FLOW, "SPD Socket %d Channel %d Dimm %d: %08x\n", Socket, Channel, Dimm, SpdParam.Buffer); + #if (CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM)) + AgesaCustomMemoryProfileSPD(SpdParam.Buffer); + #endif } else { DimmSPDPtr->DimmPresent = FALSE; } diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Tech/DDR3/mtspd3.h b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Tech/DDR3/mtspd3.h index bc608a5052..472add0af4 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Tech/DDR3/mtspd3.h +++ b/src/vendorcode/amd/agesa/f16kb/Proc/Mem/Tech/DDR3/mtspd3.h @@ -95,7 +95,7 @@ #define SPD_FTB 9 -#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) +#if CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_JEDEC) || CONFIG(CPU_AMD_AGESA_OPENSOURCE_MEM_CUSTOM) #define SPD_DIVIDENT 10 #define SPD_DIVISOR 11