[coreboot-gerrit] Patch set updated for coreboot: device/dram/ddr2: Add common function to select common CAS en freq

Arthur Heymans (arthur@aheymans.xyz) gerrit at coreboot.org
Fri Feb 10 14:57:52 CET 2017


Arthur Heymans (arthur at aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18320

-gerrit

commit a2875b6968f3c0287dad388fa6921ad254b7fe1c
Author: Arthur Heymans <arthur at aheymans.xyz>
Date:   Fri Feb 10 12:08:16 2017 +0100

    device/dram/ddr2: Add common function to select common CAS en freq
    
    This function has a CAS mask as input encoded in the same way as SPD
    byte 18.
    
    It tries to find the fastest frequency at the lowest possible CAS
    latency.
    
    Change-Id: I3ab39d38a243edddfde8f70ebd23f79ff774e90e
    Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
 src/device/dram/ddr2.c         | 86 ++++++++++++++++++++++++++++++++++++++++++
 src/include/device/dram/ddr2.h | 15 +++++++-
 2 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/src/device/dram/ddr2.c b/src/device/dram/ddr2.c
index b712192..6d13d85 100644
--- a/src/device/dram/ddr2.c
+++ b/src/device/dram/ddr2.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2017 Patrick Rudolph <siro at das-labor.org>
+ * Copyright (C) 2017 Arthur Heymans <arthur at aheymans.xyz>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -110,6 +111,21 @@ static u8 spd_get_msbs(u8 c)
 }
 
 /**
+ * \brief Return index of MSB set
+ *
+ * Returns the index fof MSB set.
+ */
+static u8 spd_get_lsbs(u8 c)
+{
+	int i;
+	for (i = 0; i < 7; i++)
+		if (c & (1 << i))
+			return i;
+
+	return 0;
+}
+
+/**
  * \brief Decode SPD tck cycle time
  *
  * Decodes a raw SPD data from a DDR2 DIMM.
@@ -593,3 +609,73 @@ void dram_print_spd_ddr2(const dimm_attr *dimm)
 	print_us("  tPLL              : ", dimm->tPLL);
 	print_us("  tRR               : ", dimm->tRR);
 }
+
+int get_common_freq_cas(u8 max_freq, u8 cas_mask, const dimm_attr **dimm,
+			int num_dimms, u8 *selected_freq, u8 *selected_cas)
+{
+	int i, found, high_supp_cas, low_supp_cas;
+	u8 curr_freq, curr_cas;
+
+	const int ddr2_speeds_table[] = {
+		TCK_200MHZ,
+		TCK_266MHZ,
+		TCK_333MHZ,
+		TCK_400MHZ,
+		TCK_533MHZ,
+		TCK_666MHZ,
+		TCK_700MHZ,
+		TCK_800MHZ,
+	};
+
+	for (i = 0; i < num_dimms; i++) {
+		if (dimm[i]->dimm_type == SPD_DIMM_TYPE_UNDEFINED)
+			continue;
+		cas_mask &= dimm[i]->cas_supported;
+	}
+
+	if (!cas_mask) {
+		printk(BIOS_DEBUG, "No common supported CAS\n");
+		return 1;
+	}
+
+	high_supp_cas = spd_get_msbs(cas_mask);
+	low_supp_cas = spd_get_lsbs(cas_mask);
+
+	/* Loop from fast to slow frequency, from low to high CAS latency */
+	for (curr_freq = max_freq;
+		     curr_freq >= 0; curr_freq--) {
+		printram("Trying speed: %d\n", curr_freq);
+		for (curr_cas = low_supp_cas;
+		     curr_cas <= low_supp_cas; curr_cas++) {
+			printram(" Trying CAS: %d\n", curr_freq);
+			found = 1;
+			for (i = 0; i < num_dimms; i++) {
+				if (dimm[i]->dimm_type ==
+					SPD_DIMM_TYPE_UNDEFINED)
+					continue;
+
+				printram("  Testing DIMM: %d\n", i);
+				if (dimm[i]->cycle_time[curr_cas] == 0) {
+					printram("   CAS not supported");
+					found = 0;
+					break;
+				}
+
+				if (dimm[i]->cycle_time[curr_cas] >
+					ddr2_speeds_table[curr_freq]) {
+					printram("   Timing too fast\n");
+					found = 0;
+					break;
+				}
+			}
+			if (found) {
+				*selected_freq = curr_freq;
+				*selected_cas = curr_cas;
+				return 0;
+			}
+		}
+	}
+
+	printk(BIOS_DEBUG, "No common CAS Frequency combination possible!\n");
+	return 1;
+}
diff --git a/src/include/device/dram/ddr2.h b/src/include/device/dram/ddr2.h
index 236be49..d13559e 100644
--- a/src/include/device/dram/ddr2.h
+++ b/src/include/device/dram/ddr2.h
@@ -46,6 +46,18 @@
 #define TCK_333MHZ      768
 #define TCK_266MHZ      960
 #define TCK_200MHZ      1280
+
+enum dram_freq {
+	DDR2_200MHZ,
+	DDR2_266MHZ,
+	DDR2_333MHZ,
+	DDR2_400MHZ,
+	DDR2_533MHZ,
+	DDR2_666MHZ,
+	DDR2_700MHZ,
+	DDR2_800MHZ,
+};
+
 /** @} */
 
 /**
@@ -198,6 +210,7 @@ u32 spd_decode_spd_size_ddr2(u8 byte0);
 u32 spd_decode_eeprom_size_ddr2(u8 byte1);
 int spd_decode_ddr2(dimm_attr *dimm, spd_raw_data spd);
 void dram_print_spd_ddr2(const dimm_attr *dimm);
-
+int get_common_freq_cas(u8 max_freq, u8 cas_mask, const dimm_attr **dimm,
+			int num_dimms, u8 *selected_freq, u8 *selected_cas);
 
 #endif /* DEVICE_DRAM_DDR2L_H */



More information about the coreboot-gerrit mailing list