this patch calculates BUFF_SC according to set of rules guessed out of
some various results i came up with different DIMM setups.

looking into this patch reveals it is just begging for optimization, so role
up
your sleeves, kick out those old optimization shoes, and see how you handle
this better 8-) (uwe suggested using a table, and no argue there...)

Signed-off-by: Elia Yehuda <[EMAIL PROTECTED]>
Index: coreboot-v2/src/northbridge/intel/i82810/raminit.c
===================================================================
--- coreboot-v2/src/northbridge/intel/i82810/raminit.c	(revision 3761)
+++ coreboot-v2/src/northbridge/intel/i82810/raminit.c	(working copy)
@@ -220,28 +220,186 @@
  * Common results (tested on actual hardware) are:
  *
  * (DRP: c = 128MB dual sided, d = 128MB single sided, f = 256MB dual sided)
+ * (DIMMx: DS = Dual-sided, SS = Single-sided
  *
- * BUFF_SC  TOM     DRP    DIMM0                DIMM1
+ * BUFF_SC  BUFF_SC in binary           TOM     DRP    DIMM0      DIMM1
  * ----------------------------------------------------------------------------
- * 0x3356   128MB   0x0c   128MB dual-sided     -
- * 0xcc56   128MB   0xc0   -                    128MB dual-sided
- * 0x77da   128MB   0x0d   128MB single-sided   -
- * 0xddda   128MB   0xd0   -                    128MB single-sided
- * 0x0001   256MB   0xcc   128MB dual-sided     128MB dual-sided
- * 0x55c6   256MB   0xdd   128MB single-sided   128MB single-sided
- * 0x4445   256MB   0xcd   128MB single-sided   128MB dual-sided
- * 0x1145   256MB   0xdc   128MB dual-sided     128MB single-sided
- * 0x3356   256MB   0x0f   256MB dual-sided     -
- * 0xcc56   256MB   0xf0   -                    256MB dual-sided
- * 0x0001   384MB   0xcf   256MB dual-sided     128MB dual-sided
- * 0x0001   384MB   0xfc   128MB dual-sided     256MB dual-sided
- * 0x1145   384MB   0xdf   256MB dual-sided     128MB single-sided
- * 0x4445   384MB   0xfd   128MB single-sided   256MB dual-sided
- * 0x0001   512MB   0xff   256MB dual-sided     256MB dual-sided
+ * 0x3356   0 0 1 1 00 11 01 01 01 10   128MB   0x0c   128MB DS   -
+ * 0xcc56   1 1 0 0 11 00 01 01 01 10   128MB   0xc0   -          128MB DS
+ * 0x77da   0 1 1 1 01 11 11 01 10 10   128MB   0x0d   128MB SS   -
+ * 0xddda   1 1 0 1 11 01 11 01 10 10   128MB   0xd0   -          128MB SS
+ * 0x0001   0 0 0 0 00 00 00 00 00 01   256MB   0xcc   128MB DS   128MB DS
+ * 0x55c6   0 1 0 1 01 01 11 00 01 10   256MB   0xdd   128MB SS   128MB SS
+ * 0x4445   0 1 0 0 01 00 01 00 01 01   256MB   0xcd   128MB SS   128MB DS
+ * 0x1145   0 0 0 1 00 01 01 00 01 01   256MB   0xdc   128MB DS   128MB SS
+ * 0x3356   0 0 1 1 00 11 01 01 01 10   256MB   0x0f   256MB DS   -
+ * 0xcc56   1 1 0 0 11 00 01 01 01 10   256MB   0xf0   -          256MB DS
+ * 0x0001   0 0 0 0 00 00 00 00 00 01   384MB   0xcf   256MB DS   128MB DS
+ * 0x0001   0 0 0 0 00 00 00 00 00 01   384MB   0xfc   128MB DS   256MB DS
+ * 0x1145   0 0 0 1 00 01 01 00 01 01   384MB   0xdf   256MB DS   128MB SS
+ * 0x4445   0 1 0 0 01 00 01 00 01 01   384MB   0xfd   128MB SS   256MB DS
+ * 0x0001   0 0 0 0 00 00 00 00 00 01   512MB   0xff   256MB DS   256MB DS
+ *
+ * Here is some rough reverse engineering of those codes :
+ *
+ *	0:1   00 = 0 DIMMs
+ *	      01 = 2 dual
+ *		   1 dual + 1 single
+ *		   1 single + 1 dual
+ *	      10 = 1 DIMM only
+ *		   2 single
+ *	2:3   00 = 2 dual sided
+ *	      01 = 1 dual sided only
+ *		   2 single sided
+ *		   1 dual + 1 single
+ *		   1 single + 1 dual
+ *	      10 = 1 single sided only
+ *	4:5   00 = 2 DIMMs
+ *	      01 = 1 DIMM only
+ *	6:7   00 = 2 dual
+ *	      01 = 1 dual only
+ *		   1 dual + 1 single
+ *		   1 single + 1 dual
+ *	      11 = 1 single
+ *		   2 single
+ *	8:9   00 = 2 dual
+ *		   1 single + 1 dual
+ *		   1 dual only in slot #1
+ *	      01 = 1 single only in slot #1
+ *		   1 dual + 1 single
+ *		   2 single
+ *	      11 = no dimm in slot #1
+ *	10:11 00 = 1 dual only in slot #0
+ *		   2 dual
+ *		   1 dual + 1 single
+ *	      01 = 1 single only in slot #0
+ *		   2 single
+ *		   1 single + 1 dual
+ *	      11 = no dimm in slot #0
+ *	12     0 = 1 dual only in slot #1
+ *		   2 dual
+ *		   1 single + 1 dual
+ *	       1 = no dimm in slot #1
+ *		   1 single
+ *		   2 single
+ *		   1 dual + 1 single
+ *	13     0 = any in slot #1
+ *	       1 = no dimm in slot #1
+ *	14     0 = 1 dual only in slot #0
+ *		   2 dual
+ *		   1 dual + 1 single
+ *	       1 = no dimm in slot #0
+ *		   1 single only in slot #0
+ *		   2 single
+ *		   1 single + 1 dual
+ *	15     0 = no dimm in slot #1
+ *		   2 DIMMs
+ *	       1 = no dimm in slot #0
+ *
  */
 static void set_dram_buffer_strength(const struct mem_controller *ctrl)
 {
-	pci_write_config16(ctrl->d0, BUFF_SC, 0x77da);
+	struct dimm_info dimm0, dimm1;
+	u16 buff_sc;
+
+	/* check 1st slot */
+	if (smbus_read_byte(ctrl->channel0[0], 2) == 4) {
+		dimm0.size = smbus_read_byte(ctrl->channel0[0], 31);
+		dimm0.dual = (smbus_read_byte(ctrl->channel0[0], 5) > 1);
+		dimm0.single = !dimm0.dual;
+	} else {
+		dimm0.size = dimm0.dual = dimm0.single = 0;
+	}
+
+	/* check 2nd slot */
+	if (smbus_read_byte(ctrl->channel0[1], 2) == 4) {
+		dimm1.size = smbus_read_byte(ctrl->channel0[1], 31);
+		dimm1.dual = (smbus_read_byte(ctrl->channel0[1], 5) > 1);
+		dimm1.single = !dimm1.dual;
+	} else {
+		dimm1.size = dimm1.dual = dimm1.single = 0;
+	}
+	
+	buff_sc = 0;
+	/* tame the beast... */
+	if ( (dimm0.dual && dimm1.dual) || 
+		(dimm0.dual && dimm1.single) || 
+		(dimm0.single && dimm1.dual) ) {
+		buff_sc |= 1;
+	}
+	if ( (dimm0.size && !dimm1.size) || 
+		(!dimm0.size && dimm1.size) || 
+		(dimm0.single && dimm1.single) ) {
+		buff_sc |= 1 << 1;
+	}
+	if ( (dimm0.dual && !dimm1.size) || 
+		(!dimm0.size && dimm1.dual) || 
+		(dimm0.single && dimm1.single) ||
+		(dimm0.dual && dimm1.single) ||
+		(dimm0.single && dimm1.dual) ) {
+		buff_sc |= 1 << 2;
+	}
+	if ( (dimm0.single && !dimm1.size) || 
+		(!dimm0.size && dimm1.single) ) {
+		buff_sc |= 1 << 3;
+	}
+	if ( (dimm0.size && !dimm1.size) || 
+		(!dimm0.size && dimm1.size) ) {
+		buff_sc |= 1 << 4;
+	}
+	if ( (dimm0.dual && !dimm1.size) || 
+		(!dimm0.size && dimm1.dual) || 
+		(dimm0.dual && dimm1.single) || 
+		(dimm0.single && dimm1.dual) ) {
+		buff_sc |= 1 << 6;
+	}
+	if ( (dimm0.single && !dimm1.size) || 
+		(!dimm0.size && dimm1.single) || 
+		(dimm0.single && dimm1.single) ) {
+		buff_sc |= 3 << 6;
+	}
+	if ( (!dimm0.size && dimm1.single) || 
+		(dimm0.dual && dimm1.single) || 
+		(dimm0.single && dimm1.single) ) {
+		buff_sc |= 1 << 8;
+	}
+	if (dimm0.size && !dimm1.size) {
+		buff_sc |= 3 << 8;
+	}
+	if ( (dimm0.single && !dimm1.size) || 
+		(dimm0.single && dimm1.single) || 
+		(dimm0.single && dimm1.dual) ) {
+		buff_sc |= 1 << 10;
+	}
+	if (!dimm0.size && dimm1.size) {
+		buff_sc |= 3 << 10;
+	}
+	if ( (dimm0.size && !dimm1.size) || 
+		(dimm0.single && !dimm1.size) || 
+		(!dimm0.size && dimm1.single) ||
+		(dimm0.single && dimm1.single) ||
+		(dimm0.dual && dimm1.single) ) {
+		buff_sc |= 1 << 12;
+	}
+	if (dimm0.size && !dimm1.size) {
+		buff_sc |= 1 << 13;
+	}
+	if ( (!dimm0.size && dimm1.size) || 
+		(dimm0.single && !dimm1.size) || 
+		(dimm0.single && dimm1.single) ||
+		(dimm0.single && dimm1.dual) ) {
+		buff_sc |= 1 << 14;
+	}
+	if (!dimm0.size && dimm1.size) {
+		buff_sc |= 1 << 15;
+	}
+	
+	print_debug("BUFF_SC calculated to 0x");
+	print_debug_hex16(buff_sc);
+	print_debug("\r\n");
+
+	/* go a head and set the BUFF_SC */
+	pci_write_config16(ctrl->d0, BUFF_SC, buff_sc);
 }
 
 /*-----------------------------------------------------------------------------
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to