Skip to content

Commit

Permalink
Add new DDR4 DDIMM keyword ENTIRE_SPD_WITHOUT_EFD
Browse files Browse the repository at this point in the history
With the DDR4 DDIMM SPD there are really two parts. There is the
640 bytes of information you typically see in a DIMM's SPD and then
there are 2 KB - 640 bytes of EFD (extensible function descriptors)
to give vendors space to add customized data. In many cases we want
the ENTIRE_SPD (including the EFD area) but in other cases we want
to save some time/space and only read in the first 640 bytes. This
new keyword will give us that flexibility.

Change-Id: I88ed58b37417b576f2ec4a779ee0c114791c6c21
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/84070
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Reviewed-by: Matthew Raybuck <matthew.raybuck@ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
crgeddes authored and dcrowell77 committed Sep 27, 2019
1 parent 7b87226 commit 0f3e041
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 22 deletions.
8 changes: 7 additions & 1 deletion src/include/usr/vpd/spdenums.H
Expand Up @@ -356,9 +356,15 @@ enum
LRMM_CRC = SPD_FIRST_MOD_SPEC | 0xb4,
SPD_LAST_MOD_SPEC = SPD_FIRST_MOD_SPEC | 0xb5,

// Latest DDR SPD specifcations have standard SPD
// in the front followed by extendable function
// descriptors (EFDs). ENTIRE_SPD will grab everything
// ENTIRE_SPD_WITHOUT_EFD will skip getting the EFD info
ENTIRE_SPD_WITHOUT_EFD = 0xFFFD,
//read entire SPD contents
ENTIRE_SPD = 0xFFFE,
// This keyword should be last in the list
// Invalid Keyword
ENTIRE_SPD = 0xFFFE, //read entire SPD
INVALID_SPD_KEYWORD = 0xFFFF,
};

Expand Down
5 changes: 4 additions & 1 deletion src/usr/fapi2/plat_spd_access.C
Expand Up @@ -108,7 +108,10 @@ fapi2::ReturnCode getSPD(

if( l_memModule == SPD::MEM_DDIMM )
{
o_size = SPD::DDIMM_DDR4_SPD_SIZE;
// currently getSPD only supports the ENTIRE_SPD
// keyword. In the DDIMM case this include the EFD
// data so be sure to reflect that in the size we return.
o_size = SPD::OCMB_SPD_EFD_COMBINED_SIZE;
}
else
{
Expand Down
10 changes: 5 additions & 5 deletions src/usr/hwas/hwasPlat.C
Expand Up @@ -589,19 +589,19 @@ errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
errlHndl_t l_errl = nullptr;

// Allocate buffer to hold SPD and init to 0
size_t l_spdBufferSize = SPD::OCMB_SPD_EFD_COMBINED_SIZE;
size_t l_spdBufferSize = SPD::DDIMM_DDR4_SPD_SIZE;
uint8_t* l_spdBuffer = new uint8_t[l_spdBufferSize];
memset(l_spdBuffer, 0, l_spdBufferSize);
uint16_t l_chipId = 0;
uint8_t l_chipEc = 0;

do {

// Read the full SPD.
// Read the SPD off the ocmb but skip reading the EFD to save time.
l_errl = deviceRead(i_target,
l_spdBuffer,
l_spdBufferSize,
DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD));
DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD_WITHOUT_EFD));

// If unable to retrieve the SPD buffer then can't
// extract the IDEC data, so return error.
Expand All @@ -614,11 +614,11 @@ errlHndl_t ocmbIdecPhase1(const TARGETING::TargetHandle_t& i_target)
}

// Make sure we got back the size we were expecting.
assert(l_spdBufferSize == SPD::OCMB_SPD_EFD_COMBINED_SIZE,
assert(l_spdBufferSize == SPD::DDIMM_DDR4_SPD_SIZE,
"ocmbIdecPhase1> OCMB SPD read size %d "
"doesn't match the expected size %d",
l_spdBufferSize,
SPD::OCMB_SPD_EFD_COMBINED_SIZE);
SPD::DDIMM_DDR4_SPD_SIZE);

l_errl = getOcmbIdecFromSpd(i_target,
l_spdBuffer,
Expand Down
19 changes: 5 additions & 14 deletions src/usr/vpd/ocmb_spd.C
Expand Up @@ -152,25 +152,16 @@ errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target,
}
}

// For ENTIRE_SPD, we must read OCMB SPD and EFD combined size.
size_t dataSize = entry->length;
if (i_keyword == ENTIRE_SPD)
{
assert(((io_buflen >= OCMB_SPD_EFD_COMBINED_SIZE)
|| (io_buffer == nullptr)),
"Buffer must be at least 2 KB in ocmbGetSPD for ENTIRE_SPD");
dataSize = OCMB_SPD_EFD_COMBINED_SIZE;
}

// Support passing in nullptr buffer to return VPD field size.
if (io_buffer == nullptr)
{
io_buflen = dataSize;
io_buflen = entry->length;
break;
}


l_errl = spdCheckSize(io_buflen,
dataSize,
entry->length,
i_keyword);

if (l_errl != nullptr)
Expand All @@ -180,7 +171,7 @@ errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target,

l_errl = ocmbFetchData(i_target,
entry->offset,
dataSize,
entry->length,
io_buffer,
i_location);

Expand All @@ -190,7 +181,7 @@ errlHndl_t ocmbGetSPD(T::TargetHandle_t i_target,
}

// Return the size read.
io_buflen = dataSize;
io_buflen = entry->length;

} while(0);

Expand Down
3 changes: 2 additions & 1 deletion src/usr/vpd/spdDDR4_DDIMM.H
Expand Up @@ -127,7 +127,8 @@ const KeywordData ddr4DDIMMData[] =
{ TCKMAX_FINE_OFFSET, 0x7c, 0x01, 0x00, 0x00, false, false, ALL },
{ BASE_CONFIG_CRC, 0x7f, 0x02, 0x00, 0x00, true, false, ALL },
// Module Specific fields supported on DDR4 only
{ ENTIRE_SPD, 0x00, 0x280, 0x00, 0x00, false, false, ALL },
{ ENTIRE_SPD_WITHOUT_EFD, 0x00, 0x280, 0x00, 0x00, false, false, ALL },
{ ENTIRE_SPD, 0x00, 0x800, 0x00, 0x00, false, false, ALL },
//---------------------------------------------------------------------------------------
};

Expand Down

0 comments on commit 0f3e041

Please sign in to comment.