intel sandy/ivy: Improve DIMM replacement detection

When MRC cache is available, first read only the SPD unique
identifier bytes required to detect possible DIMM replacement.
As this is 11 vs 256 bytes with slow SMBus operations, we save
about 70ms for every installed DIMM on normal boot path.

In the DIMM replacement case this adds some 10ms per installed DIMM
as some SPD gets read twice, but we are on slow RAM training boot path
anyways.

Change-Id: I294a56e7b7562c3dea322c644b21a15abb033870
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/17491
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
This commit is contained in:
Kyösti Mälkki 2016-11-18 19:59:23 +02:00
parent 38cb82222c
commit e258b9a2d5
20 changed files with 69 additions and 64 deletions

View File

@ -72,7 +72,7 @@ void mainboard_config_superio(void)
{
}
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
void *spd_file;
size_t spd_file_len = 0;

View File

@ -177,11 +177,11 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 5, 6 },
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd (&spd[0], 0x50);
read_spd (&spd[1], 0x51);
read_spd (&spd[2], 0x52);
read_spd (&spd[3], 0x53);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[1], 0x51, id_only);
read_spd (&spd[2], 0x52, id_only);
read_spd (&spd[3], 0x53, id_only);
}
#if 0

View File

@ -109,11 +109,11 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 5, 6 },
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd (&spd[0], 0x50);
read_spd (&spd[1], 0x51);
read_spd (&spd[2], 0x52);
read_spd (&spd[3], 0x53);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[1], 0x51, id_only);
read_spd (&spd[2], 0x52, id_only);
read_spd (&spd[3], 0x53, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -125,9 +125,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 0, 0, -1 }, /* P13: Empty */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -209,7 +209,7 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 0, 0, -1 }, /* P13: Empty */
};
void mainboard_get_spd(spd_raw_data *spd) {
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
memcpy(&spd[0], locate_spd(), 128);
}

View File

@ -179,9 +179,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 0, 0, -1 }, /* P13: Empty */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
void mainboard_config_superio(void)

View File

@ -139,10 +139,10 @@ static void early_ec_init(void)
}
}
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
void mainboard_fill_pei_data(struct pei_data *pei_data)

View File

@ -174,9 +174,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 0, 5 }, /* P13: Back port (OC5) */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
void mainboard_early_init(int s3resume)

View File

@ -176,9 +176,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 0, 4 }, /* P13: internal USB 2.0 (OC4) */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
void mainboard_early_init(int s3resume)

View File

@ -60,10 +60,10 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: camera (LCD), no OC */
};
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x51);
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume)

View File

@ -63,9 +63,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: camera (LCD), no OC */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x51);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -63,9 +63,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: camera, no OC */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x51);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -78,9 +78,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: CAMERA (LCD), no OC */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd (&spd[0], 0x50);
read_spd (&spd[2], 0x51);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -65,9 +65,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: camera, no OC */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd (&spd[0], 0x50);
read_spd (&spd[2], 0x51);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -75,10 +75,10 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, 6 },
};
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
read_spd (&spd[0], 0x50);
read_spd (&spd[2], 0x51);
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume)

View File

@ -78,9 +78,9 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 1, 1, -1 }, /* P13: webcam, no OC */
};
void mainboard_get_spd(spd_raw_data *spd) {
read_spd (&spd[0], 0x50);
read_spd (&spd[2], 0x51);
void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[0], 0x50, id_only);
read_spd (&spd[2], 0x51, id_only);
}
void mainboard_early_init(int s3resume) {

View File

@ -236,12 +236,12 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
{ 0, 0, -1 }, /* P13: Empty */
};
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
/* get onboard dimm spd */
memcpy(&spd[2], locate_spd(), 256);
/* read removable dimm spd */
read_spd(&spd[0], 0x50);
read_spd(&spd[0], 0x50, id_only);
}
void mainboard_early_init(int s3resume)

View File

@ -205,10 +205,10 @@ void mainboard_fill_pei_data(struct pei_data *pei_data)
*pei_data = pei_data_template;
}
void mainboard_get_spd(spd_raw_data *spd)
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
{
read_spd(&spd[0], 0x50);
read_spd(&spd[2], 0x52);
read_spd(&spd[0], 0x50, id_only);
read_spd(&spd[2], 0x52, id_only);
}
const struct southbridge_usb_port mainboard_usb_ports[] = {

View File

@ -361,12 +361,17 @@ static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
return match;
}
void read_spd(spd_raw_data * spd, u8 addr)
void read_spd(spd_raw_data * spd, u8 addr, bool id_only)
{
int j;
if (id_only) {
for (j = 117; j < 128; j++)
(*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
} else {
for (j = 0; j < 256; j++)
(*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
}
}
static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
{
@ -4235,14 +4240,12 @@ static void init_dram_ddr3(int mobile, int min_tck, int s3resume)
ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
}
if (!s3resume) {
memset(spds, 0, sizeof(spds));
mainboard_get_spd(spds);
}
/* verify MRC cache for fast boot */
if (!s3resume && ctrl_cached) {
/* Load SPD unique information data. */
memset(spds, 0, sizeof(spds));
mainboard_get_spd(spds, 1);
/* check SPD CRC16 to make sure the DIMMs haven't been replaced */
fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
if (!fast_boot)
@ -4273,6 +4276,8 @@ static void init_dram_ddr3(int mobile, int min_tck, int s3resume)
ctrl.tCK = min_tck;
/* Get DDR3 SPD data */
memset(spds, 0, sizeof(spds));
mainboard_get_spd(spds, 0);
dram_find_spds_ddr3(spds, &ctrl);
err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);

View File

@ -20,7 +20,7 @@
#include <device/dram/ddr3.h>
/* The order is ch0dimmA, ch0dimmB, ch1dimmA, ch1dimmB. */
void read_spd(spd_raw_data *spd, u8 addr);
void mainboard_get_spd(spd_raw_data *spd);
void read_spd(spd_raw_data *spd, u8 addr, bool id_only);
void mainboard_get_spd(spd_raw_data *spd, bool id_only);
#endif /* RAMINIT_H */