Hi Ward,

I wanted to calculate the optimal timing for any setup with mixed DIMMs
where the timing parameters may be compatible but not identical.
This patch is a step in the right direction (hopefully). I think Marc
already reviewed parts of it last year, but I couldn't find the
conversation anymore.

Warning: The spec is horribly backwards in some places, and the code
sort of inherits this. I spent a few days figuring out why the old code
even worked, and then I noticed it wasn't as bad as it originally looked.

Feel free to comment, fix, apply, rip to shreds.

Signed-off-by: Carl-Daniel Hailfinger <[email protected]>

Index: LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c
===================================================================
--- LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c       
(Revision 4614)
+++ LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c       
(Arbeitskopie)
@@ -39,7 +39,7 @@
 #error This file needs CONFIG_USE_PRINTK_IN_CAR
 #endif
 
-#define RAM_TIMING_DEBUG 0
+#define RAM_TIMING_DEBUG 1
 
 #if RAM_TIMING_DEBUG == 1
 #define printk_raminit printk_debug
@@ -1499,7 +1499,8 @@
                        }
                        if (value0 != value1) {
                                printk_raminit("SPD values differ between 
channel 0/1 for byte %i\n", addr);
-                               goto single_channel;
+                               printk_raminit("Ignoring the differences for 
now!\n", addr);
+                               //goto single_channel;
                        }
                }
        }
@@ -1786,6 +1787,51 @@
        return 0;
 }
 
+int check_spd_latency_available(u32 spd_device, unsigned min_cycle_time, 
unsigned min_latency)
+{
+       int latencies;
+       int latency;
+       int index;
+       int value;
+
+       latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
+       if (latencies < 0)
+               return -1;
+       if (latencies == 0)
+               return 1;
+
+       /* Compute the lowest cas latency supported */
+       latency = log2(latencies) -2;
+
+       /* Walk through searching for the selected latency */
+       for (index = 0; index < 3; index++, latency++) {
+               if (!(latencies & (1 << latency))) {
+                       continue;
+               }
+               if (latency == min_latency)
+                       break;
+       }
+       /* If I can't find the latency or my index is bad error */
+       if ((latency != min_latency) || (index >= 3)) {
+               return -2;
+       }
+
+       /* Read the min_cycle_time for this latency */
+       value = spd_read_byte(spd_device, latency_indicies[index]);
+       if (value < 0)
+               return -1;
+
+       value = convert_to_linear(value);
+       /* All is good if the selected clock speed
+        * is what I need or slower.
+        */
+       if (value <= min_cycle_time)
+               return 1;
+
+       /* That didn't work out... */
+       return -2;
+}
+
 static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller 
*ctrl, struct mem_info *meminfo)
 {
        /* Compute the minimum cycle time for these dimms */
@@ -1856,10 +1902,6 @@
        printk_raminit("3 min_latency: %08x\n", min_latency);
 
        for (i = 0; (i < DIMM_SOCKETS); i++) {
-               int latencies;
-               int latency;
-               int index;
-               int value;
                u32 spd_device = ctrl->channel0[i];
 
                if (!(meminfo->dimm_mask & (1 << i))) {
@@ -1870,42 +1912,17 @@
                        }
                }
 
-               latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
-               if (latencies < 0) goto hw_error;
-               if (latencies == 0) {
+               switch (check_spd_latency_available(spd_device, min_cycle_time, 
min_latency)) {
+               case -2:
+                       /* We have an error, disable the dimm */
+                       meminfo->dimm_mask = disable_dimm(ctrl, i, meminfo);
+                       break;
+               case -1:
+                       goto hw_error;
+                       break;
+               case 1:
                        continue;
                }
-
-               /* Compute the lowest cas latency supported */
-               latency = log2(latencies) -2;
-
-               /* Walk through searching for the selected latency */
-               for (index = 0; index < 3; index++, latency++) {
-                       if (!(latencies & (1 << latency))) {
-                               continue;
-                       }
-                       if (latency == min_latency)
-                               break;
-               }
-               /* If I can't find the latency or my index is bad error */
-               if ((latency != min_latency) || (index >= 3)) {
-                       goto dimm_err;
-               }
-
-               /* Read the min_cycle_time for this latency */
-               value = spd_read_byte(spd_device, latency_indicies[index]);
-               if (value < 0) goto hw_error;
-
-               value = convert_to_linear(value);
-               /* All is good if the selected clock speed
-                * is what I need or slower.
-                */
-               if (value <= min_cycle_time) {
-                       continue;
-               }
-               /* Otherwise I have an error, disable the dimm */
-       dimm_err:
-               meminfo->dimm_mask = disable_dimm(ctrl, i, meminfo);
        }
 
        printk_raminit("4 min_cycle_time: %08x\n", min_cycle_time);


-- 
http://www.hailfinger.org/


-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to