Refactor K8 rev F DDR2 CL timing retrieval.
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Fri, 16 Jan 2009 03:03:40 +0000 (03:03 +0000)
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Fri, 16 Jan 2009 03:03:40 +0000 (03:03 +0000)
This will allow usage of compatible DIMMS in a dual channel setup
instead of requiring the DIMMS to be identical.

Code impact is minimal because a large chunk of code has been moved into
a separate function with almost no changes.

Tested, yields identical results and identical logs.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3866 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/northbridge/amd/amdk8/raminit_f.c

index 196209525b783e07668aa300709e9fb442cce5df..8bfb08fa2559cbf0c1f0b501df6e55ca62d66ab6 100644 (file)
@@ -1702,6 +1702,96 @@ static unsigned convert_to_linear(unsigned value)
        return value;
 }
 
+static const uint8_t latency_indicies[] = { 25, 23, 9 };
+
+int find_optimum_spd_latency(u32 spd_device, unsigned *min_latency, unsigned *min_cycle_time)
+{
+       int new_cycle_time, new_latency;
+       int index;
+       int latencies;
+       int latency;
+
+       /* First find the supported CAS latencies
+        * Byte 18 for DDR SDRAM is interpreted:
+        * bit 3 == CAS Latency = 3
+        * bit 4 == CAS Latency = 4
+        * bit 5 == CAS Latency = 5
+        * bit 6 == CAS Latency = 6
+        */
+       new_cycle_time = 0x500;
+       new_latency = 6;
+
+       latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
+       if (latencies <= 0)
+               return 1;
+
+       printk_raminit("\tlatencies: %08x\n", latencies);
+       /* Compute the lowest cas latency which can be expressed in this
+        * particular SPD EEPROM. You can store at most settings for 3
+        * contiguous CAS latencies, so by taking the highest CAS
+        * latency maked as supported in the SPD and subtracting 2 you
+        * get the lowest expressable CAS latency. That latency is not
+        * necessarily supported, but a (maybe invalid) entry exists
+        * for it.
+        */
+       latency = log2(latencies) - 2;
+
+       /* Loop through and find a fast clock with a low latency */
+       for (index = 0; index < 3; index++, latency++) {
+               int value;
+               if ((latency < 3) || (latency > 6) ||
+                       (!(latencies & (1 << latency)))) {
+                       continue;
+               }
+               value = spd_read_byte(spd_device, latency_indicies[index]);
+               if (value < 0) {
+                       return -1;
+               }
+
+               printk_raminit("\tindex: %08x\n", index);
+               printk_raminit("\t\tlatency: %08x\n", latency);
+               printk_raminit("\t\tvalue1: %08x\n", value);
+
+               value = convert_to_linear(value);
+
+               printk_raminit("\t\tvalue2: %08x\n", value);
+
+               /* Only increase the latency if we decrease the clock */
+               if (value >= *min_cycle_time ) {
+                       if (value < new_cycle_time) {
+                               new_cycle_time = value;
+                               new_latency = latency;
+                       } else if (value == new_cycle_time) {
+                               if (new_latency > latency) {
+                                       new_latency = latency;
+                               }
+                       }
+               }
+               printk_raminit("\t\tnew_cycle_time: %08x\n", new_cycle_time);
+               printk_raminit("\t\tnew_latency: %08x\n", new_latency);
+
+       }
+
+       if (new_latency > 6){
+               return 1;
+       }
+
+       /* Does min_latency need to be increased? */
+       if (new_cycle_time > *min_cycle_time) {
+               *min_cycle_time = new_cycle_time;
+       }
+
+       /* Does min_cycle_time need to be increased? */
+       if (new_latency > *min_latency) {
+               *min_latency = new_latency;
+       }
+
+       printk_raminit("2 min_cycle_time: %08x\n", *min_cycle_time);
+       printk_raminit("2 min_latency: %08x\n", *min_latency);
+
+       return 0;
+}
+
 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 */
@@ -1710,8 +1800,6 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *
        int i;
        uint32_t value;
 
-       static const uint8_t latency_indicies[] = { 25, 23, 9 };
-
        static const uint16_t min_cycle_times[] = { // use full speed to compare
                [NBCAP_MEMCLK_NOLIMIT] = 0x250, /*2.5ns */
                [NBCAP_MEMCLK_333MHZ] = 0x300, /* 3.0ns */
@@ -1735,10 +1823,6 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *
         * by both the memory controller and the dimms.
         */
        for (i = 0; i < DIMM_SOCKETS; i++) {
-               int new_cycle_time, new_latency;
-               int index;
-               int latencies;
-               int latency;
                u32 spd_device = ctrl->channel0[i];
 
                printk_raminit("1.1 dimm_mask: %08x\n", meminfo->dimm_mask);
@@ -1750,83 +1834,15 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *
                        }
                }
 
-               /* First find the supported CAS latencies
-                * Byte 18 for DDR SDRAM is interpreted:
-                * bit 3 == CAS Latency = 3
-                * bit 4 == CAS Latency = 4
-                * bit 5 == CAS Latency = 5
-                * bit 6 == CAS Latency = 6
-                */
-               new_cycle_time = 0x500;
-               new_latency = 6;
-
-               latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
-               if (latencies <= 0) continue;
-
                printk_raminit("i: %08x\n",i);
-               printk_raminit("\tlatencies: %08x\n", latencies);
-               /* Compute the lowest cas latency which can be expressed in this
-                * particular SPD EEPROM. You can store at most settings for 3
-                * contiguous CAS latencies, so by taking the highest CAS
-                * latency maked as supported in the SPD and subtracting 2 you
-                * get the lowest expressable CAS latency. That latency is not
-                * necessarily supported, but a (maybe invalid) entry exists
-                * for it.
-                */
-               latency = log2(latencies) - 2;
-
-               /* Loop through and find a fast clock with a low latency */
-               for (index = 0; index < 3; index++, latency++) {
-                       int value;
-                       if ((latency < 3) || (latency > 6) ||
-                               (!(latencies & (1 << latency)))) {
-                               continue;
-                       }
-                       value = spd_read_byte(spd_device, latency_indicies[index]);
-                       if (value < 0) {
-                               goto hw_error;
-                       }
-
-                       printk_raminit("\tindex: %08x\n", index);
-                       printk_raminit("\t\tlatency: %08x\n", latency);
-                       printk_raminit("\t\tvalue1: %08x\n", value);
-
-                       value = convert_to_linear(value);
 
-                       printk_raminit("\t\tvalue2: %08x\n", value);
-
-                       /* Only increase the latency if we decrease the clock */
-                       if (value >= min_cycle_time ) {
-                               if (value < new_cycle_time) {
-                                       new_cycle_time = value;
-                                       new_latency = latency;
-                               } else if (value == new_cycle_time) {
-                                       if (new_latency > latency) {
-                                               new_latency = latency;
-                                       }
-                               }
-                       }
-                       printk_raminit("\t\tnew_cycle_time: %08x\n", new_cycle_time);
-                       printk_raminit("\t\tnew_latency: %08x\n", new_latency);
-
-               }
-
-               if (new_latency > 6){
+               switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
+               case -1:
+                       goto hw_error;
+                       break;
+               case 1:
                        continue;
-               }
-
-               /* Does min_latency need to be increased? */
-               if (new_cycle_time > min_cycle_time) {
-                       min_cycle_time = new_cycle_time;
-               }
-
-               /* Does min_cycle_time need to be increased? */
-               if (new_latency > min_latency) {
-                       min_latency = new_latency;
-               }
-
-               printk_raminit("2 min_cycle_time: %08x\n", min_cycle_time);
-               printk_raminit("2 min_latency: %08x\n", min_latency);
+               }       
        }
        /* Make a second pass through the dimms and disable
         * any that cannot support the selected memclk and cas latency.