summaryrefslogtreecommitdiffstats
path: root/src/usr/lpc
diff options
context:
space:
mode:
authorBill Hoffa <wghoffa@us.ibm.com>2017-06-16 17:11:20 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-09-18 15:50:35 -0400
commit54a3bfc6323e7231580da74bcd965988d3e780af (patch)
tree78b037f38f1400ce71187a7e0bf3184bb61da9bc /src/usr/lpc
parent9511dde54f55257edd1c47ff709742638c21fbe8 (diff)
downloadtalos-hostboot-54a3bfc6323e7231580da74bcd965988d3e780af.tar.gz
talos-hostboot-54a3bfc6323e7231580da74bcd965988d3e780af.zip
Add support for LPC error detection and recovery
Change-Id: Iea9bd4425aeb798acd85484402c627fb623cae94 Also-By: Matt Ploetz <maploetz@us.ibm.com> RTC: 133649 RTC: 134582 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/45397 Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-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> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/lpc')
-rw-r--r--src/usr/lpc/lpcdd.C600
-rw-r--r--src/usr/lpc/lpcdd.H121
-rw-r--r--src/usr/lpc/test/lpcddtest.H68
3 files changed, 541 insertions, 248 deletions
diff --git a/src/usr/lpc/lpcdd.C b/src/usr/lpc/lpcdd.C
index b0dd00fd7..efcfa0346 100644
--- a/src/usr/lpc/lpcdd.C
+++ b/src/usr/lpc/lpcdd.C
@@ -50,6 +50,9 @@
#include <initservice/taskargs.H>
#include <config.h>
#include <arch/memorymap.H>
+#include <util/misc.H>
+#include <errl/errlreasoncodes.H>
+
trace_desc_t* g_trac_lpc;
TRAC_INIT( & g_trac_lpc, LPC_COMP_NAME, 2*KILOBYTE, TRACE::BUFFER_SLOW);
@@ -106,6 +109,13 @@ errlHndl_t lpcRead(DeviceFW::OperationType i_opType,
// then we have to use our special side copy of the driver
if( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL )
{
+ //First check/clear the LPC bus of errors and commit any errors found
+ l_err = Singleton<LpcDD>::instance().checkForLpcErrors();
+ if (l_err)
+ {
+ errlCommit(l_err, LPC_COMP_ID);
+ }
+
l_err = Singleton<LpcDD>::instance().readLPC( l_type,
l_addr,
io_buffer,
@@ -116,6 +126,14 @@ errlHndl_t lpcRead(DeviceFW::OperationType i_opType,
if( g_altLpcDD
&& (i_target == g_altLpcDD->getProc()) )
{
+ //First check/clear the LPC bus of errors and commit
+ // any errors found
+ l_err = g_altLpcDD->checkForLpcErrors();
+ if (l_err)
+ {
+ errlCommit(l_err, LPC_COMP_ID);
+ }
+
l_err = g_altLpcDD->readLPC( l_type,
l_addr,
io_buffer,
@@ -130,7 +148,7 @@ errlHndl_t lpcRead(DeviceFW::OperationType i_opType,
alt_huid = TARGETING::get_huid(g_altLpcDD->getProc());
}
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_READLPC
* @reasoncode LPC::RC_BAD_TARGET
* @userdata1[00:31] Requested target
@@ -197,6 +215,13 @@ errlHndl_t lpcWrite(DeviceFW::OperationType i_opType,
// then we have to use our special side copy of the driver
if( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL )
{
+ //First check/clear the LPC bus of errors and commit any errors found
+ l_err = Singleton<LpcDD>::instance().checkForLpcErrors();
+ if (l_err)
+ {
+ errlCommit(l_err, LPC_COMP_ID);
+ }
+
l_err = Singleton<LpcDD>::instance().writeLPC( l_type,
l_addr,
io_buffer,
@@ -207,6 +232,14 @@ errlHndl_t lpcWrite(DeviceFW::OperationType i_opType,
if( g_altLpcDD
&& (i_target == g_altLpcDD->getProc()) )
{
+ //First check/clear the LPC bus of errors and commit
+ // any errors found
+ l_err = g_altLpcDD->checkForLpcErrors();
+ if (l_err)
+ {
+ errlCommit(l_err, LPC_COMP_ID);
+ }
+
l_err = g_altLpcDD->writeLPC( l_type,
l_addr,
io_buffer,
@@ -221,7 +254,7 @@ errlHndl_t lpcWrite(DeviceFW::OperationType i_opType,
alt_huid = TARGETING::get_huid(g_altLpcDD->getProc());
}
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_WRITELPC
* @reasoncode LPC::RC_BAD_TARGET
* @userdata1[00:31] Requested target
@@ -272,7 +305,7 @@ errlHndl_t create_altmaster_objects( bool i_create,
{
TRACFCOMP(g_trac_lpc, "LPC::create_altmaster_objects> Alt-master object already exists");
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_CREATE_ALTMASTER
* @reasoncode LPC::RC_ALTMASTER_EXISTS
* @userdata1 Requested proc
@@ -300,7 +333,7 @@ errlHndl_t create_altmaster_objects( bool i_create,
{
TRACFCOMP(g_trac_lpc, "LPC::create_altmaster_objects> Cannot create another object using master sentinel");
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_CREATE_ALTMASTER
* @reasoncode LPC::RC_CANT_USE_SENTINEL
* @userdata1 <unused>
@@ -329,7 +362,7 @@ errlHndl_t create_altmaster_objects( bool i_create,
{
TRACFCOMP(g_trac_lpc, "LPC::create_altmaster_objects> Cannot create another object using master proc");
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_CREATE_ALTMASTER
* @reasoncode LPC::RC_CANT_USE_MASTER
* @userdata1 <unused>
@@ -438,14 +471,15 @@ LpcDD::LpcDD( TARGETING::Target* i_proc )
mmio_dev_map(reinterpret_cast<void *>(baseAddr),
LPC_SPACE_SIZE )));
- //@todo RTC:126644
- // Initialize the hardware
-// errlHndl_t l_errl = hwReset(LpcDD::RESET_INIT);
-// if( l_errl )
-// {
-// TRACFCOMP( g_trac_lpc, "Errors initializing LPC logic... Beware! PLID=%.8X", l_errl->plid() );
-// errlCommit(l_errl, LPC_COMP_ID);
-// }
+ /* @todo RTC:126644
+ Initialize the hardware
+ errlHndl_t l_errl = hwReset(LpcDD::RESET_INIT);
+ if( l_errl )
+ {
+ TRACFCOMP( g_trac_lpc, "Errors initializing LPC logic... Beware! PLID=%.8X", l_errl->plid() );
+ errlCommit(l_errl, LPC_COMP_ID);
+ }
+ **/
}
LpcDD::~LpcDD()
@@ -459,11 +493,11 @@ LpcDD::~LpcDD()
*/
errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
{
- errlHndl_t l_err = NULL;
-// @todo RTC:133649 Support P9 LPC controller - error detection
-#if 0
- TRACFCOMP( g_trac_lpc, ENTER_MRK"LpcDD::hwReset(i_resetLevel=%d)>", i_resetLevel );
+ errlHndl_t l_err = NULL;
+ uint32_t i_addr = 0;
+ uint64_t l_addr = 0;
+ TRACFCOMP( g_trac_lpc, ENTER_MRK"LpcDD::hwReset(i_resetLevel=%d)>", i_resetLevel );
// check iv_resetActive to avoid infinite loops
// and don't reset if in the middle of FFDC collection
@@ -475,10 +509,6 @@ errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
iv_resetActive = true;
do {
- // always read/write 64 bits to SCOM
- uint64_t scom_data_64 = 0x0;
- size_t scom_size = sizeof(uint64_t);
-
/***************************************/
/* Handle the different reset levels */
/***************************************/
@@ -488,7 +518,8 @@ errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
{// Nothing to do here, so just break
break;
}
- case RESET_INIT:
+/* @todo - RTC:179179
+ case RESET_INIT:
{
// Set OPB LPCM FIR Mask
// hostboot will monitor these FIR bits
@@ -503,27 +534,60 @@ errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
OPB_LPCM_FIR_MASK_WO_OR_REG));
if( l_err ) { break; }
}
+**/
- case RESET_ECCB:
- {
- // Write Reset Register to reset FW Logic registers
- TRACFCOMP(g_trac_lpc, "LpcDD::hwReset> Writing ECCB_RESET_REG to reset ECCB FW Logic");
- scom_data_64 = 0x0;
- l_err = deviceOp( DeviceFW::WRITE,
- iv_proc,
- &(scom_data_64),
- scom_size,
- DEVICE_SCOM_ADDRESS(ECCB_RESET_REG) );
-
- break;
- }
-
- case RESET_OPB_LPCHC_SOFT:
+ case RESET_OPB_LPCHC_HARD:
{
TRACFCOMP(g_trac_lpc, "LpcDD::hwReset> Writing OPB_MASTER_LS_CONTROL_REG to disable then enable First Error Data Capture");
- size_t opsize = sizeof(uint32_t);
+ //Clear all error indicators in LPCM OPB Master Actual
+ // Status Reg
+ i_addr = OPBM_STATUS_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
+ uint32_t * l_status_ptr
+ = reinterpret_cast<uint32_t*>(l_addr);
+ //Clear under mask - aka write 1 clears
+ *l_status_ptr = OPB_ERROR_MASK;
+ eieio();
+
+ //Clear related bits in the LPCM OPB Master Accumulated
+ // Status Reg
+ i_addr = OPBM_ACCUM_STATUS_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
+ uint32_t * l_accum_status_ptr
+ = reinterpret_cast<uint32_t*>(l_addr);
+ //Clear under mask - aka write 1 clears
+ *l_accum_status_ptr = OPB_ERROR_MASK;
+ eieio();
+ //Reset LPCHC Logic
+ TRACFCOMP(g_trac_lpc, "LpcDD::hwReset> Writing LPCHC_RESET_REG to reset LPCHC Logic");
+ i_addr = LPCHC_RESET_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
+ uint32_t * l_reset_ptr
+ = reinterpret_cast<uint32_t*>(l_addr);
+ //The spec states the act of a write is all that matters
+ //The data itself doesn't matter, so using an arbitrary
+ //value
+ *l_reset_ptr = 0x12345678;
+ eieio();
+
+ //Issue LPC Abort
+ i_addr = LPCHC_LPC_BUS_ABORT_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
+ uint32_t * l_abort_ptr
+ = reinterpret_cast<uint32_t*>(l_addr);
+ //The spec states the act of a write is all that matters
+ //The data itself doesn't matter, so using an arbitrary
+ //value
+ *l_abort_ptr = 0x12345678;
+ eieio();
+
+/* @todo - RTC:179179 - Re-enable FEDC
// First read OPB_MASTER_LS_CONTROL_REG
uint32_t lpc_data = 0x0;
l_err = _readLPC( LPC::TRANS_REG,
@@ -563,47 +627,25 @@ errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
scom_size,
DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_WOX_AND_REG) );
if (l_err) { break; }
-
+**/
break;
}
- case RESET_OPB_LPCHC_HARD:
+/* @todo - RTC:179179 - Properly categorize errors into SOFT/HARD errors and
+ update this implementation based on results
+ case RESET_OPB_LPCHC_SOFT:
{
- TRACFCOMP(g_trac_lpc, "LpcDD::hwReset> Writing LPCHC_RESET_REG to reset LPCHC Logic");
-
- size_t opsize = sizeof(uint32_t);
- uint32_t lpc_data = 0x0;
- l_err = _writeLPC( LPC::TRANS_REG,
- LPCHC_RESET_REG,
- &lpc_data,
- opsize );
- if (l_err) { break; }
-
- // sleep 1ms for LPCHC to execute internal
- // reset+init sequence
- nanosleep( 0, NS_PER_MSEC );
-
- // Clear FIR register
- scom_data_64 = ~(OPB_LPCM_FIR_ERROR_MASK);
- l_err = deviceOp(
- DeviceFW::WRITE,
- iv_proc,
- &(scom_data_64),
- scom_size,
- DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_WOX_AND_REG) );
- if (l_err) { break; }
-
break;
}
+**/
// else - unsupported reset level
default:
{
-
TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::hwReset> Unsupported Reset Level Passed In: 0x%X", i_resetLevel);
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_LPCDD_HWRESET
* @reasoncode LPC::RC_UNSUPPORTED_OPERATION
* @userdata1 Unsupported Reset Level Parameter
@@ -651,7 +693,6 @@ errlHndl_t LpcDD::hwReset( ResetLevels i_resetLevel )
}
TRACFCOMP( g_trac_lpc, EXIT_MRK"LpcDD::hwReset()=%.8X:%.4X", ERRL_GETEID_SAFE(l_err), ERRL_GETRC_SAFE(l_err) );
-#endif
return l_err;
}
@@ -702,6 +743,15 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
*o_addr =
getLPCBaseAddr()+ i_addr + LPC::LPCHC_REG_SPACE- LPC_ADDR_START;
break;
+ case LPC::TRANS_ERR:
+ if( i_addr >= 0x10000 )
+ {
+ invalid_address = true;
+ break;
+ }
+ *o_addr =
+ getLPCBaseAddr()+ i_addr + LPC::LPCHC_ERR_SPACE- LPC_ADDR_START;
+ break;
case LPC::TRANS_ABS:
//Just use the address as given
*o_addr = getLPCBaseAddr() + i_addr;
@@ -714,7 +764,7 @@ errlHndl_t LpcDD::checkAddr(LPC::TransType i_type,
{
TRACFCOMP( g_trac_lpc, "LpcDD::checkAddr() Invalid address : i_type=%d, i_addr=%X", i_type, i_addr );
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_LPCDD_CHECKADDR
* @reasoncode LPC::RC_INVALID_ADDR
* @userdata1[0:31] LPC Address
@@ -786,7 +836,7 @@ errlHndl_t LpcDD::_readLPC(LPC::TransType i_type,
{
TRACFCOMP( g_trac_lpc, "readLPC> Unsupported buffer size : %d", io_buflen );
/*@
- * @errortype
+ * @errortype ERRL_SEV_UNRECOVERABLE
* @moduleid LPC::MOD_LPCDD_READLPC
* @reasoncode LPC::RC_BAD_ARG
* @userdata1[0:31] LPC Address
@@ -809,6 +859,9 @@ errlHndl_t LpcDD::_readLPC(LPC::TransType i_type,
//Sync the IO op
eieio();
+ // Check Error bits
+ l_err = checkForLpcErrors();
+
} while(0);
LPC_TRACFCOMP( g_trac_lpc, "readLPC> %08X[%d] = %08X", l_addr, io_buflen, *reinterpret_cast<uint32_t*>( o_buffer ) >> (8 * (4 - io_buflen)) );
@@ -861,203 +914,316 @@ errlHndl_t LpcDD::_writeLPC(LPC::TransType i_type,
}
eieio();
#endif
+
+ // Check Error bits
+ l_err = checkForLpcErrors();
+
} while(0);
return l_err;
}
-
-
/**
* @brief Add Error Registers to an existing Error Log
*/
void LpcDD::addFFDC(errlHndl_t & io_errl)
{
+ errlHndl_t l_err = nullptr;
+ uint32_t i_addr = 0;
+ uint64_t l_addr = 0;
+ uint32_t lpcAddr_buffer;
+ size_t l_buflen = sizeof(uint32_t);
+
// check iv_ffdcActive to avoid infinite loops
- if ( iv_ffdcActive == false )
- {
- iv_ffdcActive = true;
+ do{
- TRACFCOMP( g_trac_lpc, "LpcDD::addFFDC> adding FFDC to Error Log EID=0x%X, PLID=0x%X",
- io_errl->eid(), io_errl->plid() );
+ if ( iv_ffdcActive == false )
+ {
+ iv_ffdcActive = true;
- ERRORLOG::ErrlUserDetailsLogRegister l_eud(iv_proc);
+ TRACFCOMP( g_trac_lpc, "LpcDD::addFFDC> adding FFDC to Error Log EID=0x%X, PLID=0x%X",
+ io_errl->eid(), io_errl->plid() );
- // @todo RTC:133649 Support P9 LPC controller - error detection
- // Add ECCB Status Register
- //l_eud.addData(DEVICE_SCOM_ADDRESS(ECCB_STAT_REG));
+ i_addr = LPCHC_ERROR_ADDR_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err)
+ {
+ // Additional FFDC is not necessary, just delete error and break
+ delete l_err;
+ l_err = nullptr;
+ break;
+ }
- // Add OPB LPC Master FIR
- //l_eud.addData(DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG));
+ memcpy(&lpcAddr_buffer, reinterpret_cast<void*>(l_addr), l_buflen);
+ eieio();
- //@todo - add more LPC regs RTC:37744
- //LPCIRQ_STATUS = 0x38
- //SYS_ERR_ADDR = 0x40
+ io_errl->addFFDC(LPC_COMP_ID,
+ &lpcAddr_buffer,
+ l_buflen,
+ 0, // version
+ ERRORLOG::ERRL_UDT_NOFORMAT, // parser ignores data
+ false);
- l_eud.addToLog(io_errl);
+ // reset FFDC active flag
+ iv_ffdcActive = false;
+ }
- // reset FFDC active flag
- iv_ffdcActive = false;
- }
+ }while(0);
return;
}
/**
- * @brief Check For Errors in OPB and LPCHC Status Registers
+ * @brief Compute error severity from OPBM Status Register
*/
-errlHndl_t LpcDD::checkForOpbErrors( ResetLevels &o_resetLevel )
+void LpcDD::computeOpbmErrSev(OpbmErrReg_t i_opbmErrData,
+ ResetLevels &o_resetLevel)
{
- errlHndl_t l_err = NULL;
- bool errorFound = false;
-
- // Used to set Reset Levels, if necessary
o_resetLevel = RESET_CLEAR;
- // Default status values in case we fail in reading the registers
- OpbLpcmFirReg_t fir_reg;
- fir_reg.data64 = 0xDEADBEEFDEADBEEF;
- uint64_t fir_data = 0x0;
-
- // always read/write 64 bits to SCOM
- size_t scom_size = sizeof(uint64_t);
-
- do {
- // Read FIR Register
- l_err = deviceOp( DeviceFW::READ,
- iv_proc,
- &(fir_data),
- scom_size,
- DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG) );
- if( l_err ) { break; }
+ // First check the soft errors
+ /* @todo - RTC:179179 Revisit below Reset Levels **/
+ if( i_opbmErrData.rxits )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> Invalid Transfer Size Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxicmd )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> Invalid Command Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxiaa )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> Invalid Address Alignment Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxopbe )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> OPB Error Acknowledged: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxicmdb )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> OPB Master Command Buffer Parity Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxidatab )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> OPM Master Data Buffer Parity Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ // Now look for HARD errors that will override SOFT errors reset Level
+ if( i_opbmErrData.rxopbt )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_HARD;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> OPM Timeout Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxiaddr )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_HARD;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> Invalid Address Error: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+ if( i_opbmErrData.rxctgtel )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_HARD;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeOpbmErrSev> OPB Master Timeout: OPBM Status Reg =0x%8X, ResetLevel=%d",
+ i_opbmErrData, o_resetLevel);
+ }
+}
- // Mask data to just the FIR bits we care about
- fir_reg.data64 = fir_data & OPB_LPCM_FIR_ERROR_MASK;
+/**
+ * @brief Compute error severity from LPCHC Status Register
+ */
+void LpcDD::computeLpchcErrSev(LpchcErrReg_t i_lpchcErrData,
+ ResetLevels &o_resetLevel)
+{
+ o_resetLevel = RESET_CLEAR;
- // First look for SOFT errors
- if( 1 == fir_reg.rxits )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_SOFT;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Invalid Transfer Size: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ // First check the soft errors
+ // All of these errors are set from bad LPC end points. Setting all to soft
+ /* @todo - RTC:179179 Revisit below Reset Levels **/
+ if( i_lpchcErrData.lreset )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Lreset Event: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.syncab )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Sync Abnormal Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.syncnr )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Sync No Response Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.syncne )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Sync Normal Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.syncto )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Sync Timeout Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.tctar )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> Target Cycle TAR Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
+ if( i_lpchcErrData.mctar )
+ {
+ o_resetLevel = RESET_OPB_LPCHC_SOFT;
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::computeLpchcErrSev> LPC Bus Master Cycle TAR Error: LPCHC Status Reg =0x%8X, ResetLevel=%d",
+ i_lpchcErrData, o_resetLevel);
+ }
- if( 1 == fir_reg.rxicmd )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_SOFT;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Invalid Command: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+}
- if( 1 == fir_reg.rxiaa )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_SOFT;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Invalid Address Alignment: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+/**
+ * @brief Check For Errors in OPB and LPCHC Status Registers
+ */
+errlHndl_t LpcDD::checkForLpcErrors()
+{
+ errlHndl_t l_err = NULL;
- if( 1 == fir_reg.rxcbpe )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_SOFT;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Command Buffer Parity Error: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ uint32_t i_addr = 0;
+ uint64_t l_addr = 0;
+ uint32_t opbm_buffer;
+ uint32_t lpchc_buffer;
+ size_t l_buflen = sizeof(uint32_t);
+ ResetLevels l_opbmResetLevel = RESET_CLEAR;
+ ResetLevels l_lpchcResetLevel = RESET_CLEAR;
- if( 1 == fir_reg.rxdbpe )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_SOFT;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Data Buffer Parity Error: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ OpbmErrReg_t opbm_err_union;
+ opbm_err_union.data32 = 0x0;
+ LpchcErrReg_t lpchc_err_union;
+ lpchc_err_union.data32 = 0x0;
- // Now look for HARD errors that will override SOFT errors reset Level
- if( 1 == fir_reg.rxhopbe )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_HARD;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> OPB Bus Error: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ do {
+ // LPC error registers are not modeled in FSP simics.
+ // Skip if we are running simics.
+ if (Util::isSimicsRunning())
+ { break; }
- if( 1 == fir_reg.rxhopbt )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_HARD;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> OPB Bus Timeout: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ // Read OPBM Status Register via MMIO
+ i_addr = OPBM_ACCUM_STATUS_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
- if( 1 == fir_reg.rxctgtel )
- {
- errorFound = true;
- o_resetLevel = RESET_OPB_LPCHC_HARD;
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> CI Load/CI Store/OPB Master Hang Timeout: OPB_LPCM_FIR_REG=0x%.16X, ResetLevel=%d",
- fir_reg.data64, o_resetLevel);
- }
+ memcpy( &opbm_buffer, reinterpret_cast<void*>(l_addr), l_buflen );
+ eieio();
+ // Read LPC Host Controller Status register via MMIO
+ i_addr = LPCHC_REG;
+ l_err = checkAddr( LPC::TRANS_ERR, i_addr, &l_addr );
+ if (l_err) { break; }
- }while(0);
+ memcpy( &lpchc_buffer, reinterpret_cast<void*>(l_addr), l_buflen );
+ eieio();
+ // Mask error bits
+ opbm_err_union.data32 = (opbm_buffer & OPB_ERROR_MASK);
+ lpchc_err_union.data32 = (lpchc_buffer & LPCHC_ERROR_MASK);
- // If there is any error create an error log
- if ( errorFound )
- {
- // If we failed on a register read above, but still found an error,
- // delete register read error log and create an original error log
- // for the found error
- if ( l_err )
+ // First look for errors in the OPBM bit mask
+ if (opbm_err_union.data32 != 0)
{
- TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForOpbErrors> Deleting register read error. Returning error created for the found error");
- delete l_err;
- }
-
- /*@
- * @errortype
- * @moduleid LPC::MOD_LPCDD_CHECKFOROPBERRORS
- * @reasoncode LPC::RC_OPB_ERROR
- * @userdata1 OPB FIR Register Data
- * @userdata2 Reset Level
- * @devdesc LpcDD::checkForOpbErrors> Error(s) found in OPB
- * and/or LPCHC Status Register
- * @custdesc Error(s) found in OPB and/or LPCHC Status Register
- */
- l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- LPC::MOD_LPCDD_CHECKFOROPBERRORS,
- LPC::RC_OPB_ERROR,
- fir_reg.data64,
- o_resetLevel );
-
- l_err->addHwCallout( iv_proc,
- HWAS::SRCI_PRIORITY_HIGH,
- HWAS::NO_DECONFIG,
- HWAS::GARD_NULL );
-
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForLpcErrors> Error found in OPB Master Status Register: 0x%8X",opbm_err_union.data32);
+ computeOpbmErrSev(opbm_err_union, l_opbmResetLevel);
- // Log FIR Register Data
- ERRORLOG::ErrlUserDetailsLogRegister l_eud(iv_proc);
-
- l_eud.addDataBuffer(&fir_data, scom_size,
- DEVICE_SCOM_ADDRESS(OPB_LPCM_FIR_REG));
-
- l_eud.addToLog(l_err);
+ if(l_opbmResetLevel != RESET_CLEAR)
+ {
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid LPC::MOD_LPCDD_CHECKFORLPCERRORS
+ * @reasoncode LPC::RC_OPB_ERROR
+ * @userdata1 OPBM Error Status Register
+ * @userdata2 Reset Level
+ * @devdesc LpcDD::checkLpcErrors> Error(s) found in OPB
+ * Status Register
+ * @custdesc Error(s) found in OPB Status Register
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ LPC::MOD_LPCDD_CHECKFORLPCERRORS,
+ LPC::RC_OPB_ERROR,
+ opbm_buffer,
+ l_opbmResetLevel);
+
+ // Gather additional ffdc data
+ addFFDC(l_err);
+ l_err->addHwCallout( iv_proc,
+ HWAS::SRCI_PRIORITY_NONE,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL );
+
+ /* @todo - RTC:179179 Use l_opbmResetLevel **/
+ hwReset(RESET_OPB_LPCHC_HARD);
+ }
+ }
+ // Check the LPC host controller bit mask, only if there are no errors
+ // from the OPBM bit mask
+ if (lpchc_err_union.data32 != 0 && l_err == NULL)
+ {
+ TRACFCOMP( g_trac_lpc, ERR_MRK"LpcDD::checkForLpcErrors> Error found in LPC Host Controller Status Register: 0x%8X",lpchc_err_union.data32);
+ computeLpchcErrSev(lpchc_err_union, l_lpchcResetLevel);
- addFFDC(l_err);
- l_err->collectTrace(LPC_COMP_NAME);
+ if(l_lpchcResetLevel != RESET_CLEAR)
+ {
+ /*@
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid LPC::MOD_LPCDD_CHECKFORLPCERRORS
+ * @reasoncode LPC::RC_LPCHC_ERROR
+ * @userdata1 LPCHC Error Status Register
+ * @userdata2 Reset Level
+ * @devdesc LpcDD::checkForLpcErrors> Error(s) found in LPCHC
+ * Status Register
+ * @custdesc Error(s) found in LPCHC Status Register
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ LPC::MOD_LPCDD_CHECKFORLPCERRORS,
+ LPC::RC_LPCHC_ERROR,
+ lpchc_buffer,
+ l_lpchcResetLevel);
+
+ l_err->addHwCallout( iv_proc,
+ HWAS::SRCI_PRIORITY_NONE,
+ HWAS::NO_DECONFIG,
+ HWAS::GARD_NULL );
+
+ // Gather addtional ffdc data
+ addFFDC(l_err);
+ l_err->collectTrace(LPC_COMP_NAME);
+ /* @todo - RTC:179179 Use l_opbmResetLevel **/
+ hwReset(RESET_OPB_LPCHC_HARD);
+ }
+ }
- }
+ }while(0);
return l_err;
-
}
-
/**
* @brief Read an address from LPC space
*/
@@ -1070,6 +1236,7 @@ errlHndl_t LpcDD::readLPC(LPC::TransType i_type,
mutex_lock(ivp_mutex);
errlHndl_t l_err = _readLPC( i_type, i_addr, o_buffer, io_buflen );
mutex_unlock(ivp_mutex);
+
return l_err;
}
@@ -1085,5 +1252,6 @@ errlHndl_t LpcDD::writeLPC(LPC::TransType i_type,
mutex_lock(ivp_mutex);
errlHndl_t l_err = _writeLPC( i_type, i_addr, i_buffer, io_buflen );
mutex_unlock(ivp_mutex);
+
return l_err;
}
diff --git a/src/usr/lpc/lpcdd.H b/src/usr/lpc/lpcdd.H
index 3cebf07bd..be7af6aef 100644
--- a/src/usr/lpc/lpcdd.H
+++ b/src/usr/lpc/lpcdd.H
@@ -78,6 +78,12 @@ class LpcDD
const void* i_buffer,
size_t& io_buflen);
+ /**
+ * @brief Check For Errors in OPB and LPCHC Status Registers
+ *
+ * @return Error log if error found
+ */
+ errlHndl_t checkForLpcErrors();
/**
* @brief Enums for different levels of resetting PNOR communication levels
@@ -85,10 +91,9 @@ class LpcDD
enum ResetLevels
{
RESET_CLEAR = 0x00000000, /**< Clear Reset Level */
- RESET_ECCB = 0x00000001, /**< ECCB FW Logic */
- RESET_OPB_LPCHC_SOFT = 0x00000002, /**< OPB LPCHC Clear Errors */
- RESET_OPB_LPCHC_HARD = 0x00000004, /**< OPB LPCHC Reset Logic */
- RESET_INIT = 0x00000008, /**< Initial HW setup */
+ RESET_OPB_LPCHC_SOFT = 0x00000001, /**< OPB LPCHC Clear Errors */
+ RESET_OPB_LPCHC_HARD = 0x00000002, /**< OPB LPCHC Reset Logic */
+ RESET_INIT = 0x00000004, /**< Initial HW setup */
};
@@ -156,12 +161,11 @@ class LpcDD
/**
* @brief Constructor
- * @param[in] Processor target associated with the ECCB logic
+ * @param[in] Processor target associated with the LPC Master
*/
LpcDD( TARGETING::Target* i_proc
= TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
-
/**
* @brief Destructor
*/
@@ -181,55 +185,110 @@ class LpcDD
/** Size that LPC takes up (0xC0000000 to 0xFFFFFFFF)*/
LPC_SPACE_SIZE = 0x40000000,
- /**< OPB LPCM Sync FIR Reg - used to read the FIR*/
- OPB_LPCM_FIR_REG = 0x01010C00,
-
/**< OPB LPCM Sync FIR Reg WOX_AND - used to clear the FIR */
OPB_LPCM_FIR_WOX_AND_REG = 0x01010C01,
/**< OPB LPCM Sync FIR Mask Reg WO_OR - used to set the mask */
OPB_LPCM_FIR_MASK_WO_OR_REG = 0x01010C05,
- OPB_LPCM_FIR_ERROR_MASK = 0xFF00000000000000, /**< Error Bits MASK */
-
// LPCHC reset-related registers
OPB_MASTER_LS_CONTROL_REG = 0x008, /**<OPBM LS Control Reg */
- LPCHC_RESET_REG = 0x0FC, /**<LPC HC Reset Register */
+ LPCHC_SYNC_CYCLE_COUNTER_INFINITE = 0xFF000000,
+
+ /** OPB Master Accumulated Status Register - used to check error bits*/
+ OPBM_ACCUM_STATUS_REG = 0x0,
+
+ /** OPB Master Actual Status Register */
+ OPBM_STATUS_REG = 0x004C,
+
+ /** LPC Host Controller Status Register - used to check error bits*/
+ LPCHC_REG = 0x2038,
+
+ /** LPC Host Controller Error Addr Register - used to check error bits*/
+ LPCHC_ERROR_ADDR_REG = 0x2040,
+
+ /** LPC Host Controller Reset Register */
+ LPCHC_LPC_BUS_ABORT_REG = 0x20F8,
+
+ /** LPC Host Controller Reset Register */
+ LPCHC_RESET_REG = 0x20FC,
+
+ OPB_ERROR_MASK = 0x20000FC3, /**< OPBM Error Bits MASK */
+
+ LPCHC_ERROR_MASK = 0x000004FC /**< LPCHC Error Bits MASK */
- LPCHC_SYNC_CYCLE_COUNTER_INFINITE = 0xFF000000
};
+ /**
+ * @brief OPB Master Status Register Layout
+ */
+ union OpbmErrReg_t
+ {
+ uint32_t data32;
+ struct
+ {
+ uint32_t reserved : 2; // 0:1 reserved
+ uint32_t rxctgtel : 1; // 2 - OPB master timeout
+ uint32_t rxfwrdcv : 1; // 3 - FW read cache valid(status only)
+ uint32_t reserved1 : 16; // 4:19 reserved
+ uint32_t rxits : 1; // 20 - Invalid Transfer Size
+ uint32_t rxicmd : 1; // 21 - Invalid Command
+ uint32_t rxiaa : 1; // 22 - Invalid address alignment
+ uint32_t rxiaddr : 1; // 23 - Invalid address
+ uint32_t rxopbe : 1; // 24 - OPB error acknowledge
+ uint32_t rxopbt : 1; // 25 - OPB timeout
+ uint32_t reserved2 : 4; // 26:29 reserved
+ uint32_t rxicmdb : 1; // 30 - Command buffer parity error
+ uint32_t rxidatab : 1; // 31 - Data buffer parity error
+
+ };
+ OpbmErrReg_t() : data32(0) {};
+ };
/**
- * @brief OPB-LPCM FIR Register Layout
+ * @brief LPCHC Status Register Layout
*/
- union OpbLpcmFirReg_t
+ union LpchcErrReg_t
{
- uint64_t data64;
+ uint32_t data32;
struct
{
- uint64_t rxits : 1; // Invalid Transfer Size
- uint64_t rxicmd : 1; // Invalid Command
- uint64_t rxiaa : 1; // Invalid Address Alignment
- uint64_t rxhopbe : 1; // OPB Bus Error
- uint64_t rxhopbt : 1; // OPB Bus Timeout
- uint64_t rxctgtel : 1; // CI Load/CI Store/OPB Master Hang Timeout
- uint64_t rxcbpe : 1; // Command Buffer Parity Error
- uint64_t rxdbpe : 1; // Data Buffer Parity Error
- uint64_t reserved : 56;
+ uint32_t reserved : 17; // 0:16 IRQSER status - not used
+ uint32_t reserved1 : 4; // 17:20 reserved
+ uint32_t lreset : 1; // 21 - Lreset Event
+ uint32_t reserved2 : 2; // 22:23 reserved
+ uint32_t syncab : 1; // 24 - Sync Abnormal
+ uint32_t syncnr : 1; // 25 - Sync no response
+ uint32_t syncne : 1; // 26 - Sync normal error
+ uint32_t syncto : 1; // 27 - Sync timeout
+ uint32_t tctar : 1; // 28 - Target cycle TAR error
+ uint32_t mctar : 1; // 29 - LPC bus master cycle TAR error
+ uint32_t mzeror : 1; // 30 - LPC bus master 0 request
+ uint32_t moner : 1; // 31 - LPC bus master 1 request
};
- OpbLpcmFirReg_t() : data64(0) {};
+ LpchcErrReg_t() : data32(0) {};
};
/**
- * @brief Check For Errors in OPB and LPCHC Status Registers
*
- * @parm o_resetLevel if error, reset level to clear error
- * @return Error log if error found
+ * @brief Compute the Severity of the errors from the OPBM Status Register
+ *
+ * @parm i_opbmErrData Masked bits of the OPBM error register
+ * @parm o_resetLevel Level of severity of the error reported
+ */
+ void computeOpbmErrSev(OpbmErrReg_t i_opbmErrData,
+ ResetLevels &o_resetLevel);
+
+ /**
+ * @brief Compute the Severity of the errors from the LPCHC Status Register
+ *
+ * @parm i_lpchcErrData Masked bits of the LPCHC error register
+ * @parm o_resetLevel Level of severity of the error reported
*/
- errlHndl_t checkForOpbErrors( ResetLevels &o_resetLevel );
+ void computeLpchcErrSev(LpchcErrReg_t i_lpchcErrData,
+ ResetLevels &o_resetLevel);
/**
* @brief Sanity check the input address for a LPC op and return
@@ -302,7 +361,7 @@ class LpcDD
mutex_t* ivp_mutex;
/**
- * @brief Processor target associated with the ECCB logic
+ * @brief Processor target associated with the LPC Master
*/
TARGETING::Target* iv_proc;
diff --git a/src/usr/lpc/test/lpcddtest.H b/src/usr/lpc/test/lpcddtest.H
index 0883f83e7..2e7395451 100644
--- a/src/usr/lpc/test/lpcddtest.H
+++ b/src/usr/lpc/test/lpcddtest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -222,6 +222,72 @@ class LpcDdTest : public CxxTest::TestSuite
TS_FAIL("LpcDD::test_hwfail> No error from bad address");
}
}
+
+
+ /**
+ * @brief LPC HW Failure
+ * Test handling of invalid address
+ * This address has to be within the range to pass checkAddr, but
+ * not actaully a valid LPC address.
+ */
+ void _test_invalidAddress(void)
+ {
+ TRACFCOMP( g_trac_lpc, "LpcDdTest::test_invalidAddress>" );
+ errlHndl_t l_err = NULL;
+
+ TARGETING::Target* sentinel =
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ size_t opsize = 4;
+ uint8_t data[12];
+
+ // pass a bad address
+ l_err = deviceRead( sentinel,
+ data,
+ opsize,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_ABS,0xDEADBEEF) );
+ if( l_err )
+ {
+ delete l_err;
+ }
+ else
+ {
+ TS_FAIL("LpcDD::test_invalidAddress> No error from invalid address test");
+ }
+ }
+
+ /**
+ * @brief LPC HW Failure
+ * Test handling of invalid address
+ * This address has to be within the range to pass checkAddr, but
+ * not actaully a valid LPC address.
+ */
+ void _test_invalidTransferSize(void)
+ {
+ TRACFCOMP( g_trac_lpc, "LpcDdTest::test_invalidTransferSize>" );
+ errlHndl_t l_err = NULL;
+
+ TARGETING::Target* sentinel =
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ size_t opsize = 4;
+ uint8_t data[12];
+
+ // pass a bad address
+ l_err = deviceRead( sentinel,
+ data,
+ opsize,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_ABS,0x12345678) );
+ if( l_err )
+ {
+ delete l_err;
+ }
+ else
+ {
+ TS_FAIL("LpcDD::test_invalidTransferSize> No error from invalid transfer size test");
+ }
+ }
+
+
+
};
#endif
OpenPOWER on IntegriCloud