Arthur Heymans (arthur@aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18320
-gerrit
commit 56749b2babb48e97eb0287e7ef46f5e2501b8944 Author: Arthur Heymans arthur@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 finds highest common CAS and select tCLK based on the dimm with highest minumum tCLK at that selected CAS.
Change-Id: I3ab39d38a243edddfde8f70ebd23f79ff774e90e Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- src/device/dram/ddr2.c | 54 ++++++++++++++++++++++++++++++++++++++++++ src/include/device/dram/ddr2.h | 15 +++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/src/device/dram/ddr2.c b/src/device/dram/ddr2.c index b712192..a8e49a6 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@das-labor.org + * Copyright (C) 2017 Arthur Heymans arthur@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 @@ -593,3 +594,56 @@ void dram_print_spd_ddr2(const dimm_attr *dimm) print_us(" tPLL : ", dimm->tPLL); print_us(" tRR : ", dimm->tRR); } + +u32 get_common_freq_cas(u8 cas_mask, const dimm_attr *dimm, int num_dimms, + u8 *selected_cas) +{ + int i, high_common_cas; + u32 tCLK = 0; + + 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 0; + } + + high_common_cas = spd_get_msbs(cas_mask); + for (i = 0; i < num_dimms; i++) { + if (dimm[i].dimm_type == SPD_DIMM_TYPE_UNDEFINED) + continue; + if (dimm[i].cycle_time[high_common_cas] == 0) + printk(BIOS_DEBUG, "No minimum tCLK defined for dimm %d at CAS %d\n", + i, high_common_cas); + if (tCLK < dimm[i].cycle_time[high_common_cas]) + tCLK = dimm[i].cycle_time[high_common_cas]; + } + + if (tCLK == 0) { + printk(BIOS_DEBUG, "No valid minimum tCLK found\n"); + return 0; + } + + if (tCLK <= TCK_800MHZ) { + tCLK = TCK_800MHZ; + } else if (tCLK <= TCK_666MHZ) { + tCLK = TCK_666MHZ; + } else if (tCLK <= TCK_533MHZ) { + tCLK = TCK_533MHZ; + } else if (tCLK <= TCK_400MHZ) { + tCLK = TCK_400MHZ; + } else if (tCLK <= TCK_333MHZ) { + tCLK = TCK_333MHZ; + } else if (tCLK <= TCK_266MHZ) { + tCLK = TCK_266MHZ; + } else { /* if (tCLK <= TCK_200MHZ) */ + tCLK = TCK_200MHZ; + } + + *selected_cas = high_common_cas; + return tCLK; +} diff --git a/src/include/device/dram/ddr2.h b/src/include/device/dram/ddr2.h index 236be49..dc986f0 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); - +u32 get_common_freq_cas(u8 cas_mask, const dimm_attr *dimm, int num_dimms, + u8 *selected_cas);
#endif /* DEVICE_DRAM_DDR2L_H */