northbridge/amd/amdfam10: Set DIMM voltage based on SPD data

Change-Id: I67a76cf0e4ebc33fbd7dd151bb68dce1fc6ba680
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/11957
Tested-by: build bot (Jenkins)
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Timothy Pearson 2015-09-05 18:56:05 -05:00 committed by Martin Roth
parent 65eec4d959
commit 2a83935d9f
5 changed files with 49 additions and 2 deletions

View File

@ -83,6 +83,10 @@ config DIMM_REGISTERED
bool bool
default n default n
config DIMM_VOLTAGE_SET_SUPPORT
bool
default n
if DIMM_FBDIMM if DIMM_FBDIMM
config DIMM_SUPPORT config DIMM_SUPPORT
hex hex

View File

@ -303,8 +303,7 @@ void northbridge_acpi_write_vars(device_t device)
} else { } else {
if((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on other than bus 0 if((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on other than bus 0
CBST = (u8) (0x0f); CBST = (u8) (0x0f);
} } else {
else {
CBST = (u8) (0x00); CBST = (u8) (0x00);
} }
} }

View File

@ -1063,6 +1063,36 @@ static int amdfam10_get_smbios_data17(int* count, int handle, int parent_handle,
snprintf(string_buffer, sizeof (string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]); snprintf(string_buffer, sizeof (string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]);
t->serial_number = smbios_add_string(t->eos, string_buffer); t->serial_number = smbios_add_string(t->eos, string_buffer);
} }
if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
/* JEDEC specifies 1.8V only, so assume that the memory is configured for 1.8V */
t->minimum_voltage = 1800;
t->maximum_voltage = 1800;
t->configured_voltage = 1800;
} else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
#if IS_ENABLED(CONFIG_DIMM_DDR3)
/* Find the maximum and minimum supported voltages */
uint8_t supported_voltages = mem_info->dct_stat[node].DimmSupportedVoltages[slot];
if (supported_voltages & 0x8)
t->minimum_voltage = 1150;
else if (supported_voltages & 0x4)
t->minimum_voltage = 1250;
else if (supported_voltages & 0x2)
t->minimum_voltage = 1350;
else if (supported_voltages & 0x1)
t->minimum_voltage = 1500;
if (supported_voltages & 0x1)
t->maximum_voltage = 1500;
else if (supported_voltages & 0x2)
t->maximum_voltage = 1350;
else if (supported_voltages & 0x4)
t->maximum_voltage = 1250;
else if (supported_voltages & 0x8)
t->maximum_voltage = 1150;
t->configured_voltage = mem_info->dct_stat[node].DimmConfiguredVoltage[slot];
#endif
}
t->memory_error_information_handle = 0xFFFE; /* no error information handle available */ t->memory_error_information_handle = 0xFFFE; /* no error information handle available */
single_len = t->length + smbios_string_table_len(t->eos); single_len = t->length + smbios_string_table_len(t->eos);
len += single_len; len += single_len;

View File

@ -336,6 +336,11 @@ restartinit:
goto fatalexit; goto fatalexit;
} }
#if IS_ENABLED(DIMM_VOLTAGE_SET_SUPPORT)
printk(BIOS_DEBUG, "mctAutoInitMCT_D: DIMMSetVoltage\n");
DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */
#endif
printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n"); printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n");
SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/ SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/
@ -2128,6 +2133,9 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
pDCTstat->DimmBanks[i] = 1ULL << (((mctRead_SPD(smbaddr, SPD_Density) & 0x70) >> 4) + 3); pDCTstat->DimmBanks[i] = 1ULL << (((mctRead_SPD(smbaddr, SPD_Density) & 0x70) >> 4) + 3);
pDCTstat->DimmWidth[i] = 1ULL << ((mctRead_SPD(smbaddr, SPD_BusWidth) & 0x7) + 3); pDCTstat->DimmWidth[i] = 1ULL << ((mctRead_SPD(smbaddr, SPD_BusWidth) & 0x7) + 3);
} }
/* Check supported voltage(s) */
pDCTstat->DimmSupportedVoltages[i] = mctRead_SPD(smbaddr, SPD_Voltage) & 0x7;
pDCTstat->DimmSupportedVoltages[i] ^= 0x1; /* Invert LSB to convert from SPD format to internal bitmap format */
/* Check module type */ /* Check module type */
byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE) & 0x7; byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE) & 0x7;
if (byte == JED_RDIMM || byte == JED_MiniRDIMM) { if (byte == JED_RDIMM || byte == JED_MiniRDIMM) {

View File

@ -202,6 +202,7 @@
#define JED_MiniRDIMM 0x5 /* Mini-RDIMM */ #define JED_MiniRDIMM 0x5 /* Mini-RDIMM */
#define SPD_Density 4 /* Bank address bits,SDRAM capacity */ #define SPD_Density 4 /* Bank address bits,SDRAM capacity */
#define SPD_Addressing 5 /* Row/Column address bits */ #define SPD_Addressing 5 /* Row/Column address bits */
#define SPD_Voltage 6 /* Supported voltage bitfield */
#define SPD_Organization 7 /* rank#,Device width */ #define SPD_Organization 7 /* rank#,Device width */
#define SPD_BusWidth 8 /* ECC, Bus width */ #define SPD_BusWidth 8 /* ECC, Bus width */
#define JED_ECC 8 /* ECC capability */ #define JED_ECC 8 /* ECC capability */
@ -581,6 +582,10 @@ struct DCTStatStruc { /* A per Node structure*/
struct _sDCTStruct s_C_DCTPtr[2]; struct _sDCTStruct s_C_DCTPtr[2];
/* struct _sDCTStruct s_C_DCT1Ptr[8]; */ /* struct _sDCTStruct s_C_DCT1Ptr[8]; */
/* DIMM supported voltage bitmap ([2:0]: 1.25V, 1.35V, 1.5V) */
uint8_t DimmSupportedVoltages[MAX_DIMMS_SUPPORTED];
uint32_t DimmConfiguredVoltage[MAX_DIMMS_SUPPORTED]; /* mV */
uint8_t DimmRows[MAX_DIMMS_SUPPORTED]; uint8_t DimmRows[MAX_DIMMS_SUPPORTED];
uint8_t DimmCols[MAX_DIMMS_SUPPORTED]; uint8_t DimmCols[MAX_DIMMS_SUPPORTED];
uint8_t DimmRanks[MAX_DIMMS_SUPPORTED]; uint8_t DimmRanks[MAX_DIMMS_SUPPORTED];
@ -901,6 +906,7 @@ u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val);
void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct); void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct);
void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node); void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node);
void mctSMBhub_Init(u32 node); void mctSMBhub_Init(u32 node);
void DIMMSetVoltages(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
int mctRead_SPD(u32 smaddr, u32 reg); int mctRead_SPD(u32 smaddr, u32 reg);
void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);