ddr_spd.c 3.1 KB

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