[coreboot-gerrit] Change in coreboot[master]: [WIP]nb/x4x/raminit: Rewrite SPD decode and timing selection

Arthur Heymans (Code Review) gerrit at coreboot.org
Wed Apr 5 19:51:48 CEST 2017


Arthur Heymans has uploaded a new change for review. ( https://review.coreboot.org/19143 )

Change subject: [WIP]nb/x4x/raminit: Rewrite SPD decode and timing selection
......................................................................

[WIP]nb/x4x/raminit: Rewrite SPD decode and timing selection

This is mostly written from scratch.

This improves the following:
* This fixes incorrect CAS/Freq detection on DDR2;

* Timing selection does not use loops;

* Removes ddr3 spd decode, since there is no DDR3 raminit. For this it
  would be nice to use similar common functions for DDR3;

* Raminit would bail out if dimm was unsupported, no in some cases it
  just marks the dimm slot as empty;

* It dramatically reduces stack usage since it does not allocate 4
  times 256 bytes to store full SPDs, amongs other unused things that
  were stored in sysinfo.

Change-Id: I760eeaa3bd4f2bc25a517ddb1b9533c971454071
Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
M src/northbridge/intel/x4x/raminit.c
M src/northbridge/intel/x4x/raminit_ddr2.c
M src/northbridge/intel/x4x/x4x.h
3 files changed, 235 insertions(+), 384 deletions(-)


  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/43/19143/1

diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c
index 7d352f1..6186069 100644
--- a/src/northbridge/intel/x4x/raminit.c
+++ b/src/northbridge/intel/x4x/raminit.c
@@ -28,147 +28,77 @@
 #include <pc80/mc146818rtc.h>
 #include <spd.h>
 #include <string.h>
+#include <device/dram/ddr2.h>
 
 static inline int spd_read_byte(unsigned int device, unsigned int address)
 {
 	return smbus_read_byte(device, address);
 }
 
-static void sdram_read_spds(struct sysinfo *s)
+u32 fsb2mhz(u32 speed)
 {
-	u8 i, j, chan;
-	int status = 0;
-	FOR_EACH_DIMM(i) {
-		if (s->spd_map[i] == 0) {
-			/* Non-existent SPD address */
-			s->dimms[i].card_type = RAW_CARD_UNPOPULATED;
-			continue;
-		}
-		for (j = 0; j < 64; j++) {
-			status = spd_read_byte(s->spd_map[i], j);
-			if (status < 0) {
-				/* No SPD here */
-				s->dimms[i].card_type = RAW_CARD_UNPOPULATED;
-				break;
-			}
-			s->dimms[i].spd_data[j] = (u8) status;
-			if (j == 62)
-				s->dimms[i].card_type = ((u8) status) & 0x1f;
-		}
-		if (status >= 0)
-			hexdump(s->dimms[i].spd_data, 64);
-	}
-
-	s->spd_type = 0;
-	int fail = 1;
-	FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-		switch ((enum ddrxspd) s->dimms[i].spd_data[2]) {
-		case DDR2SPD:
-			if (s->spd_type == 0)
-				s->spd_type = DDR2;
-			else if (s->spd_type == DDR3)
-				die("DIMM type mismatch\n");
-			break;
-		case DDR3SPD:
-		default:
-			if (s->spd_type == 0)
-				s->spd_type = DDR3;
-			else if (s->spd_type == DDR2)
-				die("DIMM type mismatch\n");
-			break;
-		}
-	}
-	if (s->spd_type == DDR3) {
-		FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-			s->dimms[i].sides = (s->dimms[i].spd_data[5] & 0x0f) + 1;
-			s->dimms[i].ranks = ((s->dimms[i].spd_data[7] >> 3) & 0x7) + 1;
-			s->dimms[i].chip_capacity = (s->dimms[i].spd_data[4] & 0xf);
-			s->dimms[i].banks = 8;
-			s->dimms[i].rows = ((s->dimms[i].spd_data[5] >> 3) & 0x7) + 12;
-			s->dimms[i].cols = (s->dimms[i].spd_data[5] & 0x7) + 9;
-			s->dimms[i].cas_latencies = 0xfe;
-			s->dimms[i].cas_latencies &= (s->dimms[i].spd_data[14] << 1);
-			if (s->dimms[i].cas_latencies == 0)
-				s->dimms[i].cas_latencies = 0x40;
-			s->dimms[i].tAAmin = s->dimms[i].spd_data[16];
-			s->dimms[i].tCKmin = s->dimms[i].spd_data[12];
-			s->dimms[i].width = s->dimms[i].spd_data[7] & 0x7;
-			s->dimms[i].page_size = s->dimms[i].width * (1 << s->dimms[i].cols); // Bytes
-			s->dimms[i].tRAS = ((s->dimms[i].spd_data[21] & 0xf) << 8) |
-				s->dimms[i].spd_data[22];
-			s->dimms[i].tRP = s->dimms[i].spd_data[20];
-			s->dimms[i].tRCD = s->dimms[i].spd_data[18];
-			s->dimms[i].tWR = s->dimms[i].spd_data[17];
-			fail = 0;
-		}
-	} else if (s->spd_type == DDR2) {
-		FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-			s->dimms[i].sides = (s->dimms[i].spd_data[5] & 0x7) + 1;
-			s->dimms[i].banks = (s->dimms[i].spd_data[17] >> 2) - 1;
-			s->dimms[i].chip_capacity = s->dimms[i].banks;
-			s->dimms[i].rows = s->dimms[i].spd_data[3];// - 12;
-			s->dimms[i].cols = s->dimms[i].spd_data[4];// - 9;
-			s->dimms[i].cas_latencies = s->dimms[i].spd_data[18];
-			if (s->dimms[i].cas_latencies == 0)
-				s->dimms[i].cas_latencies = 0x60; // 6,5 CL
-			s->dimms[i].tAAmin = s->dimms[i].spd_data[26];
-			s->dimms[i].tCKmin = s->dimms[i].spd_data[25];
-			s->dimms[i].width = (s->dimms[i].spd_data[13] >> 3) - 1;
-			s->dimms[i].page_size = (s->dimms[i].width+1) * (1 << s->dimms[i].cols); // Bytes
-			s->dimms[i].tRAS = s->dimms[i].spd_data[30];
-			s->dimms[i].tRP = s->dimms[i].spd_data[27];
-			s->dimms[i].tRCD = s->dimms[i].spd_data[29];
-			s->dimms[i].tWR = s->dimms[i].spd_data[36];
-			s->dimms[i].ranks = s->dimms[i].sides; // XXX
-
-			printk(BIOS_DEBUG, "DIMM %d\n", i);
-			printk(BIOS_DEBUG, "  Sides     : %d\n", s->dimms[i].sides);
-			printk(BIOS_DEBUG, "  Banks     : %d\n", s->dimms[i].banks);
-			printk(BIOS_DEBUG, "  Ranks     : %d\n", s->dimms[i].ranks);
-			printk(BIOS_DEBUG, "  Rows      : %d\n", s->dimms[i].rows);
-			printk(BIOS_DEBUG, "  Cols      : %d\n", s->dimms[i].cols);
-			printk(BIOS_DEBUG, "  Page size : %d\n", s->dimms[i].page_size);
-			printk(BIOS_DEBUG, "  Width     : %d\n", (s->dimms[i].width+1)*8);
-			fail = 0;
-		}
-	}
-	if (fail)
-		die("No memory dimms, halt\n");
-
-	FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
-		FOR_EACH_POPULATED_DIMM_IN_CHANNEL(s->dimms, chan, i) {
-			int dimm_config;
-			if (s->dimms[i].ranks == 1) {
-				if (s->dimms[i].width == 0)	/* x8 */
-					dimm_config = 1;
-				else				/* x16 */
-					dimm_config = 3;
-			} else {
-				if (s->dimms[i].width == 0)	/* x8 */
-					dimm_config = 2;
-				else
-					die("Dual-rank x16 not supported\n");
-			}
-			s->dimm_config[chan] |=
-				dimm_config << (i % DIMMS_PER_CHANNEL) * 2;
-		}
-		printk(BIOS_DEBUG, "  Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
-	}
+	return (speed * 267) + 800;
 }
 
-static u8 msbpos(u8 val) //Reverse
+u32 ddr2mhz(u32 speed)
 {
-	u8 i;
-	for (i = 7; (i >= 0) && ((val & (1 << i)) == 0); i--)
-		;
-	return i;
+	static const u16 mhz[] = { 0, 0, 667, 800, 1067, 1333 };
+
+	if (speed >= ARRAY_SIZE(mhz))
+		return 0;
+
+	return mhz[speed];
+}
+
+static void select_cas_dramfreq_ddr2(struct sysinfo *s,
+				u32 (*tCLK_cas)[8])
+{
+	u8 selected_cas;
+	u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6;
+	u32 common_min_tclk[8];
+	u32 common_tCLK;
+
+	get_common_min_tclk(cas_mask, TOTAL_DIMMS, common_min_tclk,
+			tCLK_cas);
+	/* On this northbridge the highest DDR2 frequency is 800MHz */
+	common_tCLK = get_common_freq_cas(cas_mask, common_min_tclk,
+					&selected_cas, TCK_400MHZ);
+
+	if (common_tCLK == 0)
+		die("Could not find common memory frequency and CAS\n");
+
+	s->selected_timings.CAS = selected_cas;
+        s->selected_timings.tclk = common_tCLK;
+
+	switch (s->selected_timings.tclk) {
+	case TCK_200MHZ:
+	case TCK_266MHZ:
+		/* FIXME: this works on vendor BIOS */
+		die("Selected dran frequency not supported\n");
+	case TCK_333MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_667MHz;
+		break;
+	case TCK_400MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_800MHz;
+		break;
+	}
+
+	switch (s->selected_timings.tclk) {
+	case TCK_200MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_400MHz; break;
+	case TCK_266MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_533MHz; break;
+	case TCK_333MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_667MHz; break;
+	case TCK_400MHZ:
+		s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break;
+	}
 }
 
 static void mchinfo_ddr2(struct sysinfo *s)
 {
 	const u32 eax = cpuid_ext(0x04, 0).eax;
-	s->cores = ((eax >> 26) & 0x3f) + 1;
-	printk(BIOS_WARNING, "%d CPU cores\n", s->cores);
+	printk(BIOS_WARNING, "%d CPU cores\n", ((eax >> 26) & 0x3f) + 1);
 
 	u32 capid = pci_read_config16(PCI_DEV(0, 0, 0), 0xe8);
 	if (!(capid & (1<<(79-64))))
@@ -188,118 +118,185 @@
 		printk(BIOS_WARNING, "VT-d enabled\n");
 }
 
-static void sdram_detect_ram_speed(struct sysinfo *s)
+struct abs_timings {
+	u32 min_tclk;
+	u32 min_tRAS;
+	u32 min_tRP;
+	u32 min_tRCD;
+	u32 min_tWR;
+	u32 min_tRFC;
+	u32 min_tWTR;
+	u32 min_tRRD;
+	u32 min_tRTP;
+	u32 tCLK_cas[TOTAL_DIMMS][8];
+};
+
+static int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd,
+		struct abs_timings *saved_timings, struct sysinfo *s)
 {
-	u8 i;
-	u8 commoncas = 0;
-	u8 currcas;
-	u8 currfreq;
-	u8 maxfreq;
-	u8 freq = 0;
+	struct dimm_attr_st decoded_dimm;
+	int i;
 
-	// spdidx,cycletime @CAS				 5	   6
-	u8 idx800[7][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {23, 0x30},
-			   {9, 0x25} };
-	int found = 0;
+	if (spd_decode_ddr2(&decoded_dimm, raw_spd) != SPD_STATUS_OK)
+		return 1;
 
-	// Find max FSB speed
-	switch (MCHBAR32(0xc00) & 0x7) {
-	case 0x0:
-		s->max_fsb = FSB_CLOCK_1066MHz;
+	if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP))
+		dram_print_spd_ddr2(&decoded_dimm);
+
+	/* 
+	  * Used to be content of spd byte 62 which does not make
+	  * that much sense.
+	  */
+	s->dimms[dimm_idx].width = decoded_dimm.width;
+	if (s->dimms[dimm_idx].width & (0x8 | 0x10)) {
+		printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n",
+			dimm_idx, s->dimms[dimm_idx].width);
+		return 1;
+	}
+	/*
+	 * This boils down to:
+	 * "Except for the x16 configuration, all DDR2 devices have a
+	 * 1KB page size. For the x16 configuration, the page size is 2KB
+	 * for all densities except the 256Mb device, which has a 1KB page size."
+	 * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory'
+	 */
+	 s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width *
+		 (1 << decoded_dimm.col_bits);
+
+	switch (decoded_dimm.banks) {
+	case 4:
+		s->dimms[dimm_idx].n_banks = 0;
 		break;
-	case 0x2:
-		s->max_fsb = FSB_CLOCK_800MHz;
-		break;
-	case 0x4:
-		s->max_fsb = FSB_CLOCK_1333MHz;
+	case 8:
+		s->dimms[dimm_idx].n_banks = 1;
 		break;
 	default:
-		s->max_fsb = FSB_CLOCK_800MHz;
-		printk(BIOS_WARNING, "Can't detect FSB, setting 800MHz\n");
-		break;
+		printk(BIOS_ERR, "DIMM%d Unsupported #banks: x%d. Disabling dimm\n",
+			 dimm_idx, s->dimms[dimm_idx].width);
+		return 1;
 	}
 
-	// Max RAM speed
-	if (s->spd_type == DDR2) {
+	s->dimms[dimm_idx].ranks = decoded_dimm.ranks;
+	s->dimms[dimm_idx].rows = decoded_dimm.row_bits;
+	s->dimms[dimm_idx].cols = decoded_dimm.col_bits;
 
-		maxfreq = MEM_CLOCK_800MHz;
+	saved_timings->min_tRAS =
+		MAX(saved_timings->min_tRAS, decoded_dimm.tRAS);
+	saved_timings->min_tRP =
+		MAX(saved_timings->min_tRP, decoded_dimm.tRP);
+	saved_timings->min_tRCD =
+		MAX(saved_timings->min_tRCD, decoded_dimm.tRCD);
+	saved_timings->min_tWR =
+		MAX(saved_timings->min_tWR, decoded_dimm.tWR);
+	saved_timings->min_tRFC =
+		MAX(saved_timings->min_tRFC, decoded_dimm.tRFC);
+	saved_timings->min_tWTR =
+		MAX(saved_timings->min_tWTR, decoded_dimm.tWTR);
+	saved_timings->min_tRRD =
+		MAX(saved_timings->min_tRRD, decoded_dimm.tRRD);
+	saved_timings->min_tRTP =
+		MAX(saved_timings->min_tRTP, decoded_dimm.tRTP);
+	for (i = 0; i < 8; i++) {
+		saved_timings->tCLK_cas[dimm_idx][i] =
+			decoded_dimm.cycle_time[i];
+	}
+	return 0;
+}
 
-		// Choose common CAS latency from {6,5}, 4 does not work
-		commoncas = 0x60;
+static void select_discrete_timings(struct sysinfo *s,
+				struct abs_timings *timings)
+{
+	s->selected_timings.tRAS = DIV_ROUND_UP(timings->min_tRAS,
+						s->selected_timings.tclk);
+	s->selected_timings.tRP = DIV_ROUND_UP(timings->min_tRP,
+						s->selected_timings.tclk);
+	s->selected_timings.tRCD = DIV_ROUND_UP(timings->min_tRCD,
+						s->selected_timings.tclk);
+	s->selected_timings.tWR = DIV_ROUND_UP(timings->min_tWR,
+						s->selected_timings.tclk);
+	s->selected_timings.tRFC = DIV_ROUND_UP(timings->min_tRFC,
+						s->selected_timings.tclk);
+	s->selected_timings.tWTR = DIV_ROUND_UP(timings->min_tWTR,
+						s->selected_timings.tclk);
+	s->selected_timings.tRRD = DIV_ROUND_UP(timings->min_tRRD,
+						s->selected_timings.tclk);
+	s->selected_timings.tRTP = DIV_ROUND_UP(timings->min_tRTP,
+						s->selected_timings.tclk);
+}
+static void print_selected_timings(struct sysinfo *s)
+{
+	printk(BIOS_DEBUG, "Selected timings:\n");
+	printk(BIOS_DEBUG, "\tFSB:  %dMHz\n", fsb2mhz(s->selected_timings.fsb_clk));
+	printk(BIOS_DEBUG, "\tDDR:  %dMHz\n", ddr2mhz(s->selected_timings.mem_clk));
 
-		FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-			commoncas &= s->dimms[i].cas_latencies;
+	printk(BIOS_DEBUG, "\tCAS:  %d\n", s->selected_timings.CAS);
+	printk(BIOS_DEBUG, "\ttRAS: %d\n", s->selected_timings.tRAS);
+	printk(BIOS_DEBUG, "\ttRP:  %d\n", s->selected_timings.tRP);
+	printk(BIOS_DEBUG, "\ttRCD: %d\n", s->selected_timings.tRCD);
+	printk(BIOS_DEBUG, "\ttWR:  %d\n", s->selected_timings.tWR);
+	printk(BIOS_DEBUG, "\ttRFC: %d\n", s->selected_timings.tRFC);
+	printk(BIOS_DEBUG, "\ttWTR: %d\n", s->selected_timings.tWTR);
+	printk(BIOS_DEBUG, "\ttRRD: %d\n", s->selected_timings.tRRD);
+	printk(BIOS_DEBUG, "\ttRTP: %d\n", s->selected_timings.tRTP);
+}
+
+static void decode_spd_select_timings(struct sysinfo *s)
+{
+	unsigned int device;
+	u8 dram_type_mask = (1 << DDR2) | (1 << DDR3);
+	u8 raw_spd[128];
+	int i, j;
+	struct abs_timings saved_timings;
+
+	saved_timings.min_tRAS = 0;
+	saved_timings.min_tRP = 0;
+	saved_timings.min_tRCD = 0;
+	saved_timings.min_tWR = 0;
+	saved_timings.min_tRFC = 0;
+	saved_timings.min_tWTR = 0;
+	saved_timings.min_tRRD = 0;
+	saved_timings.min_tRTP = 0;
+	memset(&saved_timings.tCLK_cas, 0,
+		sizeof(&saved_timings.tCLK_cas));
+
+	FOR_EACH_DIMM(i) {
+		s->dimms[i].card_type = RAW_CARD_POPULATED;
+		device = s->spd_map[i];
+		if (device) {
+			s->dimms[i].card_type = RAW_CARD_UNPOPULATED;
+			continue;
 		}
-		if (commoncas == 0)
-			die("No common CAS among dimms\n");
-
-		// Working from fastest to slowest,
-		// fast->slow 5 at 800 6 at 800 5 at 667
-		found = 0;
-		for (currcas = 5; currcas <= msbpos(commoncas); currcas++) {
-			currfreq = maxfreq;
-			if (currfreq == MEM_CLOCK_800MHz) {
-				found = 1;
-				FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-					if (s->dimms[i].spd_data[idx800[currcas][0]] > idx800[currcas][1]) {
-						// this is too fast
-						found = 0;
-					}
-				}
-				if (found)
-					break;
-			}
-		}
-
-		if (!found) {
-			currcas = 5;
-			currfreq = MEM_CLOCK_667MHz;
-			found = 1;
-			FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-				if (s->dimms[i].spd_data[9] > 0x30) {
-					// this is too fast
-					found = 0;
-				}
-			}
-		}
-
-		if (!found)
-			die("No valid CAS/frequencies detected\n");
-
-		s->selected_timings.mem_clk = currfreq;
-		s->selected_timings.CAS = currcas;
-
-	} else { // DDR3
-		// Limit frequency for MCH
-		maxfreq = (s->max_ddr2_mhz == 800) ? MEM_CLOCK_800MHz : MEM_CLOCK_667MHz;
-		maxfreq >>= 3;
-		freq = MEM_CLOCK_1333MHz;
-		if (maxfreq)
-			freq = maxfreq + 2;
-		if (freq > MEM_CLOCK_1333MHz)
-			freq = MEM_CLOCK_1333MHz;
-
-		// Limit DDR speed to FSB speed
-		switch (s->max_fsb) {
-		case FSB_CLOCK_800MHz:
-			if (freq > MEM_CLOCK_800MHz)
-				freq = MEM_CLOCK_800MHz;
+		switch (spd_read_byte(s->spd_map[i], 2)) {
+		case DDR2SPD:
+			dram_type_mask &= 1 << DDR2;
+			s->spd_type = DDR2;
 			break;
-		case FSB_CLOCK_1066MHz:
-			if (freq > MEM_CLOCK_1066MHz)
-				freq = MEM_CLOCK_1066MHz;
-			break;
-		case FSB_CLOCK_1333MHz:
-			if (freq > MEM_CLOCK_1333MHz)
-				freq = MEM_CLOCK_1333MHz;
+		case DDR3SPD:
+			dram_type_mask &= 1 << DDR3;
+			s->spd_type = DDR3;
 			break;
 		default:
-			die("Invalid FSB\n");
-			break;
+			s->dimms[i].card_type = RAW_CARD_UNPOPULATED;
+			continue;
 		}
-
-		// TODO: CAS detection for DDR3
+		if (!dram_type_mask)
+			die("Mixing up dimm types is not supported\n");
+		if (s->spd_type == DDR2){
+			for (j = 0; j < 64; j++)
+				raw_spd[j] = spd_read_byte(device, j);
+			if (ddr2_save_dimminfo(i, raw_spd, &saved_timings, s)) {
+				/* something in decoded SPD was unsupported */
+				s->dimms[i].card_type = RAW_CARD_UNPOPULATED;
+				continue;
+			}
+		} else { /* DDR3: not implemented so don't decode */
+			die("DDR3 support is not implemented\n");
+		}
 	}
+	if (s->spd_type == DDR2){
+		select_cas_dramfreq_ddr2(s, saved_timings.tCLK_cas);
+	}
+	select_discrete_timings(s, &saved_timings);
 }
 
 static void checkreset_ddr2(int boot_path)
@@ -360,19 +357,13 @@
 	checkreset_ddr2(s.boot_path);
 
 	/* Detect dimms per channel */
-	s.dimms_per_ch = 2;
 	reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xe9);
-	if (reg8 & 0x10)
-		s.dimms_per_ch = 1;
-
-	printk(BIOS_DEBUG, "Dimms per channel: %d\n", s.dimms_per_ch);
+	printk(BIOS_DEBUG, "Dimms per channel: %d\n", (reg8 & 0x10) ? 1 : 2);
 
 	mchinfo_ddr2(&s);
 
-	sdram_read_spds(&s);
-
-	/* Choose Common Frequency */
-	sdram_detect_ram_speed(&s);
+	decode_spd_select_timings(&s);
+	print_selected_timings(&s);
 
 	switch (s.spd_type) {
 	case DDR2:
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index eca7189..80e9613 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -35,21 +35,6 @@
 	asm volatile("mfence":::);
 }
 
-static u32 fsb2mhz(u32 speed)
-{
-	return (speed * 267) + 800;
-}
-
-static u32 ddr2mhz(u32 speed)
-{
-	static const u16 mhz[] = { 0, 0, 667, 800, 1067, 1333 };
-
-	if (speed >= ARRAY_SIZE(mhz))
-		return 0;
-
-	return mhz[speed];
-}
-
 /* Find MSB bitfield location using bit scan reverse instruction */
 static u8 msbpos(u32 val)
 {
@@ -66,113 +51,6 @@
 	);
 
 	return (u8)(pos & 0xff);
-}
-
-static void sdram_detect_smallest_params2(struct sysinfo *s)
-{
-	u16 mult[6] = {
-		5000, // 400
-		3750, // 533
-		3000, // 667
-		2500, // 800
-		1875, // 1066
-		1500, // 1333
-	};
-
-	u8 i;
-	u32 tmp;
-	u32 maxtras = 0;
-	u32 maxtrp = 0;
-	u32 maxtrcd = 0;
-	u32 maxtwr = 0;
-	u32 maxtrfc = 0;
-	u32 maxtwtr = 0;
-	u32 maxtrrd = 0;
-	u32 maxtrtp = 0;
-
-	FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-		maxtras = MAX(maxtras, s->dimms[i].spd_data[30] * 1000);
-		maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
-		maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
-		maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
-		maxtrfc = MAX(maxtrfc, s->dimms[i].spd_data[42] * 1000 +
-				(s->dimms[i].spd_data[40] & 0xf));
-		maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
-		maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
-		maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
-	}
-	for (i = 9; i < 24; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtras) {
-			s->selected_timings.tRAS = i;
-			break;
-		}
-	}
-	for (i = 3; i < 10; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtrp) {
-			s->selected_timings.tRP = i;
-			break;
-		}
-	}
-	for (i = 3; i < 10; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtrcd) {
-			s->selected_timings.tRCD = i;
-			break;
-		}
-	}
-	for (i = 3; i < 15; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtwr) {
-			s->selected_timings.tWR = i;
-			break;
-		}
-	}
-	for (i = 15; i < 78; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtrfc) {
-			s->selected_timings.tRFC = ((i + 16) & 0xfe) - 15;
-			break;
-		}
-	}
-	for (i = 4; i < 15; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtwtr) {
-			s->selected_timings.tWTR = i;
-			break;
-		}
-	}
-	for (i = 2; i < 15; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtrrd) {
-			s->selected_timings.tRRD = i;
-			break;
-		}
-	}
-	for (i = 4; i < 15; i++) {
-		tmp = mult[s->selected_timings.mem_clk] * i;
-		if (tmp >= maxtrtp) {
-			s->selected_timings.tRTP = i;
-			break;
-		}
-	}
-
-	s->selected_timings.fsb_clk = s->max_fsb;
-
-	printk(BIOS_DEBUG, "Selected timings:\n");
-	printk(BIOS_DEBUG, "\tFSB:  %dMHz\n", fsb2mhz(s->selected_timings.fsb_clk));
-	printk(BIOS_DEBUG, "\tDDR:  %dMHz\n", ddr2mhz(s->selected_timings.mem_clk));
-
-	printk(BIOS_DEBUG, "\tCAS:  %d\n", s->selected_timings.CAS);
-	printk(BIOS_DEBUG, "\ttRAS: %d\n", s->selected_timings.tRAS);
-	printk(BIOS_DEBUG, "\ttRP:  %d\n", s->selected_timings.tRP);
-	printk(BIOS_DEBUG, "\ttRCD: %d\n", s->selected_timings.tRCD);
-	printk(BIOS_DEBUG, "\ttWR:  %d\n", s->selected_timings.tWR);
-	printk(BIOS_DEBUG, "\ttRFC: %d\n", s->selected_timings.tRFC);
-	printk(BIOS_DEBUG, "\ttWTR: %d\n", s->selected_timings.tWTR);
-	printk(BIOS_DEBUG, "\ttRRD: %d\n", s->selected_timings.tRRD);
-	printk(BIOS_DEBUG, "\ttRTP: %d\n", s->selected_timings.tRTP);
 }
 
 static void clkcross_ddr2(struct sysinfo *s)
@@ -535,8 +413,7 @@
 	twl = s->selected_timings.CAS - 1;
 
 	FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-		if (s->dimms[i].banks == 1) {
-			/* 8 banks */
+		if (s->dimms[i].n_banks == 1) {
 			trpmod = 1;
 			bankmod = 0;
 		}
@@ -1577,6 +1454,7 @@
 	};
 
 	u8 drbtab[10] = {0x04, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x08, 0x20, 0x10};
+	u8 tab_width;
 
 	// DRA
 	rankpop0 = 0;
@@ -1587,11 +1465,12 @@
 			i = ch << 1;
 		else
 			i = (ch << 1) + 1;
-		dra = dratab[s->dimms[i].banks]
-			[s->dimms[i].width]
+		tab_width = (s->dimms[i].width >> 3) - 1; /* 16->1, 8->0 */
+		dra = dratab[s->dimms[i].n_banks]
+			[tab_width]
 			[s->dimms[i].cols-9]
 			[s->dimms[i].rows-12];
-		if (s->dimms[i].banks == 1)
+		if (s->dimms[i].n_banks == 1)
 			dra |= 0x80;
 		if (ch == 0) {
 			c0dra |= dra << (r*8);
@@ -1624,12 +1503,10 @@
 		if (ch == 0) {
 			dra0 = (c0dra >> (8*r)) & 0x7f;
 			c0drb = (u16)(c0drb + drbtab[dra0]);
-			s->dimms[i].rank_capacity_mb = drbtab[dra0] << 6;
 			MCHBAR16(0x200 + 2*r) = c0drb;
 		} else {
 			dra1 = (c1dra >> (8*r)) & 0x7f;
 			c1drb = (u16)(c1drb + drbtab[dra1]);
-			s->dimms[i].rank_capacity_mb = drbtab[dra1] << 6;
 			MCHBAR16(0x600 + 2*r) = c1drb;
 		}
 	}
@@ -1898,9 +1775,6 @@
 	u8 ch;
 	u8 r, bank;
 	u32 reg32;
-
-	// Select timings based on SPD info
-	sdram_detect_smallest_params2(s);
 
 	if (s->boot_path != BOOT_PATH_WARM_RESET) {
 		// Clear self refresh
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index 32d4b96..423c195 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -144,6 +144,7 @@
 #define TOTAL_DIMMS 4
 #define DIMMS_PER_CHANNEL (TOTAL_DIMMS / TOTAL_CHANNELS)
 #define RAW_CARD_UNPOPULATED 0xff
+#define RAW_CARD_POPULATED 0
 
 #define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != RAW_CARD_UNPOPULATED)
 #define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != RAW_CARD_UNPOPULATED)
@@ -242,6 +243,7 @@
 
 struct timings {
 	unsigned int	CAS;
+	unsigned int    tclk;
 	enum fsb_clock	fsb_clk;
 	enum mem_clock	mem_clk;
 	unsigned int	tRAS;
@@ -256,42 +258,24 @@
 
 struct dimminfo {
 	unsigned int	card_type; /* 0xff: unpopulated,
-				      0xa - 0xf: raw card type A - F */
+				      0xa - 0xf: raw card type A - F */ 
 	enum chip_width	width;
-	enum chip_cap	chip_capacity;
+	/* enum chip_cap	chip_capacity; */
 	unsigned int	page_size; /* of whole DIMM in Bytes (4096 or 8192) */
-	unsigned int	sides;
-	unsigned int	banks;
+	/* unsigned int	sides; */
+	unsigned int	n_banks; /* 4 -> 0, 8 -> 1 */
 	unsigned int	ranks;
 	unsigned int	rows;
 	unsigned int	cols;
-	unsigned int	cas_latencies;
-	unsigned int	tAAmin;
-	unsigned int	tCKmin;
-	unsigned int	tWR;
-	unsigned int	tRP;
-	unsigned int	tRCD;
-	unsigned int	tRAS;
-	unsigned int	rank_capacity_mb; /* per rank in Megabytes */
-	u8		spd_data[256];
 };
 
 /* The setup is up to two DIMMs per channel */
 struct sysinfo {
-	int		txt_enabled;
-	int		cores;
 	int		boot_path;
 	int		max_ddr2_mhz;
-	int		max_ddr3_mt;
 	enum fsb_clock	max_fsb;
-	int		max_fsb_mhz;
-	int		max_render_mhz;
-	int		enable_igd;
-	int		enable_peg;
-	u16		ggc;
 
 	int		dimm_config[2];
-	int		dimms_per_ch;
 	int		spd_type;
 	int		channel_capacity[2];
 	struct timings	selected_timings;
@@ -336,6 +320,8 @@
 u8 decode_pciebar(u32 *const base, u32 *const len);
 void sdram_initialize(int boot_path, const u8 *spd_map);
 void raminit_ddr2(struct sysinfo *);
+u32 fsb2mhz(u32 speed);
+u32 ddr2mhz(u32 speed);
 
 struct acpi_rsdp;
 #ifndef __SIMPLE_DEVICE__

-- 
To view, visit https://review.coreboot.org/19143
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I760eeaa3bd4f2bc25a517ddb1b9533c971454071
Gerrit-PatchSet: 1
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Arthur Heymans <arthur at aheymans.xyz>



More information about the coreboot-gerrit mailing list