summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/device/dram/ddr3.c53
-rw-r--r--src/include/device/dram/ddr3.h1
2 files changed, 38 insertions, 16 deletions
diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c
index cb5b685d10..b3bcd680fe 100644
--- a/src/device/dram/ddr3.c
+++ b/src/device/dram/ddr3.c
@@ -46,6 +46,24 @@ int dimm_is_registered(enum spd_dimm_type type)
return 0;
}
+static u16 crc16(const u8 *ptr, int n_crc)
+{
+ int i;
+ u16 crc = 0;
+
+ while (--n_crc >= 0) {
+ crc = (crc ^ (int)*ptr++) << 8;
+ for (i = 0; i < 8; ++i)
+ if (crc & 0x8000) {
+ crc = (crc << 1) ^ 0x1021;
+ } else {
+ crc = crc << 1;
+ }
+ }
+
+ return crc;
+}
+
/**
* \brief Calculate the CRC of a DDR3 SPD
*
@@ -56,9 +74,7 @@ int dimm_is_registered(enum spd_dimm_type type)
*/
u16 spd_ddr3_calc_crc(u8 *spd, int len)
{
- int n_crc, i;
- u8 *ptr;
- u16 crc;
+ int n_crc;
/* Find the number of bytes covered by CRC */
if (spd[0] & 0x80) {
@@ -71,19 +87,24 @@ u16 spd_ddr3_calc_crc(u8 *spd, int len)
/* Not enough bytes available to get the CRC */
return 0;
- /* Compute the CRC */
- crc = 0;
- ptr = spd;
- while (--n_crc >= 0) {
- crc = crc ^ (int)*ptr++ << 8;
- for (i = 0; i < 8; ++i)
- if (crc & 0x8000) {
- crc = crc << 1 ^ 0x1021;
- } else {
- crc = crc << 1;
- }
- }
- return crc;
+ return crc16(spd, n_crc);
+}
+
+/**
+ * \brief Calculate the CRC of a DDR3 SPD unique identifier
+ *
+ * @param spd pointer to raw SPD data
+ * @param len length of data in SPD
+ *
+ * @return the CRC of SPD data bytes 117..127, or 0 when spd data is truncated.
+ */
+u16 spd_ddr3_calc_unique_crc(u8 *spd, int len)
+{
+ if (len < (117 + 11))
+ /* Not enough bytes available to get the CRC */
+ return 0;
+
+ return crc16(&spd[117], 11);
}
/**
diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h
index 7388012f86..905aa8407a 100644
--- a/src/include/device/dram/ddr3.h
+++ b/src/include/device/dram/ddr3.h
@@ -199,6 +199,7 @@ enum ddr3_xmp_profile {
typedef u8 spd_raw_data[256];
u16 spd_ddr3_calc_crc(u8 *spd, int len);
+u16 spd_ddr3_calc_unique_crc(u8 *spd, int len);
int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd_data);
int dimm_is_registered(enum spd_dimm_type type);
void dram_print_spd_ddr3(const dimm_attr * dimm);