blob: b3a57fac2f333499b2a705b2b1342623c4c51090 [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 */
46#define ECC_NONE 0 /* Doesnt support ECC (or is BIOS disabled) */
47#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 tnow = 0;
Martin Roth4dcd13d2016-02-24 13:53:07 -080089
Martin Roth9b1b3352016-02-24 12:27:06 -080090 // Intel CPU
Ben Gardner90f7d112016-03-15 15:25:22 -050091 if (cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6) {
92 if (cpu_id.dts_pmp & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -080093 rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh);
94 tabs = ((msrl >> 16) & 0x7F);
95 rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh);
96 tjunc = ((msrl >> 16) & 0x7F);
Ben Gardner90f7d112016-03-15 15:25:22 -050097 if (tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90°C if boggus value received.
Martin Roth4dcd13d2016-02-24 13:53:07 -080098 tnow = tjunc - tabs;
99 dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
Martin Roth9b1b3352016-02-24 12:27:06 -0800100 v->check_temp = tnow;
101 }
102 return;
103 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800104
Martin Roth9b1b3352016-02-24 12:27:06 -0800105 // AMD CPU
Ben Gardner90f7d112016-03-15 15:25:22 -0500106 if (cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800107 pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr);
108 amd_raw_temp = ((rtcr >> 21) & 0x7FF);
109 v->check_temp = (int)(amd_raw_temp / 8);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800110 dprint(LINE_CPU+1, 30, v->check_temp, 3, 0);
111 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800112}
113
114void print_cpu_line(float dram_freq, float fsb_freq, int ram_type)
115{
116 int cur_col = COL_SPEC;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800117
Martin Roth9b1b3352016-02-24 12:27:06 -0800118 cprint(LINE_CPU, cur_col, "RAM: ");
119 cur_col += 5;
120 dprint(LINE_CPU, cur_col, dram_freq, 4, 1);
121 cur_col += 4;
122 cprint(LINE_CPU, cur_col, "MHz (");
123 cur_col += 5;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800124
Ben Gardner90f7d112016-03-15 15:25:22 -0500125 switch (ram_type) {
126 default:
127 case 1:
128 cprint(LINE_CPU, cur_col, "DDR-");
129 cur_col += 4;
130 break;
131 case 2:
132 cprint(LINE_CPU, cur_col, "DDR2-");
133 cur_col += 5;
134 break;
135 case 3:
136 cprint(LINE_CPU, cur_col, "DDR3-");
137 cur_col += 5;
138 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800139 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800140
Ben Gardner90f7d112016-03-15 15:25:22 -0500141 if (dram_freq < 500) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800142 dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0);
143 cur_col += 3;
144 } else {
145 dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800146 cur_col += 4;
Martin Roth9b1b3352016-02-24 12:27:06 -0800147 }
148 cprint(LINE_CPU, cur_col, ")");
Martin Roth4dcd13d2016-02-24 13:53:07 -0800149 cur_col++;
150
Ben Gardner90f7d112016-03-15 15:25:22 -0500151 if (fsb_freq > 10) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800152 cprint(LINE_CPU, cur_col, " - BCLK: ");
153 cur_col += 9;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800154
155 dprint(LINE_CPU, cur_col, fsb_freq, 3, 0);
Martin Roth9b1b3352016-02-24 12:27:06 -0800156 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800157}
158
159void print_ram_line(float cas, int rcd, int rp, int ras, int chan)
160{
161 int cur_col = COL_SPEC;
162
163 cprint(LINE_RAM, cur_col, "Timings: CAS ");
Martin Roth4dcd13d2016-02-24 13:53:07 -0800164 cur_col += 13;
Martin Roth9b1b3352016-02-24 12:27:06 -0800165
166 // CAS Latency (tCAS)
167 if (cas == 1.5) {
168 cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3;
169 } else if (cas == 2.5) {
170 cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3;
171 } else if (cas < 10) {
172 dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1;
173 } else {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800174 dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800175 }
176 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
177
178 // RAS-To-CAS (tRCD)
179 if (rcd < 10) {
180 dprint(LINE_RAM, cur_col, rcd, 1, 0);
181 cur_col += 1;
182 } else {
183 dprint(LINE_RAM, cur_col, rcd, 2, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800184 cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800185 }
186 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
187
188 // RAS Precharge (tRP)
189 if (rp < 10) {
190 dprint(LINE_RAM, cur_col, rp, 1, 0);
191 cur_col += 1;
192 } else {
193 dprint(LINE_RAM, cur_col, rp, 2, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800194 cur_col += 2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800195 }
196 cprint(LINE_RAM, cur_col, "-"); cur_col += 1;
197
198 // RAS Active to precharge (tRAS)
199 if (ras < 10) {
200 dprint(LINE_RAM, cur_col, ras, 1, 0);
201 cur_col += 1;
202 } else {
203 dprint(LINE_RAM, cur_col, ras, 2, 0);
204 cur_col += 2;
205 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800206
207
Ben Gardner90f7d112016-03-15 15:25:22 -0500208 switch (chan) {
209 case 0:
210 break;
211 case 1:
212 cprint(LINE_RAM, cur_col, " @ 64-bit Mode");
213 break;
214 case 2:
215 cprint(LINE_RAM, cur_col, " @ 128-bit Mode");
216 break;
217 case 3:
218 cprint(LINE_RAM, cur_col, " @ 192-bit Mode");
219 break;
220 case 4:
221 cprint(LINE_RAM, cur_col, " @ 256-bit Mode");
222 break;
Martin Roth9b1b3352016-02-24 12:27:06 -0800223 }
224}
225
226static void poll_fsb_nothing(void)
227{
Martin Roth9b1b3352016-02-24 12:27:06 -0800228 char *name;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800229
Martin Roth9b1b3352016-02-24 12:27:06 -0800230 /* Print the controller name */
231 name = controllers[ctrl.index].name;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800232 cprint(LINE_CPU, COL_SPEC, "Chipset: ");
Martin Roth9b1b3352016-02-24 12:27:06 -0800233 cprint(LINE_CPU, COL_SPEC+9, name);
234 return;
235}
236
237static void poll_timings_nothing(void)
238{
239 char *ram_type;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800240
Martin Roth9b1b3352016-02-24 12:27:06 -0800241 /* Print the controller name */
242 ram_type = controllers[ctrl.index].ram_type;
243 cprint(LINE_RAM, COL_SPEC, "RAM Type: ");
244 cprint(LINE_RAM, COL_SPEC+10, ram_type);
245 return;
246}
247
248static void setup_nothing(void)
249{
250 ctrl.cap = ECC_NONE;
251 ctrl.mode = ECC_NONE;
252}
253
254static void poll_nothing(void)
255{
256/* Code to run when we don't know how, or can't ask the memory
257 * controller about memory errors.
258 */
259 return;
260}
261
262static void setup_wmr(void)
263{
264 ulong dev0;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800265
Martin Roth9b1b3352016-02-24 12:27:06 -0800266 // Activate MMR I/O
267 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
268 if (!(dev0 & 0x1)) {
269 pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
270 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800271}
272
273
274static void setup_nhm(void)
275{
276 static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
277 unsigned long did, vid, mc_control, mc_ssrcontrol;
278 int i;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800279
Martin Roth9b1b3352016-02-24 12:27:06 -0800280 //Nehalem supports Scrubbing */
281 ctrl.cap = ECC_SCRUB;
282 ctrl.mode = ECC_NONE;
283
284 /* First, locate the PCI bus where the MCH is located */
285
Ben Gardner90f7d112016-03-15 15:25:22 -0500286 for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800287 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
288 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
289 vid &= 0xFFFF;
290 did &= 0xFF00;
Ben Gardner90f7d112016-03-15 15:25:22 -0500291 if (vid == 0x8086 && did >= 0x2C00) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800292 nhm_bus = possible_nhm_bus[i];
Ben Gardner90f7d112016-03-15 15:25:22 -0500293 }
294 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800295
296 /* Now, we have the last IMC bus number in nhm_bus */
297 /* Check for ECC & Scrub */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800298
299 pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control);
Ben Gardner90f7d112016-03-15 15:25:22 -0500300 if ((mc_control >> 4) & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800301 ctrl.mode = ECC_CORRECT;
302 pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
Ben Gardner90f7d112016-03-15 15:25:22 -0500303 if (mc_ssrcontrol & 3) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800304 ctrl.mode = ECC_SCRUB;
305 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800306 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800307}
308
309static void setup_nhm32(void)
310{
311 static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
312 unsigned long did, vid, mc_control, mc_ssrcontrol;
313 int i;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800314
Martin Roth9b1b3352016-02-24 12:27:06 -0800315 //Nehalem supports Scrubbing */
316 ctrl.cap = ECC_SCRUB;
317 ctrl.mode = ECC_NONE;
318
319 /* First, locate the PCI bus where the MCH is located */
Ben Gardner90f7d112016-03-15 15:25:22 -0500320 for (i = 0; i < sizeof(possible_nhm_bus) / sizeof(possible_nhm_bus[0]); i++) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800321 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid);
322 pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did);
323 vid &= 0xFFFF;
324 did &= 0xFF00;
Ben Gardner90f7d112016-03-15 15:25:22 -0500325 if (vid == 0x8086 && did >= 0x2C00) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800326 nhm_bus = possible_nhm_bus[i];
Ben Gardner90f7d112016-03-15 15:25:22 -0500327 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800328 }
329
330 /* Now, we have the last IMC bus number in nhm_bus */
331 /* Check for ECC & Scrub */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800332 pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control);
Ben Gardner90f7d112016-03-15 15:25:22 -0500333 if ((mc_control >> 1) & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800334 ctrl.mode = ECC_CORRECT;
335 pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol);
Ben Gardner90f7d112016-03-15 15:25:22 -0500336 if (mc_ssrcontrol & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800337 ctrl.mode = ECC_SCRUB;
338 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800339 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800340}
341
342static void setup_amd64(void)
343{
344 static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL };
345 unsigned long nbxcfg;
346 unsigned int mcgsrl;
347 unsigned int mcgsth;
348 unsigned long mcanb;
349 unsigned long dramcl;
350
351 /* All AMD64 support Chipkill */
352 ctrl.cap = ECC_CHIPKILL;
353
354 /* Check First if ECC DRAM Modules are used */
355 pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800356
Martin Roth9b1b3352016-02-24 12:27:06 -0800357 if (cpu_id.vers.bits.extendedModel >= 4) {
358 /* NEW K8 0Fh Family 90 nm */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800359
Ben Gardner90f7d112016-03-15 15:25:22 -0500360 if ((dramcl >> 19)&1) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800361 /* Fill in the correct memory capabilites */
362 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
363 ctrl.mode = ddim[(nbxcfg >> 22)&3];
364 } else {
365 ctrl.mode = ECC_NONE;
366 }
367 /* Enable NB ECC Logging by MSR Write */
368 rdmsr(0x017B, mcgsrl, mcgsth);
369 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800370
Martin Roth9b1b3352016-02-24 12:27:06 -0800371 /* Clear any previous error */
372 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800373 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
Martin Roth4dcd13d2016-02-24 13:53:07 -0800374 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -0800375 /* OLD K8 130 nm */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800376
Ben Gardner90f7d112016-03-15 15:25:22 -0500377 if ((dramcl >> 17)&1) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800378 /* Fill in the correct memory capabilites */
379 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
380 ctrl.mode = ddim[(nbxcfg >> 22)&3];
381 } else {
382 ctrl.mode = ECC_NONE;
383 }
384 /* Enable NB ECC Logging by MSR Write */
385 rdmsr(0x017B, mcgsrl, mcgsth);
386 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800387
Martin Roth9b1b3352016-02-24 12:27:06 -0800388 /* Clear any previous error */
389 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
390 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC );
391 }
392}
393
394static void setup_k10(void)
395{
396 static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL };
397 unsigned long nbxcfg;
398 unsigned int mcgsrl;
399 unsigned int mcgsth;
400 unsigned long mcanb;
401 unsigned long dramcl;
402 ulong msr_low, msr_high;
403
404 // All AMD64 support Chipkill */
405 ctrl.cap = ECC_CHIPKILL;
406
407 // Check First if ECC DRAM Modules are used */
408 pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800409
Ben Gardner90f7d112016-03-15 15:25:22 -0500410 if ((dramcl >> 19)&1) {
411 // Fill in the correct memory capabilites */
412 pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
413 ctrl.mode = ddim[(nbxcfg >> 22)&3];
414 } else {
415 ctrl.mode = ECC_NONE;
416 }
417 // Enable NB ECC Logging by MSR Write */
418 rdmsr(0x017B, mcgsrl, mcgsth);
419 wrmsr(0x017B, 0x10, mcgsth);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800420
Ben Gardner90f7d112016-03-15 15:25:22 -0500421 // Clear any previous error */
422 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
423 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
Martin Roth4dcd13d2016-02-24 13:53:07 -0800424
Ben Gardner90f7d112016-03-15 15:25:22 -0500425 /* Enable ECS */
426 rdmsr(0xC001001F, msr_low, msr_high);
427 wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
428 rdmsr(0xC001001F, msr_low, msr_high);
Martin Roth9b1b3352016-02-24 12:27:06 -0800429}
430
431static void setup_apu(void)
432{
Martin Roth9b1b3352016-02-24 12:27:06 -0800433 ulong msr_low, msr_high;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800434
Martin Roth9b1b3352016-02-24 12:27:06 -0800435 /* Enable ECS */
436 rdmsr(0xC001001F, msr_low, msr_high);
437 wrmsr(0xC001001F, msr_low, (msr_high | 0x4000));
438 rdmsr(0xC001001F, msr_low, msr_high);
Martin Roth9b1b3352016-02-24 12:27:06 -0800439}
440
441/*
442static void poll_amd64(void)
443{
444
445 unsigned long mcanb;
446 unsigned long page, offset;
447 unsigned long celog_syndrome;
448 unsigned long mcanb_add;
449
450 pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
451
452 if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800453 // Find out about the first correctable error
454 // Syndrome code -> bits use a complex matrix. Will add this later
455 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800456 pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
457
Martin Roth4dcd13d2016-02-24 13:53:07 -0800458 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -0800459 celog_syndrome = (mcanb >> 15)&0xFF;
460
Martin Roth4dcd13d2016-02-24 13:53:07 -0800461 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800462 page = (mcanb_add >> 12);
463 offset = (mcanb_add >> 3) & 0xFFF;
464
Martin Roth4dcd13d2016-02-24 13:53:07 -0800465 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800466 print_ecc_err(page, offset, 1, celog_syndrome, 0);
467
Martin Roth4dcd13d2016-02-24 13:53:07 -0800468 // Clear the error registers
Martin Roth9b1b3352016-02-24 12:27:06 -0800469 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
470 }
471 if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800472 // Found out about the first uncorrectable error
473 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800474 pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
475
Martin Roth4dcd13d2016-02-24 13:53:07 -0800476 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800477 page = (mcanb_add >> 12);
478 offset = (mcanb_add >> 3) & 0xFFF;
479
Martin Roth4dcd13d2016-02-24 13:53:07 -0800480 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800481 print_ecc_err(page, offset, 0, 0, 0);
482
Martin Roth4dcd13d2016-02-24 13:53:07 -0800483 // Clear the error registers
Martin Roth9b1b3352016-02-24 12:27:06 -0800484 pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF );
485
486 }
487
488}
489*/
490
491static void setup_amd751(void)
492{
493 unsigned long dram_status;
494
495 /* Fill in the correct memory capabilites */
496 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status);
497 ctrl.cap = ECC_CORRECT;
Ben Gardner90f7d112016-03-15 15:25:22 -0500498 ctrl.mode = (dram_status & (1 << 2)) ? ECC_CORRECT : ECC_NONE;
Martin Roth9b1b3352016-02-24 12:27:06 -0800499}
500
501/*
502static void poll_amd751(void)
503{
504 unsigned long ecc_status;
505 unsigned long bank_addr;
506 unsigned long bank_info;
507 unsigned long page;
508 int bits;
509 int i;
510
Martin Roth4dcd13d2016-02-24 13:53:07 -0800511 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800512 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status);
513 if (ecc_status & (3 << 8)) {
514 for(i = 0; i < 6; i++) {
515 if (!(ecc_status & (1 << i))) {
516 continue;
517 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800518 // Find the bank the error occured on
Martin Roth9b1b3352016-02-24 12:27:06 -0800519 bank_addr = 0x40 + (i << 1);
520
Martin Roth4dcd13d2016-02-24 13:53:07 -0800521 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800522 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info);
523
Martin Roth4dcd13d2016-02-24 13:53:07 -0800524 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800525 page = (bank_info & 0xFF80) << 4;
526 bits = (((ecc_status >> 8) &3) == 2)?1:2;
527
Martin Roth4dcd13d2016-02-24 13:53:07 -0800528 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800529 print_ecc_err(page, 0, bits==1?1:0, 0, 0);
530
531 }
532
Martin Roth4dcd13d2016-02-24 13:53:07 -0800533 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800534 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0);
535 }
536}
537
538// Still waiting for the CORRECT intel datasheet
539static void setup_i85x(void)
540{
541 unsigned long drc;
542 ctrl.cap = ECC_CORRECT;
543
544 pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc);
545 ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE;
546
547}
548*/
549
550static void setup_amd76x(void)
551{
552 static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
553 unsigned long ecc_mode_status;
554
555 /* Fill in the correct memory capabilites */
556 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
557 ctrl.cap = ECC_CORRECT;
558 ctrl.mode = ddim[(ecc_mode_status >> 10)&3];
559}
560
561/*
562static void poll_amd76x(void)
563{
564 unsigned long ecc_mode_status;
565 unsigned long bank_addr;
566 unsigned long bank_info;
567 unsigned long page;
568
569 // Read the error status
570 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
571 // Multibit error
572 if (ecc_mode_status & (1 << 9)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800573 // Find the bank the error occured on
Martin Roth9b1b3352016-02-24 12:27:06 -0800574 bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2);
575
Martin Roth4dcd13d2016-02-24 13:53:07 -0800576 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800577 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
578
Martin Roth4dcd13d2016-02-24 13:53:07 -0800579 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800580 page = (bank_info & 0xFF800000) >> 12;
581
Martin Roth4dcd13d2016-02-24 13:53:07 -0800582 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800583 print_ecc_err(page, 0, 1, 0, 0);
584
585 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800586 // Singlebit error
Martin Roth9b1b3352016-02-24 12:27:06 -0800587 if (ecc_mode_status & (1 << 8)) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800588 // Find the bank the error occured on
Martin Roth9b1b3352016-02-24 12:27:06 -0800589 bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2);
590
Martin Roth4dcd13d2016-02-24 13:53:07 -0800591 // Now get the information on the erroring bank
Martin Roth9b1b3352016-02-24 12:27:06 -0800592 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
593
Martin Roth4dcd13d2016-02-24 13:53:07 -0800594 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800595 page = (bank_info & 0xFF800000) >> 12;
596
Martin Roth4dcd13d2016-02-24 13:53:07 -0800597 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800598 print_ecc_err(page, 0, 0, 0, 0);
599
600 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800601 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800602 if (ecc_mode_status & (3 << 8)) {
603 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status);
604 }
605}
606*/
607
608static void setup_cnb20(void)
609{
610 /* Fill in the correct memory capabilites */
611 ctrl.cap = ECC_CORRECT;
612
613 /* FIXME add ECC error polling. I don't have the documentation
614 * do it right now.
615 */
616}
617
618static void setup_E5400(void)
619{
620 unsigned long mcs;
621
622
623 /* Read the hardware capabilities */
624 pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs);
625
626 /* Fill in the correct memory capabilities */
627 ctrl.mode = 0;
628 ctrl.cap = ECC_SCRUB;
629
630 /* Checking and correcting enabled */
631 if (((mcs >> 5) & 1) == 1) {
632 ctrl.mode |= ECC_CORRECT;
633 }
634
635 /* scrub enabled */
636 if (((mcs >> 7) & 1) == 1) {
637 ctrl.mode |= __ECC_SCRUB;
638 }
639}
640
641
642static void setup_iE7xxx(void)
643{
644 unsigned long mchcfgns;
645 unsigned long drc;
646 unsigned long device;
647 unsigned long dvnp;
648
649 /* Read the hardare capabilities */
650 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns);
651 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
652
653 /* This is a check for E7205 */
654 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device);
655
656 /* Fill in the correct memory capabilities */
657 ctrl.mode = 0;
658 ctrl.cap = ECC_CORRECT;
659
660 /* checking and correcting enabled */
661 if (((drc >> 20) & 3) == 2) {
662 ctrl.mode |= ECC_CORRECT;
663 }
664
665 /* E7205 doesn't support scrubbing */
666 if (device != 0x255d) {
667 /* scrub enabled */
668 /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */
669 ctrl.cap = ECC_SCRUB;
670 if (mchcfgns & 1) {
671 ctrl.mode |= __ECC_SCRUB;
672 }
673
674 /* Now, we can active Dev1/Fun1 */
675 /* Thanks to Tyan for providing us the board to solve this */
676 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp);
Ben Gardner90f7d112016-03-15 15:25:22 -0500677 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, (dvnp & 0xFE));
Martin Roth9b1b3352016-02-24 12:27:06 -0800678
679 /* Clear any routing of ECC errors to interrupts that the BIOS might have set up */
680 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0);
681 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0);
682 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0);
Martin Roth9b1b3352016-02-24 12:27:06 -0800683 }
684
685 /* Clear any prexisting error reports */
686 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3);
687 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -0800688}
689
690static void setup_iE7520(void)
691{
692 unsigned long mchscrb;
693 unsigned long drc;
694 unsigned long dvnp1;
695
696 /* Read the hardare capabilities */
697 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb);
698 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
699
700 /* Fill in the correct memory capabilities */
701 ctrl.mode = 0;
702 ctrl.cap = ECC_CORRECT;
703
704 /* Checking and correcting enabled */
705 if (((drc >> 20) & 3) != 0) {
706 ctrl.mode |= ECC_CORRECT;
707 }
708
709 /* scrub enabled */
710 ctrl.cap = ECC_SCRUB;
711 if ((mchscrb & 3) == 2) {
712 ctrl.mode |= __ECC_SCRUB;
713 }
714
715 /* Now, we can activate Fun1 */
716 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1);
Ben Gardner90f7d112016-03-15 15:25:22 -0500717 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, (dvnp1 | 0x20));
Martin Roth9b1b3352016-02-24 12:27:06 -0800718
719 /* Clear any prexisting error reports */
720 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747);
721 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747);
Martin Roth9b1b3352016-02-24 12:27:06 -0800722}
723
724/*
725static void poll_iE7xxx(void)
726{
727 unsigned long ferr;
728 unsigned long nerr;
729
730 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr);
731 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
732
733 if (ferr & 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800734 // Find out about the first correctable error
Martin Roth9b1b3352016-02-24 12:27:06 -0800735 unsigned long celog_add;
736 unsigned long celog_syndrome;
737 unsigned long page;
738
Martin Roth4dcd13d2016-02-24 13:53:07 -0800739 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800740 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800741 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -0800742 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome);
743
Martin Roth4dcd13d2016-02-24 13:53:07 -0800744 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800745 page = (celog_add & 0x0FFFFFC0) >> 6;
746
Martin Roth4dcd13d2016-02-24 13:53:07 -0800747 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800748 print_ecc_err(page, 0, 1, celog_syndrome, 0);
749
Martin Roth4dcd13d2016-02-24 13:53:07 -0800750 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -0800751 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
752 }
753
754 if (ferr & 2) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800755 // Found out about the first uncorrectable error
Martin Roth9b1b3352016-02-24 12:27:06 -0800756 unsigned long uccelog_add;
757 unsigned long page;
758
Martin Roth4dcd13d2016-02-24 13:53:07 -0800759 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800760 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
761
Martin Roth4dcd13d2016-02-24 13:53:07 -0800762 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800763 page = (uccelog_add & 0x0FFFFFC0) >> 6;
764
Martin Roth4dcd13d2016-02-24 13:53:07 -0800765 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800766 print_ecc_err(page, 0, 0, 0, 0);
767
Martin Roth4dcd13d2016-02-24 13:53:07 -0800768 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -0800769 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
770 }
771
Martin Roth4dcd13d2016-02-24 13:53:07 -0800772 // Check if DRAM_NERR contains data
Martin Roth9b1b3352016-02-24 12:27:06 -0800773 if (nerr & 3) {
774 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
775 }
776
777}
778*/
779
780static void setup_i440gx(void)
781{
782 static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
783 unsigned long nbxcfg;
784
785 /* Fill in the correct memory capabilites */
786 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg);
787 ctrl.cap = ECC_CORRECT;
788 ctrl.mode = ddim[(nbxcfg >> 7)&3];
789}
790
791/*
792static void poll_i440gx(void)
793{
794 unsigned long errsts;
795 unsigned long page;
796 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800797 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800798 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts);
799 if (errsts & 0x11) {
800 unsigned long eap;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800801 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800802 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap);
803
Martin Roth4dcd13d2016-02-24 13:53:07 -0800804 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800805 page = (eap & 0xFFFFF000) >> 12;
806 bits = 0;
807 if (eap &3) {
808 bits = ((eap & 3) == 1)?1:2;
809 }
810
811 if (bits) {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800812 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800813 print_ecc_err(page, 0, bits==1?1:0, 0, 0);
814 }
815
Martin Roth4dcd13d2016-02-24 13:53:07 -0800816 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800817 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11);
818 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3);
819 }
820
821}
822*/
823
824
825static void setup_i840(void)
826{
827 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
828 unsigned long mchcfg;
829
830 /* Fill in the correct memory capabilites */
831 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
832 ctrl.cap = ECC_CORRECT;
833 ctrl.mode = ddim[(mchcfg >> 7)&3];
834}
835
836/*
837static void poll_i840(void)
838{
839 unsigned long errsts;
840 unsigned long page;
841 unsigned long syndrome;
842 int channel;
843 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800844 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800845 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
846 if (errsts & 3) {
847 unsigned long eap;
848 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800849 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -0800850 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
851 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
852
Martin Roth4dcd13d2016-02-24 13:53:07 -0800853 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800854 page = (eap & 0xFFFFF800) >> 11;
855 channel = eap & 1;
856 syndrome = derrctl_sts & 0xFF;
857 bits = ((errsts & 3) == 1)?1:2;
858
Martin Roth4dcd13d2016-02-24 13:53:07 -0800859 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800860 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
861
Martin Roth4dcd13d2016-02-24 13:53:07 -0800862 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800863 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10);
864 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
865 }
866}
867*/
868
869
870static void setup_i875(void)
871{
Martin Roth9b1b3352016-02-24 12:27:06 -0800872 long *ptr;
Ben Gardner90f7d112016-03-15 15:25:22 -0500873 ulong dev0, dev6;
Martin Roth9b1b3352016-02-24 12:27:06 -0800874
875 /* Fill in the correct memory capabilites */
876
877 ctrl.cap = ECC_CORRECT;
878 ctrl.mode = ECC_NONE;
879
880 /* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */
881 /* Activate Device 6 */
882 pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0);
883 pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2));
884
885 /* Activate Device 6 MMR */
886 pci_conf_read( 0, 6, 0, 0x04, 2, &dev6);
887 pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2));
888
889 /* Read the MMR Base Address & Define the pointer*/
890 pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
891 ptr=(long*)(dev6+0x68);
892
893 if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; }
894
895 /* Reseting state */
896 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
897}
898
899static void setup_i925(void)
900{
Martin Roth9b1b3352016-02-24 12:27:06 -0800901 // Activate MMR I/O
902 ulong dev0, drc;
903 unsigned long tolm;
904 long *ptr;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800905
Martin Roth9b1b3352016-02-24 12:27:06 -0800906 pci_conf_read( 0, 0, 0, 0x54, 4, &dev0);
907 dev0 = dev0 | 0x10000000;
908 pci_conf_write( 0, 0, 0, 0x54, 4, dev0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800909
Martin Roth9b1b3352016-02-24 12:27:06 -0800910 // CDH start
911 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
912 if (!(dev0 & 0xFFFFC000)) {
913 pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm);
914 pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8);
915 }
916 // CDH end
917
918 // ECC Checking
919 ctrl.cap = ECC_CORRECT;
920
921 dev0 &= 0xFFFFC000;
922 ptr=(long*)(dev0+0x120);
923 drc = *ptr & 0xFFFFFFFF;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800924
925 if (((drc >> 20) & 3) == 2) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800926 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800927 ctrl.mode = ECC_CORRECT;
928 } else {
929 ctrl.mode = ECC_NONE;
Martin Roth9b1b3352016-02-24 12:27:06 -0800930 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800931}
932
933static void setup_p35(void)
934{
Martin Roth9b1b3352016-02-24 12:27:06 -0800935 // Activate MMR I/O
936 ulong dev0, capid0;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800937
Martin Roth9b1b3352016-02-24 12:27:06 -0800938 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
939 if (!(dev0 & 0x1)) {
940 pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1);
941 }
942
943 // ECC Checking (No poll on X38/48 for now)
944 pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0);
945 if ((capid0 >> 8) & 1) {
946 ctrl.cap = ECC_NONE;
947 } else {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800948 ctrl.cap = ECC_CORRECT;
Martin Roth9b1b3352016-02-24 12:27:06 -0800949 }
950
Martin Roth4dcd13d2016-02-24 13:53:07 -0800951 ctrl.mode = ECC_NONE;
952
Martin Roth9b1b3352016-02-24 12:27:06 -0800953 /*
954 ulong toto;
955 pci_conf_write(0, 31, 3, 0x40, 1, 0x1);
956 pci_conf_read(0, 31, 3, 0x0, 4, &toto);
957 hprint(11,0,toto);
958 pci_conf_read(0, 31, 3, 0x10, 4, &toto);
959 hprint(11,10,toto) ;
960 pci_conf_read(0, 31, 3, 0x20, 4, &toto);
961 hprint(11,20,toto) ;
962 pci_conf_read(0, 28, 0, 0x0, 4, &toto);
963 hprint(11,30,toto);
964 pci_conf_read(0, 31, 0, 0x0, 4, &toto);
965 hprint(11,40,toto) ;
966 pci_conf_read(0, 31, 1, 0x0, 4, &toto);
967 hprint(11,50,toto) ;
968 pci_conf_read(0, 31, 2, 0x0, 4, &toto);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800969 hprint(11,60,toto) ;
Martin Roth9b1b3352016-02-24 12:27:06 -0800970 */
971}
972
973/*
974static void poll_i875(void)
975{
976 unsigned long errsts;
977 unsigned long page;
978 unsigned long des;
979 unsigned long syndrome;
980 int channel;
981 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800982 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -0800983 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
984 if (errsts & 0x81) {
985 unsigned long eap;
986 unsigned long derrsyn;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800987 // Read the error location, syndrome and channel
Martin Roth9b1b3352016-02-24 12:27:06 -0800988 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
989 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn);
990 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des);
991
Martin Roth4dcd13d2016-02-24 13:53:07 -0800992 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -0800993 page = (eap & 0xFFFFF000) >> 12;
994 syndrome = derrsyn;
995 channel = des & 1;
996 bits = (errsts & 0x80)?0:1;
997
Martin Roth4dcd13d2016-02-24 13:53:07 -0800998 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -0800999 print_ecc_err(page, 0, bits, syndrome, channel);
1000
Martin Roth4dcd13d2016-02-24 13:53:07 -08001001 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001002 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
1003 }
1004}
1005*/
1006
1007static void setup_i845(void)
1008{
1009 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1010 unsigned long drc;
1011
Martin Roth4dcd13d2016-02-24 13:53:07 -08001012 // Fill in the correct memory capabilites
Martin Roth9b1b3352016-02-24 12:27:06 -08001013 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
1014 ctrl.cap = ECC_CORRECT;
1015 ctrl.mode = ddim[(drc >> 20)&3];
1016}
1017
1018/*
1019static void poll_i845(void)
1020{
1021 unsigned long errsts;
1022 unsigned long page, offset;
1023 unsigned long syndrome;
1024 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001025 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001026 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1027 if (errsts & 3) {
1028 unsigned long eap;
1029 unsigned long derrsyn;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001030 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001031 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap);
1032 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn);
1033
Martin Roth4dcd13d2016-02-24 13:53:07 -08001034 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001035 offset = (eap & 0xFE) << 4;
1036 page = (eap & 0x3FFFFFFE) >> 8;
1037 syndrome = derrsyn;
1038 bits = ((errsts & 3) == 1)?1:2;
1039
Martin Roth4dcd13d2016-02-24 13:53:07 -08001040 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001041 print_ecc_err(page, offset, bits==1?1:0, syndrome, 0);
1042
Martin Roth4dcd13d2016-02-24 13:53:07 -08001043 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001044 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
1045 }
1046}
1047*/
1048
1049
1050static void setup_i820(void)
1051{
1052 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
1053 unsigned long mchcfg;
1054
Martin Roth4dcd13d2016-02-24 13:53:07 -08001055 // Fill in the correct memory capabilites
Martin Roth9b1b3352016-02-24 12:27:06 -08001056 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg);
1057 ctrl.cap = ECC_CORRECT;
1058 ctrl.mode = ddim[(mchcfg >> 7)&3];
1059}
1060
1061/*
1062static void poll_i820(void)
1063{
1064 unsigned long errsts;
1065 unsigned long page;
1066 unsigned long syndrome;
1067 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001068 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001069 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1070 if (errsts & 3) {
1071 unsigned long eap;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001072 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001073 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap);
1074
Martin Roth4dcd13d2016-02-24 13:53:07 -08001075 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001076 page = (eap & 0xFFFFF000) >> 4;
1077 syndrome = eap & 0xFF;
1078 bits = ((errsts & 3) == 1)?1:2;
1079
Martin Roth4dcd13d2016-02-24 13:53:07 -08001080 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001081 print_ecc_err(page, 0, bits==1?1:0, syndrome, 0);
1082
Martin Roth4dcd13d2016-02-24 13:53:07 -08001083 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001084 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
1085 }
1086}
1087*/
1088
1089static void setup_i850(void)
1090{
1091 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1092 unsigned long mchcfg;
1093
Martin Roth4dcd13d2016-02-24 13:53:07 -08001094 // Fill in the correct memory capabilites
Martin Roth9b1b3352016-02-24 12:27:06 -08001095 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
1096 ctrl.cap = ECC_CORRECT;
1097 ctrl.mode = ddim[(mchcfg >> 7)&3];
1098}
1099
1100/*
1101static void poll_i850(void)
1102{
1103 unsigned long errsts;
1104 unsigned long page;
1105 unsigned long syndrome;
1106 int channel;
1107 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001108 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001109 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1110 if (errsts & 3) {
1111 unsigned long eap;
1112 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001113 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001114 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
1115 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
1116
Martin Roth4dcd13d2016-02-24 13:53:07 -08001117 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001118 page = (eap & 0xFFFFF800) >> 11;
1119 channel = eap & 1;
1120 syndrome = derrctl_sts & 0xFF;
1121 bits = ((errsts & 3) == 1)?1:2;
1122
Martin Roth4dcd13d2016-02-24 13:53:07 -08001123 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001124 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
1125
Martin Roth4dcd13d2016-02-24 13:53:07 -08001126 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001127 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1128 }
1129}
1130*/
1131
1132static void setup_i860(void)
1133{
1134 static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
1135 unsigned long mchcfg;
1136 unsigned long errsts;
1137
Martin Roth4dcd13d2016-02-24 13:53:07 -08001138 // Fill in the correct memory capabilites
Martin Roth9b1b3352016-02-24 12:27:06 -08001139 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
1140 ctrl.cap = ECC_CORRECT;
1141 ctrl.mode = ddim[(mchcfg >> 7)&3];
1142
Martin Roth4dcd13d2016-02-24 13:53:07 -08001143 // Clear any prexisting error reports
Martin Roth9b1b3352016-02-24 12:27:06 -08001144 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1145 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1146}
1147
1148/*
1149static void poll_i860(void)
1150{
1151 unsigned long errsts;
1152 unsigned long page;
1153 unsigned char syndrome;
1154 int channel;
1155 int bits;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001156 // Read the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001157 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
1158 if (errsts & 3) {
1159 unsigned long eap;
1160 unsigned long derrctl_sts;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001161 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001162 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
1163 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
1164
Martin Roth4dcd13d2016-02-24 13:53:07 -08001165 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001166 page = (eap & 0xFFFFFE00) >> 9;
1167 channel = eap & 1;
1168 syndrome = derrctl_sts & 0xFF;
1169 bits = ((errsts & 3) == 1)?1:2;
1170
Martin Roth4dcd13d2016-02-24 13:53:07 -08001171 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001172 print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
1173
Martin Roth4dcd13d2016-02-24 13:53:07 -08001174 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001175 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1176 }
1177}
1178
1179
1180static void poll_iE7221(void)
1181{
1182 unsigned long errsts;
1183 unsigned long page;
1184 unsigned char syndrome;
1185 int channel;
1186 int bits;
1187 int errocc;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001188
Martin Roth9b1b3352016-02-24 12:27:06 -08001189 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001190
Martin Roth9b1b3352016-02-24 12:27:06 -08001191 errocc = errsts & 3;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001192
Martin Roth9b1b3352016-02-24 12:27:06 -08001193 if ((errocc == 1) || (errocc == 2)) {
1194 unsigned long eap, offset;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001195 unsigned long derrctl_sts;
1196
1197 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001198 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001199 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts);
1200
1201 // Parse the error location and error type
Martin Roth9b1b3352016-02-24 12:27:06 -08001202 channel = eap & 1;
1203 eap = eap & 0xFFFFFF80;
1204 page = eap >> 12;
1205 offset = eap & 0xFFF;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001206 syndrome = derrctl_sts & 0xFF;
Martin Roth9b1b3352016-02-24 12:27:06 -08001207 bits = errocc & 1;
1208
Martin Roth4dcd13d2016-02-24 13:53:07 -08001209 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001210 print_ecc_err(page, offset, bits, syndrome, channel);
1211
Martin Roth4dcd13d2016-02-24 13:53:07 -08001212 // Clear the error status
Martin Roth9b1b3352016-02-24 12:27:06 -08001213 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001214 }
1215
Martin Roth9b1b3352016-02-24 12:27:06 -08001216 else if (errocc == 3) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001217
1218 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
1219
Martin Roth9b1b3352016-02-24 12:27:06 -08001220 }
1221}
1222
1223
1224static void poll_iE7520(void)
1225{
1226 unsigned long ferr;
1227 unsigned long nerr;
1228
1229 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr);
1230 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr);
1231
1232 if (ferr & 0x0101) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001233 // Find out about the first correctable error
Martin Roth9b1b3352016-02-24 12:27:06 -08001234 unsigned long celog_add;
1235 unsigned long celog_syndrome;
1236 unsigned long page;
1237
Martin Roth4dcd13d2016-02-24 13:53:07 -08001238 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001239 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001240 // Read the syndrome
Martin Roth9b1b3352016-02-24 12:27:06 -08001241 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome);
1242
Martin Roth4dcd13d2016-02-24 13:53:07 -08001243 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001244 page = (celog_add & 0x7FFFFFFC) >> 2;
1245
Martin Roth4dcd13d2016-02-24 13:53:07 -08001246 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001247 print_ecc_err(page, 0, 1, celog_syndrome, 0);
1248
Martin Roth4dcd13d2016-02-24 13:53:07 -08001249 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -08001250 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101);
1251 }
1252
1253 if (ferr & 0x4646) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001254 // Found out about the first uncorrectable error
Martin Roth9b1b3352016-02-24 12:27:06 -08001255 unsigned long uccelog_add;
1256 unsigned long page;
1257
Martin Roth4dcd13d2016-02-24 13:53:07 -08001258 // Read the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001259 pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add);
1260
Martin Roth4dcd13d2016-02-24 13:53:07 -08001261 // Parse the error location
Martin Roth9b1b3352016-02-24 12:27:06 -08001262 page = (uccelog_add & 0x7FFFFFFC) >> 2;
1263
Martin Roth4dcd13d2016-02-24 13:53:07 -08001264 // Report the error
Martin Roth9b1b3352016-02-24 12:27:06 -08001265 print_ecc_err(page, 0, 0, 0, 0);
1266
Martin Roth4dcd13d2016-02-24 13:53:07 -08001267 // Clear Bit
Martin Roth9b1b3352016-02-24 12:27:06 -08001268 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646);
1269 }
1270
Martin Roth4dcd13d2016-02-24 13:53:07 -08001271 // Check if DRAM_NERR contains data
Martin Roth9b1b3352016-02-24 12:27:06 -08001272 if (nerr & 0x4747) {
1273 pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747);
1274 }
1275}
1276*/
1277
1278
1279
1280/* ----------------- Here's the code for FSB detection ----------------- */
1281/* --------------------------------------------------------------------- */
1282
1283static 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};
1284static 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};
1285static float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
1286
1287static float getP4PMmultiplier(void)
1288{
1289 //unsigned int msr_lo, msr_hi;
1290 int msr_lo, msr_hi;
1291 float coef;
1292
Martin Roth4dcd13d2016-02-24 13:53:07 -08001293
Martin Roth9b1b3352016-02-24 12:27:06 -08001294 /* Find multiplier (by MSR) */
Ben Gardner90f7d112016-03-15 15:25:22 -05001295 if (cpu_id.vers.bits.family == 6) {
1296 if (cpu_id.fid.bits.eist & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001297 rdmsr(0x198, msr_lo, msr_hi);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001298 coef = ((msr_lo) >> 8) & 0x1F;
1299 if ((msr_lo >> 14) & 0x1) { coef += 0.5f; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001300 // Atom Fix
Ben Gardner90f7d112016-03-15 15:25:22 -05001301 if (coef == 6) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001302 coef = ((msr_hi) >> 8) & 0x1F;
1303 if ((msr_hi >> 14) & 0x1) { coef += 0.5f; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001304 }
1305 } else {
1306 rdmsr(0x2A, msr_lo, msr_hi);
1307 coef = (msr_lo >> 22) & 0x1F;
1308 }
Ben Gardner90f7d112016-03-15 15:25:22 -05001309 } else {
1310 if (cpu_id.vers.bits.model < 2) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001311 rdmsr(0x2A, msr_lo, msr_hi);
1312 coef = (msr_lo >> 8) & 0xF;
1313 coef = p4model1ratios[(int)coef];
Ben Gardner90f7d112016-03-15 15:25:22 -05001314 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -08001315 rdmsr(0x2C, msr_lo, msr_hi);
1316 coef = (msr_lo >> 24) & 0x1F;
1317 }
1318 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001319
Martin Roth9b1b3352016-02-24 12:27:06 -08001320 return coef;
1321}
1322
1323static float getNHMmultiplier(void)
1324{
1325 unsigned int msr_lo, msr_hi;
1326 float coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001327
Martin Roth9b1b3352016-02-24 12:27:06 -08001328 /* Find multiplier (by MSR) */
1329 /* First, check if Flexible Ratio is Enabled */
1330 rdmsr(0x194, msr_lo, msr_hi);
Ben Gardner90f7d112016-03-15 15:25:22 -05001331 if ((msr_lo >> 16) & 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001332 coef = (msr_lo >> 8) & 0xFF;
Ben Gardner90f7d112016-03-15 15:25:22 -05001333 } else {
Martin Roth9b1b3352016-02-24 12:27:06 -08001334 rdmsr(0xCE, msr_lo, msr_hi);
1335 coef = (msr_lo >> 8) & 0xFF;
Ben Gardner90f7d112016-03-15 15:25:22 -05001336 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001337
1338 return coef;
1339}
Ben Gardner90f7d112016-03-15 15:25:22 -05001340
Martin Roth9b1b3352016-02-24 12:27:06 -08001341static float getSNBmultiplier(void)
1342{
1343 unsigned int msr_lo, msr_hi;
1344 float coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001345
Martin Roth9b1b3352016-02-24 12:27:06 -08001346 rdmsr(0xCE, msr_lo, msr_hi);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001347 coef = (msr_lo >> 8) & 0xFF;
Martin Roth9b1b3352016-02-24 12:27:06 -08001348
1349 return coef;
1350}
1351
Martin Roth4dcd13d2016-02-24 13:53:07 -08001352static void poll_fsb_ct(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001353{
1354 unsigned long mcr, mdr;
1355 double dramratio, dramclock, fsb;
1356 float coef = getP4PMmultiplier();
1357
1358 /* Build the MCR Message*/
1359 mcr = (0x10 << 24); // 10h = Read - 11h = Write
1360 mcr += (0x01 << 16); // DRAM Registers located on port 01h
1361 mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h
Martin Roth4dcd13d2016-02-24 13:53:07 -08001362 mcr &= 0xFFFFFFF0; // bit 03:00 RSVD
1363
Martin Roth9b1b3352016-02-24 12:27:06 -08001364 /* Send Message to GMCH */
Martin Roth4dcd13d2016-02-24 13:53:07 -08001365 pci_conf_write(0, 0, 0, 0xD0, 4, mcr);
1366
Martin Roth9b1b3352016-02-24 12:27:06 -08001367 /* Read Answer from Sideband bus */
Martin Roth4dcd13d2016-02-24 13:53:07 -08001368 pci_conf_read(0, 0, 0, 0xD4, 4, &mdr);
1369
Martin Roth9b1b3352016-02-24 12:27:06 -08001370 /* Get RAM ratio */
1371 switch (mdr & 0x3) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001372 default:
1373 case 0: dramratio = 3.0f; break;
1374 case 1: dramratio = 4.0f; break;
1375 case 2: dramratio = 5.0f; break;
1376 case 3: dramratio = 6.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001377 }
1378
1379 // Compute FSB & RAM Frequency
1380 fsb = ((extclock / 1000) / coef);
1381 dramclock = fsb * dramratio;
1382
1383 // Print'em all. Whoa !
1384 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001385}
1386
Ben Gardner90f7d112016-03-15 15:25:22 -05001387static void poll_fsb_amd64(void)
1388{
Martin Roth9b1b3352016-02-24 12:27:06 -08001389 unsigned int mcgsrl;
1390 unsigned int mcgsth;
1391 unsigned long fid, temp2;
1392 unsigned long dramchr;
1393 float clockratio;
1394 double dramclock;
Martin Roth869474b2016-02-24 13:47:46 -08001395 unsigned int dummy[4];
Martin Roth9b1b3352016-02-24 12:27:06 -08001396 int ram_type;
1397
1398 float coef = 10;
1399
1400 cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]);
1401
1402 /* First, got the FID by MSR */
1403 /* First look if Cool 'n Quiet is supported to choose the best msr */
1404 if (((dummy[3] >> 1) & 1) == 1) {
1405 rdmsr(0xc0010042, mcgsrl, mcgsth);
1406 fid = (mcgsrl & 0x3F);
1407 } else {
1408 rdmsr(0xc0010015, mcgsrl, mcgsth);
1409 fid = ((mcgsrl >> 24)& 0x3F);
1410 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001411
Martin Roth9b1b3352016-02-24 12:27:06 -08001412 /* Extreme simplification. */
1413 coef = ( fid / 2 ) + 4.0;
1414
1415 /* Support for .5 coef */
1416 if (fid & 1) { coef = coef + 0.5; }
1417
1418 /* Next, we need the clock ratio */
1419 if (cpu_id.vers.bits.extendedModel >= 4) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001420 /* K8 0FH */
Martin Roth9b1b3352016-02-24 12:27:06 -08001421 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1422 temp2 = (dramchr & 0x7);
1423 clockratio = coef;
1424 ram_type = 2;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001425
Martin Roth9b1b3352016-02-24 12:27:06 -08001426 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001427 case 0x0:
1428 clockratio = (int)(coef);
1429 break;
1430 case 0x1:
1431 clockratio = (int)(coef * 3.0f/4.0f);
1432 break;
1433 case 0x2:
1434 clockratio = (int)(coef * 3.0f/5.0f);
1435 break;
1436 case 0x3:
1437 clockratio = (int)(coef * 3.0f/6.0f);
1438 break;
1439 }
1440 } else {
1441 /* OLD K8 */
Martin Roth9b1b3352016-02-24 12:27:06 -08001442 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1443 temp2 = (dramchr >> 20) & 0x7;
1444 ram_type = 1;
1445 clockratio = coef;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001446
Martin Roth9b1b3352016-02-24 12:27:06 -08001447 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001448 case 0x0:
1449 clockratio = (int)(coef * 2.0f);
1450 break;
1451 case 0x2:
1452 clockratio = (int)((coef * 3.0f/2.0f) + 0.81f);
1453 break;
1454 case 0x4:
1455 clockratio = (int)((coef * 4.0f/3.0f) + 0.81f);
1456 break;
1457 case 0x5:
1458 clockratio = (int)((coef * 6.0f/5.0f) + 0.81f);
1459 break;
1460 case 0x6:
1461 clockratio = (int)((coef * 10.0f/9.0f) + 0.81f);
1462 break;
1463 case 0x7:
1464 clockratio = (int)(coef + 0.81f);
1465 break;
1466 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001467 }
1468
1469 /* Compute the final DRAM Clock */
1470 dramclock = (extclock / 1000) / clockratio;
1471
1472 /* ...and print */
1473 print_cpu_line(dramclock, (extclock / 1000 / coef), ram_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001474}
1475
Ben Gardner90f7d112016-03-15 15:25:22 -05001476static void poll_fsb_k10(void)
1477{
Martin Roth9b1b3352016-02-24 12:27:06 -08001478 unsigned int mcgsrl;
1479 unsigned int mcgsth;
1480 unsigned long temp2;
1481 unsigned long dramchr;
1482 unsigned long mainPllId;
1483 double dramclock;
1484 ulong offset = 0;
1485 int ram_type = 2;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001486
Ben Gardner90f7d112016-03-15 15:25:22 -05001487 /* First, we need the clock ratio */
1488 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1489 temp2 = (dramchr & 0x7);
Martin Roth9b1b3352016-02-24 12:27:06 -08001490
Ben Gardner90f7d112016-03-15 15:25:22 -05001491 switch (temp2) {
1492 case 0x7: temp2++;
1493 case 0x6: temp2++;
1494 case 0x5: temp2++;
1495 case 0x4: temp2++;
1496 default: temp2 += 3;
1497 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001498
1499 /* Compute the final DRAM Clock */
Martin Roth04f7f142016-03-27 21:04:00 -06001500 if (cpu_id.vers.bits.extendedModel == 1) {
Martin Roth9b1b3352016-02-24 12:27:06 -08001501 dramclock = ((temp2 * 200) / 3.0) + 0.25;
1502 } else {
1503 unsigned long target;
1504 unsigned long dx;
1505 unsigned divisor;
1506
1507 target = temp2 * 400;
1508
1509 /* Get the FID by MSR */
1510 rdmsr(0xc0010071, mcgsrl, mcgsth);
1511
1512 pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId);
1513
Ben Gardner90f7d112016-03-15 15:25:22 -05001514 if (mainPllId & 0x40)
Martin Roth9b1b3352016-02-24 12:27:06 -08001515 mainPllId &= 0x3F;
1516 else
Ben Gardner90f7d112016-03-15 15:25:22 -05001517 mainPllId = 8; /* FID for 1600 */
Martin Roth9b1b3352016-02-24 12:27:06 -08001518
1519 mcgsth = (mcgsth >> 17) & 0x3F;
Ben Gardner90f7d112016-03-15 15:25:22 -05001520 if (mcgsth) {
1521 if (mainPllId > mcgsth)
Martin Roth9b1b3352016-02-24 12:27:06 -08001522 mainPllId = mcgsth;
1523 }
1524
1525 dx = (mainPllId + 8) * 1200;
Ben Gardner90f7d112016-03-15 15:25:22 -05001526 for (divisor = 3; divisor < 100; divisor++)
1527 if ( (dx / divisor) <= target)
Martin Roth9b1b3352016-02-24 12:27:06 -08001528 break;
1529
Martin Roth4dcd13d2016-02-24 13:53:07 -08001530
Ben Gardner90f7d112016-03-15 15:25:22 -05001531 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001532
Ben Gardner90f7d112016-03-15 15:25:22 -05001533 // If Channel A not enabled, switch to channel B
1534 if (((dramchr>>14) & 0x1)) {
1535 offset = 0x100;
1536 pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr);
1537 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001538
Ben Gardner90f7d112016-03-15 15:25:22 -05001539 //DDR2 or DDR3
1540 if ((dramchr >> 8)&1) {
1541 ram_type = 3;
1542 } else {
1543 ram_type = 2;
1544 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001545
Martin Roth9b1b3352016-02-24 12:27:06 -08001546 dramclock = ((dx / divisor) / 6.0) + 0.25;
Ben Gardner90f7d112016-03-15 15:25:22 -05001547 }
Martin Roth9b1b3352016-02-24 12:27:06 -08001548
1549 /* ...and print */
1550 print_cpu_line(dramclock, 0, ram_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001551}
1552
Ben Gardner90f7d112016-03-15 15:25:22 -05001553static void poll_fsb_k12(void)
1554{
Martin Roth9b1b3352016-02-24 12:27:06 -08001555 unsigned long temp2;
1556 unsigned long dramchr;
1557 double dramratio, dramclock, fsb, did;
Ben Gardner90f7d112016-03-15 15:25:22 -05001558 unsigned int mcgsrl, mcgsth, fid, did_raw;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001559
Martin Roth9b1b3352016-02-24 12:27:06 -08001560 // Get current FID & DID
Ben Gardner90f7d112016-03-15 15:25:22 -05001561 rdmsr(0xc0010071, mcgsrl, mcgsth);
1562 did_raw = mcgsrl & 0xF;
1563 fid = (mcgsrl >> 4) & 0xF;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001564
Ben Gardner90f7d112016-03-15 15:25:22 -05001565 switch (did_raw) {
1566 default:
1567 case 0x0:
1568 did = 1.0f;
1569 break;
1570 case 0x1:
1571 did = 1.5f;
1572 break;
1573 case 0x2:
1574 did = 2.0f;
1575 break;
1576 case 0x3:
1577 did = 3.0f;
1578 break;
1579 case 0x4:
1580 did = 4.0f;
1581 break;
1582 case 0x5:
1583 did = 6.0f;
1584 break;
1585 case 0x6:
1586 did = 8.0f;
1587 break;
1588 case 0x7:
1589 did = 12.0f;
1590 break;
1591 case 0x8:
1592 did = 16.0f;
1593 break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001594 }
1595
Ben Gardner90f7d112016-03-15 15:25:22 -05001596 fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did));
Martin Roth4dcd13d2016-02-24 13:53:07 -08001597
Martin Roth9b1b3352016-02-24 12:27:06 -08001598 /* Finaly, we need the clock ratio */
1599 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001600
Ben Gardner90f7d112016-03-15 15:25:22 -05001601 if (((dramchr >> 14) & 0x1) == 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001602 pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
Martin Roth9b1b3352016-02-24 12:27:06 -08001603 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001604
Martin Roth9b1b3352016-02-24 12:27:06 -08001605 temp2 = (dramchr & 0x1F);
1606
1607 switch (temp2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001608 default:
1609 case 0x06:
1610 dramratio = 4.0f;
1611 break;
1612 case 0x0A:
1613 dramratio = 16.0f / 3.0f;
1614 break;
1615 case 0x0E:
1616 dramratio = 20.0f / 3.0f;
1617 break;
1618 case 0x12:
1619 dramratio = 8.0f;
1620 break;
1621 case 0x16:
1622 dramratio = 28.0f / 3.0f;
1623 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001624 }
1625
Martin Roth9b1b3352016-02-24 12:27:06 -08001626 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001627
Martin Roth9b1b3352016-02-24 12:27:06 -08001628 /* print */
1629 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001630}
1631
Martin Roth4dcd13d2016-02-24 13:53:07 -08001632static void poll_fsb_k16(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001633{
Martin Roth9b1b3352016-02-24 12:27:06 -08001634 unsigned long dramchr;
1635 double dramratio, dramclock, fsb;
1636
Martin Roth4dcd13d2016-02-24 13:53:07 -08001637 // FIXME: Unable to find a real way to detect multiplier.
Martin Roth9b1b3352016-02-24 12:27:06 -08001638 fsb = 100.0f;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001639
Martin Roth9b1b3352016-02-24 12:27:06 -08001640 /* Clock ratio */
1641 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1642
1643 switch (dramchr & 0x1F) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001644 default:
1645 case 0x04: /* 333 */
1646 dramratio = 10.0f / 3.0f;
1647 break;
1648 case 0x06: /* 400 */
1649 dramratio = 4.0f;
1650 break;
1651 case 0x0A: /* 533 */
1652 dramratio = 16.0f / 3.0f;
1653 break;
1654 case 0x0E: /* 667 */
1655 dramratio = 20.0f / 3.0f;
1656 break;
1657 case 0x12: /* 800 */
1658 dramratio = 8.0f;
1659 break;
1660 case 0x16: /* 933 */
1661 dramratio = 28.0f / 3.0f;
1662 break;
1663 case 0x19: /* 1050 */
1664 dramratio = 21.0f / 2.0f;
1665 break;
1666 case 0x1A: /* 1066 */
1667 dramratio = 32.0f / 3.0f;
1668 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001669 }
1670
Martin Roth9b1b3352016-02-24 12:27:06 -08001671 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001672
Martin Roth9b1b3352016-02-24 12:27:06 -08001673 /* print */
1674 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001675}
1676
Ben Gardner90f7d112016-03-15 15:25:22 -05001677static void poll_fsb_k15(void)
1678{
Martin Roth9b1b3352016-02-24 12:27:06 -08001679 unsigned long temp2;
1680 unsigned long dramchr;
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001681 double dramclock, fsb;
Ben Gardner90f7d112016-03-15 15:25:22 -05001682 unsigned int mcgsrl, mcgsth, fid, did;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001683
Martin Roth9b1b3352016-02-24 12:27:06 -08001684 // Get current FID & DID
Ben Gardner90f7d112016-03-15 15:25:22 -05001685 rdmsr(0xc0010071, mcgsrl, mcgsth);
1686 fid = mcgsrl & 0x3F;
1687 did = (mcgsrl >> 6) & 0x7;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001688
Ben Gardner90f7d112016-03-15 15:25:22 -05001689 fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001690
Martin Roth9b1b3352016-02-24 12:27:06 -08001691 /* Finaly, we need the clock ratio */
1692 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001693
Ben Gardner90f7d112016-03-15 15:25:22 -05001694 if (((dramchr >> 14) & 0x1) == 1) {
Martin Roth4dcd13d2016-02-24 13:53:07 -08001695 pci_conf_read(0, 24, 2, 0x194, 4, &dramchr);
Martin Roth9b1b3352016-02-24 12:27:06 -08001696 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001697
Martin Roth9b1b3352016-02-24 12:27:06 -08001698 temp2 = (dramchr & 0x1F);
1699
1700 switch (temp2) {
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001701 case 0x02:
1702 dramclock = 200;
Ben Gardner90f7d112016-03-15 15:25:22 -05001703 break;
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001704 case 0x04:
1705 dramclock = 333;
1706 break;
Ben Gardner90f7d112016-03-15 15:25:22 -05001707 case 0x06:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001708 dramclock = 400;
Ben Gardner90f7d112016-03-15 15:25:22 -05001709 break;
1710 case 0x0A:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001711 dramclock = 533;
Ben Gardner90f7d112016-03-15 15:25:22 -05001712 break;
1713 case 0x0E:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001714 dramclock = 667;
Ben Gardner90f7d112016-03-15 15:25:22 -05001715 break;
1716 case 0x12:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001717 dramclock = 800;
Ben Gardner90f7d112016-03-15 15:25:22 -05001718 break;
1719 case 0x16:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001720 dramclock = 933;
Ben Gardner90f7d112016-03-15 15:25:22 -05001721 break;
1722 case 0x1A:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001723 dramclock = 1066;
Ben Gardner90f7d112016-03-15 15:25:22 -05001724 break;
1725 case 0x1F:
Ricardo Ribalda Delgadoa235b0b2017-01-10 16:59:32 +01001726 dramclock = 1200;
1727 break;
1728 default:
1729 dramclock = 0;
Ben Gardner90f7d112016-03-15 15:25:22 -05001730 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001731 }
1732
Martin Roth9b1b3352016-02-24 12:27:06 -08001733 /* print */
1734 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001735}
1736
Martin Roth4dcd13d2016-02-24 13:53:07 -08001737static void poll_fsb_k14(void)
Martin Roth9b1b3352016-02-24 12:27:06 -08001738{
Martin Roth9b1b3352016-02-24 12:27:06 -08001739 unsigned long dramchr;
1740 double dramratio, dramclock, fsb;
1741
Martin Roth4dcd13d2016-02-24 13:53:07 -08001742 // FIXME: Unable to find a real way to detect multiplier.
Ben Gardner90f7d112016-03-15 15:25:22 -05001743 fsb = 100.0f;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001744
Martin Roth9b1b3352016-02-24 12:27:06 -08001745 /* Clock ratio */
1746 pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
1747
1748 switch (dramchr & 0x1F) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001749 default:
1750 case 0x06:
1751 dramratio = 4.0f;
1752 break;
1753 case 0x0A:
1754 dramratio = 16.0f / 3.0f;
1755 break;
1756 case 0x0E:
1757 dramratio = 20.0f / 3.0f;
1758 break;
1759 case 0x12:
1760 dramratio = 8.0f;
1761 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001762 }
1763
Martin Roth9b1b3352016-02-24 12:27:06 -08001764 dramclock = fsb * dramratio;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001765
Martin Roth9b1b3352016-02-24 12:27:06 -08001766 /* print */
1767 print_cpu_line(dramclock, fsb, 3);
Martin Roth9b1b3352016-02-24 12:27:06 -08001768}
1769
1770
Ben Gardner90f7d112016-03-15 15:25:22 -05001771static void poll_fsb_i925(void)
1772{
Martin Roth9b1b3352016-02-24 12:27:06 -08001773 double dramclock, dramratio, fsb;
1774 unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
1775 float coef = getP4PMmultiplier();
1776 long *ptr;
1777 int ddr_type;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001778
Martin Roth9b1b3352016-02-24 12:27:06 -08001779 pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
Martin Roth4dcd13d2016-02-24 13:53:07 -08001780
Martin Roth9b1b3352016-02-24 12:27:06 -08001781 /* Find dramratio */
1782 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1783 dev0 = dev0 & 0xFFFFC000;
1784 ptr=(long*)(dev0+0xC00);
1785 mchcfg = *ptr & 0xFFFF;
1786 ptr=(long*)(dev0+0x120);
1787 drc = *ptr & 0xFFFF;
1788 dramratio = 1;
1789
1790 mchcfg2 = (mchcfg >> 4)&3;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001791
Martin Roth9b1b3352016-02-24 12:27:06 -08001792 if ((drc&3) != 2) {
1793 // We are in DDR1 Mode
1794 if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; }
1795 ddr_type = 1;
1796 } else {
1797 // We are in DDR2 Mode
1798 ddr_type = 2;
1799 if ((mchcfg >> 2)&1) {
1800 // We are in FSB1066 Mode
1801 if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; }
1802 } else {
1803 switch (mchcfg2) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001804 case 1:
1805 dramratio = 0.66667;
1806 break;
1807 case 2:
1808 if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; }
1809 break;
1810 case 3:
1811 // Checking for FSB533 Mode & Alviso
1812 if ((mchcfg & 1) == 0) { dramratio = 1.33334; }
1813 else if (idetect == 0x2590) { dramratio = 2; }
1814 else { dramratio = 1.5; }
Martin Roth9b1b3352016-02-24 12:27:06 -08001815 }
1816 }
1817 }
Martin Roth4dcd13d2016-02-24 13:53:07 -08001818 // Compute RAM Frequency
Martin Roth9b1b3352016-02-24 12:27:06 -08001819 fsb = ((extclock / 1000) / coef);
1820 dramclock = fsb * dramratio;
1821
Martin Roth4dcd13d2016-02-24 13:53:07 -08001822
Martin Roth9b1b3352016-02-24 12:27:06 -08001823 print_cpu_line(dramclock, fsb, ddr_type);
Martin Roth9b1b3352016-02-24 12:27:06 -08001824}
1825
Ben Gardner90f7d112016-03-15 15:25:22 -05001826static void poll_fsb_i945(void)
1827{
Martin Roth9b1b3352016-02-24 12:27:06 -08001828 double dramclock, dramratio, fsb;
1829 unsigned long mchcfg, dev0;
1830 float coef = getP4PMmultiplier();
1831 long *ptr;
1832
1833 /* Find dramratio */
1834 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1835 dev0 &= 0xFFFFC000;
1836 ptr=(long*)(dev0+0xC00);
1837 mchcfg = *ptr & 0xFFFF;
1838 dramratio = 1;
1839
1840 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001841 case 1: dramratio = 1.0; break;
1842 case 2: dramratio = 1.33334; break;
1843 case 3: dramratio = 1.66667; break;
1844 case 4: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001845 }
1846
1847 // Compute RAM Frequency
1848 fsb = ((extclock / 1000) / coef);
1849
1850 dramclock = fsb * dramratio;
1851
1852 // Print
1853 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001854}
1855
Ben Gardner90f7d112016-03-15 15:25:22 -05001856static void poll_fsb_i945gme(void)
1857{
Martin Roth9b1b3352016-02-24 12:27:06 -08001858 double dramclock, dramratio, fsb;
1859 unsigned long mchcfg, dev0, fsb_mch;
1860 float coef = getP4PMmultiplier();
1861 long *ptr;
1862
1863 /* Find dramratio */
1864 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1865 dev0 &= 0xFFFFC000;
1866 ptr=(long*)(dev0+0xC00);
1867 mchcfg = *ptr & 0xFFFF;
1868 dramratio = 1;
1869
1870 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001871 case 0: fsb_mch = 400; break;
1872 default:
1873 case 1: fsb_mch = 533; break;
1874 case 2: fsb_mch = 667; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001875 }
1876
1877
1878 switch (fsb_mch) {
1879 case 400:
1880 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001881 case 2: dramratio = 1.0f; break;
1882 case 3: dramratio = 4.0f/3.0f; break;
1883 case 4: dramratio = 5.0f/3.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001884 }
1885 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001886
Martin Roth9b1b3352016-02-24 12:27:06 -08001887 default:
1888 case 533:
1889 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001890 case 2: dramratio = 3.0f/4.0f; break;
1891 case 3: dramratio = 1.0f; break;
1892 case 4: dramratio = 5.0f/4.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001893 }
1894 break;
1895
1896 case 667:
1897 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001898 case 2: dramratio = 3.0f/5.0f; break;
1899 case 3: dramratio = 4.0f/5.0f; break;
1900 case 4: dramratio = 1.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001901 }
1902 break;
1903 }
1904
1905 // Compute RAM Frequency
1906 fsb = ((extclock / 1000) / coef);
1907 dramclock = fsb * dramratio * 2;
1908
1909 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001910}
1911
1912
Ben Gardner90f7d112016-03-15 15:25:22 -05001913static void poll_fsb_i975(void)
1914{
Martin Roth9b1b3352016-02-24 12:27:06 -08001915 double dramclock, dramratio, fsb;
1916 unsigned long mchcfg, dev0, fsb_mch;
1917 float coef = getP4PMmultiplier();
1918 long *ptr;
1919
1920 /* Find dramratio */
1921 pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
1922 dev0 &= 0xFFFFC000;
1923 ptr=(long*)(dev0+0xC00);
1924 mchcfg = *ptr & 0xFFFF;
1925 dramratio = 1;
1926
1927 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001928 case 1: fsb_mch = 533; break;
1929 case 2: fsb_mch = 800; break;
1930 case 3: fsb_mch = 667; break;
1931 default: fsb_mch = 1066; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001932 }
1933
1934
1935 switch (fsb_mch) {
1936 case 533:
1937 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001938 case 0: dramratio = 1.25; break;
1939 case 1: dramratio = 1.5; break;
1940 case 2: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001941 }
1942 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08001943
Martin Roth9b1b3352016-02-24 12:27:06 -08001944 default:
1945 case 800:
1946 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001947 case 1: dramratio = 1.0; break;
1948 case 2: dramratio = 1.33334; break;
1949 case 3: dramratio = 1.66667; break;
1950 case 4: dramratio = 2.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001951 }
1952 break;
1953
1954 case 1066:
1955 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001956 case 1: dramratio = 0.75; break;
1957 case 2: dramratio = 1.0; break;
1958 case 3: dramratio = 1.25; break;
1959 case 4: dramratio = 1.5; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001960 }
1961 break;
1962 }
1963
1964 // Compute RAM Frequency
1965 fsb = ((extclock / 1000) / coef);
1966 dramclock = fsb * dramratio;
1967
1968 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08001969}
1970
Ben Gardner90f7d112016-03-15 15:25:22 -05001971static void poll_fsb_i965(void)
1972{
Martin Roth9b1b3352016-02-24 12:27:06 -08001973 double dramclock, dramratio, fsb;
1974 unsigned long mchcfg, dev0, fsb_mch;
1975 float coef = getP4PMmultiplier();
1976 long *ptr;
1977
1978 /* Find dramratio */
1979 pci_conf_read( 0, 0, 0, 0x48, 4, &dev0);
1980 dev0 &= 0xFFFFC000;
1981 ptr=(long*)(dev0+0xC00);
1982 mchcfg = *ptr & 0xFFFF;
1983 dramratio = 1;
1984
1985 switch (mchcfg & 7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001986 case 0: fsb_mch = 1066; break;
1987 case 1: fsb_mch = 533; break;
1988 default: case 2: fsb_mch = 800; break;
1989 case 3: fsb_mch = 667; break;
1990 case 4: fsb_mch = 1333; break;
1991 case 6: fsb_mch = 1600; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08001992 }
1993
1994
1995 switch (fsb_mch) {
1996 case 533:
1997 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05001998 case 1: dramratio = 2.0; break;
1999 case 2: dramratio = 2.5; break;
2000 case 3: dramratio = 3.0; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002001 }
2002 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08002003
Martin Roth9b1b3352016-02-24 12:27:06 -08002004 default:
2005 case 800:
2006 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002007 case 0: dramratio = 1.0; break;
2008 case 1: dramratio = 5.0f/4.0f; break;
2009 case 2: dramratio = 5.0f/3.0f; break;
2010 case 3: dramratio = 2.0f; break;
2011 case 4: dramratio = 8.0f/3.0f; break;
2012 case 5: dramratio = 10.0f/3.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002013 }
2014 break;
2015
2016 case 1066:
2017 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002018 case 1: dramratio = 1.0f; break;
2019 case 2: dramratio = 5.0f/4.0f; break;
2020 case 3: dramratio = 3.0f/2.0f; break;
2021 case 4: dramratio = 2.0f; break;
2022 case 5: dramratio = 5.0f/2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002023 }
2024 break;
Martin Roth4dcd13d2016-02-24 13:53:07 -08002025
Martin Roth9b1b3352016-02-24 12:27:06 -08002026 case 1333:
2027 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002028 case 2: dramratio = 1.0f; break;
2029 case 3: dramratio = 6.0f/5.0f; break;
2030 case 4: dramratio = 8.0f/5.0f; break;
2031 case 5: dramratio = 2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002032 }
2033 break;
2034
2035 case 1600:
2036 switch ((mchcfg >> 4)&7) {
Ben Gardner90f7d112016-03-15 15:25:22 -05002037 case 3: dramratio = 1.0f; break;
2038 case 4: dramratio = 4.0f/3.0f; break;
2039 case 5: dramratio = 3.0f/2.0f; break;
2040 case 6: dramratio = 2.0f; break;
Martin Roth9b1b3352016-02-24 12:27:06 -08002041 }
2042 break;
Ben Gardner90f7d112016-03-15 15:25:22 -05002043 }
Martin Roth9b1b3352016-02-24 12:27:06 -08002044
2045 // Compute RAM Frequency
2046 fsb = ((extclock / 1000) / coef);
2047 dramclock = fsb * dramratio;
2048
2049 // Print DRAM Freq
2050 print_cpu_line(dramclock, fsb, 2);
Martin Roth9b1b3352016-02-24 12:27:06 -08002051}
2052
Ben Gardner90f7d112016-03-15 15:25:22 -05002053static void poll_fsb_p35(void)
2054{
Martin Roth9b1b3352016-02-24 12:27:06 -08002055 double dramclock, dramratio, fsb;
Ben Gardner90f7d112016-03-15 15:25:22 -05002056 unsigned long mchcfg, dev0, fsb_mch, Device_ID