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 38870e4f8a07064659fc0da5104ad08d738b7eaf Author: Arthur Heymans arthur@aheymans.xyz Date: Fri Feb 10 12:08:16 2017 +0100
device/dram/ddr2: Add 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 | 57 ++++++++++++++++++++++++++++++++++++++++++ src/include/device/dram/ddr2.h | 3 ++- 2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/src/device/dram/ddr2.c b/src/device/dram/ddr2.c index c2bfe0c..835546f 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 @@ -635,3 +636,59 @@ 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; + } else { + printk(BIOS_DEBUG, "Too slow common tCLK found\n"); + return 0; + } + + *selected_cas = high_common_cas; + return tCLK; +} diff --git a/src/include/device/dram/ddr2.h b/src/include/device/dram/ddr2.h index ae02c40..4c33b1b 100644 --- a/src/include/device/dram/ddr2.h +++ b/src/include/device/dram/ddr2.h @@ -210,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 */