summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTerry J. Opie <opiet@us.ibm.com>2012-01-03 15:06:17 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-02-16 13:41:54 -0600
commit4690f9cb99f289dd88b1f1047145841d8386b0d3 (patch)
tree6a08e8c640ace271b0019bef5a542646d0969807
parent5f6568a59e35570f149d148f0cb24e068e70efcf (diff)
downloadtalos-hostboot-4690f9cb99f289dd88b1f1047145841d8386b0d3.tar.gz
talos-hostboot-4690f9cb99f289dd88b1f1047145841d8386b0d3.zip
DIMM Presence Detect
- Detect DIMMs by reading BASIC_MEMORY_TYPE - Testcases to test DIMM Presence Detect - Added new SPD Keyword Enumeration - Modified table lookup for DRAM_MANUFACTURER_ID - New DIMM SPD data from Hardware team Change-Id: I11a0b8ad4b13d6200a58efc7459396f0a12695f2 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/646 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/usr/spd/spdenums.H1
-rw-r--r--src/include/usr/spd/spdreasoncodes.H1
-rwxr-xr-xsrc/usr/spd/dimmPres.C158
-rw-r--r--src/usr/spd/dimmspd.datbin256 -> 257 bytes
-rw-r--r--src/usr/spd/makefile2
-rwxr-xr-xsrc/usr/spd/spd.C63
-rwxr-xr-xsrc/usr/spd/spd.H30
-rwxr-xr-xsrc/usr/spd/spdDDR3.H3
-rwxr-xr-xsrc/usr/spd/test/dimmPrestest.H202
-rwxr-xr-xsrc/usr/spd/test/spdtest.H2
10 files changed, 436 insertions, 26 deletions
diff --git a/src/include/usr/spd/spdenums.H b/src/include/usr/spd/spdenums.H
index 8ca1cd39f..c685fa99e 100644
--- a/src/include/usr/spd/spdenums.H
+++ b/src/include/usr/spd/spdenums.H
@@ -101,6 +101,7 @@ enum
MODULE_THERMAL_SENSOR = 0x3c,
SDRAM_OPTIONAL_FEATURES = 0x3d,
SDRAM_THERMAL_REFRESH_OPTIONS = 0x3e,
+ DIMM_BAD_DQ_DATA = 0x3f,
// This keyword should be last in the list
SPD_LAST_KEYWORD,
diff --git a/src/include/usr/spd/spdreasoncodes.H b/src/include/usr/spd/spdreasoncodes.H
index d1c128100..9fb5515e4 100644
--- a/src/include/usr/spd/spdreasoncodes.H
+++ b/src/include/usr/spd/spdreasoncodes.H
@@ -52,6 +52,7 @@ enum spdModuleId
SPD_READ_BINARY_FILE = 0x04,
SPD_WRITE_KEYWORD_VALUE = 0x05,
SPD_SPECIAL_CASES = 0x06,
+ SPD_PRESENCE_DETECT = 0x07,
};
/**
diff --git a/src/usr/spd/dimmPres.C b/src/usr/spd/dimmPres.C
new file mode 100755
index 000000000..57183f650
--- /dev/null
+++ b/src/usr/spd/dimmPres.C
@@ -0,0 +1,158 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/spd/dimmPres.C $
+//
+// 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
+/**
+ * @file dimmPres.C
+ *
+ * @brief Implementation of the DIMM Presence detect.
+ *
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/targetservice.H>
+#include <devicefw/driverif.H>
+#include <spd/spdreasoncodes.H>
+#include <spd/spdenums.H>
+
+#include "spd.H"
+
+// ----------------------------------------------
+// Globals
+// ----------------------------------------------
+
+// ----------------------------------------------
+// Trace definitions
+// ----------------------------------------------
+extern trace_desc_t * g_trac_spd;
+
+// ------------------------
+// Macros for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+//#define TRACSSCOMP(args...) TRACFCOMP(args)
+#define TRACSSCOMP(args...)
+
+// ----------------------------------------------
+// Defines
+// ----------------------------------------------
+
+
+namespace SPD
+{
+
+// Register the Presence detect code with the framework.
+DEVICE_REGISTER_ROUTE( DeviceFW::READ,
+ DeviceFW::PRESENT,
+ TARGETING::TYPE_DIMM,
+ dimmPresenceDetect );
+
+// ------------------------------------------------------------------
+// dimmPresenceDetect
+// ------------------------------------------------------------------
+errlHndl_t dimmPresenceDetect( 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;
+ bool present = false;
+ size_t presentSz = sizeof(present);
+
+ TRACSSCOMP( g_trac_spd,
+ ENTER_MRK"spdPresenceDetect()" );
+
+ do
+ {
+ // Check to be sure that the buffer is big enough.
+ if( !(io_buflen >= sizeof(bool)) )
+ {
+ TRACFCOMP( g_trac_spd,
+ ERR_MRK"spdPresenceDetect() - Invalid Data Length: %d",
+ io_buflen );
+
+ /*@
+ * @errortype
+ * @reasoncode SPD_INSUFFICIENT_BUFFER_SIZE
+ * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE
+ * @moduleid SPD_PRESENCE_DETECT
+ * @userdata1 Buffer Length
+ * @userdata2 <UNUSED>
+ * @devdesc Buffer for checking Presence Detect was not the correct size.
+ */
+ err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SPD_PRESENCE_DETECT,
+ SPD_INSUFFICIENT_BUFFER_SIZE,
+ TO_UINT64(io_buflen),
+ 0x0 );
+
+ break;
+ }
+
+ // 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 );
+
+ if( err )
+ {
+ // If an error is returned, the DIMM is not present.
+ present = false;
+ TRACUCOMP( g_trac_spd,
+ INFO_MRK"Dimm was found to be NOT present." );
+
+ memcpy( io_buffer, &present, presentSz );
+ io_buflen = 0;
+
+ // Delete the error
+ delete err;
+ err = NULL;
+ }
+ else
+ {
+ // DIMM is present...
+ present = true;
+ TRACUCOMP( g_trac_spd,
+ INFO_MRK"Dimm was found to be present." );
+
+ memcpy( io_buffer, &present, presentSz );
+ io_buflen = presentSz;
+ }
+ } while( 0 );
+
+ TRACSSCOMP( g_trac_spd,
+ EXIT_MRK"spdPresenceDetect()" );
+
+ return err;
+} // end dimmPresenceDetect
+
+
+}; // end namespace SPD
diff --git a/src/usr/spd/dimmspd.dat b/src/usr/spd/dimmspd.dat
index 8abf344bd..cb4f85c83 100644
--- a/src/usr/spd/dimmspd.dat
+++ b/src/usr/spd/dimmspd.dat
Binary files differ
diff --git a/src/usr/spd/makefile b/src/usr/spd/makefile
index dc71eb1c8..9cb0b14cb 100644
--- a/src/usr/spd/makefile
+++ b/src/usr/spd/makefile
@@ -23,7 +23,7 @@
ROOTPATH = ../../..
MODULE = spd
-OBJS = spd.o
+OBJS = spd.o dimmPres.o
SUBDIRS = test.d
diff --git a/src/usr/spd/spd.C b/src/usr/spd/spd.C
index 0a1dc5bae..1286385cd 100755
--- a/src/usr/spd/spd.C
+++ b/src/usr/spd/spd.C
@@ -144,18 +144,18 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword,
INFO_MRK"Mem Type: %04x",
memType );
- // If the user wanted the Basic Memory Type, return this now
- if( BASIC_MEMORY_TYPE == i_keyword )
- {
- io_buflen = MEM_TYPE_ADDR_SZ;
- memcpy( io_buffer, &memType, io_buflen );
- break;
- }
-
// Check the Basic Memory Type to be sure its valid before
// continuing.
if( SPD_DDR3 == memType )
{
+ // If the user wanted the Basic memory type, return this now.
+ if( BASIC_MEMORY_TYPE == i_keyword )
+ {
+ io_buflen = MEM_TYPE_ADDR_SZ;
+ memcpy( io_buffer, &memType, io_buflen );
+ break;
+ }
+
// Read the keyword value
err = spdGetValue( i_keyword,
io_buffer,
@@ -596,13 +596,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword,
if( err ) break;
- // Mask and shift if needed
- if( ddr3Data[i_entry].useBitMask )
- {
- tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask;
- tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift;
- }
-
// Get LSB
err = spdFetchData( 0x18,
1, /* Read 1 byte at a time */
@@ -659,7 +652,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword,
// Byte 0x75 [7:0]
// Byte 0x76 [7:0] - MSB
-
// Check size of buffer
err = spdCheckSize( io_buflen,
2,
@@ -675,13 +667,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword,
if( err ) break;
- // Mask and shift if needed
- if( ddr3Data[i_entry].useBitMask )
- {
- tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask;
- tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift;
- }
-
// Get LSB
err = spdFetchData( 0x75,
1, /* Read 1 byte at a time */
@@ -694,6 +679,38 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword,
io_buflen = 2;
break;
+ case DRAM_MANUFACTURER_ID:
+ // Length 2 bytes
+ // Byte 0x94 [7:0]
+ // Byte 0x95 [7:0] - MSB
+
+ // Check size of buffer
+ err = spdCheckSize( io_buflen,
+ 2,
+ i_keyword );
+
+ if( err ) break;
+
+ // Get MSB
+ err = spdFetchData( ddr3Data[i_entry].offset,
+ 1, /*Read 1 byte at a time */
+ &tmpBuffer[0],
+ i_target );
+
+ if( err ) break;
+
+ // Get LSB
+ err = spdFetchData( 0x94,
+ 1, /* Read 1 byte at a time */
+ &tmpBuffer[1],
+ i_target );
+
+ if( err ) break;
+
+ // Set number of bytes read
+ io_buflen = 2;
+ break;
+
default:
TRACFCOMP( g_trac_spd,
ERR_MRK"Unknown keyword (0x%04x) for DDR3 special cases!",
diff --git a/src/usr/spd/spd.H b/src/usr/spd/spd.H
index 81da52888..087d3353e 100755
--- a/src/usr/spd/spd.H
+++ b/src/usr/spd/spd.H
@@ -256,6 +256,36 @@ errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr,
size_t i_numBytes,
void * o_data );
+/**
+ * @brief This function performs the presence detect for all DIMMs.
+ *
+ * @param[in] i_opType - Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ *
+ * @param[in] i_target - The target to query.
+ *
+ * @param[in/out] io_buffer - Buffer to contain the boolean for presence
+ * detect.
+ *
+ * @param[in/out] io_buflen - Size of buffer provided for doing the presence
+ * detect. Will always be 1. If size returned equals 0, the request
+ * failed.
+ *
+ * @param[in] i_accessType - DeviceFW::AccessType enum.
+ *
+ * @param[in] i_args - An arguement for the Device Driver framework. There
+ * are no args for this function.
+ *
+ * @return errlHndl_t - NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t & io_buflen,
+ int64_t i_accessType,
+ va_list i_args );
+
}; // end SPD namespace
#endif // __SPD_H
diff --git a/src/usr/spd/spdDDR3.H b/src/usr/spd/spdDDR3.H
index 4b36b40a9..57e66eabc 100755
--- a/src/usr/spd/spdDDR3.H
+++ b/src/usr/spd/spdDDR3.H
@@ -114,8 +114,9 @@ KeywordData ddr3Data[] =
{ MODULE_CRC, 0x7e, 0x02, false, 0x00, 0x00, false },
{ MODULE_PART_NUMBER, 0x80, 0x12, false, 0x00, 0x00, false },
{ MODULE_REVISION_CODE, 0x92, 0x02, false, 0x00, 0x00, false },
- { DRAM_MANUFACTURER_ID, 0x94, 0x02, false, 0x00, 0x00, false },
+ { DRAM_MANUFACTURER_ID, 0x95, 0x02, false, 0x00, 0x00, true },
{ MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, false, 0x00, 0x00, false },
+ { DIMM_BAD_DQ_DATA, 0xb0, 0x50, false, 0x00, 0x00, false },
// ----------------------------------------------------------------------------------
};
diff --git a/src/usr/spd/test/dimmPrestest.H b/src/usr/spd/test/dimmPrestest.H
new file mode 100755
index 000000000..46dad62c5
--- /dev/null
+++ b/src/usr/spd/test/dimmPrestest.H
@@ -0,0 +1,202 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/spd/test/dimmPrestest.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
+#ifndef __DIMMPRESTEST_H
+#define __DIMMPRESTEST_H
+
+/**
+ * @file dimmPrestest.H
+ *
+ * @brief Test cases for DIMM Presence detect
+ */
+#include <sys/time.h>
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <devicefw/driverif.H>
+#include <targeting/predicates/predicatectm.H>
+
+#include <spd/spdreasoncodes.H>
+#include <spd/spdenums.H>
+#include "spdtest.H"
+#include "../spd.H"
+
+extern trace_desc_t* g_trac_spd;
+
+using namespace TARGETING;
+using namespace SPD;
+
+class DIMMPresTest: public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief This test is for testing the DIMM Presence detect logic.
+ */
+ void testDimmPres ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ bool present = false;
+ size_t presentSize = sizeof(present);
+
+ TRACFCOMP( g_trac_spd,
+ ENTER_MRK"testDimmPres()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get DIMM Targets
+ TargetHandleList dimmList;
+ getDIMMTargets( dimmList );
+
+ if( ( 0 == dimmList.size() ) ||
+ ( NULL == dimmList[0] ) )
+ {
+ TRACFCOMP( g_trac_spd,
+ "testDimmPres() - No DIMMs found!" );
+ break;
+ }
+
+ for( uint32_t dimm = 0; dimm < dimmList.size(); dimm++ )
+ {
+ cmds++;
+ theTarget = dimmList[dimm];
+
+ // Check presence
+ err = deviceRead( theTarget,
+ &present,
+ presentSize,
+ DEVICE_PRESENT_ADDRESS() );
+
+ if( err )
+ {
+ fails++;
+ TS_FAIL( "testDimmPres() - Error returned from DIMM Presence "
+ "Detect call!" );
+ errlCommit( err,
+ SPD_COMP_ID );
+ continue;
+ }
+ else if( presentSize != sizeof(present) )
+ {
+ fails++;
+ TS_FAIL( "testDimmPrs() - Size of Presence buffer is not size "
+ "of boolean!" );
+ continue;
+ }
+ else
+ {
+ // Test was good.
+ }
+ }
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_spd,
+ "testDimmPres - %d/%d fails",
+ fails, cmds );
+ }
+
+
+ /**
+ * @brief This test tests that invalid sizes for Presence detect
+ * return errors.
+ */
+ void testDimmPresInvalidSize ( void )
+ {
+ errlHndl_t err = NULL;
+ uint64_t cmds = 0x0;
+ uint64_t fails = 0x0;
+ bool present = false;
+ size_t presentSize = 0x0;
+
+ TRACFCOMP( g_trac_spd,
+ ENTER_MRK"testDimmPresInvalidSize()" );
+
+ do
+ {
+ TARGETING::Target * theTarget = NULL;
+
+ // Get DIMM Targets
+ TargetHandleList dimmList;
+ getDIMMTargets( dimmList );
+
+ if( ( 0 == dimmList.size() ) ||
+ ( NULL == dimmList[0] ) )
+ {
+ TRACFCOMP( g_trac_spd,
+ "testDimmPresInvalidSize() - No DIMMs found!" );
+ break;
+ }
+
+ for( uint32_t dimm = 0; dimm < dimmList.size(); dimm++ )
+ {
+ cmds++;
+ theTarget = dimmList[dimm];
+
+ // Check presence
+ err = deviceRead( theTarget,
+ &present,
+ presentSize,
+ DEVICE_PRESENT_ADDRESS() );
+
+ if( !err )
+ {
+ fails++;
+ TS_FAIL( "testDimmPresInvalidSize() - Error not flagged for "
+ "invalid size!" );
+ errlCommit( err,
+ SPD_COMP_ID );
+ continue;
+ }
+ else
+ {
+ // Delete the error and continue
+ delete err;
+ err = NULL;
+ continue;
+ }
+ }
+
+ if( err )
+ {
+ break;
+ }
+ } while( 0 );
+
+ TRACFCOMP( g_trac_spd,
+ "testDimmPresInvalidSize() - %d/%d fails",
+ fails, cmds );
+ }
+
+
+};
+
+#endif
diff --git a/src/usr/spd/test/spdtest.H b/src/usr/spd/test/spdtest.H
index 3fdf86da7..351e3d846 100755
--- a/src/usr/spd/test/spdtest.H
+++ b/src/usr/spd/test/spdtest.H
@@ -62,7 +62,7 @@ void getDIMMTargets ( TargetHandleList & o_dimmList )
TARGETING::TargetService::CHILD,
TARGETING::TargetService::ALL,
&predDimm );
- TRACFCOMP( g_trac_spd,
+ TRACDCOMP( g_trac_spd,
"getDIMMTargets() - found %d DIMMs",
o_dimmList.size() );
return;
OpenPOWER on IntegriCloud