ddr_spd.c 3.1 KB

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