diff options
author | Terry J. Opie <opiet@us.ibm.com> | 2012-04-30 11:08:27 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-06-19 10:33:05 -0500 |
commit | 733ba77cc3d60ac69143a9fb5be21202495d02a7 (patch) | |
tree | 9be74e03ade55b898f67e4f82e825a36ca74df9c /src | |
parent | e9de3b17d17a3c230ae9db3ed7d4139950cd4963 (diff) | |
download | blackbird-hostboot-733ba77cc3d60ac69143a9fb5be21202495d02a7.tar.gz blackbird-hostboot-733ba77cc3d60ac69143a9fb5be21202495d02a7.zip |
SPD Write Support
RTC: 35776
Depends-on: I2348a2da90ea85a966f3724f8b3694a0b8f03916
Depends-on: Ia0f22c87f8bc3959324fa8347e191f2b47b4325c
Change-Id: I66bdc8baf491abb0df5427d16bc586e293c6f506
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1048
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/spd/spdif.H | 4 | ||||
-rw-r--r-- | src/include/usr/spd/spdreasoncodes.H | 51 | ||||
-rwxr-xr-x | src/usr/mvpd/mvpd.C | 4 | ||||
-rwxr-xr-x | src/usr/spd/dimmPres.C | 8 | ||||
-rwxr-xr-x | src/usr/spd/spd.C | 633 | ||||
-rwxr-xr-x | src/usr/spd/spd.H | 209 | ||||
-rwxr-xr-x | src/usr/spd/spdDDR3.H | 400 | ||||
-rwxr-xr-x | src/usr/spd/test/spdtest.H | 154 |
8 files changed, 1060 insertions, 403 deletions
diff --git a/src/include/usr/spd/spdif.H b/src/include/usr/spd/spdif.H index f536babd8..c56a8dabf 100644 --- a/src/include/usr/spd/spdif.H +++ b/src/include/usr/spd/spdif.H @@ -43,8 +43,8 @@ namespace SPD */ struct pnorInformation { - uint64_t sectionSize; - uint64_t maxSections; + uint64_t segmentSize; + uint64_t maxSegments; PNOR::SectionId pnorSection; PNOR::SideSelect pnorSide; }; diff --git a/src/include/usr/spd/spdreasoncodes.H b/src/include/usr/spd/spdreasoncodes.H index 68adffca5..96b207494 100644 --- a/src/include/usr/spd/spdreasoncodes.H +++ b/src/include/usr/spd/spdreasoncodes.H @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/usr/spd/spdreasoncodes.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2012 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/include/usr/spd/spdreasoncodes.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ /** * @file spdreasoncodes.H * @@ -55,6 +56,9 @@ enum spdModuleId SPD_PRESENCE_DETECT = 0x07, SPD_CHECK_MODULE_SPECIFIC_KEYWORD = 0x08, SPD_GET_PNOR_ADDR = 0x09, + SPD_WRITE_VALUE = 0x0a, + SPD_GET_KEYWORD_ENTRY = 0x0b, + SPD_WRITE_DATA = 0x0c, }; /** @@ -80,6 +84,9 @@ enum spdReasonCode SPD_MOD_SPECIFIC_MISMATCH_LRMM = SPD_COMP_ID | 0x0c, SPD_MOD_SPECIFIC_UNSUPPORTED = SPD_COMP_ID | 0x0d, SPD_SIZE_MISMATCH = SPD_COMP_ID | 0x0e, + SPD_INVALID_WRITE_METHOD = SPD_COMP_ID | 0x0f, + SPD_NULL_ENTRY = SPD_COMP_ID | 0x10, + SPD_KEYWORD_NOT_WRITABLE = SPD_COMP_ID | 0x11, }; }; // end SPD diff --git a/src/usr/mvpd/mvpd.C b/src/usr/mvpd/mvpd.C index 9aab6f40a..07c98560e 100755 --- a/src/usr/mvpd/mvpd.C +++ b/src/usr/mvpd/mvpd.C @@ -741,8 +741,8 @@ errlHndl_t mvpdFetchData ( uint64_t i_byteAddr, // but with different address offsets. Saves us having to // duplicate the code between the 2 modules. SPD::pnorInformation info; - info.sectionSize = MVPD_SECTION_SIZE; - info.maxSections = MVPD_MAX_SECTIONS; + info.segmentSize = MVPD_SECTION_SIZE; + info.maxSegments = MVPD_MAX_SECTIONS; info.pnorSection = PNOR::MODULE_VPD; info.pnorSide = PNOR::SIDELESS; err = SPD::readPNOR( i_byteAddr, diff --git a/src/usr/spd/dimmPres.C b/src/usr/spd/dimmPres.C index e1b349c93..3cc573414 100755 --- a/src/usr/spd/dimmPres.C +++ b/src/usr/spd/dimmPres.C @@ -117,10 +117,10 @@ errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, // Read Byte 2 (BASIC_MEMORY_TYPE) for the target passed in. uint16_t data = 0x0; size_t dataSz = sizeof(data); - err = spdGetKeywordValue( BASIC_MEMORY_TYPE, - &data, - dataSz, - i_target ); + err = deviceRead( i_target, + &data, + dataSz, + DEVICE_SPD_ADDRESS( SPD::BASIC_MEMORY_TYPE ) ); if( err ) { diff --git a/src/usr/spd/spd.C b/src/usr/spd/spd.C index e472d7885..6786ad689 100755 --- a/src/usr/spd/spd.C +++ b/src/usr/spd/spd.C @@ -56,7 +56,7 @@ uint64_t g_spdPnorAddr = 0x0; // By setting to false, allows debug at a later time by allowing to // substitute a binary file (dimmspd.dat) into PNOR. -const bool g_readPNOR = true; +const bool g_usePNOR = true; // ---------------------------------------------- // Trace definitions @@ -97,68 +97,70 @@ namespace SPD bool compareEntries ( const KeywordData e1, const KeywordData e2 ); -// Register the perform Op with the routing code for DIMMs. -DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, - DeviceFW::SPD, - TARGETING::TYPE_DIMM, - spdAccess ); - -// ------------------------------------------------------------------ -// spdRead -// ------------------------------------------------------------------ -errlHndl_t spdAccess( DeviceFW::OperationType i_opType, - TARGETING::Target * i_target, - void * io_buffer, - size_t & io_buflen, - int64_t i_accessType, - va_list i_args ) -{ - errlHndl_t err = NULL; - uint64_t keyword = va_arg( i_args, uint64_t ); +/** + * @brief This function will read the DIMM memory type. + * + * @param[out] o_memType - The memory type value to return. + * + * @param[in] i_target - The target to read data from. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer + * to the error log. + */ +errlHndl_t getMemType ( uint8_t & o_memType, + TARGETING::Target * i_target ); - if( DeviceFW::READ == i_opType ) - { - // Read the SPD keyword - err = spdGetKeywordValue( keyword, - io_buffer, - io_buflen, - i_target ); - } - else - { - // Write the SPD keyword - err = spdWriteKeywordValue( keyword, - io_buffer, - io_buflen, - i_target ); - } +/** + * @brief This function will scan the table and return the entry + * corresponding to the keyword being requested. + * + * @param[in] i_keyword - The keyword being requested. + * + * @param[in] i_memType - The memory type of the target. + * + * @param[out] o_entry - The table entry corresponding to the keyword. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to + * the error log. + */ +errlHndl_t getKeywordEntry ( uint64_t i_keyword, + uint64_t i_memType, + KeywordData *& o_entry ); - return err; -} // end spdRead +// Register the perform Op with the routing code for DIMMs. +DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::SPD, + TARGETING::TYPE_DIMM, + spdGetKeywordValue ); +DEVICE_REGISTER_ROUTE( DeviceFW::WRITE, + DeviceFW::SPD, + TARGETING::TYPE_DIMM, + spdWriteKeywordValue ); // ------------------------------------------------------------------ // spdGetKeywordValue // ------------------------------------------------------------------ -errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, +errlHndl_t spdGetKeywordValue ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, - TARGETING::Target * i_target ) + int64_t i_accessType, + va_list i_args ) { errlHndl_t err = NULL; + uint64_t keyword = va_arg( i_args, uint64_t ); TRACSSCOMP( g_trac_spd, ENTER_MRK"spdGetKeywordValue(), io_buflen: %d, keyword: 0x%04x", - io_buflen, i_keyword ); + io_buflen, keyword ); do { // Read the Basic Memory Type uint8_t memType = 0x0; - err = spdFetchData( MEM_TYPE_ADDR, - MEM_TYPE_ADDR_SZ, - &memType, - i_target ); + err = getMemType( memType, + i_target ); if( err ) { @@ -174,7 +176,7 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, if( SPD_DDR3 == memType ) { // If the user wanted the Basic memory type, return this now. - if( BASIC_MEMORY_TYPE == i_keyword ) + if( BASIC_MEMORY_TYPE == keyword ) { io_buflen = MEM_TYPE_ADDR_SZ; memcpy( io_buffer, &memType, io_buflen ); @@ -182,11 +184,11 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, } // Read the keyword value - err = spdGetValue( i_keyword, - io_buffer, - io_buflen, - i_target, - memType ); + err = spdGetValue( keyword, + io_buffer, + io_buflen, + i_target, + memType ); if( err ) { @@ -212,7 +214,9 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, SPD_GET_KEYWORD_VALUE, SPD_INVALID_BASIC_MEMORY_TYPE, memType, - i_keyword ); + keyword ); + + break; } } while( 0 ); @@ -226,37 +230,68 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, // ------------------------------------------------------------------ // spdWriteKeywordValue // ------------------------------------------------------------------ -errlHndl_t spdWriteKeywordValue ( uint64_t i_keyword, +errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, - TARGETING::Target * i_target ) + int64_t i_accessType, + va_list i_args ) { errlHndl_t err = NULL; + uint64_t keyword = va_arg( i_args, uint64_t ); TRACSSCOMP( g_trac_spd, ENTER_MRK"spdWriteKeywordValue()" ); do { - // TODO - This will be implemented with story 39177 - TRACFCOMP( g_trac_spd, - ERR_MRK"SPD writes are not supported yet!" ); + // Get memory type + uint8_t memType = 0x0; + err = getMemType( memType, + i_target ); - /*@ - * @errortype - * @reasoncode SPD_NOT_SUPPORTED - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid SPD_WRITE_KEYWORD_VALUE - * @userdata1 i_keyword - * @userdata2 <UNUSED> - * @devdesc SPD Writes are not supported yet. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SPD_WRITE_KEYWORD_VALUE, - SPD_NOT_SUPPORTED, - i_keyword, - 0x0 ); - break; + if( err ) + { + break; + } + + // Check DDR3 + if( SPD_DDR3 == memType ) + { + err = spdWriteValue( keyword, + io_buffer, + io_buflen, + i_target, + memType ); + + if( err ) + { + break; + } + } + else + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Invalid Basic Memory Type (0x%04x)", + memType ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_WRITE_KEYWORD_VALUE + * @userdata1 Basic Memory Type (Byte 2) + * @userdata2 Keyword Requested + * @devdesc Invalid Basic Memory Type + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_WRITE_KEYWORD_VALUE, + SPD_INVALID_BASIC_MEMORY_TYPE, + memType, + keyword ); + + break; + } } while( 0 ); TRACSSCOMP( g_trac_spd, @@ -281,12 +316,12 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, do { - if( g_readPNOR ) + if( likely( g_usePNOR ) ) { // Setup info needed to read from PNOR pnorInformation info; - info.sectionSize = DIMM_SPD_SECTION_SIZE; - info.maxSections = DIMM_SPD_MAX_SECTIONS; + info.segmentSize = DIMM_SPD_SECTION_SIZE; + info.maxSegments = DIMM_SPD_MAX_SECTIONS; info.pnorSection = PNOR::DIMM_JEDEC_VPD; info.pnorSide = PNOR::SIDELESS; err = readPNOR( i_byteAddr, @@ -323,82 +358,123 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, // ------------------------------------------------------------------ -// spdGetValue +// spdWriteData // ------------------------------------------------------------------ -errlHndl_t spdGetValue ( uint64_t i_keyword, - void * io_buffer, - size_t & io_buflen, - TARGETING::Target * i_target, - uint64_t i_DDRRev ) +errlHndl_t spdWriteData ( uint64_t i_offset, + size_t i_numBytes, + void * i_data, + TARGETING::Target * i_target ) { errlHndl_t err = NULL; - uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer); - KeywordData * kwdData; - uint32_t arraySize = 0x0; TRACSSCOMP( g_trac_spd, - ENTER_MRK"spdGetValue()" ); + ENTER_MRK"spdWriteData()" ); do { - if( SPD_DDR3 == i_DDRRev ) + if( likely( g_usePNOR ) ) { - // Put the table into an array - arraySize = (sizeof(ddr3Data)/sizeof(ddr3Data[0])); - kwdData = ddr3Data; + // Setup info needed to write from PNOR + pnorInformation info; + info.segmentSize = DIMM_SPD_SECTION_SIZE; + info.maxSegments = DIMM_SPD_MAX_SECTIONS; + info.pnorSection = PNOR::DIMM_JEDEC_VPD; + info.pnorSide = PNOR::SIDELESS; + err = writePNOR( i_offset, + i_numBytes, + i_data, + i_target, + info, + g_spdPnorAddr, + &g_spdMutex ); + + if( err ) + { + break; + } } else { TRACFCOMP( g_trac_spd, - ERR_MRK"Unsupported DDRx Revision (0x%04x)", - i_DDRRev ); + ERR_MRK"There is no way to write SPD when not using PNOR!" ); /*@ * @errortype - * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @reasoncode SPD_INVALID_WRITE_METHOD * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid SPD_GET_VALUE - * @userdata1 SPD Keyword - * @userdata2 The DDR Revision - * @devdesc Invalid DDR Revision + * @moduleid SPD_WRITE_DATA + * @userdata1 Write Offset + * @userdata2 Number of Bytes to Write + * @devdesc g_usePNOR is false, but there isn't an + * alternate way to write PNOR. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SPD_GET_VALUE, - SPD_INVALID_BASIC_MEMORY_TYPE, - i_keyword, - i_DDRRev ); + SPD_WRITE_DATA, + SPD_INVALID_WRITE_METHOD, + i_offset, + i_numBytes ); break; } + } while( 0 ); - // Set the searching structure equal to the keyword we're looking for. - KeywordData tmpKwdData; - tmpKwdData.keyword = i_keyword; - KeywordData * entry = std::lower_bound( kwdData, - &kwdData[arraySize], - tmpKwdData, - compareEntries ); + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdWriteData()" ); - if( ( entry == &kwdData[arraySize] ) || - ( i_keyword != entry->keyword ) ) + return err; +} + + +// ------------------------------------------------------------------ +// spdGetValue +// ------------------------------------------------------------------ +errlHndl_t spdGetValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev ) +{ + errlHndl_t err = NULL; + uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer); + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdGetValue()" ); + + do + { + KeywordData * entry = NULL; + err = getKeywordEntry( i_keyword, + i_DDRRev, + entry ); + + if( err ) + { + break; + } + + // Check to be sure entry is not NULL. + if( NULL == entry ) { TRACFCOMP( g_trac_spd, - ERR_MRK"No matching keyword entry found!" ); + ERR_MRK"Entry Pointer is NULL!" ); /*@ * @errortype - * @reasoncode SPD_KEYWORD_NOT_FOUND + * @reasoncode SPD_NULL_ENTRY * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid SPD_GET_VALUE * @userdata1 SPD Keyword - * @userdata2 <UNUSED> - * @devdesc Invalid SPD Keyword + * @userdata2[0:31] Buffer Size + * @userdata2[32:63] Memory Type + * @devdesc The table entry associated with keyword was + * NULL. */ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, SPD_GET_VALUE, - SPD_KEYWORD_NOT_FOUND, + SPD_NULL_ENTRY, i_keyword, - 0x0 ); + TWO_UINT32_TO_UINT64( io_buflen, + i_DDRRev ) ); break; } @@ -476,6 +552,126 @@ errlHndl_t spdGetValue ( uint64_t i_keyword, // ------------------------------------------------------------------ +// spdWriteValue +// ------------------------------------------------------------------ +errlHndl_t spdWriteValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdWriteValue()" ); + + do + { + KeywordData * entry = NULL; + err = getKeywordEntry( i_keyword, + i_DDRRev, + entry ); + + if( err ) + { + break; + } + + if( NULL == entry ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Entry pointer is NULL!" ); + + /*@ + * @errortype + * @reasoncode SPD_NULL_ENTRY + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_WRITE_VALUE + * @userdata1 SPD Keyword + * @userdata2[0:31] Buffer Length + * @userdata2[32:63] Memory Type + * @devdesc The table entry associated with keyword was + * NULL. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_WRITE_VALUE, + SPD_NULL_ENTRY, + i_keyword, + TWO_UINT32_TO_UINT64( io_buflen, + i_DDRRev ) ); + + break; + } + + // Check write flag + if( entry->writable ) + { + // Check the Size to be equal to entry written + err = spdCheckSize( io_buflen, + entry->length, + i_keyword ); + + if( err ) + { + break; + } + + // Write value + err = spdWriteData( entry->offset, + io_buflen, + io_buffer, + i_target ); + + if( err ) + { + break; + } + + // Send mbox message with new data to Fsp + err = spdSendMboxWriteMsg(); + + if( err ) + { + break; + } + } + else + { + // Error if not writable + TRACFCOMP( g_trac_spd, + ERR_MRK"Trying to write keyword (0x%04x) that is non-" + "writable", + i_keyword ); + + /*@ + * @errortype + * @reasoncode SPD_KEYWORD_NOT_WRITABLE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_WRITE_VALUE + * @userdata1 SPD Keyword + * @userdata2[0:31] Buffer Length + * @userdata2[32:63] Memory Type + * @devdesc The SPD Keyword is not writable. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_WRITE_VALUE, + SPD_KEYWORD_NOT_WRITABLE, + i_keyword, + TWO_UINT32_TO_UINT64( io_buflen, + i_DDRRev ) ); + + break; + } + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdWriteValue()" ); + + return err; +} + + +// ------------------------------------------------------------------ // spdSpecialCases // ------------------------------------------------------------------ errlHndl_t spdSpecialCases ( KeywordData i_kwdData, @@ -820,6 +1016,33 @@ errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr, // ------------------------------------------------------------------ +// spdSendMboxWriteMsg +// ------------------------------------------------------------------ +errlHndl_t spdSendMboxWriteMsg ( void ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdSendMboxWriteMsg()" ); + + do + { + // TODO - Since all writes to SPD will be greather than 16 bytes, + // there is a need for the "extra_data" option from mbox. This is not + // available as of yet. + // + // This will be implemented with Story 41365, which cannot be done + // until story 34032 has been completed. + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdSendMboxWriteMsg()" ); + + return err; +} + + +// ------------------------------------------------------------------ // readPNOR // ------------------------------------------------------------------ errlHndl_t readPNOR ( uint64_t i_byteAddr, @@ -864,7 +1087,7 @@ errlHndl_t readPNOR ( uint64_t i_byteAddr, } // Offset cached address by vpd location multiplier - addr += (vpdLocation * i_pnorInfo.sectionSize); + addr += (vpdLocation * i_pnorInfo.segmentSize); // Now offset into that chunk of data by i_byteAddr addr += i_byteAddr; @@ -888,6 +1111,74 @@ errlHndl_t readPNOR ( uint64_t i_byteAddr, // ------------------------------------------------------------------ +// writePNOR +// ------------------------------------------------------------------ +errlHndl_t writePNOR ( uint64_t i_byteAddr, + size_t i_numBytes, + void * i_data, + TARGETING::Target * i_target, + pnorInformation & i_pnorInfo, + uint64_t &io_cachedAddr, + mutex_t * i_mutex ) +{ + errlHndl_t err = NULL; + int64_t vpdLocation = 0; + uint64_t addr = 0x0; + const char * writeAddr = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"writePNOR()" ); + + do + { + // Check if we have the PNOR addr cached. + if( 0x0 == io_cachedAddr ) + { + err = getPnorAddr( i_pnorInfo, + io_cachedAddr, + i_mutex ); + + if( err ) + { + break; + } + } + addr = io_cachedAddr; + + // Find vpd location of the target + err = getVpdLocation( vpdLocation, + i_target ); + + if( err ) + { + break; + } + + // Offset cached address by vpd location multiplier + addr += (vpdLocation * i_pnorInfo.segmentSize); + + // Now offset into that chunk of data by i_byteAddr + addr += i_byteAddr; + + TRACUCOMP( g_trac_spd, + INFO_MRK"Address to write: 0x%08x", + addr ); + + // Write the data + writeAddr = reinterpret_cast<const char*>( addr ); + memcpy( (void*)(writeAddr), + i_data, + i_numBytes ); + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"writePNOR()" ); + + return err; +} + + +// ------------------------------------------------------------------ // getPnorAddr // ------------------------------------------------------------------ errlHndl_t getPnorAddr ( pnorInformation & i_pnorInfo, @@ -913,7 +1204,7 @@ errlHndl_t getPnorAddr ( pnorInformation & i_pnorInfo, } // Check the Size - uint32_t expectedSize = i_pnorInfo.sectionSize * i_pnorInfo.maxSections; + uint32_t expectedSize = i_pnorInfo.segmentSize * i_pnorInfo.maxSegments; if( expectedSize != info.size ) { TRACFCOMP( g_trac_spd, @@ -1209,4 +1500,114 @@ errlHndl_t checkModSpecificKeyword ( KeywordData i_kwdData, } +// ------------------------------------------------------------------ +// getMemType +// ------------------------------------------------------------------ +errlHndl_t getMemType ( uint8_t & o_memType, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + + err = spdFetchData( MEM_TYPE_ADDR, + MEM_TYPE_ADDR_SZ, + &o_memType, + i_target ); + + TRACUCOMP( g_trac_spd, + "SPD::getMemType() - MemType: 0x%02x, Error: %s", + o_memType, + ((NULL == err) ? "No" : "Yes") ); + + return err; +} + + +// ------------------------------------------------------------------ +// getKeywordEntry +// ------------------------------------------------------------------ +errlHndl_t getKeywordEntry ( uint64_t i_keyword, + uint64_t i_memType, + KeywordData *& o_entry ) +{ + errlHndl_t err = NULL; + KeywordData * kwdData; + uint32_t arraySize = 0x0; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"getKeywordEntry()" ); + + do + { + if( SPD_DDR3 == i_memType ) + { + // Put the table into an array + arraySize = (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + kwdData = ddr3Data; + } + else + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Unsupported DDRx Revision (0x%04x)", + i_memType ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_GET_KEYWORD_ENTRY + * @userdata1 SPD Keyword + * @userdata2 The DDR Revision + * @devdesc Invalid DDR Revision + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_GET_KEYWORD_ENTRY, + SPD_INVALID_BASIC_MEMORY_TYPE, + i_keyword, + i_memType ); + + break; + } + + // Set the searching structure equal to the keyword we're looking for. + KeywordData tmpKwdData; + tmpKwdData.keyword = i_keyword; + KeywordData * entry = std::lower_bound( kwdData, + &kwdData[arraySize], + tmpKwdData, + compareEntries ); + + if( ( entry == &kwdData[arraySize] ) || + ( i_keyword != entry->keyword ) ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"No matching keyword entry found!" ); + + /*@ + * @errortype + * @reasoncode SPD_KEYWORD_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_GET_KEYWORD_ENTRY + * @userdata1 SPD Keyword + * @userdata2 <UNUSED> + * @devdesc Invalid SPD Keyword + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_GET_KEYWORD_ENTRY, + SPD_KEYWORD_NOT_FOUND, + i_keyword, + 0x0 ); + + break; + } + + o_entry = entry; + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"getKeywordEntry()" ); + + return err; +} + + } // end namespace SPD diff --git a/src/usr/spd/spd.H b/src/usr/spd/spd.H index f8ad6da5a..a5bf27c5c 100755 --- a/src/usr/spd/spd.H +++ b/src/usr/spd/spd.H @@ -84,15 +84,14 @@ struct KeywordData uint8_t bitMask; // Bit mask uint8_t shift; // Used for fields < 1 byte to right justify all values. bool isSpecialCase; // Whether or not this entry is a special case. + bool writable; // Whether this keyword can be written to. modSpecTypes_t modSpec; // Module Specific type keyword is valid for. }; /** -* -* @brief Perform an SPD operation. It follows a pre-defined -* prototype function in order to be registered with the device -* driver framework. + * @brief This function is used to read SPD keywords from collected + * SPD data for the given target * * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in * driververif.H @@ -100,11 +99,10 @@ struct KeywordData * @param[in] i_target - DIMM Target device * * @param [in/out] io_buffer - Pointer to the data that was read from -* the target device. It will also be used to contain data to -* be written to the device. +* the target device. * -* @param [in/out] io_buflen - Length of the buffer to be read or written -* to/from the target. This value should indicate the size of the +* @param [in/out] io_buflen - Length of the buffer to be read +* from the target. This value should indicate the size of the * io_buffer parameter that has been allocated. Being returned it will * indicate the number of valid bytes in the buffer being returned. * @@ -113,60 +111,48 @@ struct KeywordData * * @param [in] i_args - This is an argument list for the device driver * framework. -* -* @return errlHndl_t - NULL if successful, otherwise a pointer to the -* error log. -* -*/ -errlHndl_t spdAccess ( DeviceFW::OperationType i_opType, - TARGETING::Target * i_target, - void * io_buffer, - size_t & io_buflen, - int64_t i_accessType, - va_list i_args ); - -/** - * @brief This function is used to read SPD keywords from collected - * SPD data for the given target - * - * @param[in] i_keyword - The SPD keyword to access. - * - * @param[in/out] io_buffer - The buffer that will contain the data - * read from the SPD data. - * - * @param[in/out] io_buflen - The requested number of bytes to read. - * The actual number of bytes read will be returned. - * - * @param[in] i_target - The target DIMM to access the data for. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the * error log. */ -errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, +errlHndl_t spdGetKeywordValue ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, - TARGETING::Target * i_target ); + int64_t i_accessType, + va_list i_args ); /** * @brief This function is used to write SPD keyword values. - * - * @param[in] i_keyword - The SPD keyword to access. - * - * @param[in/out] io_buffer - The buffer that will contain the data - * read from the SPD data. - * - * @param[in/out] io_buflen - The requested number of bytes to read. - * The actual number of bytes read will be returned. - * - * @param[in] i_target - The target DIMM to access the data for. +* +* @param[in] i_opType - Operation Type - See DeviceFW::OperationType in +* driververif.H +* +* @param[in] i_target - DIMM Target device +* +* @param [in/out] io_buffer - Pointer to the data that will contain data +* to be written to the device. +* +* @param [in/out] io_buflen - Length of the buffer to be written +* to the target. This value should indicate the size of the +* io_buffer parameter that has been allocated. Being returned it will +* indicate the number of valid bytes written to the target. +* +* @param [in] i_accessType - Access Type - See DeviceFW::AccessType in +* usrif.H +* +* @param [in] i_args - This is an argument list for the device driver +* framework. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the * error log. */ -errlHndl_t spdWriteKeywordValue ( uint64_t i_keyword, +errlHndl_t spdWriteKeywordValue ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, void * io_buffer, size_t & io_buflen, - TARGETING::Target * i_target ); + int64_t i_accessType, + va_list i_args ); /** * @param This function is a wrapper for reading the correct keyword. @@ -190,6 +176,28 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, TARGETING::Target * i_target ); /** + * @brief This function is a wrapper for writing the correct keyword. + * It will route the write to whatever function has the latest + * supported access code. + * + * @param[in] i_offset - The offset into the JEDEC SPD layout. + * + * @param[in] i_numbytes - Number of bytes to read. + * + * @param[in] i_data - The data buffer that will return the data read. + * + * @param[in] i_target - The target DIMM to access. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t spdWriteData ( uint64_t i_offset, + size_t i_numBytes, + void * i_data, + TARGETING::Target * i_target ); + + +/** * @param This function will read the SPD keyword from the appropriate * table. * @@ -214,6 +222,33 @@ errlHndl_t spdGetValue ( uint64_t i_keyword, TARGETING::Target * i_target, uint64_t i_DDRRev ); + +/** + * @brief This function will write the SPD keyword from the appropriate + * table. + * + * @param[in] i_keyword - The SPD keyword to access. + * + * @param[in/out] io_buffer - The buffer that will contain the data + * written from the SPD data. + * + * @param[in/out] io_buflen - The requested number of bytes to write. + * The actual number of bytes written will be returned. + * + * @param[in] i_target - The target DIMM to access the data for. + * + * @param[in] i_DDRRev - The DIMM DDR Revision. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t spdWriteValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev ); + + /** * @param This function handles the special case keywords where * the data isn't sequential, or is broken up between two different @@ -357,6 +392,86 @@ errlHndl_t getPnorAddr ( pnorInformation & i_pnorInfo, errlHndl_t getVpdLocation ( int64_t & o_vpdLocation, TARGETING::Target * i_target ); + +/** + * @brief This function will read the PNOR at the correct offset and number of + * bytes for the keyword requested. + * + * @param[in] i_byteAddr - The offset to access in the PNOR. + * + * @param[in] i_numBytes - Number of bytes to read. + * + * @param[out] o_data - The data buffer that the read data will be placed + * into. + * + * @param[in] i_target - The chip target to access the data for. + * + * @param[in] i_pnorInfo - Information about the PNOR section and side that we + * need to know to make the request. + * + * @param[in/out] io_cachedAddr - The address offset to the data chunk in + * PNOR. + * + * @param[in] i_mutex - The mutex to lock/unlock while setting io_isAddrCached + * and io_cachedAddr. It is assumed that those parameters are global + * variables in the code where they reside. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the error + * log. + */ +errlHndl_t readPNOR ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target, + pnorInformation & i_pnorInfo, + uint64_t &io_cachedAddr, + mutex_t i_mutex ); + +/** + * @brief This function will write the PNOR at the correct offset and number + * of bytes for the keyword requested. + * + * @param[in] i_byteAddr - The offset to access in the PNOR. + * + * @param[in] i_numBytes - The number of bytes to write. + * + * @param[in] i_data - The data buffer of the data to be written. + * + * @param[in] i_target - The chip target to access the data for. + * + * @param[in] i_pnorInfo - Information about the PNOR section and side that we + * need to know to make the request. + * + * @param[in/out] io_cachedAddr - The address offset to the data chunk in + * PNOR. + * + * @param[in] i_mutex - The mutex to lock/unlock while setting io_isAddrCached + * and io_cachedAddr. It is assumed that those parameters are global + * variables in the code where they reside. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the error + * log. + */ +errlHndl_t writePNOR ( uint64_t i_byteAddr, + size_t i_numBytes, + void * i_data, + TARGETING::Target * i_target, + pnorInformation & i_pnorInfo, + uint64_t &io_cachedAddr, + mutex_t * i_mutex ); + +/** + * @brief This function handles sending the mailbox message to the Fsp to + * notify of updates to the data. + * + * TODO with Story 41365 + * @param NONE, yet. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the error + * log. + */ +errlHndl_t spdSendMboxWriteMsg ( void ); + }; // end SPD namespace #endif // __SPD_H diff --git a/src/usr/spd/spdDDR3.H b/src/usr/spd/spdDDR3.H index b60ce34a8..35f17846e 100755 --- a/src/usr/spd/spdDDR3.H +++ b/src/usr/spd/spdDDR3.H @@ -53,206 +53,206 @@ KeywordData ddr3Data[] = // // Special cases listed below will be handled out of the normal table lookup // handler code. - // ---------------------------------------------------------------------------------- - // Keyword offset size Use Bitmsk Shift - // Bitmsk Number - // ---------------------------------------------------------------------------------- - { CRC_EXCLUDE, 0x00, 0x01, true, 0x80, 0x07, false, NA }, - { SPD_BYTES_TOTAL, 0x00, 0x01, true, 0x70, 0x04, false, NA }, - { SPD_BYTES_USED, 0x00, 0x01, true, 0x0F, 0x00, false, NA }, - { SPD_MAJOR_REVISION, 0x01, 0x01, true, 0xF0, 0x04, false, NA }, - { SPD_MINOR_REVISION, 0x01, 0x01, true, 0x0F, 0x00, false, NA }, - { BASIC_MEMORY_TYPE, 0x02, 0x01, false, 0x00, 0x00, false, NA }, - { MODULE_TYPE, 0x03, 0x01, true, 0x0F, 0x00, false, NA }, - { BANK_ADDRESS_BITS, 0x04, 0x01, true, 0x70, 0x04, false, NA }, - { DENSITY, 0x04, 0x01, true, 0x0F, 0x00, false, NA }, - { ROW_ADDRESS, 0x05, 0x01, true, 0x38, 0x03, false, NA }, - { COL_ADDRESS, 0x05, 0x01, true, 0x07, 0x00, false, NA }, - { MODULE_NOMINAL_VOLTAGE, 0x06, 0x01, true, 0x07, 0x00, false, NA }, - { MODULE_RANKS, 0x07, 0x01, true, 0x38, 0x03, false, NA }, - { MODULE_DRAM_WIDTH, 0x07, 0x01, true, 0x07, 0x00, false, NA }, - { ECC_BITS, 0x08, 0x01, true, 0x18, 0x03, false, NA }, - { MODULE_MEMORY_BUS_WIDTH, 0x08, 0x01, true, 0x07, 0x00, false, NA }, - { FTB_DIVIDEND, 0x09, 0x01, true, 0xF0, 0x04, false, NA }, - { FTB_DIVISOR, 0x09, 0x01, true, 0x0F, 0x00, false, NA }, - { MTB_DIVIDEND, 0x0a, 0x01, false, 0x00, 0x00, false, NA }, - { MTB_DIVISOR, 0x0b, 0x01, false, 0x00, 0x00, false, NA }, - { TCK_MIN, 0x0c, 0x01, false, 0x00, 0x00, false, NA }, - { CAS_LATENCIES_SUPPORTED, 0x0f, 0x02, true, 0x7F, 0x00, true, NA }, - { MIN_CAS_LATENCY, 0x10, 0x01, false, 0x00, 0x00, false, NA }, - { TWR_MIN, 0x11, 0x01, false, 0x00, 0x00, false, NA }, - { TRCD_MIN, 0x12, 0x01, false, 0x00, 0x00, false, NA }, - { TRRD_MIN, 0x13, 0x01, false, 0x00, 0x00, false, NA }, - { TRP_MIN, 0x14, 0x01, false, 0x00, 0x00, false, NA }, - { TRC_MIN, 0x15, 0x02, true, 0xF0, 0x04, true, NA }, - { TRAS_MIN, 0x15, 0x02, true, 0x0F, 0x00, true, NA }, - { TRFC_MIN, 0x19, 0x02, false, 0x00, 0x00, true, NA }, - { TWTR_MIN, 0x1a, 0x01, false, 0x00, 0x00, false, NA }, - { TRTP_MIN, 0x1b, 0x01, false, 0x00, 0x00, false, NA }, - { TFAW_MIN, 0x1c, 0x02, true, 0x0F, 0x00, true, NA }, - { DLL_OFF, 0x1e, 0x01, true, 0x80, 0x07, false, NA }, - { RZQ_7, 0x1e, 0x01, true, 0x02, 0x01, false, NA }, - { RZQ_6, 0x1e, 0x01, true, 0x01, 0x00, false, NA }, - { PASR, 0x1f, 0x01, true, 0x80, 0x07, false, NA }, - { ODTS, 0x1f, 0x01, true, 0x08, 0x03, false, NA }, - { ASR, 0x1f, 0x01, true, 0x04, 0x02, false, NA }, - { ETR_1X, 0x1f, 0x01, true, 0x02, 0x01, false, NA }, - { ETR, 0x1f, 0x01, true, 0x01, 0x00, false, NA }, - { THERMAL_SENSOR_PRESENT, 0x20, 0x01, true, 0x80, 0x07, false, NA }, - { THERMAL_SENSOR_ACCURACY, 0x20, 0x01, true, 0x7F, 0x00, false, NA }, - { SDRAM_DEVICE_TYPE_NONSTD, 0x21, 0x01, true, 0x80, 0x07, false, NA }, - { SDRAM_DEVICE_TYPE, 0x21, 0x01, true, 0x7F, 0x00, false, NA }, - { MODULE_TYPE_SPECIFIC_SECTION, 0x3c, 0x39, false, 0x00, 0x00, false, NA }, - { MODULE_MANUFACTURER_ID, 0x76, 0x02, false, 0x00, 0x00, true, NA }, - { MODULE_MANUFACTURING_LOCATION, 0x77, 0x01, false, 0x00, 0x00, false, NA }, - { MODULE_MANUFACTURING_DATE, 0x78, 0x02, false, 0x00, 0x00, false, NA }, - { MODULE_SERIAL_NUMBER, 0x7a, 0x04, false, 0x00, 0x00, false, NA }, - { MODULE_CRC, 0x7e, 0x02, false, 0x00, 0x00, false, NA }, - { MODULE_PART_NUMBER, 0x80, 0x12, false, 0x00, 0x00, false, NA }, - { MODULE_REVISION_CODE, 0x92, 0x02, false, 0x00, 0x00, false, NA }, - { DRAM_MANUFACTURER_ID, 0x95, 0x02, false, 0x00, 0x00, true, NA }, - { MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, false, 0x00, 0x00, false, NA }, - { TCKMIN_FINE_OFFSET, 0x22, 0x01, false, 0x00, 0x00, false, NA }, - { TAAMIN_FINE_OFFSET, 0x23, 0x01, false, 0x00, 0x00, false, NA }, - { TRCDMIN_FINE_OFFSET, 0x24, 0x01, false, 0x00, 0x00, false, NA }, - { TRPMIN_FINE_OFFSET, 0x25, 0x01, false, 0x00, 0x00, false, NA }, - { TRCMIN_FINE_OFFSET, 0x26, 0x01, false, 0x00, 0x00, false, NA }, - { MODULE_THERMAL_SENSOR, 0x20, 0x01, false, 0x00, 0x00, false, NA }, - { SDRAM_OPTIONAL_FEATURES, 0x1e, 0x01, false, 0x00, 0x00, false, NA }, - { SDRAM_THERMAL_REFRESH_OPTIONS, 0x1f, 0x01, false, 0x00, 0x00, false, NA }, - { DIMM_BAD_DQ_DATA, 0xb0, 0x50, false, 0x00, 0x00, false, NA }, - { MODSPEC_COM_NOM_HEIGHT_MAX, 0x3c, 0x01, true, 0x0f, 0x00, false, ALL }, - { MODSPEC_COM_MAX_THICK_BACK, 0x3d, 0x01, true, 0xf0, 0x04, false, ALL }, - { MODSPEC_COM_MAX_THICK_FRONT, 0x3d, 0x01, true, 0x0f, 0x00, false, ALL }, - { MODSPEC_COM_RAW_CARD_EXT, 0x3e, 0x01, true, 0x80, 0x07, false, ALL }, - { MODSPEC_COM_RAW_CARD_REV, 0x3e, 0x01, true, 0x60, 0x05, false, ALL }, - { MODSPEC_COM_RAW_CARD, 0x3e, 0x01, true, 0x0f, 0x00, false, ALL }, - { MODSPEC_COM_ADDR_MAPPING, 0x3f, 0x01, true, 0x01, 0x00, false, ALL }, - { RMM_ROWS_RDIMM, 0x3f, 0x01, true, 0x0c, 0x02, false, RMM }, - { RMM_REGS_RDIMM, 0x3f, 0x01, true, 0x03, 0x00, false, RMM }, - { RMM_HEAT_SP, 0x40, 0x01, true, 0x80, 0x07, false, RMM }, - { RMM_HEAT_SP_CHARS, 0x40, 0x01, true, 0x7F, 0x00, false, RMM }, - { RMM_MFR_ID_CODE, 0x42, 0x02, false, 0x00, 0x00, true, RMM }, - { RMM_REG_REV_NUM, 0x43, 0x01, false, 0x00, 0x00, false, RMM }, - { RMM_REG_TYPE, 0x44, 0x01, true, 0x07, 0x00, false, RMM }, - { RMM_RC1, 0x45, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC0, 0x45, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC3, 0x46, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC2, 0x46, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC5, 0x47, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC4, 0x47, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC7, 0x48, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC6, 0x48, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC9, 0x49, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC8, 0x49, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC11, 0x4a, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC10, 0x4a, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC13, 0x4b, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC12, 0x4b, 0x01, true, 0x0f, 0x00, false, RMM }, - { RMM_RC15, 0x4c, 0x01, true, 0xf0, 0x04, false, RMM }, - { RMM_RC14, 0x4c, 0x01, true, 0x0f, 0x00, false, RMM }, - { LRMM_HEAT_SP, 0x3f, 0x01, true, 0x80, 0x07, false, LRMM }, - { LRMM_RANK_NUMBERING, 0x3f, 0x01, true, 0x20, 0x05, false, LRMM }, - { LRMM_MEMBUF_ORIEN, 0x3f, 0x01, true, 0x10, 0x04, false, LRMM }, - { LRMM_NUM_ROWS, 0x3f, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_MIRRORING, 0x3f, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_REVISION_NUM, 0x40, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_MFR_ID_CODE, 0x42, 0x02, false, 0x00, 0x00, true, LRMM }, - { LRMM_F0RC3, 0x43, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F0RC2, 0x43, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F0RC5, 0x44, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F0RC4, 0x44, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F1RC11, 0x45, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F1RC8, 0x45, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F1RC13, 0x46, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F1RC12, 0x46, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F1RC15, 0x47, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F1RC14, 0x47, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F3RC9_800_1600, 0x48, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F3RC8_800_1600, 0x48, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F4RC11_800_1600, 0x49, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F3RC11_800_1600, 0x49, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F4RC10_800_1600, 0x49, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F3RC10_800_1600, 0x49, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F6RC11_800_1600, 0x4a, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F5RC11_800_1600, 0x4a, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F6RC10_800_1600, 0x4a, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F5RC10_800_1600, 0x4a, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F8RC11_800_1600, 0x4b, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F7RC11_800_1600, 0x4b, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F8RC10_800_1600, 0x4b, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F7RC10_800_1600, 0x4b, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F10RC11_800_1600, 0x4c, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F9RC11_800_1600, 0x4c, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F10RC10_800_1600, 0x4c, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F9RC10_800_1600, 0x4c, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_RTT_WR_800_1600, 0x4d, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_RTT_NOM_800_1600, 0x4d, 0x01, true, 0x1c, 0x02, false, LRMM }, - { LRMM_IMPEDANCE_800_1600, 0x4d, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F3RC9_1333_1600, 0x4e, 0x01, true, 0xF0, 0x04, false, LRMM }, - { LRMM_F3RC8_1333_1600, 0x4e, 0x01, true, 0x0F, 0x00, false, LRMM }, - { LRMM_F4RC11_1333_1600, 0x4f, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F3RC11_1333_1600, 0x4f, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F4RC10_1333_1600, 0x4f, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F3RC10_1333_1600, 0x4f, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F6RC11_1333_1600, 0x50, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F5RC11_1333_1600, 0x50, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F6RC10_1333_1600, 0x50, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F5RC10_1333_1600, 0x50, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F8RC11_1333_1600, 0x51, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F7RC11_1333_1600, 0x51, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F8RC10_1333_1600, 0x51, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F7RC10_1333_1600, 0x51, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F10RC11_1333_1600, 0x52, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F9RC11_1333_1600, 0x52, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F10RC10_1333_1600, 0x52, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F9RC10_1333_1600, 0x52, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_RTT_WR_1333_1600, 0x53, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_RTT_NOM_1333_1600, 0x53, 0x01, true, 0x1c, 0x02, false, LRMM }, - { LRMM_IMPEDANCE_1333_1600, 0x53, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F3RC9_1866_2133, 0x54, 0x01, true, 0xf0, 0x04, false, LRMM }, - { LRMM_F3RC8_1866_2133, 0x54, 0x01, true, 0x0f, 0x00, false, LRMM }, - { LRMM_F4RC11_1866_2133, 0x55, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F3RC11_1866_2133, 0x55, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F4RC10_1866_2133, 0x55, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F3RC10_1866_2133, 0x55, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F6RC11_1866_2133, 0x56, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F5RC11_1866_2133, 0x56, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F6RC10_1866_2133, 0x56, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F5RC10_1866_2133, 0x56, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F8RC11_1866_2133, 0x57, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F7RC11_1866_2133, 0x57, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F8RC10_1866_2133, 0x57, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F7RC10_1866_2133, 0x57, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_F10RC11_1866_2133, 0x58, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_F9RC11_1866_2133, 0x58, 0x01, true, 0x30, 0x04, false, LRMM }, - { LRMM_F10RC10_1866_2133, 0x58, 0x01, true, 0x0c, 0x02, false, LRMM }, - { LRMM_F9RC10_1866_2133, 0x58, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_RTT_WR_1866_2133, 0x59, 0x01, true, 0xc0, 0x06, false, LRMM }, - { LRMM_RTT_NOM_1866_2133, 0x59, 0x01, true, 0x1c, 0x02, false, LRMM }, - { LRMM_IMPEDANCE_1866_2133, 0x59, 0x01, true, 0x03, 0x00, false, LRMM }, - { LRMM_MIN_DELAY_150V, 0x5a, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_MAX_DELAY_150V, 0x5b, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_MIN_DELAY_135V, 0x5c, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_MAX_DELAY_135V, 0x5d, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_MIN_DELAY_125V, 0x5e, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_MAX_DELAY_125V, 0x5f, 0x01, true, 0x7f, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE0, 0x66, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE1, 0x67, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE2, 0x68, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE3, 0x69, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE4, 0x6a, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE5, 0x6b, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE6, 0x6c, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE7, 0x6d, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE8, 0x6e, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE9, 0x6f, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE10, 0x70, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE11, 0x71, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE12, 0x72, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE13, 0x73, 0x01, false, 0x00, 0x00, false, LRMM }, - { LRMM_PERSONALITY_BYTE14, 0x74, 0x01, false, 0x00, 0x00, false, LRMM }, - // ---------------------------------------------------------------------------------- + // --------------------------------------------------------------------------------------- + // Keyword offset size Use Bitmsk Shift Spec Writ- Mod + // Bitmsk Number Case able Spec + // --------------------------------------------------------------------------------------- + { CRC_EXCLUDE, 0x00, 0x01, true, 0x80, 0x07, false, false, NA }, + { SPD_BYTES_TOTAL, 0x00, 0x01, true, 0x70, 0x04, false, false, NA }, + { SPD_BYTES_USED, 0x00, 0x01, true, 0x0F, 0x00, false, false, NA }, + { SPD_MAJOR_REVISION, 0x01, 0x01, true, 0xF0, 0x04, false, false, NA }, + { SPD_MINOR_REVISION, 0x01, 0x01, true, 0x0F, 0x00, false, false, NA }, + { BASIC_MEMORY_TYPE, 0x02, 0x01, false, 0x00, 0x00, false, false, NA }, + { MODULE_TYPE, 0x03, 0x01, true, 0x0F, 0x00, false, false, NA }, + { BANK_ADDRESS_BITS, 0x04, 0x01, true, 0x70, 0x04, false, false, NA }, + { DENSITY, 0x04, 0x01, true, 0x0F, 0x00, false, false, NA }, + { ROW_ADDRESS, 0x05, 0x01, true, 0x38, 0x03, false, false, NA }, + { COL_ADDRESS, 0x05, 0x01, true, 0x07, 0x00, false, false, NA }, + { MODULE_NOMINAL_VOLTAGE, 0x06, 0x01, true, 0x07, 0x00, false, false, NA }, + { MODULE_RANKS, 0x07, 0x01, true, 0x38, 0x03, false, false, NA }, + { MODULE_DRAM_WIDTH, 0x07, 0x01, true, 0x07, 0x00, false, false, NA }, + { ECC_BITS, 0x08, 0x01, true, 0x18, 0x03, false, false, NA }, + { MODULE_MEMORY_BUS_WIDTH, 0x08, 0x01, true, 0x07, 0x00, false, false, NA }, + { FTB_DIVIDEND, 0x09, 0x01, true, 0xF0, 0x04, false, false, NA }, + { FTB_DIVISOR, 0x09, 0x01, true, 0x0F, 0x00, false, false, NA }, + { MTB_DIVIDEND, 0x0a, 0x01, false, 0x00, 0x00, false, false, NA }, + { MTB_DIVISOR, 0x0b, 0x01, false, 0x00, 0x00, false, false, NA }, + { TCK_MIN, 0x0c, 0x01, false, 0x00, 0x00, false, false, NA }, + { CAS_LATENCIES_SUPPORTED, 0x0f, 0x02, true, 0x7F, 0x00, true, false, NA }, + { MIN_CAS_LATENCY, 0x10, 0x01, false, 0x00, 0x00, false, false, NA }, + { TWR_MIN, 0x11, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRCD_MIN, 0x12, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRRD_MIN, 0x13, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRP_MIN, 0x14, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRC_MIN, 0x15, 0x02, true, 0xF0, 0x04, true, false, NA }, + { TRAS_MIN, 0x15, 0x02, true, 0x0F, 0x00, true, false, NA }, + { TRFC_MIN, 0x19, 0x02, false, 0x00, 0x00, true, false, NA }, + { TWTR_MIN, 0x1a, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRTP_MIN, 0x1b, 0x01, false, 0x00, 0x00, false, false, NA }, + { TFAW_MIN, 0x1c, 0x02, true, 0x0F, 0x00, true, false, NA }, + { DLL_OFF, 0x1e, 0x01, true, 0x80, 0x07, false, false, NA }, + { RZQ_7, 0x1e, 0x01, true, 0x02, 0x01, false, false, NA }, + { RZQ_6, 0x1e, 0x01, true, 0x01, 0x00, false, false, NA }, + { PASR, 0x1f, 0x01, true, 0x80, 0x07, false, false, NA }, + { ODTS, 0x1f, 0x01, true, 0x08, 0x03, false, false, NA }, + { ASR, 0x1f, 0x01, true, 0x04, 0x02, false, false, NA }, + { ETR_1X, 0x1f, 0x01, true, 0x02, 0x01, false, false, NA }, + { ETR, 0x1f, 0x01, true, 0x01, 0x00, false, false, NA }, + { THERMAL_SENSOR_PRESENT, 0x20, 0x01, true, 0x80, 0x07, false, false, NA }, + { THERMAL_SENSOR_ACCURACY, 0x20, 0x01, true, 0x7F, 0x00, false, false, NA }, + { SDRAM_DEVICE_TYPE_NONSTD, 0x21, 0x01, true, 0x80, 0x07, false, false, NA }, + { SDRAM_DEVICE_TYPE, 0x21, 0x01, true, 0x7F, 0x00, false, false, NA }, + { MODULE_TYPE_SPECIFIC_SECTION, 0x3c, 0x39, false, 0x00, 0x00, false, false, NA }, + { MODULE_MANUFACTURER_ID, 0x76, 0x02, false, 0x00, 0x00, true, false, NA }, + { MODULE_MANUFACTURING_LOCATION, 0x77, 0x01, false, 0x00, 0x00, false, false, NA }, + { MODULE_MANUFACTURING_DATE, 0x78, 0x02, false, 0x00, 0x00, false, false, NA }, + { MODULE_SERIAL_NUMBER, 0x7a, 0x04, false, 0x00, 0x00, false, false, NA }, + { MODULE_CRC, 0x7e, 0x02, false, 0x00, 0x00, false, false, NA }, + { MODULE_PART_NUMBER, 0x80, 0x12, false, 0x00, 0x00, false, false, NA }, + { MODULE_REVISION_CODE, 0x92, 0x02, false, 0x00, 0x00, false, false, NA }, + { DRAM_MANUFACTURER_ID, 0x95, 0x02, false, 0x00, 0x00, true, false, NA }, + { MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, false, 0x00, 0x00, false, false, NA }, + { TCKMIN_FINE_OFFSET, 0x22, 0x01, false, 0x00, 0x00, false, false, NA }, + { TAAMIN_FINE_OFFSET, 0x23, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRCDMIN_FINE_OFFSET, 0x24, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRPMIN_FINE_OFFSET, 0x25, 0x01, false, 0x00, 0x00, false, false, NA }, + { TRCMIN_FINE_OFFSET, 0x26, 0x01, false, 0x00, 0x00, false, false, NA }, + { MODULE_THERMAL_SENSOR, 0x20, 0x01, false, 0x00, 0x00, false, false, NA }, + { SDRAM_OPTIONAL_FEATURES, 0x1e, 0x01, false, 0x00, 0x00, false, false, NA }, + { SDRAM_THERMAL_REFRESH_OPTIONS, 0x1f, 0x01, false, 0x00, 0x00, false, false, NA }, + { DIMM_BAD_DQ_DATA, 0xb0, 0x50, false, 0x00, 0x00, false, true, NA }, + { MODSPEC_COM_NOM_HEIGHT_MAX, 0x3c, 0x01, true, 0x0f, 0x00, false, false, ALL }, + { MODSPEC_COM_MAX_THICK_BACK, 0x3d, 0x01, true, 0xf0, 0x04, false, false, ALL }, + { MODSPEC_COM_MAX_THICK_FRONT, 0x3d, 0x01, true, 0x0f, 0x00, false, false, ALL }, + { MODSPEC_COM_RAW_CARD_EXT, 0x3e, 0x01, true, 0x80, 0x07, false, false, ALL }, + { MODSPEC_COM_RAW_CARD_REV, 0x3e, 0x01, true, 0x60, 0x05, false, false, ALL }, + { MODSPEC_COM_RAW_CARD, 0x3e, 0x01, true, 0x0f, 0x00, false, false, ALL }, + { MODSPEC_COM_ADDR_MAPPING, 0x3f, 0x01, true, 0x01, 0x00, false, false, ALL }, + { RMM_ROWS_RDIMM, 0x3f, 0x01, true, 0x0c, 0x02, false, false, RMM }, + { RMM_REGS_RDIMM, 0x3f, 0x01, true, 0x03, 0x00, false, false, RMM }, + { RMM_HEAT_SP, 0x40, 0x01, true, 0x80, 0x07, false, false, RMM }, + { RMM_HEAT_SP_CHARS, 0x40, 0x01, true, 0x7F, 0x00, false, false, RMM }, + { RMM_MFR_ID_CODE, 0x42, 0x02, false, 0x00, 0x00, true, false, RMM }, + { RMM_REG_REV_NUM, 0x43, 0x01, false, 0x00, 0x00, false, false, RMM }, + { RMM_REG_TYPE, 0x44, 0x01, true, 0x07, 0x00, false, false, RMM }, + { RMM_RC1, 0x45, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC0, 0x45, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC3, 0x46, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC2, 0x46, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC5, 0x47, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC4, 0x47, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC7, 0x48, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC6, 0x48, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC9, 0x49, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC8, 0x49, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC11, 0x4a, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC10, 0x4a, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC13, 0x4b, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC12, 0x4b, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { RMM_RC15, 0x4c, 0x01, true, 0xf0, 0x04, false, false, RMM }, + { RMM_RC14, 0x4c, 0x01, true, 0x0f, 0x00, false, false, RMM }, + { LRMM_HEAT_SP, 0x3f, 0x01, true, 0x80, 0x07, false, false, LRMM }, + { LRMM_RANK_NUMBERING, 0x3f, 0x01, true, 0x20, 0x05, false, false, LRMM }, + { LRMM_MEMBUF_ORIEN, 0x3f, 0x01, true, 0x10, 0x04, false, false, LRMM }, + { LRMM_NUM_ROWS, 0x3f, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_MIRRORING, 0x3f, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_REVISION_NUM, 0x40, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_MFR_ID_CODE, 0x42, 0x02, false, 0x00, 0x00, true, false, LRMM }, + { LRMM_F0RC3, 0x43, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F0RC2, 0x43, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F0RC5, 0x44, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F0RC4, 0x44, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F1RC11, 0x45, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F1RC8, 0x45, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F1RC13, 0x46, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F1RC12, 0x46, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F1RC15, 0x47, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F1RC14, 0x47, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F3RC9_800_1600, 0x48, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F3RC8_800_1600, 0x48, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F4RC11_800_1600, 0x49, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F3RC11_800_1600, 0x49, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F4RC10_800_1600, 0x49, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F3RC10_800_1600, 0x49, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F6RC11_800_1600, 0x4a, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F5RC11_800_1600, 0x4a, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F6RC10_800_1600, 0x4a, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F5RC10_800_1600, 0x4a, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F8RC11_800_1600, 0x4b, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F7RC11_800_1600, 0x4b, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F8RC10_800_1600, 0x4b, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F7RC10_800_1600, 0x4b, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F10RC11_800_1600, 0x4c, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F9RC11_800_1600, 0x4c, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F10RC10_800_1600, 0x4c, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F9RC10_800_1600, 0x4c, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_RTT_WR_800_1600, 0x4d, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_RTT_NOM_800_1600, 0x4d, 0x01, true, 0x1c, 0x02, false, false, LRMM }, + { LRMM_IMPEDANCE_800_1600, 0x4d, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F3RC9_1333_1600, 0x4e, 0x01, true, 0xF0, 0x04, false, false, LRMM }, + { LRMM_F3RC8_1333_1600, 0x4e, 0x01, true, 0x0F, 0x00, false, false, LRMM }, + { LRMM_F4RC11_1333_1600, 0x4f, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F3RC11_1333_1600, 0x4f, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F4RC10_1333_1600, 0x4f, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F3RC10_1333_1600, 0x4f, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F6RC11_1333_1600, 0x50, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F5RC11_1333_1600, 0x50, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F6RC10_1333_1600, 0x50, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F5RC10_1333_1600, 0x50, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F8RC11_1333_1600, 0x51, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F7RC11_1333_1600, 0x51, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F8RC10_1333_1600, 0x51, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F7RC10_1333_1600, 0x51, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F10RC11_1333_1600, 0x52, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F9RC11_1333_1600, 0x52, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F10RC10_1333_1600, 0x52, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F9RC10_1333_1600, 0x52, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_RTT_WR_1333_1600, 0x53, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_RTT_NOM_1333_1600, 0x53, 0x01, true, 0x1c, 0x02, false, false, LRMM }, + { LRMM_IMPEDANCE_1333_1600, 0x53, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F3RC9_1866_2133, 0x54, 0x01, true, 0xf0, 0x04, false, false, LRMM }, + { LRMM_F3RC8_1866_2133, 0x54, 0x01, true, 0x0f, 0x00, false, false, LRMM }, + { LRMM_F4RC11_1866_2133, 0x55, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F3RC11_1866_2133, 0x55, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F4RC10_1866_2133, 0x55, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F3RC10_1866_2133, 0x55, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F6RC11_1866_2133, 0x56, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F5RC11_1866_2133, 0x56, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F6RC10_1866_2133, 0x56, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F5RC10_1866_2133, 0x56, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F8RC11_1866_2133, 0x57, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F7RC11_1866_2133, 0x57, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F8RC10_1866_2133, 0x57, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F7RC10_1866_2133, 0x57, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_F10RC11_1866_2133, 0x58, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_F9RC11_1866_2133, 0x58, 0x01, true, 0x30, 0x04, false, false, LRMM }, + { LRMM_F10RC10_1866_2133, 0x58, 0x01, true, 0x0c, 0x02, false, false, LRMM }, + { LRMM_F9RC10_1866_2133, 0x58, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_RTT_WR_1866_2133, 0x59, 0x01, true, 0xc0, 0x06, false, false, LRMM }, + { LRMM_RTT_NOM_1866_2133, 0x59, 0x01, true, 0x1c, 0x02, false, false, LRMM }, + { LRMM_IMPEDANCE_1866_2133, 0x59, 0x01, true, 0x03, 0x00, false, false, LRMM }, + { LRMM_MIN_DELAY_150V, 0x5a, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_MAX_DELAY_150V, 0x5b, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_MIN_DELAY_135V, 0x5c, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_MAX_DELAY_135V, 0x5d, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_MIN_DELAY_125V, 0x5e, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_MAX_DELAY_125V, 0x5f, 0x01, true, 0x7f, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE0, 0x66, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE1, 0x67, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE2, 0x68, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE3, 0x69, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE4, 0x6a, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE5, 0x6b, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE6, 0x6c, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE7, 0x6d, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE8, 0x6e, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE9, 0x6f, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE10, 0x70, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE11, 0x71, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE12, 0x72, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE13, 0x73, 0x01, false, 0x00, 0x00, false, false, LRMM }, + { LRMM_PERSONALITY_BYTE14, 0x74, 0x01, false, 0x00, 0x00, false, false, LRMM }, + // --------------------------------------------------------------------------------------- }; diff --git a/src/usr/spd/test/spdtest.H b/src/usr/spd/test/spdtest.H index e00abe773..94b6df38b 100755 --- a/src/usr/spd/test/spdtest.H +++ b/src/usr/spd/test/spdtest.H @@ -59,6 +59,19 @@ void getDIMMTargets ( TargetHandleList & o_dimmList ) return; } +errlHndl_t getMemType( TARGETING::Target * i_target, + uint8_t & i_memType ) +{ + errlHndl_t err = NULL; + size_t theSize = 0x1; + err = deviceRead( i_target, + &i_memType, + theSize, + DEVICE_SPD_ADDRESS( SPD::BASIC_MEMORY_TYPE ) ); + + return err; +} + class SPDTest: public CxxTest::TestSuite { public: @@ -100,11 +113,8 @@ class SPDTest: public CxxTest::TestSuite // Get the DDR revision uint8_t memType = 0x0; - size_t memTypeSize = 0x1; - err = deviceRead( theTarget, - &memType, - memTypeSize, - DEVICE_SPD_ADDRESS( SPD::BASIC_MEMORY_TYPE ) ); + err = getMemType( theTarget, + memType ); if( err ) { @@ -226,21 +236,81 @@ class SPDTest: public CxxTest::TestSuite } // Operate on first DIMM + cmds++; theTarget = dimmList[0]; uint8_t * theData = NULL; size_t theSize = 0; - cmds++; + // Get Memory Type + uint8_t memType = 0x0; + err = getMemType( theTarget, + memType ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWrite - failed to read memtype!" ); + errlCommit( err, + SPD_COMP_ID ); + break; + } + + // Get the size + if( SPD_DDR3 == memType ) + { + for( uint32_t entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( SPD::DIMM_BAD_DQ_DATA == ddr3Data[entry].keyword ) + { + theSize = ddr3Data[entry].length; + break; + } + } + } + else + { + fails++; + TRACFCOMP( g_trac_spd, + "testSpdWrite - memory type: 0x%04x", + memType ); + TS_FAIL( "testSpdWrite - Unsupported Memory Type!" ); + errlCommit( err, + SPD_COMP_ID ); + break; + } + + // Allocate data buffer + theData = static_cast<uint8_t*>(malloc( theSize )); + + // Read the data out first + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWrite - failed to read DIMM Bad DQ data!" ); + errlCommit( err, + SPD_COMP_ID ); + break; + } + + // Write the data back err = deviceWrite( theTarget, theData, theSize, - DEVICE_SPD_ADDRESS( SPD_FIRST_NORM_KEYWORD ) ); + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); - if( NULL == err ) + if( err ) { // No error returned, failure fails++; - TS_FAIL( "testSpdWrite - No error returned from deviceWrite()" ); + TS_FAIL( "testSpdWrite - Error writing data to DIMM Bad DQ " + "data" ); break; } else @@ -369,6 +439,70 @@ class SPDTest: public CxxTest::TestSuite fails, cmds ); } + /** + */ + void testSpdInvalidWrite ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdInvalidWrite()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdInvalidSize - No DIMMs found!" ); + break; + } + + // Test on first DIMM only. + theTarget = dimmList[0]; + size_t theSize = 0x10; + uint8_t * theData = static_cast<uint8_t*>(malloc( theSize )); + + cmds++; + err = deviceWrite( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( SPD::SPD_FIRST_NORM_KEYWORD ) ); + + // clean up the data + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + + if( NULL == err ) + { + fails++; + TS_FAIL( "No failure for Invalid Write attempt to " + "SPD_FIRST_NORM_KEYWORD" ); + break; + } + else + { + delete err; + err = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testSpdInvalidWrite - %d/%d fails", + fails, cmds ); + } + /** * @brief This test will test reading the Module specific keywords. @@ -546,7 +680,7 @@ class SPDTest: public CxxTest::TestSuite * order, according to the keyword enumeration, to enable the search * algorithm to work correctly. */ - void testspdDDR3TableOrder( void ) + void testspdDDR3TableOrder ( void ) { uint64_t prevKeyword = 0x0; uint64_t fails = 0x0; |