summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/pnor/pnordd.C1128
-rw-r--r--src/usr/pnor/pnordd.H319
-rw-r--r--src/usr/pnor/test/pnorddtest.H75
3 files changed, 1096 insertions, 426 deletions
diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C
index 36a014412..5f53a9c84 100644
--- a/src/usr/pnor/pnordd.C
+++ b/src/usr/pnor/pnordd.C
@@ -54,6 +54,7 @@ void erase_fake_pnor( uint64_t i_pnorAddr, size_t i_size );
extern trace_desc_t* g_trac_pnor;
+
namespace PNOR
{
@@ -130,7 +131,7 @@ errlHndl_t ddRead(DeviceFW::OperationType i_opType,
* @return errlHndl_t
*/
errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
- TARGETING::Target* i_target,
+ TARGETING::Target* i_target,
void* io_buffer,
size_t& io_buflen,
int64_t i_accessType,
@@ -159,6 +160,82 @@ errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
return l_err;
}
+/**
+ * @brief Used for VPO testing via istep hack. Will be removed once VPO Bringup is done.
+ * TODO (RTC:42487: Remove this once VPO PNOR bringup is done.
+ */
+void testRealPnor(void *io_pArgs)
+{
+ // TARGETING::Target* l_testTarget =
+ // TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ size_t l_size = sizeof(uint64_t);
+ errlHndl_t l_err = NULL;
+ uint64_t fails = 0;
+ uint64_t total = 0;
+
+ TRACFCOMP(g_trac_pnor, "PNOR::testRealPnor> starting" );
+
+ PnorDD* pnordd = NULL;
+ pnordd = new PnorDD(PnorDD::MODEL_REAL_CMD);
+
+
+ // Perform PnorDD read
+ const uint64_t l_address = 0x4;
+ uint64_t l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PnorDdTest::testRealPnor: PNORDD read 1: readFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+
+ TRACFCOMP(g_trac_pnor, "PNOR::testRealPnor> l_readData=0x%.16x", l_readData );
+ TRACFCOMP(g_trac_pnor, "PNOR::testRealPnor> Try writing data" );
+
+ uint64_t l_writeData = 0x12345678FEEDB0B0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+
+ total++;
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PNOR::testRealPnor: PNORDD write 1: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+
+ // Perform PnorDD read
+ l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_pnor, "E>PNOR::testRealPnor: PNORDD read 2: readFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+
+ TRACFCOMP(g_trac_pnor, "PNOR::testRealPnor> PNORDD read 2: l_readData=0x%.16x", l_readData );
+
+ TRACFCOMP(g_trac_pnor, "PNOR::testRealPnor> %d/%d fails", fails, total );
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+}
// Register PNORDD access functions to DD framework
DEVICE_REGISTER_ROUTE(DeviceFW::READ,
@@ -207,22 +284,13 @@ errlHndl_t PnorDD::readFlash(void* o_buffer,
break;
}
- // LPC is accessed 32-bits at a time...
- uint32_t* word_ptr = static_cast<uint32_t*>(o_buffer);
- uint64_t words_read = 0;
- for( uint32_t addr = i_address;
- addr < (i_address+io_buflen);
- addr += sizeof(uint32_t) )
- {
- // flash is mapped directly in the FW space
- l_err = readLPC( addr + LPCHC_FW_SPACE,
- word_ptr[words_read] );
- if( l_err ) { break; }
+ //If we get here we're doing either MODEL_LPC_MEM or MODEL_REAL_CMD
+ mutex_lock(&cv_mutex);
+ l_err = bufferedSfcRead(i_address, io_buflen, o_buffer);
+ mutex_unlock(&cv_mutex);
+
+ if(l_err) { break;}
- words_read++;
- }
- io_buflen = words_read*sizeof(uint32_t);
- if( l_err ) { break; }
}while(0);
return l_err;
@@ -256,45 +324,58 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
break;
}
- // LPC is accessed 32-bits at a time, but we also need to be
- // smart about handling erases. In NOR flash we can set bits
- // without an erase but we cannot clear them. When we erase
- // we have to erase an entire block of data at a time.
- uint32_t* word_ptr = static_cast<uint32_t*>(i_buffer);
- uint32_t cur_addr = static_cast<uint32_t>(l_address);
- uint64_t num_blocks = getNumAffectedBlocks(cur_addr,io_buflen);
+ //If we get here we're doing either MODEL_LPC_MEM or MODEL_REAL_CMD
+
+ // LPC is accessed 32-bits at a time, but SFC has a 256byte buffer
+ // but we also need to be smart about handling erases. In NOR
+ // flash we can clear bits without an erase but we cannot set them.
+ // When we erase we have to erase an entire block of data at a time.
+
+ uint32_t cur_writeStart_addr = static_cast<uint32_t>(l_address);
+ uint32_t cur_blkStart_addr = findEraseBlock(cur_writeStart_addr);
+ uint32_t cur_blkEnd_addr = cur_blkStart_addr + iv_erasesize_bytes;
+ uint32_t write_bytes = iv_erasesize_bytes;
+ uint64_t num_blocks = getNumAffectedBlocks(cur_writeStart_addr,io_buflen);
uint64_t bytes_left = io_buflen;
+
// loop through erase blocks until we've gotten through all
// affected blocks
for( uint64_t block = 0;
block < num_blocks;
++block )
{
- TRACDCOMP( g_trac_pnor, "Block %d: bytes_left=%d, cur_addr=0x%.8X", block, bytes_left, cur_addr );
+ write_bytes = iv_erasesize_bytes;
+ if(bytes_left < iv_erasesize_bytes )
+ {
+ uint32_t end_waste = 0;
+ //deduct any unused space at the end of the erase block
+ if( cur_blkEnd_addr > (cur_writeStart_addr + bytes_left))
+ {
+ end_waste = cur_blkEnd_addr - (cur_writeStart_addr + bytes_left);
+ write_bytes -= end_waste;
+ }
+
+ //deduct any unused space at the beginning of the erase block
+ write_bytes = write_bytes - (cur_writeStart_addr - cur_blkStart_addr);
+ }
// write a single block of data out to flash efficiently
- l_err = compareAndWriteBlock( cur_addr,
- (bytes_left-1)/sizeof(uint32_t)+1,
- word_ptr );
+ mutex_lock(&cv_mutex);
+ l_err = compareAndWriteBlock(cur_blkStart_addr,
+ cur_writeStart_addr,
+ write_bytes,
+ (void*)((uint64_t)i_buffer + ((uint64_t)cur_writeStart_addr-l_address)));
+ mutex_unlock(&cv_mutex);
+
if( l_err ) { break; }
//@todo (RTC:37744) - How should we handle PNOR errors?
- // move on to the next block
- if( bytes_left > ERASESIZE_BYTES )
- {
- bytes_left -= ERASESIZE_BYTES;
- cur_addr += ERASESIZE_BYTES;
- }
- else
- {
- // final block of partial data
- // align cur_addr to the beginning of the block
- cur_addr = findEraseBlock(cur_addr+bytes_left);
- // figure out the remaining data in the last block
- bytes_left = (l_address + io_buflen - cur_addr);
- }
- word_ptr += ((bytes_left-1)/sizeof(uint32_t))+1;
+ cur_blkStart_addr = cur_blkEnd_addr; //move start to end of current erase block
+ cur_blkEnd_addr += iv_erasesize_bytes;; //increment end by erase block size.
+ cur_writeStart_addr += write_bytes;
+ bytes_left -= write_bytes;
+
}
if( l_err ) { break; }
@@ -315,6 +396,7 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
/********************
Private/Protected Methods
********************/
+mutex_t PnorDD::cv_mutex = MUTEX_INITIALIZER;
/**
* @brief Constructor
@@ -322,19 +404,12 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
PnorDD::PnorDD( PnorMode_t i_mode )
: iv_mode(i_mode)
{
- mutex_init(&iv_mutex);
-
- for( uint64_t x=0; x < (PNORSIZE/ERASESIZE_BYTES); x++ )
- {
- iv_erases[x] = 0;
- }
+ iv_erasesize_bytes = ERASESIZE_BYTES_DEFAULT;
+ iv_erases = NULL;
//In the normal case we will choose the mode for the caller
if( MODEL_UNKNOWN == iv_mode )
{
- //Use ECCB scoms to drive LPC, flat memory map behind ECCB, no SPI
- //iv_mode = MODEL_FLAT_ECCB;
-
//Break into 32-bit LPC ops but use memcpy into cache area
iv_mode = MODEL_LPC_MEM;
@@ -342,6 +417,11 @@ PnorDD::PnorDD( PnorMode_t i_mode )
//@fixme - how?? I can't use targetting yet to tell I'm in VPO...
}
+ if( MODEL_REAL_CMD == iv_mode )
+ {
+ sfcInit( );
+ }
+
TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> Using mode %d", iv_mode);
}
@@ -350,8 +430,132 @@ PnorDD::PnorDD( PnorMode_t i_mode )
*/
PnorDD::~PnorDD()
{
+ if(iv_erases)
+ {
+ delete iv_erases;
+ }
+}
+
+bool PnorDD::cv_sfcInitDone = false; //Static flag to ensure we only init the SFC one time.
+uint32_t PnorDD::cv_nor_chipid = 0; //Detected NOR Flash Type
+
+/**
+ * STATIC
+ * @brief Static Initializer
+ */
+void PnorDD::sfcInit( )
+{
+ TRACDCOMP(g_trac_pnor, "PnorDD::sfcInit> iv_mode=0x%.8x", iv_mode );
+ errlHndl_t l_err = NULL;
+
+ //Initial configuration settings for SFC:
+ #define oadrnb_init 0x04000000 //Set MMIO/Direct window to start at 64MB
+ #define oadrns_init 0x0000000F //Set the MMIO/Direct window size to 64MB
+ #define adrcbf_init 0x00000000 //Set the flash index to 0
+ #define adrcmf_init 0x0000000F //Set the flash size to 64MB
+ #define conf_init 0x00000002 //Disable Direct Access Cache
+
+ do {
+ mutex_lock(&cv_mutex);
+
+ if(!cv_sfcInitDone)
+ {
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_OADRNB,
+ oadrnb_init);
+ if(l_err) { break; }
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_OADRNS,
+ oadrns_init);
+ if(l_err) { break; }
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_ADRCBF,
+ adrcbf_init);
+ if(l_err) { break; }
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_ADRCMF,
+ adrcmf_init);
+ if(l_err) { break; }
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CONF,
+ conf_init);
+ if(l_err) { break; }
+
+ cv_sfcInitDone = true;
+
+ //Determine NOR Flash type, configure SFC and PNOR DD as needed
+ l_err = getNORChipId(cv_nor_chipid);
+ TRACFCOMP(g_trac_pnor, "PnorDD::sfcInit: cv_nor_chipid=0x%.8x> ", cv_nor_chipid );
+
+ //TODO: Need to add support for VPO (RTC: 42325), Spansion NOR (RTC: 42326),
+ // Micron NOR (RTC: 42328), Macronix (RTC: 42330), and Simics (RTC: 42331)
+ // There will probably be some overlap between those stories, but keeping them
+ // all separate for now to ensure everything is covered.
+ if(SIMICS_NOR_ID == cv_nor_chipid)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDD::sfcInit: Configuring SFC for SIMICS NOR> " );
+ uint32_t sm_erase_op = SPI_SIM_SM_ERASE_OP;
+ iv_erasesize_bytes = SPI_SIM_SM_ERASE_SZ;
+
+ /*Simics model doesn't currently support this*/
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CONF4,
+ sm_erase_op);
+ if(l_err) { break; }
+
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CONF5,
+ iv_erasesize_bytes);
+ if(l_err) { break; }
+
+ //create array to count erases.
+ iv_erases = new uint8_t[PNORSIZE/iv_erasesize_bytes];
+ for( uint64_t x=0; x < (PNORSIZE/iv_erasesize_bytes); x++ )
+ {
+ iv_erases[x] = 0;
+ }
+
+ if(l_err) { break; }
+
+
+ }
+ else
+ {
+ TRACFCOMP( g_trac_pnor, "PnorDD::sfcInit> Unsupported NOR type detected : cv_nor_chipid=%d", cv_nor_chipid );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORDD_SFCINIT
+ * @reasoncode PNOR::RC_UNSUPORTED_HARDWARE
+ * @userdata1 NOR Flash Chip ID
+ * @userdata2 <not used>
+ * @devdesc PnorDD::sfcInit>
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORDD_SFCINIT,
+ PNOR::RC_UNSUPORTED_HARDWARE,
+ TO_UINT64(cv_nor_chipid));
+
+ //Set chip ID back to zero to avoid later chip specific logic.
+ cv_nor_chipid = 0;
+ }
+
+ }
+
+ }while(0);
+
+ mutex_unlock(&cv_mutex);
+
+ if( l_err )
+ {
+ errlCommit(l_err,PNOR_COMP_ID);
+ }
+
- //Nothing to do for now
}
/**
@@ -392,125 +596,412 @@ errlHndl_t PnorDD::verifyFlashAddressRange(uint64_t i_address,
}
/**
- * @brief Read a LPC Host Controller Register
+ * @brief Write a SFC Register
*/
-errlHndl_t PnorDD::readRegLPC(LpcRegAddr i_addr,
- uint32_t& o_data)
+errlHndl_t PnorDD::writeRegSfc(SfcRange i_range,
+ uint32_t i_addr,
+ uint32_t i_data)
{
errlHndl_t l_err = NULL;
+ uint32_t lpc_addr;
- // add the offset into the LPC register space
- uint32_t lpc_addr = i_addr + LPCHC_REG_SPACE;
+ if(SFC_CMD_SPACE == i_range)
+ {
+ lpc_addr = LPC_SFC_CMDREG_OFFSET | i_addr;
+ } else {
+ lpc_addr = LPC_SFC_CMDBUF_OFFSET | i_addr;
+ }
+
+ TRACDCOMP( g_trac_pnor, "PnorDD::writeRegSfc> lpc_addr=0x%.8x, i_data=0x%.8x",
+ lpc_addr, i_data );
+ l_err = writeLPC(lpc_addr, i_data);
- // call the generic LPC function
- l_err = readLPC( lpc_addr, o_data );
return l_err;
}
/**
- * @brief Write a LPC Host Controller Register
+ * @brief Read a SFC Register
*/
-errlHndl_t PnorDD::writeRegLPC(LpcRegAddr i_addr,
- uint32_t i_data)
+errlHndl_t PnorDD::readRegSfc(SfcRange i_range,
+ uint32_t i_addr,
+ uint32_t& o_data)
{
errlHndl_t l_err = NULL;
+ uint32_t lpc_addr;
+
+ if(SFC_CMD_SPACE == i_range)
+ {
+ lpc_addr = LPC_SFC_CMDREG_OFFSET | i_addr;
+ } else {
+ lpc_addr = LPC_SFC_CMDBUF_OFFSET | i_addr;
+ }
- // add the offset into the LPC register space
- uint32_t lpc_addr = i_addr + LPCHC_REG_SPACE;
+ l_err = readLPC(lpc_addr, o_data);
+ TRACDCOMP( g_trac_pnor, "PnorDD::readRegSfc> lpc_addr=0x%.8x, o_data=0x%.8x",
+ lpc_addr, o_data );
- // call the generic LPC function
- l_err = writeLPC( lpc_addr, i_data );
return l_err;
}
+
/**
- * @brief Read a SPI Register
+ * @brief Poll for SFC Op Complete
*/
-errlHndl_t PnorDD::readRegSPI(SpiRegAddr i_addr,
- uint32_t& o_data)
+errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime)
{
- //@todo (RTC:35728) - SPI Support
- TRACFCOMP( g_trac_pnor, "PnorDD::readRegSPI> Unsupported Operation : i_addr=%d", i_addr );
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORDD_READREGSPI
- * @reasoncode PNOR::RC_UNSUPPORTED_OPERATION
- * @userdata1 Requested Address
- * @userdata2 <unused>
- * @devdesc PnorDD::readRegSPI> Unsupported Operation
- */
- return new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORDD_READREGSPI,
- PNOR::RC_UNSUPPORTED_OPERATION,
- TO_UINT64(i_addr),
- 0);
-
- /* Anything more than this??
-
- // add the offset into the LPC register space
- uint32_t lpc_addr = i_addr + LPC_SPI_REG_OFFSET;
-
- // call the generic LPC function
- l_err = readLPC( lpc_addr, o_data );
-
- */
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::pollSfcOpComplete> i_pollTime=0x%.8x",
+ i_pollTime );
+
+ do {
+ //Poll for complete status
+ SfcStatReg_t sfc_stat;
+ uint64_t poll_time = 0;
+ uint64_t loop = 0;
+ while( poll_time < i_pollTime )
+ {
+ l_err = readRegSfc(SFC_CMD_SPACE,
+ SFC_REG_STATUS,
+ sfc_stat.data32);
+ if(l_err) { break; }
+
+ if( sfc_stat.done == 1 )
+ {
+ break;
+ }
+
+ // want to start out incrementing by small numbers then get bigger
+ // to avoid a really tight loop in an error case so we'll increase
+ // the wait each time through
+ nanosleep( 0, SFC_POLL_INCR_NS*(++loop) );
+ poll_time += SFC_POLL_INCR_NS*loop;
+ }
+ if( l_err ) { break; }
+
+ // check for errors or timeout
+ // TODO: What errors do we check?
+ if( (sfc_stat.done == 0) )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDD::pollSfcOpComplete> Error or timeout from LPC Status Register" );
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORDD_POLLSFCOPCOMPLETE
+ * @reasoncode PNOR::RC_LPC_ERROR
+ * @userdata1[0:31] NOR Flash Chip ID
+ * @userdata1[32:63] Total poll time (ns)
+ * @userdata2[0:31] ECCB Status Register
+ * @devdesc PnorDD::readLPC> Error or timeout from
+ * LPC Status Register
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORDD_POLLSFCOPCOMPLETE,
+ PNOR::RC_LPC_ERROR,
+ TWO_UINT32_TO_UINT64(cv_nor_chipid,poll_time),
+ TWO_UINT32_TO_UINT64(sfc_stat.data32,0));
+
+ l_err->collectTrace("PNOR");
+ l_err->collectTrace("XSCOM");
+ //@todo (RTC:37744) - Any cleanup or recovery needed?
+ break;
+ }
+
+
+ }while(0);
+
+ return l_err;
+
}
/**
- * @brief Write a SPI Register
+ * @brief Read the NOR FLash ChipID
*/
-errlHndl_t PnorDD::writeRegSPI(SpiRegAddr i_addr,
- uint32_t i_data)
+errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId,
+ uint32_t i_spiOpcode)
{
- //@todo (RTC:35728) - SPI Support
- TRACFCOMP( g_trac_pnor, "PnorDD::writeRegSPI> Unsupported Operation : i_addr=%d", i_addr );
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORDD_WRITEREGSPI
- * @reasoncode PNOR::RC_UNSUPPORTED_OPERATION
- * @userdata1 Requested Address
- * @userdata2 <unused>
- * @devdesc PnorDD::writeRegSPI> Unsupported Operation
- */
- return new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORDD_WRITEREGSPI,
- PNOR::RC_UNSUPPORTED_OPERATION,
- TO_UINT64(i_addr),
- 0);
-
- /* Anything more than this??
-
- // add the offset into the LPC register space
- uint32_t lpc_addr = i_addr + LPC_SPI_REG_OFFSET;
-
- // call the generic LPC function
- l_err = writeLPC( lpc_addr, i_data );
-
- */
-
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::getNORChipId> i_spiOpcode=0x%.8x",
+ i_spiOpcode );
+
+ do {
+
+ //Issue Get Chip ID command
+ SfcCmdReg_t sfc_cmd;
+ sfc_cmd.opcode = i_spiOpcode;
+ sfc_cmd.length = 0;
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CMD,
+ sfc_cmd.data32);
+ if(l_err) { break; }
+
+ //Poll for complete status
+ l_err = pollSfcOpComplete();
+ if(l_err) { break; }
+
+ //Read the ChipID from the Command Buffer
+ l_err = readRegSfc(SFC_CMDBUF_SPACE,
+ 0, //Offset into CMD BUFF space in bytes
+ o_chipId);
+ if(l_err) {
+ break;
+ }
+
+ }while(0);
+
+ return l_err;
+
}
/**
- * @brief Read an address from LPC space
+ * @brief Load SFC command buffer with data from PNOR
*/
-errlHndl_t PnorDD::readLPC(uint32_t i_addr,
- uint32_t& o_data)
+errlHndl_t PnorDD::loadSfcBuf(uint32_t i_addr,
+ size_t i_size)
+{
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::loadSfcBuf> i_addr=0x%.8x, i_size=0x%.8x",
+ i_addr, i_size );
+
+ do {
+ //Write flash address to ADR reg
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_ADR,
+ i_addr);
+ if(l_err) { break; }
+
+ //Issue ReadRaw command with size to read
+ SfcCmdReg_t sfc_cmd;
+ sfc_cmd.opcode = SFC_OP_READRAW;
+ sfc_cmd.length = i_size;
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CMD,
+ sfc_cmd.data32);
+ if(l_err) { break; }
+
+ //Poll for complete status
+ l_err = pollSfcOpComplete();
+ if(l_err) { break; }
+
+ }while(0);
+
+ return l_err;
+
+}
+
+/**
+ * @brief Flush SFC command buffer data to PNOR Flash
+ */
+errlHndl_t PnorDD::flushSfcBuf(uint32_t i_addr,
+ size_t i_size)
{
errlHndl_t l_err = NULL;
- bool need_unlock = false;
+ TRACDCOMP( g_trac_pnor, "PnorDD::flushSfcBuf> i_addr=0x%.8x, i_size=0x%.8x",
+ i_addr, i_size );
do {
+ //Write flash address to ADR reg
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_ADR,
+ i_addr);
+ if(l_err) { break; }
+
+ //Issue WriteRaw command + size to write
+ SfcCmdReg_t sfc_cmd;
+ sfc_cmd.opcode = SFC_OP_WRITERAW;
+ sfc_cmd.length = i_size;
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CMD,
+ sfc_cmd.data32);
+ if(l_err) { break; }
+
+ //Poll for complete status
+ l_err = pollSfcOpComplete();
+ if(l_err) { break; }
+
+ }while(0);
+
+ return l_err;
+
+}
+
+/**
+ * @brief Perform command based read of PNOR, maximizing use of
+ * SFC Command buffer..
+ */
+errlHndl_t PnorDD::bufferedSfcRead(uint32_t i_addr,
+ size_t i_size,
+ void* o_data)
+{
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::bufferedSfcRead> i_addr=0x%.8x, i_size=0x%.8x",
+ i_addr, i_size );
+
+ do{
+
if( MODEL_LPC_MEM == iv_mode )
{
- read_fake_pnor( i_addr - LPCHC_FW_SPACE,
- static_cast<void*>(&o_data),
- sizeof(uint32_t) );
+ read_fake_pnor( i_addr,
+ o_data,
+ i_size );
break;
}
- // Note: If we got here then iv_mode is
- // either MODEL_FLAT_ECCB or MODEL_REAL
+ // Note: If we got here then iv_mode is MODEL_REAL_CMD
+
+ // Command based reads are buffered 256 bytes at a time.
+ uint32_t chunk_size = 0;
+ uint64_t addr = i_addr;
+ uint64_t end_addr = i_addr + i_size;
+
+ while(addr < end_addr)
+ {
+ chunk_size = SFC_CMDBUF_SIZE;
+ if( (addr + SFC_CMDBUF_SIZE) > end_addr)
+ {
+ chunk_size = end_addr - addr;
+ }
+
+ //Read data via SFC CMD Buffer
+ l_err = loadSfcBuf(addr, chunk_size);
+ if(l_err) { break;}
+
+ //read SFC CMD Buffer via MMIO
+ l_err = readSfcBuffer(chunk_size,
+ (void*)((uint64_t)o_data + (addr-i_addr)));
+ if(l_err) { break;}
+
+ addr += chunk_size;
+ }
+ }while(0);
+
+ return l_err;
+
+}
+
+
+/**
+ * @brief Perform command based write of PNOR, maximizing use of
+ * SFC Command buffer..
+ */
+errlHndl_t PnorDD::bufferedSfcWrite(uint32_t i_addr,
+ size_t i_size,
+ void* i_data)
+{
+ TRACDCOMP( g_trac_pnor, "PnorDD::bufferedSfcWrite> i_addr=0x%.8x, i_size=0x%.8x",
+ i_addr, i_size );
+
+ errlHndl_t l_err = NULL;
+
+ do{
+ if( MODEL_LPC_MEM == iv_mode )
+ {
+ write_fake_pnor( i_addr,
+ i_data,
+ i_size );
+ break;
+ }
+
+ // Note: If we got here then iv_mode is MODEL_REAL_CMD
+
+ // Command based reads are buffered 256 bytes at a time.
+ uint32_t chunk_size = 0;
+ uint64_t addr = i_addr;
+ uint64_t end_addr = i_addr + i_size;
+
+ while(addr < end_addr)
+ {
+ chunk_size = SFC_CMDBUF_SIZE;
+ if( (addr + SFC_CMDBUF_SIZE) > end_addr)
+ {
+ chunk_size = end_addr - addr;
+ }
+
+ //write data to SFC CMD Buffer via MMIO
+ l_err = writeSfcBuffer(chunk_size,
+ (void*)((uint64_t)i_data + (addr-i_addr)));
+ if(l_err) { break;}
+
+ //Fetch bits into SFC CMD Buffer
+ l_err = flushSfcBuf(addr, chunk_size);
+ if(l_err) { break;}
+
+ addr += chunk_size;
+ }
+ }while(0);
+
+ return l_err;
+
+}
+
+
+/**
+ * @brief Read data in SFC Command buffer and put into buffer
+ */
+errlHndl_t PnorDD::readSfcBuffer(size_t i_size,
+ void* o_data)
+{
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::readSfcBuffer> i_size=0x%.8x",
+ i_size );
+
+ // SFC Command Buffer is accessed 32-bits at a time
+ uint32_t* word_ptr = static_cast<uint32_t*>(o_data);
+ uint32_t word_size = i_size/4;
+ for( uint32_t words_read = 0;
+ words_read < word_size;
+ words_read ++ )
+ {
+ l_err = readRegSfc(SFC_CMDBUF_SPACE,
+ words_read*4, //Offset into CMD BUFF space in bytes
+ word_ptr[words_read]);
+ TRACDCOMP( g_trac_pnor, "PnorDD::readSfcBuffer: Read offset=0x%.8x, data_read=0x%.8x",
+ words_read*4, word_ptr[words_read] );
+
+ if( l_err ) { break; }
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Write data to SFC Command buffer
+ */
+errlHndl_t PnorDD::writeSfcBuffer(size_t i_size,
+ void* i_data)
+{
+ errlHndl_t l_err = NULL;
+ TRACDCOMP( g_trac_pnor, "PnorDD::writeSfcBuffer> i_size=0x%.8x",
+ i_size );
+
+ // SFC Command Buffer is accessed 32-bits at a time
+ uint32_t* word_ptr = static_cast<uint32_t*>(i_data);
+ uint32_t word_size = i_size/4;
+ for( uint32_t words_read = 0;
+ words_read < word_size;
+ words_read ++ )
+ {
+ l_err = writeRegSfc(SFC_CMDBUF_SPACE,
+ words_read*4, //Offset into CMD BUFF space in bytes
+ word_ptr[words_read]);
+ if( l_err ) { break; }
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Read an address from LPC space
+ */
+errlHndl_t PnorDD::readLPC(uint32_t i_addr,
+ uint32_t& o_data)
+{
+ errlHndl_t l_err = NULL;
+
+ do {
//@todo (RTC:36950) - add non-master support
TARGETING::Target* scom_target =
@@ -519,10 +1010,6 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
// always read/write 64 bits to SCOM
size_t scom_size = sizeof(uint64_t);
- // atomic section >>
- mutex_lock(&iv_mutex);
- need_unlock = true;
-
// write command register with LPC address to read
ControlReg_t eccb_cmd;
eccb_cmd.read_op = 1;
@@ -588,21 +1075,12 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
}
- // atomic section <<
- mutex_unlock(&iv_mutex);
- need_unlock = false;
// copy data out to caller's buffer
o_data = eccb_stat.read_data;
} while(0);
- if( need_unlock )
- {
- mutex_unlock(&iv_mutex);
- need_unlock = false;
- }
-
return l_err;
}
@@ -613,21 +1091,10 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
uint32_t i_data)
{
errlHndl_t l_err = NULL;
- bool need_unlock = false;
- //TRACFCOMP(g_trac_pnor, "writeLPC> %.8X = %.8X", i_addr, i_data );
+ TRACDCOMP(g_trac_pnor, "writeLPC> %.8X = %.8X", i_addr, i_data );
do {
- if( MODEL_LPC_MEM == iv_mode )
- {
- write_fake_pnor( i_addr - LPCHC_FW_SPACE,
- static_cast<void*>(&i_data),
- sizeof(uint32_t) );
- break;
- }
-
- // Note: If we got here then iv_mode is
- // either MODEL_FLAT_ECCB or MODEL_REAL
//@todo (RTC:36950) - add non-master support
TARGETING::Target* scom_target =
@@ -636,11 +1103,9 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
// always read/write 64 bits to SCOM
size_t scom_size = sizeof(uint64_t);
- // atomic section >>
- mutex_lock(&iv_mutex);
- need_unlock = true;
-
// write data register
+ TRACDCOMP(g_trac_pnor, "writeLPC> Write ECCB data register");
+
uint64_t eccb_data = static_cast<uint64_t>(i_data);
eccb_data = eccb_data << 32; //left-justify my data
l_err = deviceOp( DeviceFW::WRITE,
@@ -651,6 +1116,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
if( l_err ) { break; }
// write command register with LPC address to write
+ TRACDCOMP(g_trac_pnor, "writeLPC> Write ECCB command register, cmd=0x%.16x", eccb_cmd.data64 );
ControlReg_t eccb_cmd;
eccb_cmd.read_op = 0;
eccb_cmd.address = i_addr;
@@ -661,6 +1127,7 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
DEVICE_SCOM_ADDRESS(ECCB_CTL_REG) );
if( l_err ) { break; }
+
// poll for complete
StatusReg_t eccb_stat;
uint64_t poll_time = 0;
@@ -672,6 +1139,8 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
&(eccb_stat.data64),
scom_size,
DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
+ TRACDCOMP(g_trac_pnor, "writeLPC> Poll on ECCB Status, poll_time=0x%.16x, stat=0x%.16x", eccb_stat.data64, poll_time );
+
if( l_err ) { break; }
if( eccb_stat.op_done == 1 )
@@ -713,208 +1182,160 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
break;
}
- // atomic section <<
- mutex_unlock(&iv_mutex);
- need_unlock = false;
} while(0);
- if( need_unlock )
- {
- mutex_unlock(&iv_mutex);
- need_unlock = false;
- }
return l_err;
}
+
/**
* @brief Compare the existing data in 1 erase block of the flash with
* the incoming data and write or erase as needed
*/
-errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
- uint32_t i_wordsToWrite,
- uint32_t* i_data)
+errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_blockStart,
+ uint32_t i_writeStart,
+ size_t i_bytesToWrite,
+ void* i_data)
{
- TRACDCOMP(g_trac_pnor,"compareAndWriteBlock(0x%.8X,%d,%p)", i_targetAddr, i_wordsToWrite, i_data);
+ TRACDCOMP(g_trac_pnor,">>compareAndWriteBlock(0x%.8X,0x%.8X,0x%.8X)", i_blockStart, i_writeStart, i_bytesToWrite);
errlHndl_t l_err = NULL;
+ uint8_t* read_data = NULL;
+
+ do {
- // remember any data we read so we don't have to reread it later
- typedef struct
- {
- uint32_t data;
- bool wasRead;
- bool diff;
- } readflag_t;
- readflag_t* read_data = NULL;
+ // remember any data we read so we don't have to reread it later
+ read_data = new uint8_t[iv_erasesize_bytes];
- do {
- // skip the erase block logic if we're in a memcpy mode
- if( (MODEL_MEMCPY == iv_mode) || (MODEL_LPC_MEM == iv_mode) )
+ // remember if we need to erase the block or not
+ bool need_erase = false;
+ bool need_write = false;
+
+ //STEP 1: Read data in PNOR for compares (only read section we want to write)
+ //read_start needs to be uint32* for bitwise word compares later
+ uint32_t* read_start = (uint32_t*)(read_data + i_writeStart-i_blockStart);
+ l_err = bufferedSfcRead(i_writeStart,
+ i_bytesToWrite,
+ (void*) read_start);
+ if( l_err ) { break; }
+
+ //STEP 2: walk through the write data to see if we need to do an erase
+ const uint32_t wordsToWrite = i_bytesToWrite/4;
+ uint32_t* i_dataWord = (uint32_t*) i_data;
+
+ for(uint32_t cword = 0; cword < wordsToWrite; cword++)
{
- // LPC is accessed 32-bits at a time...
- uint64_t words_written = 0;
- for( uint32_t addr = i_targetAddr;
- addr < (i_targetAddr+i_wordsToWrite*sizeof(uint32_t));
- addr += sizeof(uint32_t) )
+ // look for any bits being changed (using XOR)
+ if(read_start[cword] ^ i_dataWord[cword] )
{
- // flash is mapped directly in the FW space
- l_err = writeLPC( addr + LPCHC_FW_SPACE,
- i_data[words_written] );
- if( l_err ) { break; }
+ need_write = true;
- words_written++;
- }
- if( l_err ) { break; }
+ //Can only write zeros to NOR, see if any bits changed from 0->1
+ if( (~(read_start[cword])) & (i_dataWord[cword]) )
+ {
+ need_erase = true;
- // all done
- break;
+ // skip comparing the rest of the block,
+ // just start writing it
+ break;
+ }
+ }
}
-
- // remember any data we read so we don't have to reread it later
- read_data = new readflag_t[ERASESIZE_WORD32];
- for( size_t x = 0; x < ERASESIZE_WORD32; x++ )
+ if(need_write == false)
{
- read_data[x].wasRead = false;
- read_data[x].diff = false;
+ //No write actually needed, break out here
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> NO Write Needed! Exiting FUnction");
+ break;
}
- // remember if we need to erase the block or not
- bool need_erase = false;
-
- // walk through every word of data to see what changed
- const uint32_t block_addr = findEraseBlock(i_targetAddr);
- for( uint64_t bword = 0; bword < ERASESIZE_WORD32; bword++ )
+ //STEP 3: If the need to erase was detected, read out the rest of the Erase block
+ if(need_erase)
{
- // note: bword is the offset into the flash block
- read_data[bword].diff = false;
-
- // no need to check data before where the write starts
- if( (block_addr + bword*sizeof(uint32_t)) < i_targetAddr )
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Need to perform Erase");
+ //Get data before write section
+ if(i_writeStart > i_blockStart)
{
- continue;
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Reading beginning data i_blockStart=0x%.8x, readLen=0x%.8x",
+ i_blockStart, i_writeStart-i_blockStart);
+ l_err = bufferedSfcRead(i_blockStart,
+ i_writeStart-i_blockStart,
+ read_data);
}
- // no need to check data after where the write ends
- else if( (block_addr + bword*sizeof(uint32_t)) >=
- (i_targetAddr + i_wordsToWrite*sizeof(uint32_t)) )
+
+ //Get data after write section
+ if((i_writeStart+i_bytesToWrite) < (i_blockStart + iv_erasesize_bytes))
{
- // done looking now
- break;
+ uint32_t tail_length = i_blockStart + iv_erasesize_bytes - (i_writeStart+i_bytesToWrite);
+ uint8_t* tail_buffer = read_data + i_writeStart-i_blockStart + i_bytesToWrite;
+
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Reading tail data. addr=0x%.8x, tail_length=0x%.8x",
+ i_writeStart+i_bytesToWrite, tail_length);
+ l_err = bufferedSfcRead(i_writeStart+i_bytesToWrite,
+ tail_length,
+ tail_buffer);
+ if( l_err )
+ {
+ break; }
}
- // otherwise we need to compare our data with what is in flash now
- else
- {
- l_err = readLPC( block_addr + bword*sizeof(uint32_t)
- + LPCHC_FW_SPACE,
- read_data[bword].data );
- if( l_err ) { break; }
- read_data[bword].wasRead = true;
+ // erase the flash
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Calling eraseFlash:. i_blockStart=0x%.8x", i_blockStart);
+ l_err = eraseFlash( i_blockStart );
+ if( l_err ) { break; }
- // dword is the offset into the input data
- uint64_t dword = (block_addr + bword*sizeof(uint32_t));
- dword -= i_targetAddr; //offset into user data
- dword = dword / sizeof(uint32_t); //convert bytes to words
+ //STEP 4: Write the data back out - need to write everything since we erased the block
- // look for any bits being changed (using XOR)
- if( read_data[bword].data ^ i_data[dword] )
- {
- read_data[bword].diff = true;
-
- // look for any bits that go from 1->0
- if( read_data[bword].data & ~(i_data[dword]) )
- {
- need_erase = true;
-
- // push the user data into the read buffer
- // to get written later
- read_data[bword].data = i_data[dword];
-
- // skip comparing the rest of the block,
- // just start writing it
- break;
- }
-
- // push the user data into the read buffer
- // to get written later
- read_data[bword].data = i_data[dword];
- }
+ //re-write data before new data to write
+ if(i_writeStart > i_blockStart)
+ {
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Writing beginning data i_blockStart=0x%.8x, readLen=0x%.8x",
+ i_blockStart, i_writeStart-i_blockStart);
+ l_err = bufferedSfcWrite(i_blockStart,
+ i_writeStart-i_blockStart,
+ read_data);
}
- }
- if( l_err ) { break; }
- // erase the block if we need to
- if( need_erase )
- {
- // first we need to save off any data we didn't read yet
- // that is not part of the data we are writing
- for( uint64_t bword = 0; bword < ERASESIZE_WORD32; bword++ )
+ //Write data after new data to write
+ if((i_writeStart+i_bytesToWrite) < (i_blockStart + iv_erasesize_bytes))
{
- // mark the word as different to force a write below
- read_data[bword].diff = true;
-
- // skip what we already read
- if( read_data[bword].wasRead )
- {
- continue;
- }
-
- // dword is the offset into the input data
- uint64_t dword = (block_addr + bword*sizeof(uint32_t));
- dword -= i_targetAddr; //offset into user data
- dword = dword / sizeof(uint32_t); //convert bytes to words
-
- // restore the data before the write section
- if( (block_addr + bword*sizeof(uint32_t)) < i_targetAddr )
- {
- l_err = readLPC( block_addr + bword*sizeof(uint32_t)
- + LPCHC_FW_SPACE,
- read_data[bword].data );
- if( l_err ) { break; }
- }
- // restore the data after the write section
- else if( (block_addr + bword*sizeof(uint32_t)) >=
- (i_targetAddr + i_wordsToWrite*sizeof(uint32_t)) )
- {
- l_err = readLPC( block_addr + bword*sizeof(uint32_t)
- + LPCHC_FW_SPACE,
- read_data[bword].data );
- if( l_err ) { break; }
- }
- // otherwise we will use the write data directly
- else
- {
- read_data[bword].data = i_data[dword];
- }
+ uint32_t tail_length = i_blockStart + iv_erasesize_bytes - (i_writeStart+i_bytesToWrite);
+ uint8_t* tail_buffer = read_data + i_writeStart-i_blockStart + i_bytesToWrite;
+
+ TRACDCOMP(g_trac_pnor,"compareAndWriteBlock> Writing tail data. addr=0x%.8x, tail_length=0x%.8x",
+ i_writeStart+i_bytesToWrite, tail_length);
+ l_err = bufferedSfcWrite(i_writeStart+i_bytesToWrite,
+ tail_length,
+ tail_buffer);
+ if( l_err ) { break; }
}
- if( l_err ) { break; }
- // erase the flash
- l_err = eraseFlash( block_addr );
+ //Write the new data - always do this
+ l_err = bufferedSfcWrite(i_writeStart,
+ i_bytesToWrite,
+ i_data);
if( l_err ) { break; }
}
-
- // walk through every word again to write the data back out
- uint64_t bword_written = 0;
- for( bword_written = 0;
- bword_written < ERASESIZE_WORD32;
- bword_written++ )
+ else //
{
- // only write what we have to
- if( !(read_data[bword_written].diff) )
+ //STEP 4 ALT: No erase needed, only write the parts that changed.
+
+ for(uint32_t cword = 0; cword < wordsToWrite; cword++)
{
- continue;
- }
+ // look for any bits being changed (using XOR)
+ if(read_start[cword] ^ i_dataWord[cword] )
+ {
+ //Write the new data - always do this
+ l_err = bufferedSfcWrite(i_writeStart + (cword*4),
+ 4,
+ &i_dataWord[cword]);
+ if( l_err ) { break; }
+ }
+ if( l_err ) { break; }
- // write the word out to the flash
- l_err = writeLPC( block_addr + bword_written*sizeof(uint32_t)
- + LPCHC_FW_SPACE,
- read_data[bword_written].data );
- if( l_err ) { break; }
- //@todo (RTC:37744) - How should we handle PNOR errors?
+ }
}
- if( l_err ) { break; }
} while(0);
@@ -923,6 +1344,9 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
delete[] read_data;
}
+ TRACDCOMP(g_trac_pnor,"<<compareAndWriteBlock() Exit");
+
+
return l_err;
}
@@ -932,6 +1356,7 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
{
errlHndl_t l_err = NULL;
+ TRACDCOMP(g_trac_pnor, ">>PnorDD::eraseFlash> Block 0x%.8X", i_address );
do {
if( findEraseBlock(i_address) != i_address )
@@ -952,30 +1377,55 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
break;
}
- // log the erase of this block
- iv_erases[i_address/ERASESIZE_BYTES]++;
- TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", i_address, iv_erases[i_address/ERASESIZE_BYTES] );
+ if(iv_erases)
+ {
+ // log the erase of this block
+ iv_erases[i_address/iv_erasesize_bytes]++;
+ TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", i_address, iv_erases[i_address/iv_erasesize_bytes] );
+ }
- if( MODEL_REAL != iv_mode )
+ if( (MODEL_MEMCPY == iv_mode) || (MODEL_LPC_MEM == iv_mode))
{
- erase_fake_pnor( i_address, ERASESIZE_BYTES );
+ erase_fake_pnor( i_address, iv_erasesize_bytes );
break; //all done
}
- //@todo (RTC:35728) - issue some LPC/SPI commands to erase the block
- /*@
- * @errortype
- * @moduleid PNOR::MOD_PNORDD_ERASEFLASH
- * @reasoncode PNOR::RC_UNSUPPORTED_OPERATION
- * @userdata1 Model mode
- * @userdata2 LPC Address to erase
- * @devdesc PnorDD::eraseFlash> No support for MODEL_REAL yet
- */
- l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::MOD_PNORDD_ERASEFLASH,
- PNOR::RC_UNSUPPORTED_OPERATION,
- static_cast<uint64_t>(iv_mode),
- i_address);
+ if(cv_nor_chipid != 0)
+ {
+ TRACDCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erasing flash for cv_nor_chipid=0x%.8x, iv_mode=0x%.8x", cv_nor_chipid, iv_mode);
+ //Issue Erase command
+ SfcCmdReg_t sfc_cmd;
+ sfc_cmd.opcode = SFC_OP_ERASM;
+ sfc_cmd.length = 0; //Not used for erase
+
+ l_err = writeRegSfc(SFC_CMD_SPACE,
+ SFC_REG_CMD,
+ sfc_cmd.data32);
+ if(l_err) { break; }
+
+ //Poll for complete status
+ l_err = pollSfcOpComplete();
+ if(l_err) { break; }
+
+ }
+ else
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erase not supported for cv_nor_chipid=%d", cv_nor_chipid );
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORDD_ERASEFLASH
+ * @reasoncode PNOR::RC_UNSUPPORTED_OPERATION
+ * @userdata1 NOR Chip ID
+ * @userdata2 LPC Address to erase
+ * @devdesc PnorDD::eraseFlash> No support for MODEL_REAL yet
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORDD_ERASEFLASH,
+ PNOR::RC_UNSUPPORTED_OPERATION,
+ static_cast<uint64_t>(cv_nor_chipid),
+ i_address);
+ }
} while(0);
return l_err;
diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H
index 0ce538b4d..ed88695af 100644
--- a/src/usr/pnor/pnordd.H
+++ b/src/usr/pnor/pnordd.H
@@ -38,6 +38,13 @@ class PnorDD
public:
/**
+ * @brief Initializer called by PnorRP::init() to init the SFC
+ *
+ * @return void
+ */
+ void sfcInit( );
+
+ /**
* @brief Performs a PNOR Read Operation
*
* @parm o_buffer Buffer to read data into
@@ -65,14 +72,12 @@ class PnorDD
size_t& io_buflen,
uint64_t i_address);
-
- protected:
enum PnorMode_t {
- MODEL_UNKNOWN, //Invalid
- MODEL_MEMCPY, //No LPC logic, just do memcpy into cache area
- MODEL_LPC_MEM, //Break into 32-bit LPC ops but use memcpy into cache area
- MODEL_FLAT_ECCB, //Use ECCB scoms to drive LPC, flat memory map behind ECCB, no SPI
- MODEL_REAL, //Code for real hardware or complete sim model
+ MODEL_UNKNOWN, /**< Invalid */
+ MODEL_MEMCPY, /**< No LPC logic, just do memcpy into cache area */
+ MODEL_LPC_MEM, /**< Break into 32-bit LPC ops but use memcpy into cache area */
+ MODEL_REAL_CMD, /**< Code for real hardware or complete sim model using Commands based reads */
+ MODEL_REAL_MMIO, /**< Code for real hardware or complete sim model using MMIO reads-Not currently implemented */
};
/**
@@ -86,6 +91,9 @@ class PnorDD
*/
~PnorDD();
+ protected:
+
+
/**
* @brief Verify flash request is in appropriate address range
*
@@ -109,84 +117,232 @@ class PnorDD
};
/**
- * @brief Read a LPC Host Controller Register
+ * @brief SPI Config Info
+ * OP Codes and other MISC info for configuring SFC
+ */
+ enum SpiConfigInfo {
+ SPI_GET_CHIPID_OP = 0x9F, /**< Default Op code for getting NOR ChipID */
+
+ SPI_SIM_SM_ERASE_OP = 0x00000020, /**< Simics Op Code for Small Erase */
+ SPI_SIM_SM_ERASE_SZ = 0x1000, /**< Simics Small Erase Size */
+ };
+
+ /**
+ * @brief Supported NOR Chip IDs
*
- * @parm i_addr Register address, relative to the
- * LPC Host Controller Register Space
- * @parm o_data Buffer to read data into
+ */
+ enum NorChipIDs
+ {
+ SIMICS_NOR_ID = 0x20ba2000, /**< CHIP ID returned by Simics NOR chip */
+ };
+
+
+ enum SfcRange {
+ SFC_CMD_SPACE, /**< Indicate accessing command reg */
+ SFC_CMDBUF_SPACE, /**< Indicate accessing command buffer space */
+ };
+
+ /**
+ * @brief SFC Registers
+ * These are offsets within the SFC Register Space
+ */
+ enum SfcRegAddr {
+ SFC_REG_CONF = 0x10, /**< CONF: Direct Access Configuration */
+ SFC_REG_STATUS = 0x0C, /**< STATUS : Status Reg */
+ SFC_REG_CMD = 0x40, /**< CMD : Command */
+ SFC_REG_ADR = 0x44, /**< ADR : Address */
+ SFC_REG_ERASMS = 0x48, /**< ERASMS : Small Erase Block Size */
+ SFC_REG_ERASLGS = 0x4C, /**< ERALGS : Large Erase Block Size */
+ SFC_REG_CONF4 = 0x54, /**< CONF4 : SPI Op Code for Small Erase */
+ SFC_REG_CONF5 = 0x58, /**< CONF5 : Small Erase Size config reg */
+ SFC_REG_ADRCBF = 0x80, /**< ADRCBF : First Intf NOR Addr Offset */
+ SFC_REG_ADRCMF = 0x84, /**< ADRCMF : First Intf NOR Allocation */
+ SFC_REG_ADRCBS = 0x88, /**< ADRCBS : Second Intf NOR Addr Offset */
+ SFC_REG_ADRCMS = 0x8C, /**< ADRCMS : Second Intf NOR Allocation */
+ SFC_REG_OADRNB = 0x90, /**< OADRNB : Direct Access OBP Window Base Address */
+ SFC_REG_OADRNS = 0x94, /**< OADRNS : DIrect Access OPB Window Size */
+
+
+ };
+
+ /**
+ * @brief SFC Op Codes
+ * OP Codes for the SFC Command Register
+ */
+ enum SfcOpCodes {
+ SFC_OP_READRAW = 0x03, /**< Read Raw */
+ SFC_OP_WRITERAW = 0x02, /**< Write Raw */
+ SFC_OP_ERASM = 0x32, /**< Erase Small */
+ SFC_OP_ERALG = 0x34, /**< Erase Large */
+ SFC_OP_ENWRITPROT = 0x53, /**< Enable WRite Protect */
+ SFC_OP_CHIPID = 0x1F, /**< Get Chip ID */
+ SFC_OP_STATUS = 0x05, /**< Get Status */
+ SFC_OP_TURNOFF = 0x5E, /**< Turn Off */
+ SFC_OP_TURNON = 0x50, /**< Turn On */
+ SFC_OP_ABORT = 0x6F, /**< Super-Abort */
+ SFC_OP_START4BA = 0x37, /**< Start 4BA */
+ SFC_OP_END4BA = 0x69, /**< End 4BA */
+ };
+
+
+ enum {
+ SFC_CMDBUF_SIZE = 256, /**< SFC Command buffer is 0x100/256 bytes/0x40 words */
+
+ SFC_POLL_TIME_NS = 400000, /**< todo: Find out Max time to wait */
+ SFC_POLL_INCR_NS = 10, /**< minimum increment during poll */
+
+ };
+
+ /**
+ * @brief SFC Command Register Layout
+ */
+ union SfcCmdReg_t
+ {
+ uint32_t data32;
+ struct
+ {
+ uint32_t reserved : 16; /**< 0:15 = Reserved */
+ uint32_t opcode : 7; /**< 16:22 = OpCode */
+ uint32_t length : 9; /**< 22:31 = Num bytes for ReadRaw/WriteRaw */
+ };
+ SfcCmdReg_t() : data32(0) {};
+ };
+
+ /**
+ * @brief SFC Status Register Layout
+ */
+ union SfcStatReg_t
+ {
+ uint32_t data32;
+ struct
+ {
+ uint32_t unused : 30; /**< 0:29 = Not Currently Used */
+ uint32_t timeout : 1; /**< 30 = Timeout */
+ uint32_t done : 1; /**< 31 = Done */
+ };
+ SfcStatReg_t() : data32(0) {};
+ };
+
+
+ /**
+ * @brief Write a SFC Register
+ *
+ * @parm i_range SFC Address Range
+ * @parm i_addr SFC Register to write
+ * @parm i_data Data to write
*
* @return Error from operation
*/
- errlHndl_t readRegLPC(LpcRegAddr i_addr,
+ errlHndl_t writeRegSfc(SfcRange i_range,
+ uint32_t i_addr,
+ uint32_t i_data);
+
+ /**
+ * @brief Read a SFC Register
+ *
+ * @parm i_range SFC Address Range
+ * @parm i_addr SFC Register to read
+ * @parm o_data Data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t readRegSfc(SfcRange i_range,
+ uint32_t i_addr,
uint32_t& o_data);
/**
- * @brief Write a LPC Host Controller Register
+ * @brief Poll for SFC Op Complete
*
- * @parm i_addr Register address, relative to the
- * LPC Host Controller Register Space
- * @parm o_data Data to write
+ * @parm i_pollTime Amount of time to Poll, default SFC_POLL_TIME_NS
*
* @return Error from operation
*/
- errlHndl_t writeRegLPC(LpcRegAddr i_addr,
- uint32_t i_data);
+ errlHndl_t pollSfcOpComplete(uint64_t i_pollTime = SFC_POLL_TIME_NS);
+
/**
- * @brief SPI Registers
- * These are offsets within the SPI Register Space
+ * @brief Read the NOR FLash ChipID
+ *
+ * @parm o_chipId NOR Flash ChipID
+ * @parm i_spiOpcode SPI OpCode to use to get Chip ID
+ *
+ * @return Error from operation
*/
- enum SpiRegAddr {
- SPI_REG_CMD = 0x40, /**< CMD : Command */
- SPI_REG_ADR = 0x44, /**< ADR : Address */
- SPI_REG_ERASMS = 0x48, /**< ERASMS : Small Erase Block Size */
- SPI_REG_ERASLGS = 0x4C, /**< ERALGS : Large Erase Block Size */
- SPI_REG_ADRCBF = 0x80, /**< ADRCBF : First Intf NOR Addr Offset */
- SPI_REG_ADRCMF = 0x84, /**< ADRCMF : First Intf NOR Allocation */
- SPI_REG_ADRCBS = 0x88, /**< ADRCBS : Second Intf NOR Addr Offset */
- SPI_REG_ADRCMS = 0x8C, /**< ADRCMS : Second Intf NOR Allocation */
- };
+ errlHndl_t getNORChipId(uint32_t& o_chipId,
+ uint32_t i_spiOpcode = SPI_GET_CHIPID_OP);
/**
- * @brief SPI Op Codes
- * OP Codes for the SPI Command Register
- */
- enum SpiOpCodes {
- SPI_OP_READRAW = 0x03, /**< Read Raw */
- SPI_OP_WRITERAW = 0x02, /**< Write Raw */
- SPI_OP_ERASM = 0x32, /**< Erase Small */
- SPI_OP_ERALG = 0x34, /**< Erase Large */
- SPI_OP_ENWRITPROT = 0x53, /**< Enable WRite Protect */
- SPI_OP_CHIPID = 0x1F, /**< Get Chip ID */
- SPI_OP_STATUS = 0x05, /**< Get Status */
- SPI_OP_TURNOFF = 0x5E, /**< Turn Off */
- SPI_OP_TURNON = 0x50, /**< Turn On */
- SPI_OP_ABORT = 0x6F, /**< Super-Abort */
- SPI_OP_START4BA = 0x37, /**< Start 4BA */
- SPI_OP_END4BA = 0x69, /**< End 4BA */
- };
+ * @brief Load SFC command buffer with data from PNOR
+ *
+ * @parm i_addr PNOR flash Address to read
+ * @parm i_size Number of bytes to read.to command buffer
+ *
+ * @return Error from operation
+ */
+ errlHndl_t loadSfcBuf(uint32_t i_addr,
+ size_t i_size);
+
+ /**
+ * @brief Flush SFC command buffer contents to PNOR Flash
+ *
+ * @parm i_addr PNOR flash Address to write
+ * @parm i_size Number of bytes to write.to command buffer
+ *
+ * @return Error from operation
+ */
+ errlHndl_t flushSfcBuf(uint32_t i_addr,
+ size_t i_size);
/**
- * @brief Read a SPI Register
+ * @brief Read data in SFC Command buffer and put into buffer
*
- * @parm i_addr Register address, relative to the SPI engine
+ * @parm i_size Amount of data in Cmd Buffer to read, in bytes.
* @parm o_data Buffer to read data into
*
* @return Error from operation
*/
- errlHndl_t readRegSPI(SpiRegAddr i_addr,
- uint32_t& o_data);
+ errlHndl_t readSfcBuffer(size_t i_size,
+ void* o_data);
/**
- * @brief Write a SPI Register
+ * @brief Write data to SFC Command buffer
*
- * @parm i_addr Register address, relative to the SPI engine
- * @parm o_data Data to write
+ * @parm i_size Amount of data in Cmd Buffer to write, in bytes.
+ * @parm o_data Buffer to read data from
*
* @return Error from operation
*/
- errlHndl_t writeRegSPI(SpiRegAddr i_addr,
- uint32_t i_data);
+ errlHndl_t writeSfcBuffer(size_t i_size,
+ void* i_data);
+
+
+ /**
+ * @brief Perform command based read of PNOR, maximizing use of
+ * SFC Command buffer..
+ *
+ * @parm i_addr PNOR flash Address to read
+ * @parm i_size Amount of data to read, in bytes.
+ * @parm o_data Buffer to read data into
+ *
+ * @return Error from operation
+ */
+ errlHndl_t bufferedSfcRead(uint32_t i_addr,
+ size_t i_size,
+ void* o_data);
+
+ /**
+ * @brief Perform command based write of PNOR, maximizing use of
+ * SFC Command buffer..
+ *
+ * @parm i_addr PNOR flash Address to write
+ * @parm i_size Amount of data to write, in bytes.
+ * @parm i_data Buffer containing data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t bufferedSfcWrite(uint32_t i_addr,
+ size_t i_size,
+ void* i_data);
/**
@@ -200,15 +356,13 @@ class PnorDD
LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
LPC_DIRECT_READ_OFFSET = 0xFC000000,
- LPC_SPI_REG_OFFSET = 0xF0000C00,
+ LPC_SFC_CMDREG_OFFSET = 0xF0000C00, /** LPC Offest to SFC Command Registers */
+ LPC_SFC_CMDBUF_OFFSET = 0xF0000D00, /** LPC Offest to SFC Command Buffer space */
LPC_TOP_OF_FLASH_OFFSET = 0xFFFFFFFF,
ECCB_CTL_REG = 0x000B0020, /**< ECCB Control Reg (FW) */
ECCB_STAT_REG = 0x000B0022, /**< ECCB Status Reg (FW) */
ECCB_DATA_REG = 0x000B0023, /**< ECCB Data Reg (FW) */
- //ECCB_CTL_REG = 0x00090020, /**< ECCB Control Reg (FW) */
- //ECCB_STAT_REG = 0x00090022, /**< ECCB Status Reg (FW) */
- //ECCB_DATA_REG = 0x00090023, /**< ECCB Data Reg (FW) */
// Default Values to set for all operations
// 1101.0100.0000.000x.0000.0001.0000.0000.<address>
@@ -217,9 +371,7 @@ class PnorDD
LPC_STAT_REG_ERROR_MASK = 0xFC0000000007F700, /**< Error Bits */
PNORSIZE = 4 * MEGABYTE, //@fixme - read from TOC instead
- ERASESIZE_BYTES = 4 * KILOBYTE, /**< Minimum Erase Block (bytes) */
- ERASESIZE_WORD32 = ERASESIZE_BYTES/(sizeof(uint32_t)), /**< Erase Block (32-bit words) */
-
+ ERASESIZE_BYTES_DEFAULT = 4 * KILOBYTE, /**< Minimum Erase Block (bytes) */
ECCB_POLL_TIME_NS = 400000, /**< max time from Manfred Walz is 400ms */
ECCB_POLL_INCR_NS = 10, /**< minimum increment during poll */
};
@@ -260,15 +412,17 @@ class PnorDD
* @brief Compare the existing data in 1 erase block of the flash with
* the incoming data and write or erase as needed
*
- * @parm i_targetAddr Starting flash address to write
- * @parm i_wordsToWrite Number of 32-bit words to write
+ * @parm i_blockStart Start of Erase Block we're writing to
+ * @parm i_writeStart Starting address where we want to write data.
+ * @parm i_bytesToWrite Number of 32-bit words to write
* @parm i_data Buffer of data to write
*
* @return Error from operation
*/
- errlHndl_t compareAndWriteBlock(uint32_t i_targetAddr,
- uint32_t i_wordsToWrite,
- uint32_t* i_data);
+ errlHndl_t compareAndWriteBlock(uint32_t i_blockStart,
+ uint32_t i_writeStart,
+ size_t i_bytesToWrite,
+ void* i_data);
/**
* @brief Determine the nearest flash address aligned to an erase block
@@ -279,7 +433,7 @@ class PnorDD
*/
uint32_t findEraseBlock(uint32_t i_address)
{
- return (i_address - i_address%ERASESIZE_BYTES);
+ return (i_address - i_address%iv_erasesize_bytes);
};
/**
@@ -299,7 +453,7 @@ class PnorDD
while( findEraseBlock(addr) < (i_address+i_byteSize) )
{
blocks++;
- addr += ERASESIZE_BYTES;
+ addr += iv_erasesize_bytes;
}
return blocks;
};
@@ -349,15 +503,17 @@ class PnorDD
private: // Variables
/**
* @brief Mutex to prevent concurrent PNOR accesses
+ * This needs to be static so we can mutex across multiple instances of PnorDD
*/
- mutex_t iv_mutex;
+ static mutex_t cv_mutex;
+ //TODO: Make this dynamically sized.
/**
* @brief Track PNOR erases for wear monitoring
* (making this static so tools can find it easier)
* track writes by page (=erase block)
*/
- uint8_t iv_erases[PNORSIZE/ERASESIZE_BYTES];
+ uint8_t* iv_erases;
/**
* @brief Determine how much of the PNOR logic to use,
@@ -366,6 +522,25 @@ class PnorDD
*/
PnorMode_t iv_mode;
+ /**
+ * @brief describes the erase block size, set based on NOR chip type
+ *
+ */
+ uint32_t iv_erasesize_bytes;
+
+ /**
+ * @brief CHIP ID or the NOR chip attached to SFC.
+ *
+ */
+ static uint32_t cv_nor_chipid;
+
+ /**
+ * @brief indicates if SFC initialization has been performed.
+ *
+ */
+ static bool cv_sfcInitDone;
+
+
// Needed for testcases
friend class PnorDdTest;
};
diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H
index 29456b9d0..5a7c88b07 100644
--- a/src/usr/pnor/test/pnorddtest.H
+++ b/src/usr/pnor/test/pnorddtest.H
@@ -41,8 +41,6 @@
#include <list>
#include <targeting/common/attributes.H>
-//$$ #define BASE_SCRATCH_SPACE (3*1024*1024+1024*512) //3.5MB offset in fake PNOR
-//#define BASE_SCRATCH_SPACE (3*1024*1024) //3.0MB offset in fake PNOR
#define BASE_SCRATCH_SPACE (0x360000) // 3.5MB - 128K offset in fake PNOR
extern trace_desc_t* g_trac_pnor;
@@ -67,7 +65,7 @@ class PnorDdTest : public CxxTest::TestSuite
{
TARGETING::Target* l_testTarget =
TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -93,7 +91,7 @@ class PnorDdTest : public CxxTest::TestSuite
total++;
if(l_size != sizeof(uint64_t))
{
- TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 1: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 1: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
sizeof(uint64_t), l_size);
fails++;
}
@@ -116,7 +114,7 @@ class PnorDdTest : public CxxTest::TestSuite
total++;
if(l_size != sizeof(uint64_t))
{
- TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 2: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 2: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
sizeof(uint64_t), l_size);
fails++;
}
@@ -146,7 +144,7 @@ class PnorDdTest : public CxxTest::TestSuite
total++;
if(l_size != sizeof(uint64_t))
{
- TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 1: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 1: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
sizeof(uint64_t), l_size);
fails++;
}
@@ -175,7 +173,7 @@ class PnorDdTest : public CxxTest::TestSuite
total++;
if(l_size != sizeof(uint64_t))
{
- TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 2: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
+ TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 2: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d", l_address,
sizeof(uint64_t), l_size);
fails++;
}
@@ -194,7 +192,7 @@ class PnorDdTest : public CxxTest::TestSuite
{
TARGETING::Target* l_testTarget =
TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -321,7 +319,7 @@ class PnorDdTest : public CxxTest::TestSuite
{
TARGETING::Target* l_testTarget =
TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -329,7 +327,7 @@ class PnorDdTest : public CxxTest::TestSuite
do{
TS_TRACE("PnorDdTest::test_crossblock: starting");
- // Find the nearest erase-block (4K) boundary
+ // Find the nearest erase-block (4K) boundary
uint64_t l_boundary = (BASE_SCRATCH_SPACE+4096)
- (BASE_SCRATCH_SPACE%4096);
uint64_t l_address = 0;
@@ -384,7 +382,7 @@ class PnorDdTest : public CxxTest::TestSuite
void test_readwrite_modes(void)
{
PnorDD* pnordd = NULL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -397,6 +395,22 @@ class PnorDdTest : public CxxTest::TestSuite
supported_modes.push_back(PnorDD::MODEL_MEMCPY);
supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ //Hack to check if this is a VENICE config since Real PNOR doesn't work in simics right now.
+ //TODO: Remove this hack when simics is fixed. (RTC: 42625)
+
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,9);
+ TARGETING::Target* veniceProc = TARGETING::targetService().toTarget(epath);
+
+ if((!TARGETING::is_vpo()) &&
+ (veniceProc == NULL))
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_readwrite_modes> Adding REAL_CMD mode");
+ supported_modes.push_back(PnorDD::MODEL_REAL_CMD);
+ }
+
uint64_t scratch_space = BASE_SCRATCH_SPACE;
// loop through all of the supported modes
@@ -536,7 +550,7 @@ class PnorDdTest : public CxxTest::TestSuite
void test_smartwrite_modes(void)
{
PnorDD* pnordd = NULL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -549,6 +563,22 @@ class PnorDdTest : public CxxTest::TestSuite
supported_modes.push_back(PnorDD::MODEL_MEMCPY);
supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ //Hack to check if this is a VENICE config since Real PNOR doesn't work in simics right now.
+ //TODO: Remove this hack when simics is fixed. (RTC: 42625)
+
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,9);
+ TARGETING::Target* veniceProc = TARGETING::targetService().toTarget(epath);
+
+ if((!TARGETING::is_vpo()) &&
+ (veniceProc == NULL))
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_smartwrite_modes> Adding REAL_CMD mode");
+ supported_modes.push_back(PnorDD::MODEL_REAL_CMD);
+ }
+
uint64_t scratch_space = BASE_SCRATCH_SPACE;
// loop through all of the supported modes
@@ -683,7 +713,7 @@ class PnorDdTest : public CxxTest::TestSuite
void test_crossblock_modes(void)
{
PnorDD* pnordd = NULL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
uint64_t fails = 0;
uint64_t total = 0;
@@ -695,6 +725,21 @@ class PnorDdTest : public CxxTest::TestSuite
std::list<PnorDD::PnorMode_t> supported_modes;
supported_modes.push_back(PnorDD::MODEL_MEMCPY);
supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ //Hack to check if this is a VENICE config since Real PNOR doesn't work in simics right now.
+ //TODO: Remove this hack when simics is fixed. (RTC: 42625)
+
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,9);
+ TARGETING::Target* veniceProc = TARGETING::targetService().toTarget(epath);
+
+ if((!TARGETING::is_vpo()) &&
+ (veniceProc == NULL))
+ {
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_crossblock_modes> Adding REAL_CMD mode");
+ supported_modes.push_back(PnorDD::MODEL_REAL_CMD);
+ }
uint64_t scratch_space = BASE_SCRATCH_SPACE;
@@ -712,7 +757,7 @@ class PnorDdTest : public CxxTest::TestSuite
}
pnordd = new PnorDD(*m);
- // Find the nearest erase-block (4K) boundary
+ // Find the nearest erase-block (4K) boundary
uint64_t l_boundary = (BASE_SCRATCH_SPACE+4096)
- (BASE_SCRATCH_SPACE%4096);
uint64_t l_address = 0;
@@ -772,7 +817,7 @@ Leaving it commented out because the test-case will not dynamically find the ext
{
TARGETING::Target* l_testTarget = MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
- size_t l_size = sizeof(uint64_t);
+ size_t l_size = sizeof(uint64_t);
errlHndl_t l_err = NULL;
do{
OpenPOWER on IntegriCloud