blob: 2a7ee2992884d24842d54f5bc7b778cd24869936 [file] [log] [blame]
Martin Roth4dcd13d2016-02-24 13:53:07 -08001/*
Martin Roth9b1b3352016-02-24 12:27:06 -08002 * MemTest86+ V5 Specific code (GPL V2.0)
3 * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
4 * http://www.canardpc.com - http://www.memtest.org
Martin Roth869474b2016-02-24 13:47:46 -08005 *
6 * Edited by David McInnis Oct 4, 2014
Martin Roth9b1b3352016-02-24 12:27:06 -08007 */
8
9//#include "defs.h"
10#include "config.h"
11//#include "test.h"
12#include "pci.h"
13#include "controller.h"
14#include "spd.h"
15#include "test.h"
16#include "stdint.h"
17#include "cpuid.h"
18#include "msr.h"
19#include "dmi.h"
20
21int col, col2;
22int nhm_bus = 0x3F;
Martin Roth4dcd13d2016-02-24 13:53:07 -080023
Martin Roth9b1b3352016-02-24 12:27:06 -080024extern ulong extclock;
25extern unsigned long imc_type;
26extern struct cpu_ident cpu_id;
27/*
28#define rdmsr(msr,val1,val2) \
29 __asm__ __volatile__("rdmsr" \
30 : "=a" (val1), "=d" (val2) \
31 : "c" (msr) : "edi")
32
33#define wrmsr(msr,val1,val2) \
34 __asm__ __volatile__("wrmsr" \
35 : \
36 : "c" (msr), "a" (val1), "d" (val2) : "edi")
37*/
38/* controller ECC capabilities and mode */
39#define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */
Ben Gardner90f7d112016-03-15 15:25:22 -050040#define __ECC_DETECT 2 /* Can detect ECC errors */
41#define __ECC_CORRECT 4 /* Can correct some ECC errors */
42#define __ECC_SCRUB 8 /* Can scrub corrected ECC errors */
43#define __ECC_CHIPKILL 16 /* Can corrected multi-errors */
Martin Roth9b1b3352016-02-24 12:27:06 -080044
45#define ECC_UNKNOWN (~0UL) /* Unknown error correcting ability/status */
Elyes HAOUAS54506bf2018-08-24 09:17:59 +020046#define ECC_NONE 0 /* Doesn't support ECC (or is BIOS disabled) */
Martin Roth9b1b3352016-02-24 12:27:06 -080047#define ECC_RESERVED __ECC_UNEXPECTED /* Reserved ECC type */
48#define ECC_DETECT __ECC_DETECT
49#define ECC_CORRECT (__ECC_DETECT | __ECC_CORRECT)
Ben Gardner90f7d112016-03-15 15:25:22 -050050#define ECC_CHIPKILL (__ECC_DETECT | __ECC_CORRECT | __ECC_CHIPKILL)
Martin Roth9b1b3352016-02-24 12:27:06 -080051#define ECC_SCRUB (__ECC_DETECT | __ECC_CORRECT | __ECC_SCRUB)
52
53
54static struct ecc_info {
Ben Gardner90f7d112016-03-15 15:25:22 -050055 int index;
56 int poll;
Martin Roth9b1b3352016-02-24 12:27:06 -080057 unsigned bus;
58 unsigned dev;
59 unsigned fn;
60 unsigned cap;
61 unsigned mode;
62} ctrl =
63{
64 .index = 0,
65 /* I know of no case where the memory controller is not on the
66 * host bridge, and the host bridge is not on bus 0 device 0
67 * fn 0. But just in case leave these as variables.
68 */
Ben Gardner90f7d112016-03-15 15:25:22 -050069 .bus = 0,
70 .dev = 0,
71 .fn = 0,
Martin Roth9b1b3352016-02-24 12:27:06 -080072 /* Properties of the current memory controller */
Ben Gardner90f7d112016-03-15 15:25:22 -050073 .cap = ECC_UNKNOWN,
74 .mode = ECC_UNKNOWN,
Martin Roth9b1b3352016-02-24 12:27:06 -080075};
76
77
Martin Roth4dcd13d2016-02-24 13:53:07 -080078void coretemp(void)
Martin Roth9b1b3352016-02-24 12:27:06 -080079{
80 unsigned int msrl, msrh;
81 unsigned int tjunc, tabs, tnow;
82 unsigned long rtcr;
83 double amd_raw_temp;
Martin Roth4dcd13d2016-02-24 13:53:07 -080084
Martin Roth9b1b3352016-02-24 12:27:06 -080085 // Only enable coretemp if IMC is known
Ben Gardner90f7d112016-03-15 15:25:22 -050086 if (imc_type == 0) { return; }
Martin Roth4dcd13d2016-02-24 13:53:07 -080087
Martin Roth9b1b3352016-02-24 12:27:06 -080088 // Intel CPU
Ben Gardner90f7d112016-03-15 15:25:22 -050089 if (cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6) {
90 if (cpu_id.dts_pmp & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -080091 rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
92 tabs = ((msrl >> 16) & 0x7F);
93 rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
94 tjunc = ((msrl >> 16) & 0x7F);
Ben Gardner90f7d112016-03-15 15:25:22 -050095 if (tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received.
Martin Roth4dcd13d2016-02-24 13:53:07 -080096 tnow = tjunc - tabs;
97 dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
Martin Roth9b1b3352016-02-24 12:27:06 -080098 v->check_temp = tnow;
99 }
100 return;
101 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800102
Martin Roth9b1b3352016-02-24 12:27:06 -0800103 // AMD CPU
Ben Gardner90f7d112016-03-15 15:25:22 -0500104 if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800105 pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr);
106 amd_raw_temp = ((rtcr >> 21) & 0x7FF);
107 v->check_temp = (int)(amd_raw_temp / 8);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800108 dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
109 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800110}
111
112void print_cpu_line(float dram_freq, float fsb_freq, int ram_type)
113{
114 int cur_col = COL_SPEC;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800115
Martin Roth9b1b3352016-02-24 12:27:06 -0800116 cprint(LINE_CPU, cur_col, "RAM: ");
117 cur_col += 5;
118 dprint(LINE_CPU, cur_col, dram_freq, 4, 1);
119 cur_col += 4;
120 cprint(LINE_CPU, cur_col, "MHz (");
121 cur_col += 5;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800122
Ben Gardner90f7d112016-03-15 15:25:22 -0500123 switch (ram_type) {
124 default:
125 case 1:
126 cprint(LINE_CPU, cur_col, "DDR-");
127 cur_col += 4;
128 break;
129 case 2:
130 cprint(LINE_CPU, cur_col, "DDR2-");
131 cur_col += 5;
132 break;
133 case 3:
134 cprint(LINE_CPU, cur_col, "DDR3-");
135 cur_col += 5;
136 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800137 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800138
Ben Gardner90f7d112016-03-15 15:25:22 -0500139 if (dram_freq < 500) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800140 dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0);
141 cur_col += 3;
142 } else {
143 dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800144 cur_col += 4;
Martin Roth9b1b3352016-02-24 12:27:06 -0800145 }
146 cprint(LINE_CPU, cur_col, ")");
Martin Roth4dcd13d2016-02-24 13:53:07 -0800147 cur_col++;
148
Ben Gardner90f7d112016-03-15 15:25:22 -0500149 if (fsb_freq > 10) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800150 cprint(LINE_CPU, cur_col, " - BCLK: ");
151 cur_col += 9;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800152
153 dprint(LINE_CPU, cur_col, fsb_freq, 3, 0);
Martin Roth9b1b3352016-02-24 12:27:06 -0800154 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800155}
156
157void print_ram_line(float cas, int rcd, int rp, int ras, int chan)
158{
159 int cur_col = COL_SPEC;
160
161 cprint(LINE_RAM, cur_col, "Timings: CAS ");
Martin Roth4dcd13d2016-02-24 13:53:07 -0800162 cur_col += 13;
Martin Roth9b1b3352016-02-24 12:27:06 -0800163
164 // CAS Latency (tCAS)
165 if (cas == 1.5) {
166 cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3;
167 } else if (cas == 2.5) {
168 cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3;
169 } else if (cas < 10) {
170 dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1;
171 } else {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800172 dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800173 }
174 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
175
176 // RAS-To-CAS (tRCD)
177 if (rcd < 10) {
178 dprint(LINE_RAM, cur_col, rcd, 1, 0);
179 cur_col += 1;
180 } else {
181 dprint(LINE_RAM, cur_col, rcd, 2, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800182 cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800183 }
184 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
185
186 // RAS Precharge (tRP)
187 if (rp < 10) {
188 dprint(LINE_RAM, cur_col, rp, 1, 0);
189 cur_col += 1;
190 } else {
191 dprint(LINE_RAM, cur_col, rp, 2, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800192 cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800193 }
194 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
195
196 // RAS Active to precharge (tRAS)
197 if (ras < 10) {
198 dprint(LINE_RAM, cur_col, ras, 1, 0);
199 cur_col += 1;
200 } else {
201 dprint(LINE_RAM, cur_col, ras, 2, 0);
202 cur_col += 2;
203 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800204
205
Ben Gardner90f7d112016-03-15 15:25:22 -0500206 switch (chan) {
207 case 0:
208 break;
209 case 1:
210 cprint(LINE_RAM, cur_col, " @ 64-bit Mode");
211 break;
212 case 2:
213 cprint(LINE_RAM, cur_col, " @ 128-bit Mode");
214 break;
215 case 3:
216 cprint(LINE_RAM, cur_col, " @ 192-bit Mode");
217 break;
218 case 4:
219 cprint(LINE_RAM, cur_col, " @ 256-bit Mode");
220 break;
Martin Roth9b1b3352016-02-24 12:27:06 -0800221 }
222}
223
224static void poll_fsb_nothing(void)
225{
Martin Roth9b1b3352016-02-24 12:27:06 -0800226 char *name;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800227
Martin Roth9b1b3352016-02-24 12:27:06 -0800228 /* Print the controller name */
229 name = controllers[ctrl.index].name;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800230 cprint(LINE_CPU, COL_SPEC, "Chipset: ");
Martin Roth9b1b3352016-02-24 12:27:06 -0800231 cprint(LINE_CPU, COL_SPEC+9, name);
232 return;
233}
234
235static void poll_timings_nothing(void)
236{
237 char *ram_type;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800238
Martin Roth9b1b3352016-02-24 12:27:06 -0800239 /* Print the controller name */
240 ram_type = controllers[ctrl.index].ram_type;
241 cprint(LINE_RAM, COL_SPEC, "RAM Type: ");
242 cprint(LINE_RAM, COL_SPEC+10, ram_type);
243 return;
244}
245
246static void setup_nothing(void)
247{
248 ctrl.cap = ECC_NONE;
249 ctrl.mode = ECC_NONE;
250}
251
252static void poll_nothing(void)
253{
254/* Code to run when we don't know how, or can't ask the memory
255 * controller about memory errors.
256 */
257 return;
258}
259
260static void setup_wmr(void)
261{
262 ulong dev0;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800263
Martin Roth9b1b3352016-02-24 12:27:06 -0800264 // Activate MMR I/O
265 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
266 if (!(dev0 & 0x1)) {
267 pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
268 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800269}
270
271
272static void setup_nhm(void)
273{
274 static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
275 unsigned long did, vid, mc_control, mc_ssrcontrol;
276 int i;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800277
Martin Roth9b1b3352016-02-24 12:27:06 -0800278 //Nehalem supports Scrubbing */
279 ctrl.cap = ECC_SCRUB;
280 ctrl.mode = ECC_NONE;
281
282 /* First, locate the PCI bus where the MCH is located */
283
Ben Gardner90f7d112016-03-15 15:25:22 -0500284 for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800285 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
286 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
287 vid &= 0xFFFF;
288 did &= 0xFF00;
Ben Gardner90f7d112016-03-15 15:25:22 -0500289 if (vid == 0x8086 && did >= 0x2C00) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800290 nhm_bus = possible_nhm_bus[i];
Ben Gardner90f7d112016-03-15 15:25:22 -0500291 }
292 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800293
294 /* Now, we have the last IMC bus number in nhm_bus */
295 /* Check for ECC & Scrub */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800296
297 pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control);
Ben Gardner90f7d112016-03-15 15:25:22 -0500298 if ((mc_control >> 4) & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800299 ctrl.mode = ECC_CORRECT;
300 pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
Ben Gardner90f7d112016-03-15 15:25:22 -0500301 if (mc_ssrcontrol & 3) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800302 ctrl.mode = ECC_SCRUB;
303 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800304 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800305}
306
307static void setup_nhm32(void)
308{
309 static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
310 unsigned long did, vid, mc_control, mc_ssrcontrol;
311 int i;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800312
Martin Roth9b1b3352016-02-24 12:27:06 -0800313 //Nehalem supports Scrubbing */
314 ctrl.cap = ECC_SCRUB;
315 ctrl.mode = ECC_NONE;
316
317 /* First, locate the PCI bus where the MCH is located */
Ben Gardner90f7d112016-03-15 15:25:22 -0500318 for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800319 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
320 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
321 vid &= 0xFFFF;
322 did &= 0xFF00;
Ben Gardner90f7d112016-03-15 15:25:22 -0500323 if (vid == 0x8086 && did >= 0x2C00) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800324 nhm_bus = possible_nhm_bus[i];
Ben Gardner90f7d112016-03-15 15:25:22 -0500325 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800326 }
327
328 /* Now, we have the last IMC bus number in nhm_bus */
329 /* Check for ECC & Scrub */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800330 pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control);
Ben Gardner90f7d112016-03-15 15:25:22 -0500331 if ((mc_control >> 1) & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800332 ctrl.mode = ECC_CORRECT;
333 pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
Ben Gardner90f7d112016-03-15 15:25:22 -0500334 if (mc_ssrcontrol & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800335 ctrl.mode = ECC_SCRUB;
336 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800337 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800338}
339
340static void setup_amd64(void)
341{
342 static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL };
343 unsigned long nbxcfg;
344 unsigned int mcgsrl;
345 unsigned int mcgsth;
346 unsigned long mcanb;
347 unsigned long dramcl;
348
349 /* All AMD64 support Chipkill */
350 ctrl.cap = ECC_CHIPKILL;
351
352 /* Check First if ECC DRAM Modules are used */
353 pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800354
Martin Roth9b1b3352016-02-24 12:27:06 -0800355 if (cpu_id.vers.bits.extendedModel >= 4) {
356 /* NEW K8 0Fh Family 90 nm */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800357
Ben Gardner90f7d112016-03-15 15:25:22 -0500358 if ((dramcl >> 19)&1) {
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200359 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800360 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
361 ctrl.mode = ddim[(nbxcfg >> 22)&3];
362 } else {
363 ctrl.mode = ECC_NONE;
364 }
365 /* Enable NB ECC Logging by MSR Write */
366 rdmsr(0x017B, mcgsrl, mcgsth);
367 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800368
Martin Roth9b1b3352016-02-24 12:27:06 -0800369 /* Clear any previous error */
370 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800371 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
Martin Roth4dcd13d2016-02-24 13:53:07 -0800372 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -0800373 /* OLD K8 130 nm */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800374
Ben Gardner90f7d112016-03-15 15:25:22 -0500375 if ((dramcl >> 17)&1) {
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200376 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800377 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
378 ctrl.mode = ddim[(nbxcfg >> 22)&3];
379 } else {
380 ctrl.mode = ECC_NONE;
381 }
382 /* Enable NB ECC Logging by MSR Write */
383 rdmsr(0x017B, mcgsrl, mcgsth);
384 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800385
Martin Roth9b1b3352016-02-24 12:27:06 -0800386 /* Clear any previous error */
387 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
388 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC );
389 }
390}
391
392static void setup_k10(void)
393{
394 static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL };
395 unsigned long nbxcfg;
396 unsigned int mcgsrl;
397 unsigned int mcgsth;
398 unsigned long mcanb;
399 unsigned long dramcl;
400 ulong msr_low, msr_high;
401
402 // All AMD64 support Chipkill */
403 ctrl.cap = ECC_CHIPKILL;
404
405 // Check First if ECC DRAM Modules are used */
406 pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800407
Ben Gardner90f7d112016-03-15 15:25:22 -0500408 if ((dramcl >> 19)&1) {
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200409 // Fill in the correct memory capabilities */
Ben Gardner90f7d112016-03-15 15:25:22 -0500410 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
411 ctrl.mode = ddim[(nbxcfg >> 22)&3];
412 } else {
413 ctrl.mode = ECC_NONE;
414 }
415 // Enable NB ECC Logging by MSR Write */
416 rdmsr(0x017B, mcgsrl, mcgsth);
417 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800418
Ben Gardner90f7d112016-03-15 15:25:22 -0500419 // Clear any previous error */
420 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
421 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
Martin Roth4dcd13d2016-02-24 13:53:07 -0800422
Ben Gardner90f7d112016-03-15 15:25:22 -0500423 /* Enable ECS */
424 rdmsr(0xC001001F, msr_low, msr_high);
425 wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
426 rdmsr(0xC001001F, msr_low, msr_high);
Martin Roth9b1b3352016-02-24 12:27:06 -0800427}
428
429static void setup_apu(void)
430{
Martin Roth9b1b3352016-02-24 12:27:06 -0800431 ulong msr_low, msr_high;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800432
Martin Roth9b1b3352016-02-24 12:27:06 -0800433 /* Enable ECS */
434 rdmsr(0xC001001F, msr_low, msr_high);
435 wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
436 rdmsr(0xC001001F, msr_low, msr_high);
Martin Roth9b1b3352016-02-24 12:27:06 -0800437}
438
439/*
440static void poll_amd64(void)
441{
442
443 unsigned long mcanb;
444 unsigned long page, offset;
445 unsigned long celog_syndrome;
446 unsigned long mcanb_add;
447
448 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
449
450 if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800451 // Find out about the first correctable error
452 // Syndrome code -> bits use a complex matrix. Will add this later
453 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800454 pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
455
Martin Roth4dcd13d2016-02-24 13:53:07 -0800456 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -0800457 celog_syndrome = (mcanb >> 15)&0xFF;
458
Martin Roth4dcd13d2016-02-24 13:53:07 -0800459 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800460 page = (mcanb_add >> 12);
461 offset = (mcanb_add >> 3) & 0xFFF;
462
Martin Roth4dcd13d2016-02-24 13:53:07 -0800463 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800464 print_ecc_err(page, offset, 1, celog_syndrome, 0);
465
Martin Roth4dcd13d2016-02-24 13:53:07 -0800466 // Clear the error registers
Martin Roth9b1b3352016-02-24 12:27:06 -0800467 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
468 }
469 if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800470 // Found out about the first uncorrectable error
471 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800472 pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
473
Martin Roth4dcd13d2016-02-24 13:53:07 -0800474 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800475 page = (mcanb_add >> 12);
476 offset = (mcanb_add >> 3) & 0xFFF;
477
Martin Roth4dcd13d2016-02-24 13:53:07 -0800478 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800479 print_ecc_err(page, offset, 0, 0, 0);
480
Martin Roth4dcd13d2016-02-24 13:53:07 -0800481 // Clear the error registers
Martin Roth9b1b3352016-02-24 12:27:06 -0800482 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF );
483
484 }
485
486}
487*/
488
489static void setup_amd751(void)
490{
491 unsigned long dram_status;
492
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200493 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800494 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status);
495 ctrl.cap = ECC_CORRECT;
Ben Gardner90f7d112016-03-15 15:25:22 -0500496 ctrl.mode = (dram_status & (1 << 2)) ? ECC_CORRECT : ECC_NONE;
Martin Roth9b1b3352016-02-24 12:27:06 -0800497}
498
499/*
500static void poll_amd751(void)
501{
502 unsigned long ecc_status;
503 unsigned long bank_addr;
504 unsigned long bank_info;
505 unsigned long page;
506 int bits;
507 int i;
508
Martin Roth4dcd13d2016-02-24 13:53:07 -0800509 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800510 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status);
511 if (ecc_status & (3 << 8)) {
512 for(i = 0; i < 6; i++) {
513 if (!(ecc_status & (1 << i))) {
514 continue;
515 }
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200516 // Find the bank the error occurred on
Martin Roth9b1b3352016-02-24 12:27:06 -0800517 bank_addr = 0x40 + (i << 1);
518
Martin Roth4dcd13d2016-02-24 13:53:07 -0800519 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800520 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info);
521
Martin Roth4dcd13d2016-02-24 13:53:07 -0800522 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800523 page = (bank_info & 0xFF80) << 4;
524 bits = (((ecc_status >> 8) &3) == 2)?1:2;
525
Martin Roth4dcd13d2016-02-24 13:53:07 -0800526 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800527 print_ecc_err(page, 0, bits==1?1:0, 0, 0);
528
529 }
530
Martin Roth4dcd13d2016-02-24 13:53:07 -0800531 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800532 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0);
533 }
534}
535
536// Still waiting for the CORRECT intel datasheet
537static void setup_i85x(void)
538{
539 unsigned long drc;
540 ctrl.cap = ECC_CORRECT;
541
542 pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc);
543 ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE;
544
545}
546*/
547
548static void setup_amd76x(void)
549{
550 static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
551 unsigned long ecc_mode_status;
552
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200553 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800554 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
555 ctrl.cap = ECC_CORRECT;
556 ctrl.mode = ddim[(ecc_mode_status >> 10)&3];
557}
558
559/*
560static void poll_amd76x(void)
561{
562 unsigned long ecc_mode_status;
563 unsigned long bank_addr;
564 unsigned long bank_info;
565 unsigned long page;
566
567 // Read the error status
568 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
569 // Multibit error
570 if (ecc_mode_status & (1 << 9)) {
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200571 // Find the bank the error occurred on
Martin Roth9b1b3352016-02-24 12:27:06 -0800572 bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2);
573
Martin Roth4dcd13d2016-02-24 13:53:07 -0800574 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800575 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
576
Martin Roth4dcd13d2016-02-24 13:53:07 -0800577 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800578 page = (bank_info & 0xFF800000) >> 12;
579
Martin Roth4dcd13d2016-02-24 13:53:07 -0800580 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800581 print_ecc_err(page, 0, 1, 0, 0);
582
583 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800584 // Singlebit error
Martin Roth9b1b3352016-02-24 12:27:06 -0800585 if (ecc_mode_status & (1 << 8)) {
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200586 // Find the bank the error occurred on
Martin Roth9b1b3352016-02-24 12:27:06 -0800587 bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2);
588
Martin Roth4dcd13d2016-02-24 13:53:07 -0800589 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800590 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
591
Martin Roth4dcd13d2016-02-24 13:53:07 -0800592 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800593 page = (bank_info & 0xFF800000) >> 12;
594
Martin Roth4dcd13d2016-02-24 13:53:07 -0800595 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800596 print_ecc_err(page, 0, 0, 0, 0);
597
598 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800599 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800600 if (ecc_mode_status & (3 << 8)) {
601 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status);
602 }
603}
604*/
605
606static void setup_cnb20(void)
607{
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200608 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800609 ctrl.cap = ECC_CORRECT;
610
611 /* FIXME add ECC error polling. I don't have the documentation
612 * do it right now.
613 */
614}
615
616static void setup_E5400(void)
617{
618 unsigned long mcs;
619
620
621 /* Read the hardware capabilities */
622 pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs);
623
624 /* Fill in the correct memory capabilities */
625 ctrl.mode = 0;
626 ctrl.cap = ECC_SCRUB;
627
628 /* Checking and correcting enabled */
629 if (((mcs >> 5) & 1) == 1) {
630 ctrl.mode |= ECC_CORRECT;
631 }
632
633 /* scrub enabled */
634 if (((mcs >> 7) & 1) == 1) {
635 ctrl.mode |= __ECC_SCRUB;
636 }
637}
638
639
640static void setup_iE7xxx(void)
641{
642 unsigned long mchcfgns;
643 unsigned long drc;
644 unsigned long device;
645 unsigned long dvnp;
646
647 /* Read the hardare capabilities */
648 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns);
649 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
650
651 /* This is a check for E7205 */
652 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device);
653
654 /* Fill in the correct memory capabilities */
655 ctrl.mode = 0;
656 ctrl.cap = ECC_CORRECT;
657
658 /* checking and correcting enabled */
659 if (((drc >> 20) & 3) == 2) {
660 ctrl.mode |= ECC_CORRECT;
661 }
662
663 /* E7205 doesn't support scrubbing */
664 if (device != 0x255d) {
665 /* scrub enabled */
666 /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */
667 ctrl.cap = ECC_SCRUB;
668 if (mchcfgns & 1) {
669 ctrl.mode |= __ECC_SCRUB;
670 }
671
672 /* Now, we can active Dev1/Fun1 */
673 /* Thanks to Tyan for providing us the board to solve this */
674 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp);
Ben Gardner90f7d112016-03-15 15:25:22 -0500675 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, (dvnp & 0xFE));
Martin Roth9b1b3352016-02-24 12:27:06 -0800676
677 /* Clear any routing of ECC errors to interrupts that the BIOS might have set up */
678 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0);
679 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0);
680 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0);
Martin Roth9b1b3352016-02-24 12:27:06 -0800681 }
682
683 /* Clear any prexisting error reports */
684 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3);
685 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -0800686}
687
688static void setup_iE7520(void)
689{
690 unsigned long mchscrb;
691 unsigned long drc;
692 unsigned long dvnp1;
693
694 /* Read the hardare capabilities */
695 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb);
696 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
697
698 /* Fill in the correct memory capabilities */
699 ctrl.mode = 0;
700 ctrl.cap = ECC_CORRECT;
701
702 /* Checking and correcting enabled */
703 if (((drc >> 20) & 3) != 0) {
704 ctrl.mode |= ECC_CORRECT;
705 }
706
707 /* scrub enabled */
708 ctrl.cap = ECC_SCRUB;
709 if ((mchscrb & 3) == 2) {
710 ctrl.mode |= __ECC_SCRUB;
711 }
712
713 /* Now, we can activate Fun1 */
714 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1);
Ben Gardner90f7d112016-03-15 15:25:22 -0500715 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, (dvnp1 | 0x20));
Martin Roth9b1b3352016-02-24 12:27:06 -0800716
717 /* Clear any prexisting error reports */
718 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747);
719 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747);
Martin Roth9b1b3352016-02-24 12:27:06 -0800720}
721
722/*
723static void poll_iE7xxx(void)
724{
725 unsigned long ferr;
726 unsigned long nerr;
727
728 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr);
729 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
730
731 if (ferr & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800732 // Find out about the first correctable error
Martin Roth9b1b3352016-02-24 12:27:06 -0800733 unsigned long celog_add;
734 unsigned long celog_syndrome;
735 unsigned long page;
736
Martin Roth4dcd13d2016-02-24 13:53:07 -0800737 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800738 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800739 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -0800740 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome);
741
Martin Roth4dcd13d2016-02-24 13:53:07 -0800742 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800743 page = (celog_add & 0x0FFFFFC0) >> 6;
744
Martin Roth4dcd13d2016-02-24 13:53:07 -0800745 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800746 print_ecc_err(page, 0, 1, celog_syndrome, 0);
747
Martin Roth4dcd13d2016-02-24 13:53:07 -0800748 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -0800749 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
750 }
751
752 if (ferr & 2) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800753 // Found out about the first uncorrectable error
Martin Roth9b1b3352016-02-24 12:27:06 -0800754 unsigned long uccelog_add;
755 unsigned long page;
756
Martin Roth4dcd13d2016-02-24 13:53:07 -0800757 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800758 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
759
Martin Roth4dcd13d2016-02-24 13:53:07 -0800760 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800761 page = (uccelog_add & 0x0FFFFFC0) >> 6;
762
Martin Roth4dcd13d2016-02-24 13:53:07 -0800763 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800764 print_ecc_err(page, 0, 0, 0, 0);
765
Martin Roth4dcd13d2016-02-24 13:53:07 -0800766 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -0800767 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
768 }
769
Martin Roth4dcd13d2016-02-24 13:53:07 -0800770 // Check if DRAM_NERR contains data
Martin Roth9b1b3352016-02-24 12:27:06 -0800771 if (nerr & 3) {
772 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
773 }
774
775}
776*/
777
778static void setup_i440gx(void)
779{
780 static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
781 unsigned long nbxcfg;
782
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200783 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800784 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg);
785 ctrl.cap = ECC_CORRECT;
786 ctrl.mode = ddim[(nbxcfg >> 7)&3];
787}
788
789/*
790static void poll_i440gx(void)
791{
792 unsigned long errsts;
793 unsigned long page;
794 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800795 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800796 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts);
797 if (errsts & 0x11) {
798 unsigned long eap;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800799 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800800 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap);
801
Martin Roth4dcd13d2016-02-24 13:53:07 -0800802 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800803 page = (eap & 0xFFFFF000) >> 12;
804 bits = 0;
805 if (eap &3) {
806 bits = ((eap & 3) == 1)?1:2;
807 }
808
809 if (bits) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800810 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800811 print_ecc_err(page, 0, bits==1?1:0, 0, 0);
812 }
813
Martin Roth4dcd13d2016-02-24 13:53:07 -0800814 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800815 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11);
816 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3);
817 }
818
819}
820*/
821
822
823static void setup_i840(void)
824{
825 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
826 unsigned long mchcfg;
827
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200828 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800829 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
830 ctrl.cap = ECC_CORRECT;
831 ctrl.mode = ddim[(mchcfg >> 7)&3];
832}
833
834/*
835static void poll_i840(void)
836{
837 unsigned long errsts;
838 unsigned long page;
839 unsigned long syndrome;
840 int channel;
841 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800842 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800843 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
844 if (errsts & 3) {
845 unsigned long eap;
846 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800847 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800848 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
849 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
850
Martin Roth4dcd13d2016-02-24 13:53:07 -0800851 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800852 page = (eap & 0xFFFFF800) >> 11;
853 channel = eap & 1;
854 syndrome = derrctl_sts & 0xFF;
855 bits = ((errsts & 3) == 1)?1:2;
856
Martin Roth4dcd13d2016-02-24 13:53:07 -0800857 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800858 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
859
Martin Roth4dcd13d2016-02-24 13:53:07 -0800860 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800861 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10);
862 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
863 }
864}
865*/
866
867
868static void setup_i875(void)
869{
Martin Roth9b1b3352016-02-24 12:27:06 -0800870 long *ptr;
Ben Gardner90f7d112016-03-15 15:25:22 -0500871 ulong dev0, dev6;
Martin Roth9b1b3352016-02-24 12:27:06 -0800872
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200873 /* Fill in the correct memory capabilities */
Martin Roth9b1b3352016-02-24 12:27:06 -0800874
875 ctrl.cap = ECC_CORRECT;
876 ctrl.mode = ECC_NONE;
877
878 /* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */
879 /* Activate Device 6 */
880 pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0);
881 pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2));
882
883 /* Activate Device 6 MMR */
884 pci_conf_read( 0, 6, 0, 0x04, 2, &dev6);
885 pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2));
886
887 /* Read the MMR Base Address & Define the pointer*/
888 pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
889 ptr=(long*)(dev6+0x68);
890
891 if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; }
892
Elyes HAOUAS54506bf2018-08-24 09:17:59 +0200893 /* Resetting state */
Martin Roth9b1b3352016-02-24 12:27:06 -0800894 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
895}
896
897static void setup_i925(void)
898{
Martin Roth9b1b3352016-02-24 12:27:06 -0800899 // Activate MMR I/O
900 ulong dev0, drc;
901 unsigned long tolm;
902 long *ptr;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800903
Martin Roth9b1b3352016-02-24 12:27:06 -0800904 pci_conf_read( 0, 0, 0, 0x54, 4, &dev0);
905 dev0 = dev0 | 0x10000000;
906 pci_conf_write( 0, 0, 0, 0x54, 4, dev0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800907
Martin Roth9b1b3352016-02-24 12:27:06 -0800908 // CDH start
909 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
910 if (!(dev0 & 0xFFFFC000)) {
911 pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm);
912 pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8);
913 }
914 // CDH end
915
916 // ECC Checking
917 ctrl.cap = ECC_CORRECT;
918
919 dev0 &= 0xFFFFC000;
920 ptr=(long*)(dev0+0x120);
921 drc = *ptr & 0xFFFFFFFF;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800922
923 if (((drc >> 20) & 3) == 2) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800924 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800925 ctrl.mode = ECC_CORRECT;
926 } else {
927 ctrl.mode = ECC_NONE;
Martin Roth9b1b3352016-02-24 12:27:06 -0800928 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800929}
930
931static void setup_p35(void)
932{
Martin Roth9b1b3352016-02-24 12:27:06 -0800933 // Activate MMR I/O
934 ulong dev0, capid0;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800935
Martin Roth9b1b3352016-02-24 12:27:06 -0800936 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
937 if (!(dev0 & 0x1)) {
938 pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
939 }
940
941 // ECC Checking (No poll on X38/48 for now)
942 pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0);
943 if ((capid0 >> 8) & 1) {
944 ctrl.cap = ECC_NONE;
945 } else {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800946 ctrl.cap = ECC_CORRECT;
Martin Roth9b1b3352016-02-24 12:27:06 -0800947 }
948
Martin Roth4dcd13d2016-02-24 13:53:07 -0800949 ctrl.mode = ECC_NONE;
950
Martin Roth9b1b3352016-02-24 12:27:06 -0800951 /*
952 ulong toto;
953 pci_conf_write(0, 31, 3, 0x40, 1, 0x1);
954 pci_conf_read(0, 31, 3, 0x0, 4, &toto);
955 hprint(11,0,toto);
956 pci_conf_read(0, 31, 3, 0x10, 4, &toto);
957 hprint(11,10,toto) ;
958 pci_conf_read(0, 31, 3, 0x20, 4, &toto);
959 hprint(11,20,toto) ;
960 pci_conf_read(0, 28, 0, 0x0, 4, &toto);
961 hprint(11,30,toto);
962 pci_conf_read(0, 31, 0, 0x0, 4, &toto);
963 hprint(11,40,toto) ;
964 pci_conf_read(0, 31, 1, 0x0, 4, &toto);
965 hprint(11,50,toto) ;
966 pci_conf_read(0, 31, 2, 0x0, 4, &toto);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800967 hprint(11,60,toto) ;
Martin Roth9b1b3352016-02-24 12:27:06 -0800968 */
969}
970
971/*
972static void poll_i875(void)
973{
974 unsigned long errsts;
975 unsigned long page;
976 unsigned long des;
977 unsigned long syndrome;
978 int channel;
979 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800980 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800981 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
982 if (errsts & 0x81) {
983 unsigned long eap;
984 unsigned long derrsyn;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800985 // Read the error location, syndrome and channel
Martin Roth9b1b3352016-02-24 12:27:06 -0800986 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
987 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn);
988 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des);
989
Martin Roth4dcd13d2016-02-24 13:53:07 -0800990 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800991 page = (eap & 0xFFFFF000) >> 12;
992 syndrome = derrsyn;
993 channel = des & 1;
994 bits = (errsts & 0x80)?0:1;
995
Martin Roth4dcd13d2016-02-24 13:53:07 -0800996 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800997 print_ecc_err(page, 0, bits, syndrome, channel);
998
Martin Roth4dcd13d2016-02-24 13:53:07 -0800999 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001000 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
1001 }
1002}
1003*/
1004
1005static void setup_i845(void)
1006{
1007 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1008 unsigned long drc;
1009
Elyes HAOUAS54506bf2018-08-24 09:17:59 +02001010 // Fill in the correct memory capabilities
Martin Roth9b1b3352016-02-24 12:27:06 -08001011 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
1012 ctrl.cap = ECC_CORRECT;
1013 ctrl.mode = ddim[(drc >> 20)&3];
1014}
1015
1016/*
1017static void poll_i845(void)
1018{
1019 unsigned long errsts;
1020 unsigned long page, offset;
1021 unsigned long syndrome;
1022 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001023 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001024 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1025 if (errsts & 3) {
1026 unsigned long eap;
1027 unsigned long derrsyn;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001028 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001029 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap);
1030 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn);
1031
Martin Roth4dcd13d2016-02-24 13:53:07 -08001032 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001033 offset = (eap & 0xFE) << 4;
1034 page = (eap & 0x3FFFFFFE) >> 8;
1035 syndrome = derrsyn;
1036 bits = ((errsts & 3) == 1)?1:2;
1037
Martin Roth4dcd13d2016-02-24 13:53:07 -08001038 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001039 print_ecc_err(page, offset, bits==1?1:0, syndrome, 0);
1040
Martin Roth4dcd13d2016-02-24 13:53:07 -08001041 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001042 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
1043 }
1044}
1045*/
1046
1047
1048static void setup_i820(void)
1049{
1050 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
1051 unsigned long mchcfg;
1052
Elyes HAOUAS54506bf2018-08-24 09:17:59 +02001053 // Fill in the correct memory capabilities
Martin Roth9b1b3352016-02-24 12:27:06 -08001054 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg);
1055 ctrl.cap = ECC_CORRECT;
1056 ctrl.mode = ddim[(mchcfg >> 7)&3];
1057}
1058
1059/*
1060static void poll_i820(void)
1061{
1062 unsigned long errsts;
1063 unsigned long page;
1064 unsigned long syndrome;
1065 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001066 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001067 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1068 if (errsts & 3) {
1069 unsigned long eap;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001070 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001071 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap);
1072
Martin Roth4dcd13d2016-02-24 13:53:07 -08001073 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001074 page = (eap & 0xFFFFF000) >> 4;
1075 syndrome = eap & 0xFF;
1076 bits = ((errsts & 3) == 1)?1:2;
1077
Martin Roth4dcd13d2016-02-24 13:53:07 -08001078 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001079 print_ecc_err(page, 0, bits==1?1:0, syndrome, 0);
1080
Martin Roth4dcd13d2016-02-24 13:53:07 -08001081 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001082 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
1083 }
1084}
1085*/
1086
1087static void setup_i850(void)
1088{
1089 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1090 unsigned long mchcfg;
1091
Elyes HAOUAS54506bf2018-08-24 09:17:59 +02001092 // Fill in the correct memory capabilities
Martin Roth9b1b3352016-02-24 12:27:06 -08001093 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
1094 ctrl.cap = ECC_CORRECT;
1095 ctrl.mode = ddim[(mchcfg >> 7)&3];
1096}
1097
1098/*
1099static void poll_i850(void)
1100{
1101 unsigned long errsts;
1102 unsigned long page;
1103 unsigned long syndrome;
1104 int channel;
1105 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001106 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001107 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1108 if (errsts & 3) {
1109 unsigned long eap;
1110 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001111 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001112 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
1113 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
1114
Martin Roth4dcd13d2016-02-24 13:53:07 -08001115 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001116 page = (eap & 0xFFFFF800) >> 11;
1117 channel = eap & 1;
1118 syndrome = derrctl_sts & 0xFF;
1119 bits = ((errsts & 3) == 1)?1:2;
1120
Martin Roth4dcd13d2016-02-24 13:53:07 -08001121 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001122 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
1123
Martin Roth4dcd13d2016-02-24 13:53:07 -08001124 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001125 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1126 }
1127}
1128*/
1129
1130static void setup_i860(void)
1131{
1132 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1133 unsigned long mchcfg;
1134 unsigned long errsts;
1135
Elyes HAOUAS54506bf2018-08-24 09:17:59 +02001136 // Fill in the correct memory capabilities
Martin Roth9b1b3352016-02-24 12:27:06 -08001137 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
1138 ctrl.cap = ECC_CORRECT;
1139 ctrl.mode = ddim[(mchcfg >> 7)&3];
1140
Martin Roth4dcd13d2016-02-24 13:53:07 -08001141 // Clear any prexisting error reports
Martin Roth9b1b3352016-02-24 12:27:06 -08001142 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1143 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1144}
1145
1146/*
1147static void poll_i860(void)
1148{
1149 unsigned long errsts;
1150 unsigned long page;
1151 unsigned char syndrome;
1152 int channel;
1153 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001154 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001155 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1156 if (errsts & 3) {
1157 unsigned long eap;
1158 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001159 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001160 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
1161 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
1162
Martin Roth4dcd13d2016-02-24 13:53:07 -08001163 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001164 page = (eap & 0xFFFFFE00) >> 9;
1165 channel = eap & 1;
1166 syndrome = derrctl_sts & 0xFF;
1167 bits = ((errsts & 3) == 1)?1:2;
1168
Martin Roth4dcd13d2016-02-24 13:53:07 -08001169 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001170 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
1171
Martin Roth4dcd13d2016-02-24 13:53:07 -08001172 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001173 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1174 }
1175}
1176
1177
1178static void poll_iE7221(void)
1179{
1180 unsigned long errsts;
1181 unsigned long page;
1182 unsigned char syndrome;
1183 int channel;
1184 int bits;
1185 int errocc;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001186
Martin Roth9b1b3352016-02-24 12:27:06 -08001187 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001188
Martin Roth9b1b3352016-02-24 12:27:06 -08001189 errocc = errsts & 3;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001190
Martin Roth9b1b3352016-02-24 12:27:06 -08001191 if ((errocc == 1) || (errocc == 2)) {
1192 unsigned long eap, offset;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001193 unsigned long derrctl_sts;
1194
1195 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001196 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001197 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts);
1198
1199 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001200 channel = eap & 1;
1201 eap = eap & 0xFFFFFF80;
1202 page = eap >> 12;
1203 offset = eap & 0xFFF;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001204 syndrome = derrctl_sts & 0xFF;
Martin Roth9b1b3352016-02-24 12:27:06 -08001205 bits = errocc & 1;
1206
Martin Roth4dcd13d2016-02-24 13:53:07 -08001207 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001208 print_ecc_err(page, offset, bits, syndrome, channel);
1209
Martin Roth4dcd13d2016-02-24 13:53:07 -08001210 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001211 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001212 }
1213
Martin Roth9b1b3352016-02-24 12:27:06 -08001214 else if (errocc == 3) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001215
1216 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1217
Martin Roth9b1b3352016-02-24 12:27:06 -08001218 }
1219}
1220
1221
1222static void poll_iE7520(void)
1223{
1224 unsigned long ferr;
1225 unsigned long nerr;
1226
1227 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr);
1228 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr);
1229
1230 if (ferr & 0x0101) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001231 // Find out about the first correctable error
Martin Roth9b1b3352016-02-24 12:27:06 -08001232 unsigned long celog_add;
1233 unsigned long celog_syndrome;
1234 unsigned long page;
1235
Martin Roth4dcd13d2016-02-24 13:53:07 -08001236 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001237 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001238 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -08001239 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome);
1240
Martin Roth4dcd13d2016-02-24 13:53:07 -08001241 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001242 page = (celog_add & 0x7FFFFFFC) >> 2;
1243
Martin Roth4dcd13d2016-02-24 13:53:07 -08001244 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001245 print_ecc_err(page, 0, 1, celog_syndrome, 0);
1246
Martin Roth4dcd13d2016-02-24 13:53:07 -08001247 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -08001248 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101);
1249 }
1250
1251 if (ferr & 0x4646) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001252 // Found out about the first uncorrectable error
Martin Roth9b1b3352016-02-24 12:27:06 -08001253 unsigned long uccelog_add;
1254 unsigned long page;
1255
Martin Roth4dcd13d2016-02-24 13:53:07 -08001256 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001257 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add);
1258
Martin Roth4dcd13d2016-02-24 13:53:07 -08001259 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001260 page = (uccelog_add & 0x7FFFFFFC) >> 2;
1261
Martin Roth4dcd13d2016-02-24 13:53:07 -08001262 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001263 print_ecc_err(page, 0, 0, 0, 0);
1264
Martin Roth4dcd13d2016-02-24 13:53:07 -08001265 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -08001266 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646);
1267 }
1268
Martin Roth4dcd13d2016-02-24 13:53:07 -08001269 // Check if DRAM_NERR contains data
Martin Roth9b1b3352016-02-24 12:27:06 -08001270 if (nerr & 0x4747) {
1271 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747);
1272 }
1273}
1274*/
1275
1276
1277
1278/* ----------------- Here's the code for FSB detection ----------------- */
1279/* --------------------------------------------------------------------- */
1280
1281static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5};
1282static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0};
1283static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
1284
1285static float getP4PMmultiplier(void)
1286{
1287 //unsigned int msr_lo, msr_hi;
1288 int msr_lo, msr_hi;
1289 float coef;
1290
Martin Roth4dcd13d2016-02-24 13:53:07 -08001291
Martin Roth9b1b3352016-02-24 12:27:06 -08001292 /* Find multiplier (by MSR) */
Ben Gardner90f7d112016-03-15 15:25:22 -05001293 if (cpu_id.vers.bits.family == 6) {
1294 if (cpu_id.fid.bits.eist & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001295 rdmsr(0x198, msr_lo, msr_hi);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001296 coef = ((msr_lo) >> 8) & 0x1F;
1297 if ((msr_lo >> 14) & 0x1) { coef += 0.5f; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001298 // Atom Fix
Ben Gardner90f7d112016-03-15 15:25:22 -05001299 if (coef == 6) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001300 coef = ((msr_hi) >> 8) & 0x1F;
1301 if ((msr_hi >> 14) & 0x1) { coef += 0.5f; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001302 }
1303 } else {
1304 rdmsr(0x2A, msr_lo, msr_hi);
1305 coef = (msr_lo >> 22) & 0x1F;
1306 }
Ben Gardner90f7d112016-03-15 15:25:22 -05001307 } else {
1308 if (cpu_id.vers.bits.model < 2) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001309 rdmsr(0x2A, msr_lo, msr_hi);
1310 coef = (msr_lo >> 8) & 0xF;
1311 coef = p4model1ratios[(int)coef];
Ben Gardner90f7d112016-03-15 15:25:22 -05001312 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -08001313 rdmsr(0x2C, msr_lo, msr_hi);
1314 coef = (msr_lo >> 24) & 0x1F;
1315 }
1316 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001317
Martin Roth9b1b3352016-02-24 12:27:06 -08001318 return coef;
1319}
1320
1321static float getNHMmultiplier(void)
1322{
1323 unsigned int msr_lo, msr_hi;
1324 float coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001325
Martin Roth9b1b3352016-02-24 12:27:06 -08001326 /* Find multiplier (by MSR) */
1327 /* First, check if Flexible Ratio is Enabled */
1328 rdmsr(0x194, msr_lo, msr_hi);
Ben Gardner90f7d112016-03-15 15:25:22 -05001329 if ((msr_lo >> 16) & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001330 coef = (msr_lo >> 8) & 0xFF;
Ben Gardner90f7d112016-03-15 15:25:22 -05001331 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -08001332 rdmsr(0xCE, msr_lo, msr_hi);
1333 coef = (msr_lo >> 8) & 0xFF;
Ben Gardner90f7d112016-03-15 15:25:22 -05001334 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001335
1336 return coef;
1337}
Ben Gardner90f7d112016-03-15 15:25:22 -05001338
Martin Roth9b1b3352016-02-24 12:27:06 -08001339static float getSNBmultiplier(void)
1340{
1341 unsigned int msr_lo, msr_hi;
1342 float coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001343
Martin Roth9b1b3352016-02-24 12:27:06 -08001344 rdmsr(0xCE, msr_lo, msr_hi);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001345 coef = (msr_lo >> 8) & 0xFF;
Martin Roth9b1b3352016-02-24 12:27:06 -08001346
1347 return coef;
1348}
1349
Martin Roth4dcd13d2016-02-24 13:53:07 -08001350static void poll_fsb_ct(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001351{
1352 unsigned long mcr, mdr;
1353 double dramratio, dramclock, fsb;
1354 float coef = getP4PMmultiplier();
1355
1356 /* Build the MCR Message*/
1357 mcr = (0x10 << 24); // 10h = Read - 11h = Write
1358 mcr += (0x01 << 16); // DRAM Registers located on port 01h
1359 mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h
Martin Roth4dcd13d2016-02-24 13:53:07 -08001360 mcr &= 0xFFFFFFF0; // bit 03:00 RSVD
1361
Martin Roth9b1b3352016-02-24 12:27:06 -08001362 /* Send Message to GMCH */
Martin Roth4dcd13d2016-02-24 13:53:07 -08001363 pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
1364
Martin Roth9b1b3352016-02-24 12:27:06 -08001365 /* Read Answer from Sideband bus */
Martin Roth4dcd13d2016-02-24 13:53:07 -08001366 pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
1367
Martin Roth9b1b3352016-02-24 12:27:06 -08001368 /* Get RAM ratio */
1369 switch (mdr & 0x3) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001370 default:
1371 case 0: dramratio = 3.0f; break;
1372 case 1: dramratio = 4.0f; break;
1373 case 2: dramratio = 5.0f; break;
1374 case 3: dramratio = 6.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001375 }
1376
1377 // Compute FSB & RAM Frequency
1378 fsb = ((extclock / 1000) / coef);
1379 dramclock = fsb * dramratio;
1380
1381 // Print'em all. Whoa !
1382 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001383}
1384
Ben Gardner90f7d112016-03-15 15:25:22 -05001385static void poll_fsb_amd64(void)
1386{
Martin Roth9b1b3352016-02-24 12:27:06 -08001387 unsigned int mcgsrl;
1388 unsigned int mcgsth;
1389 unsigned long fid, temp2;
1390 unsigned long dramchr;
1391 float clockratio;
1392 double dramclock;
Martin Roth869474b2016-02-24 13:47:46 -08001393 unsigned int dummy[4];
Martin Roth9b1b3352016-02-24 12:27:06 -08001394 int ram_type;
1395
1396 float coef = 10;
1397
1398 cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]);
1399
1400 /* First, got the FID by MSR */
1401 /* First look if Cool 'n Quiet is supported to choose the best msr */
1402 if (((dummy[3] >> 1) & 1) == 1) {
1403 rdmsr(0xc0010042, mcgsrl, mcgsth);
1404 fid = (mcgsrl & 0x3F);
1405 } else {
1406 rdmsr(0xc0010015, mcgsrl, mcgsth);
1407 fid = ((mcgsrl >> 24)& 0x3F);
1408 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001409
Martin Roth9b1b3352016-02-24 12:27:06 -08001410 /* Extreme simplification. */
1411 coef = ( fid / 2 ) + 4.0;
1412
1413 /* Support for .5 coef */
1414 if (fid & 1) { coef = coef + 0.5; }
1415
1416 /* Next, we need the clock ratio */
1417 if (cpu_id.vers.bits.extendedModel >= 4) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001418 /* K8 0FH */
Martin Roth9b1b3352016-02-24 12:27:06 -08001419 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1420 temp2 = (dramchr & 0x7);
1421 clockratio = coef;
1422 ram_type = 2;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001423
Martin Roth9b1b3352016-02-24 12:27:06 -08001424 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001425 case 0x0:
1426 clockratio = (int)(coef);
1427 break;
1428 case 0x1:
1429 clockratio = (int)(coef * 3.0f/4.0f);
1430 break;
1431 case 0x2:
1432 clockratio = (int)(coef * 3.0f/5.0f);
1433 break;
1434 case 0x3:
1435 clockratio = (int)(coef * 3.0f/6.0f);
1436 break;
1437 }
1438 } else {
1439 /* OLD K8 */
Martin Roth9b1b3352016-02-24 12:27:06 -08001440 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1441 temp2 = (dramchr >> 20) & 0x7;
1442 ram_type = 1;
1443 clockratio = coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001444
Martin Roth9b1b3352016-02-24 12:27:06 -08001445 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001446 case 0x0:
1447 clockratio = (int)(coef * 2.0f);
1448 break;
1449 case 0x2:
1450 clockratio = (int)((coef * 3.0f/2.0f) + 0.81f);
1451 break;
1452 case 0x4:
1453 clockratio = (int)((coef * 4.0f/3.0f) + 0.81f);
1454 break;
1455 case 0x5:
1456 clockratio = (int)((coef * 6.0f/5.0f) + 0.81f);
1457 break;
1458 case 0x6:
1459 clockratio = (int)((coef * 10.0f/9.0f) + 0.81f);
1460 break;
1461 case 0x7:
1462 clockratio = (int)(coef + 0.81f);
1463 break;
1464 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001465 }
1466
1467 /* Compute the final DRAM Clock */
1468 dramclock = (extclock / 1000) / clockratio;
1469
1470 /* ...and print */
1471 print_cpu_line(dramclock, (extclock / 1000 / coef), ram_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001472}
1473
Ben Gardner90f7d112016-03-15 15:25:22 -05001474static void poll_fsb_k10(void)
1475{
Martin Roth9b1b3352016-02-24 12:27:06 -08001476 unsigned int mcgsrl;
1477 unsigned int mcgsth;
1478 unsigned long temp2;
1479 unsigned long dramchr;
1480 unsigned long mainPllId;
1481 double dramclock;
1482 ulong offset = 0;
1483 int ram_type = 2;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001484
Ben Gardner90f7d112016-03-15 15:25:22 -05001485 /* First, we need the clock ratio */
1486 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1487 temp2 = (dramchr & 0x7);
Martin Roth9b1b3352016-02-24 12:27:06 -08001488
Ben Gardner90f7d112016-03-15 15:25:22 -05001489 switch (temp2) {
1490 case 0x7: temp2++;
1491 case 0x6: temp2++;
1492 case 0x5: temp2++;
1493 case 0x4: temp2++;
1494 default: temp2 += 3;
1495 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001496
1497 /* Compute the final DRAM Clock */
Martin Roth04f7f142016-03-27 21:04:00 -06001498 if (cpu_id.vers.bits.extendedModel == 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001499 dramclock = ((temp2 * 200) / 3.0) + 0.25;
1500 } else {
1501 unsigned long target;
1502 unsigned long dx;
1503 unsigned divisor;
1504
1505 target = temp2 * 400;
1506
1507 /* Get the FID by MSR */
1508 rdmsr(0xc0010071, mcgsrl, mcgsth);
1509
1510 pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId);
1511
Ben Gardner90f7d112016-03-15 15:25:22 -05001512 if (mainPllId & 0x40)
Martin Roth9b1b3352016-02-24 12:27:06 -08001513 mainPllId &= 0x3F;
1514 else
Ben Gardner90f7d112016-03-15 15:25:22 -05001515 mainPllId = 8; /* FID for 1600 */
Martin Roth9b1b3352016-02-24 12:27:06 -08001516
1517 mcgsth = (mcgsth >> 17) & 0x3F;
Ben Gardner90f7d112016-03-15 15:25:22 -05001518 if (mcgsth) {
1519 if (mainPllId > mcgsth)
Martin Roth9b1b3352016-02-24 12:27:06 -08001520 mainPllId = mcgsth;
1521 }
1522
1523 dx = (mainPllId + 8) * 1200;
Ben Gardner90f7d112016-03-15 15:25:22 -05001524 for (divisor = 3; divisor < 100; divisor++)
1525 if ( (dx / divisor) <= target)
Martin Roth9b1b3352016-02-24 12:27:06 -08001526 break;
1527
Martin Roth4dcd13d2016-02-24 13:53:07 -08001528
Ben Gardner90f7d112016-03-15 15:25:22 -05001529 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001530
Ben Gardner90f7d112016-03-15 15:25:22 -05001531 // If Channel A not enabled, switch to channel B
1532 if (((dramchr>>14) & 0x1)) {
1533 offset = 0x100;
1534 pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr);
1535 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001536
Ben Gardner90f7d112016-03-15 15:25:22 -05001537 //DDR2 or DDR3
1538 if ((dramchr >> 8)&1) {
1539 ram_type = 3;
1540 } else {
1541 ram_type = 2;
1542 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001543
Martin Roth9b1b3352016-02-24 12:27:06 -08001544 dramclock = ((dx / divisor) / 6.0) + 0.25;
Ben Gardner90f7d112016-03-15 15:25:22 -05001545 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001546
1547 /* ...and print */
1548 print_cpu_line(dramclock, 0, ram_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001549}
1550
Ben Gardner90f7d112016-03-15 15:25:22 -05001551static void poll_fsb_k12(void)
1552{
Martin Roth9b1b3352016-02-24 12:27:06 -08001553 unsigned long temp2;
1554 unsigned long dramchr;
1555 double dramratio, dramclock, fsb, did;
Ben Gardner90f7d112016-03-15 15:25:22 -05001556 unsigned int mcgsrl, mcgsth, fid, did_raw;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001557
Martin Roth9b1b3352016-02-24 12:27:06 -08001558 // Get current FID & DID
Ben Gardner90f7d112016-03-15 15:25:22 -05001559 rdmsr(0xc0010071, mcgsrl, mcgsth);
1560 did_raw = mcgsrl & 0xF;
1561 fid = (mcgsrl >> 4) & 0xF;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001562
Ben Gardner90f7d112016-03-15 15:25:22 -05001563 switch (did_raw) {
1564 default:
1565 case 0x0:
1566 did = 1.0f;
1567 break;
1568 case 0x1:
1569 did = 1.5f;
1570 break;
1571 case 0x2:
1572 did = 2.0f;
1573 break;
1574 case 0x3:
1575 did = 3.0f;
1576 break;
1577 case 0x4:
1578 did = 4.0f;
1579 break;
1580 case 0x5:
1581 did = 6.0f;
1582 break;
1583 case 0x6:
1584 did = 8.0f;
1585 break;
1586 case 0x7:
1587 did = 12.0f;
1588 break;
1589 case 0x8:
1590 did = 16.0f;
1591 break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001592 }
1593
Ben Gardner90f7d112016-03-15 15:25:22 -05001594 fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did));
Martin Roth4dcd13d2016-02-24 13:53:07 -08001595
Martin Roth9b1b3352016-02-24 12:27:06 -08001596 /* Finaly, we need the clock ratio */
1597 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001598
Ben Gardner90f7d112016-03-15 15:25:22 -05001599 if (((dramchr >> 14) & 0x1) == 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001600 pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
Martin Roth9b1b3352016-02-24 12:27:06 -08001601 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001602
Martin Roth9b1b3352016-02-24 12:27:06 -08001603 temp2 = (dramchr & 0x1F);
1604
1605 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001606 default:
1607 case 0x06:
1608 dramratio = 4.0f;
1609 break;
1610 case 0x0A:
1611 dramratio = 16.0f / 3.0f;
1612 break;
1613 case 0x0E:
1614 dramratio = 20.0f / 3.0f;
1615 break;
1616 case 0x12:
1617 dramratio = 8.0f;
1618 break;
1619 case 0x16:
1620 dramratio = 28.0f / 3.0f;
1621 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001622 }
1623
Martin Roth9b1b3352016-02-24 12:27:06 -08001624 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001625
Martin Roth9b1b3352016-02-24 12:27:06 -08001626 /* print */
1627 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001628}
1629
Martin Roth4dcd13d2016-02-24 13:53:07 -08001630static void poll_fsb_k16(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001631{
Martin Roth9b1b3352016-02-24 12:27:06 -08001632 unsigned long dramchr;
1633 double dramratio, dramclock, fsb;
1634
Martin Roth4dcd13d2016-02-24 13:53:07 -08001635 // FIXME: Unable to find a real way to detect multiplier.
Martin Roth9b1b3352016-02-24 12:27:06 -08001636 fsb = 100.0f;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001637
Martin Roth9b1b3352016-02-24 12:27:06 -08001638 /* Clock ratio */
1639 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1640
1641 switch (dramchr & 0x1F) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001642 default:
1643 case 0x04: /* 333 */
1644 dramratio = 10.0f / 3.0f;
1645 break;
1646 case 0x06: /* 400 */
1647 dramratio = 4.0f;
1648 break;
1649 case 0x0A: /* 533 */
1650 dramratio = 16.0f / 3.0f;
1651 break;
1652 case 0x0E: /* 667 */
1653 dramratio = 20.0f / 3.0f;
1654 break;
1655 case 0x12: /* 800 */
1656 dramratio = 8.0f;
1657 break;
1658 case 0x16: /* 933 */
1659 dramratio = 28.0f / 3.0f;
1660 break;
1661 case 0x19: /* 1050 */
1662 dramratio = 21.0f / 2.0f;
1663 break;
1664 case 0x1A: /* 1066 */
1665 dramratio = 32.0f / 3.0f;
1666 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001667 }
1668
Martin Roth9b1b3352016-02-24 12:27:06 -08001669 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001670
Martin Roth9b1b3352016-02-24 12:27:06 -08001671 /* print */
1672 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001673}
1674
Ben Gardner90f7d112016-03-15 15:25:22 -05001675static void poll_fsb_k15(void)
1676{
Martin Roth9b1b3352016-02-24 12:27:06 -08001677 unsigned long temp2;
1678 unsigned long dramchr;
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001679 double dramclock, fsb;
Ben Gardner90f7d112016-03-15 15:25:22 -05001680 unsigned int mcgsrl, mcgsth, fid, did;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001681
Martin Roth9b1b3352016-02-24 12:27:06 -08001682 // Get current FID & DID
Ben Gardner90f7d112016-03-15 15:25:22 -05001683 rdmsr(0xc0010071, mcgsrl, mcgsth);
1684 fid = mcgsrl & 0x3F;
1685 did = (mcgsrl >> 6) & 0x7;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001686
Ben Gardner90f7d112016-03-15 15:25:22 -05001687 fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001688
Martin Roth9b1b3352016-02-24 12:27:06 -08001689 /* Finaly, we need the clock ratio */
1690 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001691
Ben Gardner90f7d112016-03-15 15:25:22 -05001692 if (((dramchr >> 14) & 0x1) == 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001693 pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
Martin Roth9b1b3352016-02-24 12:27:06 -08001694 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001695
Martin Roth9b1b3352016-02-24 12:27:06 -08001696 temp2 = (dramchr & 0x1F);
1697
1698 switch (temp2) {
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001699 case 0x02:
1700 dramclock = 200;
Ben Gardner90f7d112016-03-15 15:25:22 -05001701 break;
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001702 case 0x04:
1703 dramclock = 333;
1704 break;
Ben Gardner90f7d112016-03-15 15:25:22 -05001705 case 0x06:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001706 dramclock = 400;
Ben Gardner90f7d112016-03-15 15:25:22 -05001707 break;
1708 case 0x0A:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001709 dramclock = 533;
Ben Gardner90f7d112016-03-15 15:25:22 -05001710 break;
1711 case 0x0E:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001712 dramclock = 667;
Ben Gardner90f7d112016-03-15 15:25:22 -05001713 break;
1714 case 0x12:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001715 dramclock = 800;
Ben Gardner90f7d112016-03-15 15:25:22 -05001716 break;
1717 case 0x16:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001718 dramclock = 933;
Ben Gardner90f7d112016-03-15 15:25:22 -05001719 break;
1720 case 0x1A:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001721 dramclock = 1066;
Ben Gardner90f7d112016-03-15 15:25:22 -05001722 break;
1723 case 0x1F:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001724 dramclock = 1200;
1725 break;
1726 default:
1727 dramclock = 0;
Ben Gardner90f7d112016-03-15 15:25:22 -05001728 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001729 }
1730
Martin Roth9b1b3352016-02-24 12:27:06 -08001731 /* print */
1732 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001733}
1734
Martin Roth4dcd13d2016-02-24 13:53:07 -08001735static void poll_fsb_k14(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001736{
Martin Roth9b1b3352016-02-24 12:27:06 -08001737 unsigned long dramchr;
1738 double dramratio, dramclock, fsb;
1739
Martin Roth4dcd13d2016-02-24 13:53:07 -08001740 // FIXME: Unable to find a real way to detect multiplier.
Ben Gardner90f7d112016-03-15 15:25:22 -05001741 fsb = 100.0f;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001742
Martin Roth9b1b3352016-02-24 12:27:06 -08001743 /* Clock ratio */
1744 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1745
1746 switch (dramchr & 0x1F) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001747 default:
1748 case 0x06:
1749 dramratio = 4.0f;
1750 break;
1751 case 0x0A:
1752 dramratio = 16.0f / 3.0f;
1753 break;
1754 case 0x0E:
1755 dramratio = 20.0f / 3.0f;
1756 break;
1757 case 0x12:
1758 dramratio = 8.0f;
1759 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001760 }
1761
Martin Roth9b1b3352016-02-24 12:27:06 -08001762 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001763
Martin Roth9b1b3352016-02-24 12:27:06 -08001764 /* print */
1765 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001766}
1767
1768
Ben Gardner90f7d112016-03-15 15:25:22 -05001769static void poll_fsb_i925(void)
1770{
Martin Roth9b1b3352016-02-24 12:27:06 -08001771 double dramclock, dramratio, fsb;
1772 unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
1773 float coef = getP4PMmultiplier();
1774 long *ptr;
1775 int ddr_type;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001776
Martin Roth9b1b3352016-02-24 12:27:06 -08001777 pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001778
Martin Roth9b1b3352016-02-24 12:27:06 -08001779 /* Find dramratio */
1780 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1781 dev0 = dev0 & 0xFFFFC000;
1782 ptr=(long*)(dev0+0xC00);
1783 mchcfg = *ptr & 0xFFFF;
1784 ptr=(long*)(dev0+0x120);
1785 drc = *ptr & 0xFFFF;
1786 dramratio = 1;
1787
1788 mchcfg2 = (mchcfg >> 4)&3;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001789
Martin Roth9b1b3352016-02-24 12:27:06 -08001790 if ((drc&3) != 2) {
1791 // We are in DDR1 Mode
1792 if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; }
1793 ddr_type = 1;
1794 } else {
1795 // We are in DDR2 Mode
1796 ddr_type = 2;
1797 if ((mchcfg >> 2)&1) {
1798 // We are in FSB1066 Mode
1799 if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; }
1800 } else {
1801 switch (mchcfg2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001802 case 1:
1803 dramratio = 0.66667;
1804 break;
1805 case 2:
1806 if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; }
1807 break;
1808 case 3:
1809 // Checking for FSB533 Mode & Alviso
1810 if ((mchcfg & 1) == 0) { dramratio = 1.33334; }
1811 else if (idetect == 0x2590) { dramratio = 2; }
1812 else { dramratio = 1.5; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001813 }
1814 }
1815 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001816 // Compute RAM Frequency
Martin Roth9b1b3352016-02-24 12:27:06 -08001817 fsb = ((extclock / 1000) / coef);
1818 dramclock = fsb * dramratio;
1819
Martin Roth4dcd13d2016-02-24 13:53:07 -08001820
Martin Roth9b1b3352016-02-24 12:27:06 -08001821 print_cpu_line(dramclock, fsb, ddr_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001822}
1823
Ben Gardner90f7d112016-03-15 15:25:22 -05001824static void poll_fsb_i945(void)
1825{
Martin Roth9b1b3352016-02-24 12:27:06 -08001826 double dramclock, dramratio, fsb;
1827 unsigned long mchcfg, dev0;
1828 float coef = getP4PMmultiplier();
1829 long *ptr;
1830
1831 /* Find dramratio */
1832 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1833 dev0 &= 0xFFFFC000;
1834 ptr=(long*)(dev0+0xC00);
1835 mchcfg = *ptr & 0xFFFF;
1836 dramratio = 1;
1837
1838 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001839 case 1: dramratio = 1.0; break;
1840 case 2: dramratio = 1.33334; break;
1841 case 3: dramratio = 1.66667; break;
1842 case 4: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001843 }
1844
1845 // Compute RAM Frequency
1846 fsb = ((extclock / 1000) / coef);
1847
1848 dramclock = fsb * dramratio;
1849
1850 // Print
1851 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001852}
1853
Ben Gardner90f7d112016-03-15 15:25:22 -05001854static void poll_fsb_i945gme(void)
1855{
Martin Roth9b1b3352016-02-24 12:27:06 -08001856 double dramclock, dramratio, fsb;
1857 unsigned long mchcfg, dev0, fsb_mch;
1858 float coef = getP4PMmultiplier();
1859 long *ptr;
1860
1861 /* Find dramratio */
1862 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1863 dev0 &= 0xFFFFC000;
1864 ptr=(long*)(dev0+0xC00);
1865 mchcfg = *ptr & 0xFFFF;
1866 dramratio = 1;
1867
1868 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001869 case 0: fsb_mch = 400; break;
1870 default:
1871 case 1: fsb_mch = 533; break;
1872 case 2: fsb_mch = 667; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001873 }
1874
1875
1876 switch (fsb_mch) {
1877 case 400:
1878 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001879 case 2: dramratio = 1.0f; break;
1880 case 3: dramratio = 4.0f/3.0f; break;
1881 case 4: dramratio = 5.0f/3.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001882 }
1883 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001884
Martin Roth9b1b3352016-02-24 12:27:06 -08001885 default:
1886 case 533:
1887 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001888 case 2: dramratio = 3.0f/4.0f; break;
1889 case 3: dramratio = 1.0f; break;
1890 case 4: dramratio = 5.0f/4.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001891 }
1892 break;
1893
1894 case 667:
1895 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001896 case 2: dramratio = 3.0f/5.0f; break;
1897 case 3: dramratio = 4.0f/5.0f; break;
1898 case 4: dramratio = 1.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001899 }
1900 break;
1901 }
1902
1903 // Compute RAM Frequency
1904 fsb = ((extclock / 1000) / coef);
1905 dramclock = fsb * dramratio * 2;
1906
1907 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001908}
1909
1910
Ben Gardner90f7d112016-03-15 15:25:22 -05001911static void poll_fsb_i975(void)
1912{
Martin Roth9b1b3352016-02-24 12:27:06 -08001913 double dramclock, dramratio, fsb;
1914 unsigned long mchcfg, dev0, fsb_mch;
1915 float coef = getP4PMmultiplier();
1916 long *ptr;
1917
1918 /* Find dramratio */
1919 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1920 dev0 &= 0xFFFFC000;
1921 ptr=(long*)(dev0+0xC00);
1922 mchcfg = *ptr & 0xFFFF;
1923 dramratio = 1;
1924
1925 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001926 case 1: fsb_mch = 533; break;
1927 case 2: fsb_mch = 800; break;
1928 case 3: fsb_mch = 667; break;
1929 default: fsb_mch = 1066; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001930 }
1931
1932
1933 switch (fsb_mch) {
1934 case 533:
1935 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001936 case 0: dramratio = 1.25; break;
1937 case 1: dramratio = 1.5; break;
1938 case 2: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001939 }
1940 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001941
Martin Roth9b1b3352016-02-24 12:27:06 -08001942 default:
1943 case 800:
1944 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001945 case 1: dramratio = 1.0; break;
1946 case 2: dramratio = 1.33334; break;
1947 case 3: dramratio = 1.66667; break;
1948 case 4: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001949 }
1950 break;
1951
1952 case 1066:
1953 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001954 case 1: dramratio = 0.75; break;
1955 case 2: dramratio = 1.0; break;
1956 case 3: dramratio = 1.25; break;
1957 case 4: dramratio = 1.5; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001958 }
1959 break;
1960 }
1961
1962 // Compute RAM Frequency
1963 fsb = ((extclock / 1000) / coef);
1964 dramclock = fsb * dramratio;
1965
1966 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001967}
1968
Ben Gardner90f7d112016-03-15 15:25:22 -05001969static void poll_fsb_i965(void)
1970{
Martin Roth9b1b3352016-02-24 12:27:06 -08001971 double dramclock, dramratio, fsb;
1972 unsigned long mchcfg, dev0, fsb_mch;
1973 float coef = getP4PMmultiplier();
1974 long *ptr;
1975
1976 /* Find dramratio */
1977 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
1978 dev0 &= 0xFFFFC000;
1979 ptr=(long*)(dev0+0xC00);
1980 mchcfg = *ptr & 0xFFFF;
1981 dramratio = 1;
1982
1983 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001984 case 0: fsb_mch = 1066; break;
1985 case 1: fsb_mch = 533; break;
1986 default: case 2: fsb_mch = 800; break;
1987 case 3: fsb_mch = 667; break;
1988 case 4: fsb_mch = 1333; break;
1989 case 6: fsb_mch = 1600; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001990 }
1991
1992
1993 switch (fsb_mch) {
1994 case 533:
1995 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001996 case 1: dramratio = 2.0; break;
1997 case 2: dramratio = 2.5; break;
1998 case 3: dramratio = 3.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001999 }
2000 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08002001
Martin Roth9b1b3352016-02-24 12:27:06 -08002002 default:
2003 case 800:
2004 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002005 case 0: dramratio = 1.0; break;
2006 case 1: dramratio = 5.0f/4.0f; break;
2007 case 2: dramratio = 5.0f/3.0f; break;
2008 case 3: dramratio = 2.0f; break;
2009 case 4: dramratio = 8.0f/3.0f; break;
2010 case 5: dramratio = 10.0f/3.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002011 }
2012 break;
2013
2014 case 1066:
2015 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002016 case 1: dramratio = 1.0f; break;
2017 case 2: dramratio = 5.0f/4.0f; break;
2018 case 3: dramratio = 3.0f/2.0f; break;
2019 case 4: dramratio = 2.0f; break;
2020 case 5: dramratio = 5.0f/2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002021 }
2022 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08002023
Martin Roth9b1b3352016-02-24 12:27:06 -08002024 case 1333:
2025 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002026 case 2: dramratio = 1.0f; break;
2027 case 3: dramratio = 6.0f/5.0f; break;
2028 case 4: dramratio = 8.0f/5.0f; break;
2029 case 5: dramratio = 2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002030 }
2031 break;
2032
2033 case 1600:
2034 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002035 case 3: dramratio = 1.0f; break;
2036 case 4: dramratio = 4.0f/3.0f; break;
2037 case 5: dramratio = 3.0f/2.0f; break;
2038 case 6: dramratio = 2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -0800