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