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 a3da4fe6bd9c9bb94acd34667cf645e4236342a0 Author: Arthur Heymans arthur@aheymans.xyz Date: Wed Mar 1 20:10:55 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 1ee22bb..b0412bf 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 @@ -628,3 +629,59 @@ void dram_print_spd_ddr2(const struct dimm_attr_st *dimm) print_us(" tPLL : ", dimm->tPLL); print_us(" tRR : ", dimm->tRR); } + +u32 get_common_freq_cas(u8 cas_mask, const struct dimm_attr_st *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 7f59a7a..e7515ba 100644 --- a/src/include/device/dram/ddr2.h +++ b/src/include/device/dram/ddr2.h @@ -213,6 +213,7 @@ u32 spd_decode_spd_size_ddr2(u8 byte0); u32 spd_decode_eeprom_size_ddr2(u8 byte1); int spd_decode_ddr2(struct dimm_attr_st *dimm, u8 spd[SPD_SIZE_MAX_DDR2]); void dram_print_spd_ddr2(const struct dimm_attr_st *dimm); - +u32 get_common_freq_cas(u8 cas_mask, const struct dimm_attr_st *dimm, int num_dimms, + u8 *selected_cas);
#endif /* DEVICE_DRAM_DDR2L_H */