agesa: Add support for soldered down DDR3 initialization

Creates a new CONFIG_DDR3_SOLDERED_DOWN variable to enable
handling proper DDR3 SPD initialization. This patch is from
SageBIOS (forked coreboot) sources and is required for platforms
such as the GizmoSphere Gizmo board.

BUG=None
BRANCH=none
TEST=Run on Gizmo board and check SPD dump being same as SageBIOS
Signed-off-by: Marcelo Povoa <marcelogp@chromium.org>

Change-Id: I28e69d649252f542eb3d20d51ff8af69ae6e394a
Reviewed-on: https://chromium-review.googlesource.com/188273
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
Tested-by: Marcelo Póvoa <marcelogp@chromium.org>
Commit-Queue: Marcelo Póvoa <marcelogp@chromium.org>
This commit is contained in:
Marcelo Povoa 2014-02-27 15:48:27 -08:00 committed by chrome-internal-fetch
commit b81b1bb51a
3 changed files with 150 additions and 0 deletions

View file

@ -31,6 +31,10 @@ config S3_VGA_ROM_RUN
bool
default n
config DDR3_SOLDERED_DOWN
bool
default n
source src/northbridge/amd/agesa/family10/Kconfig
source src/northbridge/amd/agesa/family12/Kconfig
source src/northbridge/amd/agesa/family14/Kconfig

View file

@ -29,9 +29,15 @@
#include "dimmSpd.h"
#include "chip.h"
#if CONFIG_DDR3_SOLDERED_DOWN
#include CONFIG_PATH_TO_DDR3_SPD
AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc );
#endif
/* uncomment for source level debug - GDB gets really confused otherwise. */
//#pragma optimize ("", off)
#if !CONFIG_DDR3_SOLDERED_DOWN
/**
* Read a single SPD byte. If the first byte is being read, set up the
* address and offset. Following bytes auto increment.
@ -143,3 +149,71 @@ AGESA_STATUS agesa_ReadSPD(UINT32 unused1, UINT32 unused2, void *infoptr)
return AGESA_ERROR;
return readspd(SMBUS0_BASE_ADDRESS, spdAddress, (void *)info->Buffer, 128);
}
#else // CONFIG_DDR3_SOLDERED_DOWN
/*
* Get the SPD from the mainboard
*/
AGESA_STATUS agesa_ReadSPD(UINT32 unused1, UINT32 unused2, void *infoptr)
{
UINT8 *spd_ptr;
UINT16 index, crc;
AGESA_READ_SPD_PARAMS *info = infoptr;
ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
if ((dev == 0) || (dev->chip_info == 0))
return AGESA_ERROR;
if (info->MemChannelId > CONFIG_DDR3_CHANNEL_MAX) return AGESA_ERROR;
if (info->SocketId != 0) return AGESA_ERROR;
if (info->DimmId != 0) return AGESA_ERROR;
/* read the bytes from the table */
spd_ptr = (UINT8 *)info->Buffer;
for (index = 0; index < 128; index++)
spd_ptr[index] = ddr3_fake_spd[index];
/* If CRC bytes are zeroes, calculate and store the CRC of the fake table */
if ((spd_ptr[126] == 0) && (spd_ptr[127] == 0)) {
calc_fake_spd_crc( spd_ptr, &crc );
spd_ptr[126] = (UINT8)(crc & 0xFF);
spd_ptr[127] = (UINT8)(crc>>8);
}
/* print out the table */
printk(BIOS_SPEW, "\nDump the fake SPD for Channel %d\n",info->MemChannelId);
for (index = 0; index < 128; index++) {
if((index&0x0F)==0x00) printk(BIOS_SPEW, "%02x: ",index);
printk(BIOS_SPEW, "%02x ", spd_ptr[index]);
if((index&0x0F)==0x0F) printk(BIOS_SPEW, "\n");
}
return AGESA_SUCCESS;
}
AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc )
{
INT16 i;
INT16 j;
INT16 jmax;
/* should the CRC be done on bytes 0-116 or 0-125 ? */
if (SPDPtr[0] & 0x80)
jmax = 117;
else jmax = 126;
*crc = 0; /* zero out the CRC */
for (j = 0; j < jmax; j++) {
*crc = *crc ^ ((UINT16)SPDPtr[j] << 8);
for (i = 0; i < 8; i++) {
if (*crc & 0x8000) {
*crc = (*crc << 1) ^ 0x1021;
} else {
*crc = (*crc << 1);
}
}
}
return TRUE;
}
#endif

View file

@ -27,9 +27,14 @@
#include "dimmSpd.h"
#include "chip.h"
#if CONFIG_DDR3_SOLDERED_DOWN
#include CONFIG_PATH_TO_DDR3_SPD
AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc );
#endif
#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
#if !CONFIG_DDR3_SOLDERED_DOWN
/*-----------------------------------------------------------------------------
*
* readSmbusByteData - read a single SPD byte from any offset
@ -158,3 +163,70 @@ AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PA
setupFch (ioBase);
return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
}
#else // CONFIG_DDR3_SOLDERED_DOWN
/*
* Get the SPD from the mainboard
*/
AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
{
UINT8 *spd_ptr;
UINT16 index, crc;
ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
if ((dev == 0) || (dev->chip_info == 0))
return AGESA_ERROR;
if (info->MemChannelId > CONFIG_DDR3_CHANNEL_MAX) return AGESA_ERROR;
if (info->SocketId != 0) return AGESA_ERROR;
if (info->DimmId != 0) return AGESA_ERROR;
/* read the bytes from the table */
spd_ptr = (UINT8 *)info->Buffer;
for (index = 0; index < 128; index++)
spd_ptr[index] = ddr3_fake_spd[index];
/* If CRC bytes are zeroes, calculate and store the CRC of the fake table */
if ((spd_ptr[126] == 0) && (spd_ptr[127] == 0)) {
calc_fake_spd_crc( spd_ptr, &crc );
spd_ptr[126] = (UINT8)(crc & 0xFF);
spd_ptr[127] = (UINT8)(crc>>8);
}
/* print out the table */
printk(BIOS_SPEW, "\nDump the fake SPD for Channel %d\n",info->MemChannelId);
for (index = 0; index < 128; index++) {
if((index&0x0F)==0x00) printk(BIOS_SPEW, "%02x: ",index);
printk(BIOS_SPEW, "%02x ", spd_ptr[index]);
if((index&0x0F)==0x0F) printk(BIOS_SPEW, "\n");
}
return AGESA_SUCCESS;
}
AGESA_STATUS calc_fake_spd_crc( UINT8 *SPDPtr, UINT16 *crc )
{
INT16 i;
INT16 j;
INT16 jmax;
/* should the CRC be done on bytes 0-116 or 0-125 ? */
if (SPDPtr[0] & 0x80)
jmax = 117;
else jmax = 126;
*crc = 0; /* zero out the CRC */
for (j = 0; j < jmax; j++) {
*crc = *crc ^ ((UINT16)SPDPtr[j] << 8);
for (i = 0; i < 8; i++) {
if (*crc & 0x8000) {
*crc = (*crc << 1) ^ 0x1021;
} else {
*crc = (*crc << 1);
}
}
}
return TRUE;
}
#endif