summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/kgpe-d16/0027-northbridge-amd-amdfam10-Set-DIMM-voltage-based-on-S.patch
blob: 7c45877d4ef398f903ddf92a75e5fd5554a61cf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
From ca270728b0d2232efb4384f645d993403f4bc24e Mon Sep 17 00:00:00 2001
From: Timothy Pearson <kb9vqf@pearsoncomputing.net>
Date: Sat, 5 Sep 2015 18:56:05 -0500
Subject: [PATCH 027/146] northbridge/amd/amdfam10: Set DIMM voltage based on
 SPD data

---
 src/northbridge/amd/amdfam10/acpi.c         |    3 +-
 src/northbridge/amd/amdfam10/northbridge.c  |   73 ++++++++++++++++++++++-----
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.c |    6 +++
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.h |    6 +++
 4 files changed, 73 insertions(+), 15 deletions(-)

diff --git a/src/northbridge/amd/amdfam10/acpi.c b/src/northbridge/amd/amdfam10/acpi.c
index 4b86e96..92433bb 100644
--- a/src/northbridge/amd/amdfam10/acpi.c
+++ b/src/northbridge/amd/amdfam10/acpi.c
@@ -307,8 +307,7 @@ void northbridge_acpi_write_vars(device_t device)
 	} else {
 		if((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on  other than bus 0
 			CBST = (u8) (0x0f);
-		}
-		else {
+		} else {
 			CBST = (u8) (0x00);
 		}
 	}
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
index 880129b..d0a0787 100644
--- a/src/northbridge/amd/amdfam10/northbridge.c
+++ b/src/northbridge/amd/amdfam10/northbridge.c
@@ -948,19 +948,38 @@ static int amdfam10_get_smbios_data16(int* count, int handle, unsigned long *cur
 
 static uint16_t amdmct_mct_speed_enum_to_mhz(uint8_t speed)
 {
-	switch (speed) {
-		case 1:
-			return 200;
-		case 2:
-			return 266;
-		case 3:
-			return 333;
-		case 4:
-			return 400;
-		case 5:
-			return 533;
-		default:
-			return 0;
+	if (IS_ENABLED(CONFIG_DIMM_DDR2)) {
+		switch (speed) {
+			case 1:
+				return 200;
+			case 2:
+				return 266;
+			case 3:
+				return 333;
+			case 4:
+				return 400;
+			case 5:
+				return 533;
+			default:
+				return 0;
+		}
+	} else if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
+		switch (speed) {
+			case 3:
+				return 333;
+			case 4:
+				return 400;
+			case 5:
+				return 533;
+			case 6:
+				return 667;
+			case 7:
+				return 800;
+			default:
+				return 0;
+		}
+	} else {
+		return 0;
 	}
 }
 
@@ -1046,6 +1065,34 @@ 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]);
 					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)) {
+					/* 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];
+				}
 				t->memory_error_information_handle = 0xFFFE;	/* no error information handle available */
 				single_len = t->length + smbios_string_table_len(t->eos);
 				len += single_len;
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index 0c06444..303c6c7 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -327,6 +327,9 @@ restartinit:
 			printk(BIOS_DEBUG, "No Nodes?!\n");
 			goto fatalexit;
 		}
+
+		printk(BIOS_DEBUG, "mctAutoInitMCT_D: DIMMSetVoltage\n");
+		DIMMSetVoltages(pMCTstat, pDCTstatA);	/* Set the DIMM voltages (mainboard specific) */
 	
 		printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n");
 		SyncDCTsReady_D(pMCTstat, pDCTstatA);	/* Make sure DCTs are ready for accesses.*/
@@ -2120,6 +2123,9 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
 					pDCTstat->DimmBanks[i] = 1ULL << (((mctRead_SPD(smbaddr, SPD_Density) & 0x70) >> 4) + 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 */
 				byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE) & 0x7;
 				if (byte == JED_RDIMM || byte == JED_MiniRDIMM) {
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
index c790d7e..a947c2d 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
@@ -206,6 +206,7 @@
 	#define JED_MiniRDIMM	0x5	/* Mini-RDIMM */
 #define SPD_Density	4		/* Bank address bits,SDRAM capacity */
 #define SPD_Addressing	5		/* Row/Column address bits */
+#define SPD_Voltage	6		/* Supported voltage bitfield */
 #define SPD_Organization	7		/* rank#,Device width */
 #define SPD_BusWidth	8		/* ECC, Bus width */
 	#define JED_ECC		8	/* ECC capability */
@@ -585,6 +586,10 @@ struct DCTStatStruc {		/* A per Node structure*/
 	struct _sDCTStruct s_C_DCTPtr[2];
 	/* 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 DimmCols[MAX_DIMMS_SUPPORTED];
 	uint8_t DimmRanks[MAX_DIMMS_SUPPORTED];
@@ -905,6 +910,7 @@ u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val);
 void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct);
 void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node);
 void mctSMBhub_Init(u32 node);
+void DIMMSetVoltages(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
 int mctRead_SPD(u32 smaddr, u32 reg);
 void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
 void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
-- 
1.7.9.5