~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/common/ddr_spd.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

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