mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-19 19:28:36 +00:00
bcb6c2bb84
SPD has minor change from Rev 1.2 to 1.3. This patch enables Rev 1.3. The difference has ben examined and the code is compatible. Speed bins is not verified on hardware for CL7 at this moment. This patch also enables SPD Rev 1.x where x is up to "F". According to SPD spec, the lower nibble is optionally used to determine which additinal bytes or attribute bits have been defined. Software can safely use defaults. However, the upper nibble should always be checked. Signed-off-by: York Sun <yorksun@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
118 lines
2.3 KiB
C
118 lines
2.3 KiB
C
/*
|
|
* Copyright 2008 Freescale Semiconductor, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* Version 2 as published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <ddr_spd.h>
|
|
|
|
/* used for ddr1 and ddr2 spd */
|
|
static int
|
|
spd_check(const u8 *buf, u8 spd_rev, u8 spd_cksum)
|
|
{
|
|
unsigned int cksum = 0;
|
|
unsigned int i;
|
|
|
|
/*
|
|
* Check SPD revision supported
|
|
* Rev 1.2 or less supported by this code
|
|
*/
|
|
if (spd_rev >= 0x20) {
|
|
printf("SPD revision %02X not supported by this code\n",
|
|
spd_rev);
|
|
return 1;
|
|
}
|
|
if (spd_rev > 0x13) {
|
|
printf("SPD revision %02X not verified by this code\n",
|
|
spd_rev);
|
|
}
|
|
|
|
/*
|
|
* Calculate checksum
|
|
*/
|
|
for (i = 0; i < 63; i++) {
|
|
cksum += *buf++;
|
|
}
|
|
cksum &= 0xFF;
|
|
|
|
if (cksum != spd_cksum) {
|
|
printf("SPD checksum unexpected. "
|
|
"Checksum in SPD = %02X, computed SPD = %02X\n",
|
|
spd_cksum, cksum);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned int
|
|
ddr1_spd_check(const ddr1_spd_eeprom_t *spd)
|
|
{
|
|
const u8 *p = (const u8 *)spd;
|
|
|
|
return spd_check(p, spd->spd_rev, spd->cksum);
|
|
}
|
|
|
|
unsigned int
|
|
ddr2_spd_check(const ddr2_spd_eeprom_t *spd)
|
|
{
|
|
const u8 *p = (const u8 *)spd;
|
|
|
|
return spd_check(p, spd->spd_rev, spd->cksum);
|
|
}
|
|
|
|
/*
|
|
* CRC16 compute for DDR3 SPD
|
|
* Copied from DDR3 SPD spec.
|
|
*/
|
|
static int
|
|
crc16(char *ptr, int count)
|
|
{
|
|
int crc, i;
|
|
|
|
crc = 0;
|
|
while (--count >= 0) {
|
|
crc = crc ^ (int)*ptr++ << 8;
|
|
for (i = 0; i < 8; ++i)
|
|
if (crc & 0x8000)
|
|
crc = crc << 1 ^ 0x1021;
|
|
else
|
|
crc = crc << 1;
|
|
}
|
|
return crc & 0xffff;
|
|
}
|
|
|
|
unsigned int
|
|
ddr3_spd_check(const ddr3_spd_eeprom_t *spd)
|
|
{
|
|
char *p = (char *)spd;
|
|
int csum16;
|
|
int len;
|
|
char crc_lsb; /* byte 126 */
|
|
char crc_msb; /* byte 127 */
|
|
|
|
/*
|
|
* SPD byte0[7] - CRC coverage
|
|
* 0 = CRC covers bytes 0~125
|
|
* 1 = CRC covers bytes 0~116
|
|
*/
|
|
|
|
len = !(spd->info_size_crc & 0x80) ? 126 : 117;
|
|
csum16 = crc16(p, len);
|
|
|
|
crc_lsb = (char) (csum16 & 0xff);
|
|
crc_msb = (char) (csum16 >> 8);
|
|
|
|
if (spd->crc[0] == crc_lsb && spd->crc[1] == crc_msb) {
|
|
return 0;
|
|
} else {
|
|
printf("SPD checksum unexpected.\n"
|
|
"Checksum lsb in SPD = %02X, computed SPD = %02X\n"
|
|
"Checksum msb in SPD = %02X, computed SPD = %02X\n",
|
|
spd->crc[0], crc_lsb, spd->crc[1], crc_msb);
|
|
return 1;
|
|
}
|
|
}
|