fsl-ddr: add the DDR3 SPD infrastructure

- support mirrored DIMMs, not support register DIMMs
- test passed on P2020DS board with MT9JSF12872AY-1G1D1
- test passed on MPC8569MDS board with MT8JSF12864HY-1G1D1

Signed-off-by: Dave Liu <daveliu@freescale.com>
Signed-off-by: Travis Wheatley <travis.wheatley@freescale.com>
diff --git a/common/ddr_spd.c b/common/ddr_spd.c
index 78e3c5d..c058e4f 100644
--- a/common/ddr_spd.c
+++ b/common/ddr_spd.c
@@ -59,3 +59,56 @@
 
 	return spd_check(p, spd->spd_rev, spd->cksum);
 }
+
+/*
+ * CRC16 compute for DDR3 SPD
+ * Copied from DDR3 SPD spec.
+ */
+static int
+crc16(char *ptr, int count)
+{
+	int crc, i;
+
+	crc = 0;
+	while (--count >= 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 & 0xffff;
+}
+
+unsigned int
+ddr3_spd_check(const ddr3_spd_eeprom_t *spd)
+{
+	char *p = (char *)spd;
+	int csum16;
+	int len;
+	char crc_lsb;	/* byte 126 */
+	char crc_msb;	/* byte 127 */
+
+	/*
+	 * SPD byte0[7] - CRC coverage
+	 * 0 = CRC covers bytes 0~125
+	 * 1 = CRC covers bytes 0~116
+	 */
+
+	len = !(spd->info_size_crc & 0x80) ? 126 : 117;
+	csum16 = crc16(p, len);
+
+	crc_lsb = (char) (csum16 & 0xff);
+	crc_msb = (char) (csum16 >> 8);
+
+	if (spd->crc[0] == crc_lsb && spd->crc[1] == crc_msb) {
+		return 0;
+	} else {
+		printf("SPD checksum unexpected.\n"
+			"Checksum lsb in SPD = %02X, computed SPD = %02X\n"
+			"Checksum msb in SPD = %02X, computed SPD = %02X\n",
+			spd->crc[0], crc_lsb, spd->crc[1], crc_msb);
+		return 1;
+	}
+}