[coreboot] [PATCH] First part of heterogenous dualchannel support

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Fri Jan 16 04:23:51 CET 2009


First part of heterogenous dualchannel support.

Do not allow non-identical DIMMs yet, but prepare the code.

Calculate tCL related settings per DIMM in a dual channel setup. The
check for compatibility will come in a later patch, but since DIMMs
still have to be identical, this does not hurt.

Factor out tRC calculation to prepare for per-DIMM calculation.

Add diagnostic messages to tRC code.

Test booted to FILO, behaviour is identical if you ignore the added
debug messages (which are switched off by default).

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c
===================================================================
--- LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c	(Revision 3866)
+++ LinuxBIOSv2-asus_m2a-vm/src/northbridge/amd/amdk8/raminit_f.c	(Arbeitskopie)
@@ -1823,26 +1823,36 @@
 	 * by both the memory controller and the dimms.
 	 */
 	for (i = 0; i < DIMM_SOCKETS; i++) {
-		u32 spd_device = ctrl->channel0[i];
+		u32 spd_device;
 
 		printk_raminit("1.1 dimm_mask: %08x\n", meminfo->dimm_mask);
-		if (!(meminfo->dimm_mask & (1 << i))) {
-			if (meminfo->dimm_mask & (1 << (DIMM_SOCKETS + i))) { /* channelB only? */
-				spd_device = ctrl->channel1[i];
-			} else {
+		printk_raminit("i: %08x\n",i);
+
+		if (meminfo->dimm_mask & (1 << i)) {
+			spd_device = ctrl->channel0[i];
+			printk_raminit("Channel 0 settings:\n");
+
+			switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
+			case -1:
+				goto hw_error;
+				break;
+			case 1:
 				continue;
 			}
 		}
+		if (meminfo->dimm_mask & (1 << (DIMM_SOCKETS + i))) {
+			spd_device = ctrl->channel1[i];
+			printk_raminit("Channel 1 settings:\n");
 
-		printk_raminit("i: %08x\n",i);
-
-		switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
-		case -1:
-			goto hw_error;
-			break;
-		case 1:
-			continue;
-		}	
+			switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
+			case -1:
+				goto hw_error;
+				break;
+			case 1:
+				continue;
+			}
+		}
+		
 	}
 	/* Make a second pass through the dimms and disable
 	 * any that cannot support the selected memclk and cas latency.
@@ -1941,37 +1951,55 @@
 	valuex =  fraction [value & 0x7];
 	return valuex;
 }
-static int update_dimm_Trc(const struct mem_controller *ctrl,
-			    const struct mem_param *param,
-			    int i, long dimm_mask)
+
+int get_dimm_Trc_clocks(u32 spd_device, const struct mem_param *param)
 {
-	unsigned clocks, old_clocks;
-	uint32_t dtl;
 	int value;
 	int value2;
-	u32 spd_device = ctrl->channel0[i];
-
-	if (!(dimm_mask & (1 << i)) && (dimm_mask & (1 << (DIMM_SOCKETS + i)))) { /* channelB only? */
-		spd_device = ctrl->channel1[i];
-	}
-
+	int clocks;
 	value = spd_read_byte(spd_device, SPD_TRC);
-	if (value < 0) return -1;
+	if (value < 0)
+		return -1;
+	printk_raminit("update_dimm_Trc: tRC (41) = %08x\n", value);
 
 	value2 = spd_read_byte(spd_device, SPD_TRC -1);
 	value <<= 2;
 	value += convert_to_1_4(value2>>4);
 
-	value *=10;
+	value *= 10;
+	printk_raminit("update_dimm_Trc: tRC final value = %i\n", value);
 
 	clocks = (value + param->divisor - 1)/param->divisor;
+	printk_raminit("update_dimm_Trc: clocks = %i\n", clocks);
 
 	if (clocks < DTL_TRC_MIN) {
+#warning We should die here or at least disable this bank.
+		printk_notice("update_dimm_Trc: can't refresh fast enough, "
+			"want %i clocks, can %i clocks\n", clocks, DTL_TRC_MIN);
 		clocks = DTL_TRC_MIN;
 	}
+	return clocks;
+}
+
+static int update_dimm_Trc(const struct mem_controller *ctrl,
+			    const struct mem_param *param,
+			    int i, long dimm_mask)
+{
+	int clocks, old_clocks;
+	uint32_t dtl;
+	u32 spd_device = ctrl->channel0[i];
+
+	if (!(dimm_mask & (1 << i)) && (dimm_mask & (1 << (DIMM_SOCKETS + i)))) { /* channelB only? */
+		spd_device = ctrl->channel1[i];
+	}
+
+	clocks = get_dimm_Trc_clocks(spd_device, param);
+	if (clocks == -1)
+		return clocks;
 	if (clocks > DTL_TRC_MAX) {
 		return 0;
 	}
+	printk_raminit("update_dimm_Trc: clocks after adjustment = %i\n", clocks);
 
 	dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
 	old_clocks = ((dtl >> DTL_TRC_SHIFT) & DTL_TRC_MASK) + DTL_TRC_BASE;


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

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: linuxbios_k8_raminit_splitout_trc.diff
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20090116/12e4e527/attachment.ksh>


More information about the coreboot mailing list