Hello,

attached is the patch which implements the mem speed table,
mainboards describe it's mem speed ability in mem_controller structure
as the following example:

        static const struct mem_controller cpu[] = {
                {
                        .node_id = 0,
                        .f0 = PCI_DEV(0, 0x18, 0),
                        .f1 = PCI_DEV(0, 0x18, 1),
                        .f2 = PCI_DEV(0, 0x18, 2),
                        .f3 = PCI_DEV(0, 0x18, 3),
                        .channel0 = { (0xa<<3)|0, (0xa<<3)|2, (0xa<<3)|4, 
(0xa<<3)|6 },
                        .channel1 = { (0xa<<3)|1, (0xa<<3)|3, (0xa<<3)|5, 
(0xa<<3)|7 },
                        .memclk_conf = {
                                {4, 4, 2, 0, 0, 200},   /* 200M for:  4x1rank,  
2x1rank + 2x2rank, etc */
                                {4, 4, 0, 2, 0, 200},
                                {4, 4, 0, 0, 2, 200},
                                {8, 8, 8, 8, 8, 166},   /* 166M for other case 
*/
                                {0, 0, 0, 0, 0, 0},     /* the end */
                        }
                },
        };

Tao
diff -pNur freebios2-orig/src/northbridge/amd/amdk8/raminit.c freebios2/src/northbridge/amd/amdk8/raminit.c
--- freebios2-orig/src/northbridge/amd/amdk8/raminit.c	2005-04-30 16:04:13.000000000 +0800
+++ freebios2/src/northbridge/amd/amdk8/raminit.c	2005-05-11 15:48:24.000000000 +0800
@@ -1219,6 +1219,70 @@ static const struct mem_param *get_mem_p
 	return param;
 }
 
+static int read_memclk_conf(const struct mem_controller *ctrl, long dimm_mask)
+{
+	unsigned char cur_dimms, cur_1rank, cur_2rank, cur_3rank, cur_4rank, cur_speed;
+	struct memclk_conf *memclk_conf;
+	int i, ranks;
+
+	cur_dimms = cur_1rank = cur_2rank = cur_3rank = cur_4rank = 0;
+	cur_speed = 100;
+
+	for (i = 0; i < (DIMM_SOCKETS << 1); i++) {
+		if (!(dimm_mask & (1 << i)))
+			continue;
+		cur_dimms++;
+		if (i < DIMM_SOCKETS)
+			ranks = spd_read_byte(ctrl->channel0[i], 5);
+		else
+			ranks = spd_read_byte(ctrl->channel1[i - DIMM_SOCKETS], 5);
+		switch (ranks) {
+		case 1:
+			cur_1rank++;
+			break;
+		case 2:
+			cur_2rank++;
+			break;
+		case 3:
+			cur_3rank++;
+			break;
+		case 4:
+			cur_4rank++;
+			break;
+		}
+	}
+
+	if (!is_dual_channel(ctrl)) {
+		cur_dimms <<= 1;
+		cur_1rank <<= 1;
+		cur_2rank <<= 1;
+		cur_3rank <<= 1;
+		cur_4rank <<= 1;
+	}
+
+	memclk_conf = ctrl->memclk_conf;
+	while (memclk_conf->max_dimms) {
+		if (cur_speed < memclk_conf->max_speed && 
+				cur_dimms <= memclk_conf->max_dimms &&
+				cur_1rank <= memclk_conf->max_1rank &&
+				cur_2rank <= memclk_conf->max_2rank &&
+				cur_3rank <= memclk_conf->max_3rank &&
+				cur_4rank <= memclk_conf->max_4rank) {
+			cur_speed = memclk_conf->max_speed;
+		}
+		memclk_conf++;
+	}
+
+	if (cur_speed < 133)
+		return NBCAP_MEMCLK_100MHZ;
+	else if (cur_speed < 166)
+		return NBCAP_MEMCLK_133MHZ;
+	else if (cur_speed < 200)
+		return NBCAP_MEMCLK_166MHZ;
+	else
+		return NBCAP_MEMCLK_200MHZ;
+}
+
 struct spd_set_memclk_result {
 	const struct mem_param *param;
 	long dimm_mask;
@@ -1227,7 +1291,7 @@ static struct spd_set_memclk_result spd_
 {
 	/* Compute the minimum cycle time for these dimms */
 	struct spd_set_memclk_result result;
-	unsigned min_cycle_time, min_latency, bios_cycle_time;
+	unsigned min_cycle_time, min_latency, board_cycle_time, bios_cycle_time;
 	int i;
 	uint32_t value;
 
@@ -1242,6 +1306,10 @@ static struct spd_set_memclk_result spd_
 
 	value = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
 	min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
+	board_cycle_time = min_cycle_times[read_memclk_conf(ctrl, dimm_mask)];
+	if (board_cycle_time > min_cycle_time) {
+		min_cycle_time = board_cycle_time;
+	}
 	bios_cycle_time = min_cycle_times[
 		read_option(CMOS_VSTART_max_mem_clock, CMOS_VLEN_max_mem_clock, 0)];
 	if (bios_cycle_time > min_cycle_time) {
diff -pNur freebios2-orig/src/northbridge/amd/amdk8/raminit.h freebios2/src/northbridge/amd/amdk8/raminit.h
--- freebios2-orig/src/northbridge/amd/amdk8/raminit.h	2005-04-30 16:04:13.000000000 +0800
+++ freebios2/src/northbridge/amd/amdk8/raminit.h	2005-05-11 15:48:22.000000000 +0800
@@ -1,12 +1,22 @@
 #ifndef RAMINIT_H
 #define RAMINIT_H
 
+struct memclk_conf {
+	unsigned char max_dimms;
+	unsigned char max_1rank;
+	unsigned char max_2rank;
+	unsigned char max_3rank;
+	unsigned char max_4rank;
+	unsigned char max_speed;
+};
+
 #define DIMM_SOCKETS 4
 struct mem_controller {
 	unsigned node_id;
 	device_t f0, f1, f2, f3;
 	uint16_t channel0[DIMM_SOCKETS];
 	uint16_t channel1[DIMM_SOCKETS];
+	struct memclk_conf memclk_conf[8];
 };
 
 
_______________________________________________
LinuxBIOS mailing list
[email protected]
http://www.openbios.org/mailman/listinfo/linuxbios

Reply via email to