[coreboot-gerrit] New patch to review 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 12:20:25 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 e66f2169f8cc2f8f977ed2265abde5fb3d615baf
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 CAS and Frequency masks as inputs to support
    northbridges that have different limits on those. The CAS mask is
    used as defined in SPD and frequency mask is bitwise mask for
    supported frequency so e.g. : DDR2_200MH is (1 << 0), DDR2_266MHZ
    is (1 << 1), etc.
    
    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..f520904 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 freq_mask, 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 = spd_get_msbs(freq_mask);
+		     curr_freq >= spd_get_lsbs(freq_mask); 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..24d3379 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 freq_mask, 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