ddr_spd.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #include <common.h>
  9. #include <ddr_spd.h>
  10. /* used for ddr1 and ddr2 spd */
  11. static int
  12. spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum)
  13. {
  14. unsigned int cksum = 0;
  15. unsigned int i;
  16. /*
  17. * Check SPD revision supported
  18. * Rev 1.2 or less supported by this code
  19. */
  20. if (spd_rev > 0x12) {
  21. printf("SPD revision %02X not supported by this code\n",
  22. spd_rev);
  23. return 1;
  24. }
  25. /*
  26. * Calculate checksum
  27. */
  28. for (i = 0; i < 63; i++) {
  29. cksum += *buf++;
  30. }
  31. cksum &= 0xFF;
  32. if (cksum != spd_cksum) {
  33. printf("SPD checksum unexpected. "
  34. "Checksum in SPD = %02X, computed SPD = %02X\n",
  35. spd_cksum, cksum);
  36. return 1;
  37. }
  38. return 0;
  39. }
  40. unsigned int
  41. ddr1_spd_check(const ddr1_spd_eeprom_t *spd)
  42. {
  43. const u8 *p = (const u8 *)spd;
  44. return spd_check(p, spd->spd_rev, spd->cksum);
  45. }
  46. unsigned int
  47. ddr2_spd_check(const ddr2_spd_eeprom_t *spd)
  48. {
  49. const u8 *p = (const u8 *)spd;
  50. return spd_check(p, spd->spd_rev, spd->cksum);
  51. }
  52. /*
  53. * CRC16 compute for DDR3 SPD
  54. * Copied from DDR3 SPD spec.
  55. */
  56. static int
  57. crc16(char *ptr, int count)
  58. {
  59. int crc, i;
  60. crc = 0;
  61. while (--count >= 0) {
  62. crc = crc ^ (int)*ptr++ << 8;
  63. for (i = 0; i < 8; ++i)
  64. if (crc & 0x8000)
  65. crc = crc << 1 ^ 0x1021;
  66. else
  67. crc = crc << 1;
  68. }
  69. return crc & 0xffff;
  70. }
  71. unsigned int
  72. ddr3_spd_check(const ddr3_spd_eeprom_t *spd)
  73. {
  74. char *p = (char *)spd;
  75. int csum16;
  76. int len;
  77. char crc_lsb; /* byte 126 */
  78. char crc_msb; /* byte 127 */
  79. /*
  80. * SPD byte0[7] - CRC coverage
  81. * 0 = CRC covers bytes 0~125
  82. * 1 = CRC covers bytes 0~116
  83. */
  84. len = !(spd->info_size_crc & 0x80) ? 126 : 117;
  85. csum16 = crc16(p, len);
  86. crc_lsb = (char) (csum16 & 0xff);
  87. crc_msb = (char) (csum16 >> 8);
  88. if (spd->crc[0] == crc_lsb && spd->crc[1] == crc_msb) {
  89. return 0;
  90. } else {
  91. printf("SPD checksum unexpected.\n"
  92. "Checksum lsb in SPD = %02X, computed SPD = %02X\n"
  93. "Checksum msb in SPD = %02X, computed SPD = %02X\n",
  94. spd->crc[0], crc_lsb, spd->crc[1], crc_msb);
  95. return 1;
  96. }
  97. }