diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/common/ddr_spd.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/common/ddr_spd.c')
-rw-r--r-- | qemu/roms/u-boot/common/ddr_spd.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/common/ddr_spd.c b/qemu/roms/u-boot/common/ddr_spd.c new file mode 100644 index 000000000..438e71afd --- /dev/null +++ b/qemu/roms/u-boot/common/ddr_spd.c @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include <common.h> +#include <ddr_spd.h> + +/* used for ddr1 and ddr2 spd */ +static int +spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum) +{ + unsigned int cksum = 0; + unsigned int i; + + /* + * Check SPD revision supported + * Rev 1.X or less supported by this code + */ + if (spd_rev >= 0x20) { + printf("SPD revision %02X not supported by this code\n", + spd_rev); + return 1; + } + if (spd_rev > 0x13) { + printf("SPD revision %02X not verified by this code\n", + spd_rev); + } + + /* + * Calculate checksum + */ + for (i = 0; i < 63; i++) { + cksum += *buf++; + } + cksum &= 0xFF; + + if (cksum != spd_cksum) { + printf("SPD checksum unexpected. " + "Checksum in SPD = %02X, computed SPD = %02X\n", + spd_cksum, cksum); + return 1; + } + + return 0; +} + +unsigned int +ddr1_spd_check(const ddr1_spd_eeprom_t *spd) +{ + const u8 *p = (const u8 *)spd; + + return spd_check(p, spd->spd_rev, spd->cksum); +} + +unsigned int +ddr2_spd_check(const ddr2_spd_eeprom_t *spd) +{ + const u8 *p = (const u8 *)spd; + + 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; + } +} + +unsigned int ddr4_spd_check(const struct ddr4_spd_eeprom_s *spd) +{ + char *p = (char *)spd; + int csum16; + int len; + char crc_lsb; /* byte 126 */ + char crc_msb; /* byte 127 */ + + len = 126; + 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) { + 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; + } + + p = (char *)((ulong)spd + 128); + len = 126; + csum16 = crc16(p, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->mod_section.uc[126] != crc_lsb || + spd->mod_section.uc[127] != crc_msb) { + printf("SPD checksum unexpected.\n" + "Checksum lsb in SPD = %02X, computed SPD = %02X\n" + "Checksum msb in SPD = %02X, computed SPD = %02X\n", + spd->mod_section.uc[126], + crc_lsb, spd->mod_section.uc[127], + crc_msb); + return 1; + } + + return 0; +} |