Comments
Patch
===================================================================
@@ -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);
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 <c-d.hailfinger.devel.2006@gmx.net>