1 /* 2 * Copyright 2008 Freescale Semiconductor, Inc. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * Version 2 as published by the Free Software Foundation. 7 */ 8 9 #include <common.h> 10 #include <ddr_spd.h> 11 12 /* used for ddr1 and ddr2 spd */ 13 static int 14 spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum) 15 { 16 unsigned int cksum = 0; 17 unsigned int i; 18 19 /* 20 * Check SPD revision supported 21 * Rev 1.2 or less supported by this code 22 */ 23 if (spd_rev > 0x12) { 24 printf("SPD revision %02X not supported by this code\n", 25 spd_rev); 26 return 1; 27 } 28 29 /* 30 * Calculate checksum 31 */ 32 for (i = 0; i < 63; i++) { 33 cksum += *buf++; 34 } 35 cksum &= 0xFF; 36 37 if (cksum != spd_cksum) { 38 printf("SPD checksum unexpected. " 39 "Checksum in SPD = %02X, computed SPD = %02X\n", 40 spd_cksum, cksum); 41 return 1; 42 } 43 44 return 0; 45 } 46 47 unsigned int 48 ddr1_spd_check(const ddr1_spd_eeprom_t *spd) 49 { 50 const u8 *p = (const u8 *)spd; 51 52 return spd_check(p, spd->spd_rev, spd->cksum); 53 } 54 55 unsigned int 56 ddr2_spd_check(const ddr2_spd_eeprom_t *spd) 57 { 58 const u8 *p = (const u8 *)spd; 59 60 return spd_check(p, spd->spd_rev, spd->cksum); 61 } 62 63 /* 64 * CRC16 compute for DDR3 SPD 65 * Copied from DDR3 SPD spec. 66 */ 67 static int 68 crc16(char *ptr, int count) 69 { 70 int crc, i; 71 72 crc = 0; 73 while (--count >= 0) { 74 crc = crc ^ (int)*ptr++ << 8; 75 for (i = 0; i < 8; ++i) 76 if (crc & 0x8000) 77 crc = crc << 1 ^ 0x1021; 78 else 79 crc = crc << 1; 80 } 81 return crc & 0xffff; 82 } 83 84 unsigned int 85 ddr3_spd_check(const ddr3_spd_eeprom_t *spd) 86 { 87 char *p = (char *)spd; 88 int csum16; 89 int len; 90 char crc_lsb; /* byte 126 */ 91 char crc_msb; /* byte 127 */ 92 93 /* 94 * SPD byte0[7] - CRC coverage 95 * 0 = CRC covers bytes 0~125 96 * 1 = CRC covers bytes 0~116 97 */ 98 99 len = !(spd->info_size_crc & 0x80) ? 126 : 117; 100 csum16 = crc16(p, len); 101 102 crc_lsb = (char) (csum16 & 0xff); 103 crc_msb = (char) (csum16 >> 8); 104 105 if (spd->crc[0] == crc_lsb && spd->crc[1] == crc_msb) { 106 return 0; 107 } else { 108 printf("SPD checksum unexpected.\n" 109 "Checksum lsb in SPD = %02X, computed SPD = %02X\n" 110 "Checksum msb in SPD = %02X, computed SPD = %02X\n", 111 spd->crc[0], crc_lsb, spd->crc[1], crc_msb); 112 return 1; 113 } 114 } 115