summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/build/citest/etc/patches/p8_pnor.act45
-rw-r--r--src/build/citest/etc/patches/patchlist.txt7
-rwxr-xr-xsrc/build/citest/etc/workarounds.presimsetup29
-rw-r--r--src/usr/intr/intrrp.C4
-rw-r--r--src/usr/intr/test/intrtest.H32
-rw-r--r--src/usr/pnor/pnordd.C366
-rw-r--r--src/usr/pnor/pnordd.H82
-rw-r--r--src/usr/pnor/test/pnorddtest.H541
8 files changed, 929 insertions, 177 deletions
diff --git a/src/build/citest/etc/patches/p8_pnor.act b/src/build/citest/etc/patches/p8_pnor.act
new file mode 100644
index 000000000..86d7b040b
--- /dev/null
+++ b/src/build/citest/etc/patches/p8_pnor.act
@@ -0,0 +1,45 @@
+#####
+# LPC Actions through ECCB
+
+# Catch LPC Read to flash
+CAUSE_EFFECT {
+ LABEL=[LPC Read]
+ WATCH=[REG(0x000B0020)] #ECCB Control Reg (FW)
+ # look for a read command
+ CAUSE: TARGET=[REG(0x000B0020)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,D4010100 F0000000)] MASK=[LITERAL(64,FFFFFFFF F0000000)]
+ # push the address into a dummy reg
+ EFFECT: TARGET=[REG(0xDDDD0000)] OP=[EQUALTO,BUF,MASK] DATA=[REG(0x000B0020)] MASK=[LITERAL(64,00000000 0FFFFFFF)]
+ # move the address into our PNOR space (5 MB)
+ EFFECT: TARGET=[REG(0xDDDD0000)] OP=[INCREMENT,MASK] INCVAL=[5242880] MASK=[LITERAL(64,00000000 FFFFFFFF)]
+ # write the data from mainstore into another dummy reg
+ EFFECT: TARGET=[MODULE(readMainstore, 0xDDDD0000)] OP=[MODULECALL] DATA=[REG(0xDDDD0001)]
+ # Copy 32-bits into the ECCB Data Reg (FW)
+ EFFECT: TARGET=[REG(0x000B0023)] OP=[EQUALTO,BUF,MASK] DATA=[REG(0xDDDD0001)] MASK=[LITERAL(64,FFFFFFFF 00000000)]
+ # Copy the data into the ECCB Status Reg (FW) bits 6:37
+ EFFECT: TARGET=[REG(0x000B0022)] OP=[EQUALTO,BUF,MASK,SHIFT] DATA=[REG(0xDDDD0001)] MASK=[LITERAL(64,03FFFFFF FC000000)] SHIFT=[6]
+ #ECCB Status Reg (FW) done bit
+ EFFECT: TARGET=[REG(0x000B0022)] OP=[BIT,ON] BIT=[52]
+}
+
+
+# Catch LPC Write to flash
+CAUSE_EFFECT {
+ LABEL=[LPC Write]
+ WATCH=[REG(0x000B0020)] #ECCB Control Reg (FW)
+ # look for a read command
+ CAUSE: TARGET=[REG(0x000B0020)] OP=[EQUALTO,BUF,MASK] DATA=[LITERAL(64,D4000100 F0000000)] MASK=[LITERAL(64,FFFFFFFF F0000000)]
+ # push the address into a dummy reg
+ EFFECT: TARGET=[REG(0xDDDD0000)] OP=[EQUALTO,BUF,MASK] DATA=[REG(0x000B0020)] MASK=[LITERAL(64,00000000 0FFFFFFF)]
+ # move the address into our PNOR space (5 MB)
+ EFFECT: TARGET=[REG(0xDDDD0000)] OP=[INCREMENT,MASK] INCVAL=[5242880] MASK=[LITERAL(64,00000000 FFFFFFFF)]
+ # copy the data from mainstore into the dummy reg since it reads 64-bits but we only write 32
+ EFFECT: TARGET=[MODULE(readMainstore, 0xDDDD0000)] OP=[MODULECALL] DATA=[REG(0xDDDD0001)]
+ # Copy 32-bits from the ECCB Data Reg (FW) into a dummy reg
+ EFFECT: TARGET=[REG(0xDDDD0001)] OP=[EQUALTO,BUF,MASK] DATA=[REG(0x000B0023)] MASK=[LITERAL(64,FFFFFFFF 00000000)]
+ # write the data from the dummy reg into mainstore
+ EFFECT: TARGET=[MODULE(writeMainstore, 0xDDDD0000)] OP=[MODULECALL] DATA=[REG(0xDDDD0001)]
+ #ECCB Status Reg (FW) done bit
+ EFFECT: TARGET=[REG(0x000B0022)] OP=[BIT,ON] BIT=[52]
+}
+
+
diff --git a/src/build/citest/etc/patches/patchlist.txt b/src/build/citest/etc/patches/patchlist.txt
new file mode 100644
index 000000000..4ad66ac3f
--- /dev/null
+++ b/src/build/citest/etc/patches/patchlist.txt
@@ -0,0 +1,7 @@
+Enable ECCB-based LPC/PNOR access (temporary)
+-RTC: Story 37972 will be used to remove the patches
+-CQ: No fips defect because these changes are not permanent
+-Files: p8_pnor.act
+-Coreq: associated changes are also in workarounds.presimsetup
+
+
diff --git a/src/build/citest/etc/workarounds.presimsetup b/src/build/citest/etc/workarounds.presimsetup
index 21c704c8f..b7653947e 100755
--- a/src/build/citest/etc/workarounds.presimsetup
+++ b/src/build/citest/etc/workarounds.presimsetup
@@ -43,24 +43,29 @@ sed -i -e's/SETENV GFW_P8_VENICE_L3_MB_SIZE.*/SETENV GFW_P8_VENICE_L3_MB_SIZE 8/
#Note: Leave this here as an example
-#echo "+++ Update to new simics build."
+#echo "+++ Update to new simics build for ECCB support."
#mkdir -p $sb/simu/data
#egrep -v "WSALIAS HOSTBOOT_LEVEL FIPSLEVEL|WSALIAS HOSTBOOT_LEVEL SIMICSLEVEL" $BACKING_BUILD/src/simu/data/simicsInfo > $sb/simu/data/simicsInfo
-#echo "WSALIAS HOSTBOOT_LEVEL FIPSLEVEL env/gfwa/simics-4.2.0/simics-4.2.82/fips/fld36/fi111110b700.42" >> $sb/simu/data/simicsInfo
-#echo "WSALIAS HOSTBOOT_LEVEL SIMICSLEVEL env/vtechb/simics-4.2.0/simics-4.2.82/bin" >> $sb/simu/data/simicsInfo
+#echo "WSALIAS HOSTBOOT_LEVEL FIPSLEVEL env/gfwb/simics-4.2.0/simics-4.2.83/fips/fld36/fi120201a700.42" >> $sb/simu/data/simicsInfo
+#echo "WSALIAS HOSTBOOT_LEVEL SIMICSLEVEL env/vtechb/simics-4.2.0/simics-4.2.83/bin" >> $sb/simu/data/simicsInfo
-echo "+++ Add some logic regs for Simics workaround."
+echo "+++ Add some scom regs and actions for ECCB fakeout."
mkdir -p $sb/simu/data/cec-chip/
-cp --update $BACKING_BUILD/src/simu/data/cec-chip/centaur.chip $sb/simu/data/cec-chip/centaur.chip.orig
-grep -v DONE $sb/simu/data/cec-chip/centaur.chip.orig > $sb/simu/data/cec-chip/centaur.chip
-echo "INTERNALREGS # List all scom registers" >> $sb/simu/data/cec-chip/centaur.chip
-echo " 0xFF00000F, 64 # Simics workaround" >> $sb/simu/data/cec-chip/centaur.chip
-echo "END" >> $sb/simu/data/cec-chip/centaur.chip
-echo "DONE" >> $sb/simu/data/cec-chip/centaur.chip
+cp --update $BACKING_BUILD/src/simu/data/cec-chip/p8.chip $sb/simu/data/cec-chip/p8.chip.orig
+grep -v DONE $sb/simu/data/cec-chip/p8.chip.orig > $sb/simu/data/cec-chip/p8.chip
+echo "ACTIONS=p8_pnor.act #workarounds.presimsetup" >> $sb/simu/data/cec-chip/p8.chip
+echo "SCOMREGS #workarounds.presimsetup" >> $sb/simu/data/cec-chip/p8.chip
+echo " 0xDDDD0000,64 # dummy to hold pnor address" >> $sb/simu/data/cec-chip/p8.chip
+echo " 0xDDDD0001,64 # dummy to hold pnor data" >> $sb/simu/data/cec-chip/p8.chip
+echo "END" >> $sb/simu/data/cec-chip/p8.chip
+echo "DONE" >> $sb/simu/data/cec-chip/p8.chip
+cp $HOSTBOOTROOT/src/build/citest/etc/patches/p8_pnor.act $sb/simu/data/cec-chip/
+#fixme
+
echo "+++ Update to new phyp and mambo level."
mkdir -p $sb/simu/data
cp --update $BACKING_BUILD/src/simu/data/simicsInfo $sb/simu/data/simicsInfo
sed -i -e's/^WSALIAS HOSTBOOT_LEVEL MAMBOLEVEL.*/WSALIAS HOSTBOOT_LEVEL MAMBOLEVEL env\/mamboa\/2011_11_10__4.2/' $sb/simu/data/simicsInfo
-sed -i -e's/^WSALIAS HOSTBOOT_LEVEL PHYPLEVEL.*/WSALIAS HOSTBOOT_LEVEL PHYPLEVEL env\/phypa\/simics-4.2.0\/simics-4.2.82\/ph111111a700.42/' $sb/simu/data/simicsInfo
-sed -i -e's/^WSALIAS HOSTBOOT_LEVEL PHYP_PATCH_LEVEL.*/WSALIAS HOSTBOOT_LEVEL PHYP_PATCH_LEVEL env\/phypa\/simics-4.2.0\/simics-4.2.82\/patches\/ph111111a700.42/' $sb/simu/data/simicsInfo
+sed -i -e's/^WSALIAS HOSTBOOT_LEVEL PHYPLEVEL.*/WSALIAS HOSTBOOT_LEVEL PHYPLEVEL env\/phypa\/simics-4.2.0\/simics-4.2.83\/ph120201a700.42/' $sb/simu/data/simicsInfo
+sed -i -e's/^WSALIAS HOSTBOOT_LEVEL PHYP_PATCH_LEVEL.*/WSALIAS HOSTBOOT_LEVEL PHYP_PATCH_LEVEL env\/phypa\/simics-4.2.0\/simics-4.2.82\/patches\/ph120201a700.42/' $sb/simu/data/simicsInfo
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index 9025a3ce8..23aa91777 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -132,13 +132,13 @@ errlHndl_t IntrRp::_init()
// TODO Adjust the realAddr if the BAR came from a processor other
// than cpuid 0
- TRACDCOMP(g_trac_intr,"INTR: realAddr = %lx",realAddr);
+ TRACFCOMP(g_trac_intr,"INTR: realAddr = %lx",realAddr);
// VADDR_SIZE is 1MB per chip - max 32 -> 32MB
iv_baseAddr = reinterpret_cast<uint64_t>
(mmio_dev_map(reinterpret_cast<void*>(realAddr),THIRTYTWO_MB));
- TRACDCOMP(g_trac_intr,"INTR: vAddr = %lx",iv_baseAddr);
+ TRACFCOMP(g_trac_intr,"INTR: vAddr = %lx",iv_baseAddr);
err = checkAddress(iv_baseAddr);
if(!err)
diff --git a/src/usr/intr/test/intrtest.H b/src/usr/intr/test/intrtest.H
index 712e97a6e..5135d3371 100644
--- a/src/usr/intr/test/intrtest.H
+++ b/src/usr/intr/test/intrtest.H
@@ -30,6 +30,10 @@
#include <kernel/console.H>
#include <targeting/targetservice.H>
#include <targeting/util.H>
+#include <sys/time.h>
+#include <sys/mmio.h>
+
+extern trace_desc_t * g_trac_intr;
class IntrTest: public CxxTest::TestSuite
@@ -67,7 +71,7 @@ class IntrTest: public CxxTest::TestSuite
uint64_t offset = (chip << 20) | (thread << 12);
uint32_t * addr =
- reinterpret_cast<uint32_t *>(cv_baseAddr + offset);
+ reinterpret_cast<uint32_t *>(iv_baseAddr + offset);
if(offset == 0) // Master cpu
{
@@ -114,7 +118,7 @@ class IntrTest: public CxxTest::TestSuite
return;
}
- uint32_t * addr = reinterpret_cast<uint32_t *>(cv_baseAddr);
+ uint32_t * addr = reinterpret_cast<uint32_t *>(iv_baseAddr);
errlHndl_t err = INTR::disableExternalInterrupts();
@@ -161,8 +165,6 @@ class IntrTest: public CxxTest::TestSuite
return;
}
- extern trace_desc_t * g_trac_intr;
-
errlHndl_t err = NULL;
// Need to register a msgq
@@ -177,7 +179,7 @@ class IntrTest: public CxxTest::TestSuite
// Force an interrupt by writing to the MFFR on master
volatile uint8_t * mfrr =
- reinterpret_cast<uint8_t *>(cv_baseAddr+12);
+ reinterpret_cast<uint8_t *>(iv_baseAddr+12);
*(mfrr) = 0x55;
*(mfrr) = 0xff;
@@ -192,12 +194,28 @@ class IntrTest: public CxxTest::TestSuite
}
+ IntrTest() : CxxTest::TestSuite()
+ {
+ iv_baseAddr = reinterpret_cast<uint64_t>
+ (mmio_dev_map(reinterpret_cast<void*>(cv_realAddr),THIRTYTWO_MB));
+ TRACDCOMP(g_trac_intr,"IntrTest()> iv_baseAddr=0x%.X",iv_baseAddr);
+ };
+
+
+ ~IntrTest()
+ {
+ mmio_dev_unmap(reinterpret_cast<void*>(iv_baseAddr));
+ };
+
private:
- static uint64_t cv_baseAddr;
+ uint64_t iv_baseAddr;
+ static const uint64_t cv_realAddr;
};
-uint64_t IntrTest::cv_baseAddr = 0x20000000000ul;
+//note: this must be changed if the BAR changes
+const uint64_t IntrTest::cv_realAddr = 0x3fbff9000000ul;
+
#endif
diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C
index 86f4efd7b..8b7982866 100644
--- a/src/usr/pnor/pnordd.C
+++ b/src/usr/pnor/pnordd.C
@@ -41,24 +41,16 @@
#include "pnordd.H"
#include <pnor/pnorif.H>
#include <pnor/pnor_reasoncodes.H>
-
-// Uncomment this to use the fake PNOR implementation (vs the LPC path)
-// @todo - Switch with RTC 36901
-#define USE_FAKE_PNOR
-
-// Uncomment this to skip the LPC code and just do page copies
-//#define FAST_FAKE_PNOR
+#include <sys/time.h>
// Uncomment this to enable smart writing
-#define SMART_WRITE
+//#define SMART_WRITE
-#ifdef USE_FAKE_PNOR
-#define FAKE_PNOR_START 5*MEGABYTE
-#define FAKE_PNOR_END 8*MEGABYTE
-#define FAKE_PNOR_SIZE 3*MEGABYTE
+// These are used to cheat and use a chunk of our cache as a PNOR
+// iv_mode == MODEL_MEMCPY,MODEL_LPC_MEM
void write_fake_pnor( uint64_t i_pnorAddr, void* i_buffer, size_t i_size );
void read_fake_pnor( uint64_t i_pnorAddr, void* o_buffer, size_t i_size );
-#endif
+void erase_fake_pnor( uint64_t i_pnorAddr, size_t i_size );
extern trace_desc_t* g_trac_pnor;
@@ -97,9 +89,10 @@ errlHndl_t ddRead(DeviceFW::OperationType i_opType,
uint64_t l_addr = va_arg(i_args,uint64_t);
do{
- //TODO - Fix with Story 34763
+ //@todo (RTC:34763) - add support for unaligned data
// Ensure we are operating on a 32-bit (4-byte) boundary
assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
+ assert( io_buflen % 4 == 0 );
// Read the flash
l_err = Singleton<PnorDD>::instance().readFlash(io_buffer,
@@ -147,9 +140,10 @@ errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
uint64_t l_addr = va_arg(i_args,uint64_t);
do{
- //TODO - Fix with Story 34763
+ //@todo (RTC:34763) - add support for unaligned data
// Ensure we are operating on a 32-bit (4-byte) boundary
assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
+ assert( io_buflen % 4 == 0 );
// Write the flash
l_err = Singleton<PnorDD>::instance().writeFlash(io_buffer,
@@ -165,6 +159,7 @@ errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
return l_err;
}
+
// Register PNORDD access functions to DD framework
DEVICE_REGISTER_ROUTE(DeviceFW::READ,
DeviceFW::PNOR,
@@ -176,6 +171,8 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WRITE,
TARGETING::TYPE_PROC,
ddWrite);
+}; //namespace PNOR
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -194,7 +191,7 @@ errlHndl_t PnorDD::readFlash(void* o_buffer,
do{
//mask off chip select for now, will probably break up fake PNOR into
//multiple fake chips eventually
- uint64_t l_address = i_address & 0x00000000FFFFFFFF;
+ uint64_t l_address = i_address & 0x00000000FFFFFFFF;
l_err = verifyFlashAddressRange(l_address, io_buflen);
if(l_err)
@@ -203,10 +200,12 @@ errlHndl_t PnorDD::readFlash(void* o_buffer,
break;
}
-#ifdef FAST_FAKE_PNOR
- read_fake_pnor( i_address, o_buffer, io_buflen );
- break;
-#endif
+ // skip everything in MEMCPY mode
+ if( MODEL_MEMCPY == iv_mode )
+ {
+ read_fake_pnor( l_address, o_buffer, io_buflen );
+ break;
+ }
// LPC is accessed 32-bits at a time...
uint32_t* word_ptr = static_cast<uint32_t*>(o_buffer);
@@ -215,12 +214,11 @@ errlHndl_t PnorDD::readFlash(void* o_buffer,
addr < (i_address+io_buflen);
addr += sizeof(uint32_t) )
{
- uint32_t read_data = 0;
- l_err = readLPC( addr, read_data );
+ // flash is mapped directly in the FW space
+ l_err = readLPC( addr + LPCHC_FW_SPACE,
+ word_ptr[words_read] );
if( l_err ) { break; }
- memcpy( word_ptr+words_read, &read_data, sizeof(uint32_t) );
-
words_read++;
}
io_buflen = words_read*sizeof(uint32_t);
@@ -251,19 +249,20 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
l_err = verifyFlashAddressRange(l_address, io_buflen);
if(l_err) { break; }
-
-#ifdef FAST_FAKE_PNOR
- write_fake_pnor( i_address, i_buffer, io_buflen );
- break;
-#endif
+ // skip everything in MEMCPY mode
+ if( MODEL_MEMCPY == iv_mode )
+ {
+ write_fake_pnor( l_address, i_buffer, io_buflen );
+ 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 and entire block of data at a time.
+ // we have to erase an entire block of data at a time.
uint32_t* word_ptr = static_cast<uint32_t*>(i_buffer);
- uint64_t num_blocks = getNumAffectedBlocks(i_address,io_buflen);
- uint32_t cur_addr = i_address;
+ uint32_t cur_addr = static_cast<uint32_t>(l_address);
+ uint64_t num_blocks = getNumAffectedBlocks(cur_addr,io_buflen);
uint64_t bytes_left = io_buflen;
// loop through erase blocks until we've gotten through all
@@ -279,7 +278,7 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
(bytes_left-1)/sizeof(uint32_t)+1,
word_ptr );
if( l_err ) { break; }
- //@todo - How should we handle PNOR errors?
+ //@todo (RTC:37744) - How should we handle PNOR errors?
// move on to the next block
if( bytes_left > ERASESIZE_BYTES )
@@ -293,9 +292,9 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
// 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 = (i_address - cur_addr);
+ bytes_left = (l_address + io_buflen - cur_addr);
}
- word_ptr += (bytes_left-1)/sizeof(uint32_t);
+ word_ptr += ((bytes_left-1)/sizeof(uint32_t))+1;
}
if( l_err ) { break; }
@@ -317,19 +316,33 @@ errlHndl_t PnorDD::writeFlash(void* i_buffer,
Private/Protected Methods
********************/
-
/**
* @brief Constructor
*/
-PnorDD::PnorDD()
+PnorDD::PnorDD( PnorMode_t i_mode )
+: iv_mode(i_mode)
{
- TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> ");
mutex_init(&iv_mutex);
for( uint64_t x=0; x < (PNORSIZE/ERASESIZE_BYTES); x++ )
{
iv_erases[x] = 0;
}
+
+ //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;
+
+ //Override for VPO, use flat model for performance
+ //@fixme - how?? I can't use targetting yet to tell I'm in VPO...
+ }
+
+ TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> Using mode %d", iv_mode);
}
/**
@@ -351,9 +364,10 @@ errlHndl_t PnorDD::verifyFlashAddressRange(uint64_t i_address,
do{
//@todo - Do we really need any checking here?
+ // if so we should be getting the size told to us by the PNOR RP
+ // based on the TOC or global data
-#ifdef USE_FAKE_PNOR
- if((i_address+i_length) > FAKE_PNOR_SIZE)
+ if((i_address+i_length) > PNORSIZE)
{
TRACFCOMP( g_trac_pnor, "PnorDD::verifyAddressRange> Invalid Address Requested : i_address=%d", i_address );
/*@
@@ -371,8 +385,6 @@ errlHndl_t PnorDD::verifyFlashAddressRange(uint64_t i_address,
TO_UINT64(i_length));
break;
}
-#endif
-
}while(0);
@@ -387,10 +399,11 @@ errlHndl_t PnorDD::readRegLPC(LpcRegAddr i_addr,
{
errlHndl_t l_err = NULL;
- do {
- //@todo - RTC 36901 or 35728
- } while(0);
+ // add the offset into the LPC register space
+ uint32_t lpc_addr = i_addr + LPCHC_REG_SPACE;
+ // call the generic LPC function
+ l_err = readLPC( lpc_addr, o_data );
return l_err;
}
@@ -400,16 +413,23 @@ errlHndl_t PnorDD::readRegLPC(LpcRegAddr i_addr,
errlHndl_t PnorDD::writeRegLPC(LpcRegAddr i_addr,
uint32_t i_data)
{
- return NULL; //@todo - RTC 36901 or 35728
+ errlHndl_t l_err = NULL;
+
+ // add the offset into the LPC register space
+ uint32_t lpc_addr = i_addr + LPCHC_REG_SPACE;
+
+ // call the generic LPC function
+ l_err = writeLPC( lpc_addr, i_data );
+ return l_err;
}
/**
* @brief Read a SPI Register
*/
-errlHndl_t PnorDD::readRegSPI(uint32_t i_addr,
+errlHndl_t PnorDD::readRegSPI(SpiRegAddr i_addr,
uint32_t& o_data)
{
- //@todo - Finish with Story 35728
+ //@todo (RTC:35728) - SPI Support
TRACFCOMP( g_trac_pnor, "PnorDD::readRegSPI> Unsupported Operation : i_addr=%d", i_addr );
/*@
* @errortype
@@ -424,16 +444,25 @@ errlHndl_t PnorDD::readRegSPI(uint32_t i_addr,
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 );
+
+ */
}
/**
* @brief Write a SPI Register
*/
-errlHndl_t PnorDD::writeRegSPI(uint32_t i_addr,
+errlHndl_t PnorDD::writeRegSPI(SpiRegAddr i_addr,
uint32_t i_data)
{
- //@todo - Finish with Story 35728
+ //@todo (RTC:35728) - SPI Support
TRACFCOMP( g_trac_pnor, "PnorDD::writeRegSPI> Unsupported Operation : i_addr=%d", i_addr );
/*@
* @errortype
@@ -448,6 +477,16 @@ errlHndl_t PnorDD::writeRegSPI(uint32_t i_addr,
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 );
+
+ */
}
@@ -462,14 +501,19 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
bool need_unlock = false;
do {
-#ifdef USE_FAKE_PNOR
- read_fake_pnor( i_addr, static_cast<void*>(&o_data),
- sizeof(uint32_t) );
-#else
- //@todo - fill in with RTC 36901
-
- //@fixme - add non-master support (RTC 36950)
- TARGETING::Target* xscom_target =
+ if( MODEL_LPC_MEM == iv_mode )
+ {
+ read_fake_pnor( i_addr - LPCHC_FW_SPACE,
+ static_cast<void*>(&o_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 =
TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
// always read/write 64 bits to SCOM
@@ -484,21 +528,23 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
eccb_cmd.read_op = 1;
eccb_cmd.address = i_addr;
l_err = deviceOp( DeviceFW::WRITE,
- xscom_target,
+ scom_target,
&(eccb_cmd.data64),
scom_size,
- DEVICE_XSCOM_ADDRESS(ECCB_CTL_REG) );
+ DEVICE_SCOM_ADDRESS(ECCB_CTL_REG) );
if( l_err ) { break; }
// poll for complete and get the data back
StatusReg_t eccb_stat;
- while(1) //@fixme - need a timeout value
+ uint64_t poll_time = 0;
+ uint64_t loop = 0;
+ while( poll_time < ECCB_POLL_TIME_NS )
{
l_err = deviceOp( DeviceFW::READ,
- xscom_target,
+ scom_target,
&(eccb_stat.data64),
scom_size,
- DEVICE_XSCOM_ADDRESS(ECCB_STAT_REG) );
+ DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
if( l_err ) { break; }
if( eccb_stat.op_done == 1 )
@@ -506,42 +552,49 @@ errlHndl_t PnorDD::readLPC(uint32_t i_addr,
break;
}
- //@fixme - simics doesn't set the done bit yet (RTC 36901)
- 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, ECCB_POLL_INCR_NS*(++loop) );
+ poll_time += ECCB_POLL_INCR_NS*loop;
}
if( l_err ) { break; }
- // check for errors
- if( eccb_stat.data64 & LPC_STAT_REG_ERROR_MASK )
+ // check for errors or timeout
+ if( (eccb_stat.data64 & LPC_STAT_REG_ERROR_MASK)
+ || (eccb_stat.op_done == 0) )
{
- TRACFCOMP(g_trac_pnor, "PnorDD::readLPC> Error from LPC Status Register : i_addr=0x%.8X, status=0x%.16X", i_addr, eccb_stat.data64 );
+ TRACFCOMP(g_trac_pnor, "PnorDD::readLPC> Error or timeout from LPC Status Register : i_addr=0x%.8X, status=0x%.16X", i_addr, eccb_stat.data64 );
/*@
* @errortype
* @moduleid PNOR::MOD_PNORDD_READLPC
* @reasoncode PNOR::RC_LPC_ERROR
- * @userdata1 LPC Address
+ * @userdata1[0:31] LPC Address
+ * @userdata1[32:63] Total poll time (ns)
* @userdata2 ECCB Status Register
- * @devdesc PnorDD::readLPC> Error from LPC Status Register
+ * @devdesc PnorDD::readLPC> Error or timeout from
+ * LPC Status Register
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORDD_READLPC,
PNOR::RC_LPC_ERROR,
- TWO_UINT32_TO_UINT64(0,i_addr),
+ TWO_UINT32_TO_UINT64(i_addr,poll_time),
eccb_stat.data64);
l_err->collectTrace("PNOR");
l_err->collectTrace("XSCOM");
- //@todo - Any cleanup or recovery needed?
+ //@todo (RTC:37744) - Any cleanup or recovery needed?
break;
}
+
// atomic section <<
mutex_unlock(&iv_mutex);
need_unlock = false;
// copy data out to caller's buffer
o_data = eccb_stat.read_data;
-#endif
+
} while(0);
if( need_unlock )
@@ -561,16 +614,23 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
{
errlHndl_t l_err = NULL;
bool need_unlock = false;
+
+ //TRACFCOMP(g_trac_pnor, "writeLPC> %.8X = %.8X", i_addr, i_data );
do {
-#ifdef USE_FAKE_PNOR
- write_fake_pnor( i_addr, static_cast<void*>(&i_data),
- sizeof(uint32_t) );
-#else
- //@todo - fill in with RTC 36901
-
- //@fixme - add non-master support (RTC 36950)
- TARGETING::Target* xscom_target =
+ 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 =
TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
// always read/write 64 bits to SCOM
@@ -582,11 +642,12 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
// write 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,
- xscom_target,
+ scom_target,
&eccb_data,
scom_size,
- DEVICE_XSCOM_ADDRESS(ECCB_DATA_REG) );
+ DEVICE_SCOM_ADDRESS(ECCB_DATA_REG) );
if( l_err ) { break; }
// write command register with LPC address to write
@@ -594,21 +655,23 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
eccb_cmd.read_op = 0;
eccb_cmd.address = i_addr;
l_err = deviceOp( DeviceFW::WRITE,
- xscom_target,
+ scom_target,
&(eccb_cmd.data64),
scom_size,
- DEVICE_XSCOM_ADDRESS(ECCB_CTL_REG) );
+ DEVICE_SCOM_ADDRESS(ECCB_CTL_REG) );
if( l_err ) { break; }
- // poll for complete and get the data back
+ // poll for complete
StatusReg_t eccb_stat;
- while(1) //@fixme - need a timeout value
+ uint64_t poll_time = 0;
+ uint64_t loop = 0;
+ while( poll_time < ECCB_POLL_TIME_NS )
{
l_err = deviceOp( DeviceFW::READ,
- xscom_target,
+ scom_target,
&(eccb_stat.data64),
scom_size,
- DEVICE_XSCOM_ADDRESS(ECCB_STAT_REG) );
+ DEVICE_SCOM_ADDRESS(ECCB_STAT_REG) );
if( l_err ) { break; }
if( eccb_stat.op_done == 1 )
@@ -616,15 +679,19 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
break;
}
- //@fixme - simics doesn't set the done bit yet : RTC 36901
- 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, ECCB_POLL_INCR_NS*(++loop) );
+ poll_time += ECCB_POLL_INCR_NS*loop;
}
if( l_err ) { break; }
// check for errors
- if( eccb_stat.data64 & LPC_STAT_REG_ERROR_MASK )
+ if( (eccb_stat.data64 & LPC_STAT_REG_ERROR_MASK)
+ || (eccb_stat.op_done == 0) )
{
- TRACFCOMP(g_trac_pnor, "PnorDD::writeLPC> Error from LPC Status Register : i_addr=0x%.8X, status=0x%.16X", i_addr, eccb_stat.data64 );
+ TRACFCOMP(g_trac_pnor, "PnorDD::writeLPC> Error or timeout from LPC Status Register : i_addr=0x%.8X, status=0x%.16X", i_addr, eccb_stat.data64 );
/*@
* @errortype
@@ -632,7 +699,8 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
* @reasoncode PNOR::RC_LPC_ERROR
* @userdata1 LPC Address
* @userdata2 ECCB Status Register
- * @devdesc PnorDD::writeLPC> Error from LPC Status Register
+ * @devdesc PnorDD::writeLPC> Error or timeout from
+ * LPC Status Register
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_PNORDD_WRITELPC,
@@ -641,14 +709,14 @@ errlHndl_t PnorDD::writeLPC(uint32_t i_addr,
eccb_stat.data64);
l_err->collectTrace("PNOR");
l_err->collectTrace("XSCOM");
- //@todo - Any cleanup or recovery needed?
+ //@todo (RTC:37744) - Any cleanup or recovery needed?
break;
}
// atomic section <<
mutex_unlock(&iv_mutex);
need_unlock = false;
-#endif
+
} while(0);
if( need_unlock )
@@ -668,7 +736,7 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
uint32_t i_wordsToWrite,
uint32_t* i_data)
{
- TRACDCOMP(g_trac_pnor,"compareAndWriteBlock(0x%.8X,%d,%p)", i_targetAddr, i_wordsToWrite, i_data);
+ TRACFCOMP(g_trac_pnor,"compareAndWriteBlock(0x%.8X,%d,%p)", i_targetAddr, i_wordsToWrite, i_data);
errlHndl_t l_err = NULL;
// remember any data we read so we don't have to reread it later
@@ -681,24 +749,29 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
readflag_t* read_data = NULL;
do {
-#ifndef SMART_WRITE
- // 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) )
+ // skip the erase block logic if we're in a memcpy mode
+ if( (MODEL_MEMCPY == iv_mode) || (MODEL_LPC_MEM == iv_mode) )
{
- l_err = writeLPC( addr, i_data[words_written] );
+ // 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) )
+ {
+ // flash is mapped directly in the FW space
+ l_err = writeLPC( addr + LPCHC_FW_SPACE,
+ i_data[words_written] );
+ if( l_err ) { break; }
+
+ words_written++;
+ }
if( l_err ) { break; }
- words_written++;
+ // all done
+ break;
}
- o_bytesWritten = words_written*sizeof(uint32_t);
- if( l_err ) { break; }
-#else
-
// 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++ )
@@ -732,7 +805,8 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
// otherwise we need to compare our data with what is in flash now
else
{
- l_err = readLPC( block_addr + bword*sizeof(uint32_t),
+ l_err = readLPC( block_addr + bword*sizeof(uint32_t)
+ + LPCHC_FW_SPACE,
read_data[bword].data );
if( l_err ) { break; }
@@ -751,7 +825,15 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
// look for any bits that go from 1->0
if( read_data[bword].data & ~(i_data[dword]) )
{
- need_erase = true;
+ 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
@@ -786,7 +868,8 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
// 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),
+ l_err = readLPC( block_addr + bword*sizeof(uint32_t)
+ + LPCHC_FW_SPACE,
read_data[bword].data );
if( l_err ) { break; }
}
@@ -794,7 +877,8 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
else if( (block_addr + bword*sizeof(uint32_t)) >=
(i_targetAddr + i_wordsToWrite*sizeof(uint32_t)) )
{
- l_err = readLPC( block_addr + bword*sizeof(uint32_t),
+ l_err = readLPC( block_addr + bword*sizeof(uint32_t)
+ + LPCHC_FW_SPACE,
read_data[bword].data );
if( l_err ) { break; }
}
@@ -824,15 +908,14 @@ errlHndl_t PnorDD::compareAndWriteBlock(uint32_t i_targetAddr,
}
// write the word out to the flash
- l_err = writeLPC( block_addr + bword_written*sizeof(uint32_t),
+ l_err = writeLPC( block_addr + bword_written*sizeof(uint32_t)
+ + LPCHC_FW_SPACE,
read_data[bword_written].data );
if( l_err ) { break; }
- //@todo - How should we handle PNOR errors?
+ //@todo (RTC:37744) - How should we handle PNOR errors?
}
if( l_err ) { break; }
-#endif
-
} while(0);
if( read_data )
@@ -872,10 +955,27 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
// 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] );
-
- //@todo - issue some LPC/SPI commands to erase the block RTC 35728
- char* ptr = (char*)(FAKE_PNOR_START+i_address);
- memset( ptr, 0, ERASESIZE_BYTES );
+
+ if( MODEL_REAL != iv_mode )
+ {
+ erase_fake_pnor( i_address, 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);
} while(0);
return l_err;
@@ -883,12 +983,13 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address)
+/*
+ This code is used in the MODEL_MEMCPY and MODEL_LPC_MEM modes
+*/
-}; //end PNOR namespace
-
-
-
-#ifdef USE_FAKE_PNOR
+#define FAKE_PNOR_START 5*MEGABYTE
+#define FAKE_PNOR_END 8*MEGABYTE
+#define FAKE_PNOR_SIZE 3*MEGABYTE
void write_fake_pnor( uint64_t i_pnorAddr, void* i_buffer, size_t i_size )
{
//create a pointer to the offset start.
@@ -905,4 +1006,13 @@ void read_fake_pnor( uint64_t i_pnorAddr, void* o_buffer, size_t i_size )
//copy data from memory into the buffer.
memcpy(o_buffer, srcPtr, i_size);
}
-#endif
+void erase_fake_pnor( uint64_t i_pnorAddr, size_t i_size )
+{
+ //create a pointer to the offset start.
+ char * srcPtr = (char *)(FAKE_PNOR_START+i_pnorAddr);
+
+ //copy data from memory into the buffer.
+ memset( srcPtr, 0, i_size );
+}
+
+
diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H
index 6b102ea3b..28d4f0b51 100644
--- a/src/usr/pnor/pnordd.H
+++ b/src/usr/pnor/pnordd.H
@@ -23,19 +23,16 @@
#ifndef __PNOR_PNORDD_H
#define __PNOR_PNORDD_H
+#include <limits.h>
+
/** @file pnordd.H
* @brief Provides the interfaces to the PNOR Device Driver
*/
-namespace PNOR
-{
-
/**
- * @brief Type definition for PNOR address
+ * @brief PNOR Device Driver Class
+ * Provides access to the PNOR flash via the ECCB/LPC/SPI hardware
*/
-typedef uint64_t PNORAddress_t;
-
-
class PnorDD
{
@@ -70,10 +67,18 @@ class PnorDD
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
+ };
+
/**
* @brief Constructor
*/
- PnorDD();
+ PnorDD( PnorMode_t i_mode = MODEL_UNKNOWN );
/**
@@ -128,6 +133,40 @@ class PnorDD
uint32_t i_data);
/**
+ * @brief SPI Registers
+ * These are offsets within the SPI Register Space
+ */
+ 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 */
+ };
+
+ /**
+ * @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 Read a SPI Register
*
* @parm i_addr Register address, relative to the SPI engine
@@ -135,7 +174,7 @@ class PnorDD
*
* @return Error from operation
*/
- errlHndl_t readRegSPI(uint32_t i_addr,
+ errlHndl_t readRegSPI(SpiRegAddr i_addr,
uint32_t& o_data);
/**
@@ -146,7 +185,7 @@ class PnorDD
*
* @return Error from operation
*/
- errlHndl_t writeRegSPI(uint32_t i_addr,
+ errlHndl_t writeRegSPI(SpiRegAddr i_addr,
uint32_t i_data);
@@ -160,9 +199,16 @@ class PnorDD
LPCHC_IO_SPACE = 0xD0010000, /**< LPC Host Controller I/O Space */
LPCHC_REG_SPACE = 0xC0012000, /**< LPC Host Ctlr Register Space */
+ LPC_DIRECT_READ_OFFSET = 0xFC000000,
+ LPC_SPI_REG_OFFSET = 0xF0000C00,
+ 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>
@@ -173,6 +219,9 @@ class PnorDD
PNORSIZE = 3 * 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) */
+
+ ECCB_POLL_TIME_NS = 400000, /**< max time from Manfred Walz is 400ms */
+ ECCB_POLL_INCR_NS = 10, /**< minimum increment during poll */
};
@@ -211,7 +260,7 @@ 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 address to write
+ * @parm i_targetAddr Starting flash address to write
* @parm i_wordsToWrite Number of 32-bit words to write
* @parm i_data Buffer of data to write
*
@@ -309,8 +358,17 @@ class PnorDD
* track writes by page (=erase block)
*/
uint8_t iv_erases[PNORSIZE/ERASESIZE_BYTES];
+
+ /**
+ * @brief Determine how much of the PNOR logic to use,
+ * this is required due to different model functionality
+ * in the current VPO and Simics models
+ */
+ PnorMode_t iv_mode;
+
+ // Needed for testcases
+ friend class PnorDdTest;
};
-}; //end PNOR namespace
#endif
diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H
index eb874904a..dd7034889 100644
--- a/src/usr/pnor/test/pnorddtest.H
+++ b/src/usr/pnor/test/pnorddtest.H
@@ -36,11 +36,20 @@
#include <devicefw/userif.H>
#include <kernel/console.H>
#include <sys/time.h>
+#include "../pnordd.H"
+#include <list>
+#include <targeting/util.H>
-#define BASE_SCRATCH_SPACE 2*1024*1024+1024*512 //2.5MB offset in fake PNOR
+#define BASE_SCRATCH_SPACE (2*1024*1024+1024*512) //2.5MB offset in fake PNOR
extern trace_desc_t* g_trac_pnor;
-using namespace TARGETING;
+
+/*
+ Note - Some of these tests will run against non-singleton instances of the
+ PNOR DD to allow full testing of the different operating modes while leaving
+ the default mode in place for performance reasons. That will change when we
+ get to a complete PNOR model in sim or hardware.
+ */
class PnorDdTest : public CxxTest::TestSuite
{
@@ -53,14 +62,12 @@ class PnorDdTest : public CxxTest::TestSuite
*/
void test_readwrite(void)
{
- //@TODO: make this table driven so it can test more values
- //@TODO: Add some more interesting tests
-
- TARGETING::Target* l_testTarget = MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ 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 = 8;
+ uint64_t total = 0;
do{
TS_TRACE("PnorDdTest::test_readwrite: starting");
@@ -73,12 +80,14 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 1: deviceWrite() failed! Error committed.");
errlCommit(l_err,PNOR_COMP_ID);
fails++;
}
+ 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,
@@ -94,12 +103,14 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD write 2: deviceWrite() failed! Error committed.");
errlCommit(l_err,PNOR_COMP_ID);
fails++;
}
+ 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,
@@ -115,18 +126,21 @@ class PnorDdTest : public CxxTest::TestSuite
&l_readData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 1: deviceRead() failed! Error committed.");
errlCommit(l_err,PNOR_COMP_ID);
fails++;
}
+ total++;
if(l_readData != 0x12345678FEEDB0B0)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 1: Read data not expected value. Addr: 0x%llx, ExpData: 0x12345678FEEDB0B0, ActData: 0x%llx",
l_address, (long long unsigned)l_readData);
fails++;
}
+ 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,
@@ -141,20 +155,21 @@ class PnorDdTest : public CxxTest::TestSuite
&l_readData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 2: deviceRead() failed! Error committed.");
errlCommit(l_err,PNOR_COMP_ID);
fails++;
- break;
}
+ total++;
if(l_readData != 0xFEEDBEEF000ABCDE)
{
TS_FAIL("PnorDdTest::test_readwrite: PNORDD read 2: Read data not expected value. Addr: 0x%llx, ExpData: 0xFEEDBEEF000ABCDE, ActData: 0x%llx",
l_address, (long long unsigned)l_readData );
fails++;
- break;
}
+ 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,
@@ -174,11 +189,12 @@ class PnorDdTest : public CxxTest::TestSuite
*/
void test_smartwrite(void)
{
- TARGETING::Target* l_testTarget = MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ 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 = 8;
+ uint64_t total = 0;
do{
TS_TRACE("PnorDdTest::test_smartwrite: starting");
@@ -191,6 +207,7 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD write 1: deviceWrite() failed! Error committed.");
@@ -205,6 +222,7 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD write 2: deviceWrite() failed! Error committed.");
@@ -219,6 +237,7 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address+sizeof(uint64_t)));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD write 3: deviceWrite() failed! Error committed.");
@@ -233,6 +252,7 @@ class PnorDdTest : public CxxTest::TestSuite
&l_writeData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD write 4: deviceWrite() failed! Error committed.");
@@ -240,19 +260,21 @@ class PnorDdTest : public CxxTest::TestSuite
fails++;
}
- // Perform PnorDD read
+ // Perform PnorDD read of the data we just wrote
uint64_t l_readData = 0;
l_size = sizeof(uint64_t);
l_err = deviceRead(l_testTarget,
&l_readData,
l_size,
DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
if (l_err)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD read: deviceRead() failed! Error committed.");
errlCommit(l_err,PNOR_COMP_ID);
fails++;
}
+ total++;
if(l_readData != l_writeData)
{
TS_FAIL("PnorDdTest::test_smartwrite: PNORDD read: Read data not expected value. Addr: 0x%llx, ExpData: 0x%llx, ActData: 0x%llx",
@@ -260,11 +282,499 @@ class PnorDdTest : public CxxTest::TestSuite
fails++;
}
+ // Perform PnorDD read of the data after what we just wrote
+ // verifies that we restored the rest of the block
+ l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address+sizeof(uint64_t)));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite: PNORDD read: deviceRead() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != 0x1234567887654321)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite: PNORDD read: Read data not expected value. Addr: 0x%llx, ExpData: 0x%llx, ActData: 0x%llx",
+ l_address, 0x1234567887654321, l_readData);
+ fails++;
+ }
+
+ }while(0);
+
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_smartwrite> %d/%d fails", fails, total );
+ }
+
+ /**
+ * @brief PNOR DD Cross-Block testcase
+ * Access some data that crosses an erase block boundary
+ */
+ void test_crossblock(void)
+ {
+ 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;
+
+ do{
+ TS_TRACE("PnorDdTest::test_crossblock: starting");
+
+ // Find the nearest erase-block (4K) boundary
+ uint64_t l_boundary = (BASE_SCRATCH_SPACE+4096)
+ - (BASE_SCRATCH_SPACE%4096);
+ uint64_t l_address = 0;
+
+ // Perform PnorDD Write 1 - write through boundary
+ l_address = l_boundary - sizeof(uint32_t);
+ uint64_t l_writeData = 0x6666666699999999;
+ l_size = sizeof(uint64_t);
+ l_err = deviceWrite(l_testTarget,
+ &l_writeData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock: PNORDD write 1: deviceWrite() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD Read 1 - verify previous write
+ l_address = l_boundary - sizeof(uint32_t);
+ uint64_t l_readData = 0x0;
+ l_size = sizeof(uint64_t);
+ l_err = deviceRead(l_testTarget,
+ &l_readData,
+ l_size,
+ DEVICE_PNOR_ADDRESS(0, l_address));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock: PNORDD Read 1: deviceRead() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != l_writeData)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock: PNORDD read: Read data not expected value. Addr: 0x%.llx, ExpData: 0x%.llx, ActData: 0x%llx", l_address, l_writeData, l_readData);
+ fails++;
+ }
+
+ }while(0);
+
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_crossblock> %d/%d fails", fails, total );
+ }
+
+ /**
+ * @brief PNOR DD readWriteTest modes
+ * Same as test_readwrite but forcing the use of all supported modes
+ */
+ void test_readwrite_modes(void)
+ {
+ PnorDD* pnordd = NULL;
+ size_t l_size = sizeof(uint64_t);
+ errlHndl_t l_err = NULL;
+ uint64_t fails = 0;
+ uint64_t total = 0;
+
+ do{
+ TS_TRACE("PnorDdTest::test_readwrite_modes: starting");
+
+ // list of all modes to test
+ std::list<PnorDD::PnorMode_t> supported_modes;
+ supported_modes.push_back(PnorDD::MODEL_MEMCPY);
+ supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ if( !TARGETING::is_vpo() )
+ {
+ supported_modes.push_back(PnorDD::MODEL_FLAT_ECCB);
+ }
+
+ uint64_t scratch_space = BASE_SCRATCH_SPACE;
+
+ // loop through all of the supported modes
+ for( std::list<PnorDD::PnorMode_t>::iterator m
+ = supported_modes.begin();
+ m != supported_modes.end();
+ ++m )
+ {
+ scratch_space += 0x100;
+
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+ pnordd = new PnorDD(*m);
+
+ // Perform PnorDD Write 1
+ uint64_t l_address = scratch_space;
+ uint64_t l_writeData = 0x12345678FEEDB0B0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD write 1: writeFlash() failed! Error committed. mode=%d",
+ *m);
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_size != sizeof(uint64_t))
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD write 1: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d, mode=%d",
+ l_address, sizeof(uint64_t), l_size, *m);
+ fails++;
+ }
+
+ // Perform PnorDD Write 2
+ l_address = scratch_space+0x08;
+ l_writeData = 0xFEEDBEEF000ABCDE;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD write 2: writeFlash() failed! Error committed. mode=%d",
+ *m);
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_size != sizeof(uint64_t))
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD write 2: Write length not expected value. Addr: 0x%llx, Exp: %d, Act: %d, mode=%d",
+ l_address, sizeof(uint64_t), l_size, *m);
+ fails++;
+ }
+
+ // Perform PnorDD read 1
+ l_address = scratch_space;
+ uint64_t l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 1: readFlash() failed! Error committed. mode=%d",
+ *m);
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != 0x12345678FEEDB0B0)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 1: Read data not expected value. Addr: 0x%llx, ExpData: 0x12345678FEEDB0B0, ActData: 0x%llx, mode=%d",
+ l_address, (long long unsigned)l_readData, *m);
+ fails++;
+ }
+ total++;
+ if(l_size != sizeof(uint64_t))
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 1: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d, mode=%d",
+ l_address, sizeof(uint64_t), l_size, *m);
+ fails++;
+ }
+
+ // Perform PnorDD read 2
+ l_address = scratch_space+0x08;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 2: readFlash() failed! Error committed. mode=%d",
+ *m);
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != 0xFEEDBEEF000ABCDE)
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 2: Read data not expected value. Addr: 0x%llx, ExpData: 0xFEEDBEEF000ABCDE, ActData: 0x%llx, mode=%d",
+ l_address, (long long unsigned)l_readData, *m);
+ fails++;
+ }
+ total++;
+ if(l_size != sizeof(uint64_t))
+ {
+ TS_FAIL("PnorDdTest::test_readwrite_modes: PNORDD read 2: Read length not expected value. Addr: 0x%llx, Exp: %d, Act: %d, mode=%d",
+ l_address, sizeof(uint64_t), l_size, *m);
+ fails++;
+ }
+ }
+
+ }while(0);
+
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_readwrite_modes> %d/%d fails", fails, total );
+
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+ }
+
+ /**
+ * @brief PNOR DD smart write/erase test
+ * Same as test_smartwrite but forcing the use of all supported modes
+ */
+ void test_smartwrite_modes(void)
+ {
+ PnorDD* pnordd = NULL;
+ size_t l_size = sizeof(uint64_t);
+ errlHndl_t l_err = NULL;
+ uint64_t fails = 0;
+ uint64_t total = 0;
+
+ do{
+ TS_TRACE("PnorDdTest::test_smartwrite_modes: starting");
+
+ // list of all modes to test
+ std::list<PnorDD::PnorMode_t> supported_modes;
+ supported_modes.push_back(PnorDD::MODEL_MEMCPY);
+ supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ if( !TARGETING::is_vpo() )
+ {
+ supported_modes.push_back(PnorDD::MODEL_FLAT_ECCB);
+ }
+
+ uint64_t scratch_space = BASE_SCRATCH_SPACE;
+
+ // loop through all of the supported modes
+ for( std::list<PnorDD::PnorMode_t>::iterator m
+ = supported_modes.begin();
+ m != supported_modes.end();
+ ++m )
+ {
+ scratch_space += 0x100;
+
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+ pnordd = new PnorDD(*m);
+
+ // Perform PnorDD Write 1
+ uint64_t l_address = scratch_space+0x20;
+ uint64_t l_writeData = 0xAAAAAAAA55555555;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD write 1: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD Write 2 - no erase
+ l_writeData = 0xAAAAAAAAFFFFFFFF;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD write 2: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD Write 3 - put some words after the next write
+ l_writeData = 0x1234567887654321;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address+sizeof(uint64_t));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD write 3: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD Write 4 - requires erase
+ l_writeData = 0x8888888811111111;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD write 4: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD read of the data we just wrote
+ uint64_t l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD read: readFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != l_writeData)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD read: Read data not expected value. Addr: 0x%llx, ExpData: 0x%llx, ActData: 0x%llx",
+ l_address, l_writeData, l_readData);
+ fails++;
+ }
+
+ // Perform PnorDD read of the data after what we just wrote
+ // verifies that we restored the rest of the block
+ l_readData = 0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address+sizeof(uint64_t));
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD read: readFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != 0x1234567887654321)
+ {
+ TS_FAIL("PnorDdTest::test_smartwrite_modes: PNORDD read: Read data not expected value. Addr: 0x%llx, ExpData: 0x%llx, ActData: 0x%llx",
+ l_address, 0x1234567887654321, l_readData);
+ fails++;
+ }
+ }
+
}while(0);
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+
TRACFCOMP(g_trac_pnor, "PnorDdTest::test_smartwrite> %d/%d fails", fails, total );
}
-
+
+ /**
+ * @brief PNOR DD Cross-Block testcase
+ * Same as test_crossblock but forcing the use of all supported modes
+ */
+ void test_crossblock_modes(void)
+ {
+ PnorDD* pnordd = NULL;
+ size_t l_size = sizeof(uint64_t);
+ errlHndl_t l_err = NULL;
+ uint64_t fails = 0;
+ uint64_t total = 0;
+
+ do{
+ TS_TRACE("PnorDdTest::test_crossblock_modes: starting");
+
+ // list of all modes to test
+ std::list<PnorDD::PnorMode_t> supported_modes;
+ supported_modes.push_back(PnorDD::MODEL_MEMCPY);
+ supported_modes.push_back(PnorDD::MODEL_LPC_MEM);
+ if( !TARGETING::is_vpo() )
+ {
+ supported_modes.push_back(PnorDD::MODEL_FLAT_ECCB);
+ }
+
+ uint64_t scratch_space = BASE_SCRATCH_SPACE;
+
+ // loop through all of the supported modes
+ for( std::list<PnorDD::PnorMode_t>::iterator m
+ = supported_modes.begin();
+ m != supported_modes.end();
+ ++m )
+ {
+ scratch_space += 4096;
+
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+ pnordd = new PnorDD(*m);
+
+ // Find the nearest erase-block (4K) boundary
+ uint64_t l_boundary = (BASE_SCRATCH_SPACE+4096)
+ - (BASE_SCRATCH_SPACE%4096);
+ uint64_t l_address = 0;
+
+ // Perform PnorDD Write 1 - write through boundary
+ l_address = l_boundary - sizeof(uint32_t);
+ uint64_t l_writeData = 0x6666666699999999;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->writeFlash(&l_writeData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock_modes: PNORDD write 1: writeFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+
+ // Perform PnorDD Read 1 - verify previous write
+ l_address = l_boundary - sizeof(uint32_t);
+ uint64_t l_readData = 0x0;
+ l_size = sizeof(uint64_t);
+ l_err = pnordd->readFlash(&l_readData,
+ l_size,
+ l_address);
+ total++;
+ if (l_err)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock_modes: PNORDD Read 1: readFlash() failed! Error committed.");
+ errlCommit(l_err,PNOR_COMP_ID);
+ fails++;
+ }
+ total++;
+ if(l_readData != l_writeData)
+ {
+ TS_FAIL("PnorDdTest::test_crossblock_modes: PNORDD read: Read data not expected value. Addr: 0x%.llx, ExpData: 0x%.llx, ActData: 0x%llx", l_address, l_writeData, l_readData);
+ fails++;
+ }
+ }
+ }while(0);
+
+ if( pnordd )
+ {
+ delete pnordd;
+ }
+
+ TRACFCOMP(g_trac_pnor, "PnorDdTest::test_crossblock_modes> %d/%d fails", fails, total );
+ }
+
+
+};
+
/*Not really a real test, just using to verify ext image is loading properly.
Leaving it commented out because the test-case will not dynamically find the extended image based on the TOC
// void testPnorDD2(void)
@@ -283,7 +793,7 @@ Leaving it commented out because the test-case will not dynamically find the ext
l_err = deviceRead(l_testTarget,
&l_readData,
l_size,
- DEVICE_PNOR_ADDRESS(0, l_address));
+ DEVICE_PNOR_ADDRESS(0, l_address);
if (l_err)
{
TS_FAIL("testPnorDD2: PNORDD read fakeext: deviceRead() failed! Error committed.");
@@ -302,7 +812,7 @@ Leaving it commented out because the test-case will not dynamically find the ext
l_err = deviceRead(l_testTarget,
&l_readData,
l_size,
- DEVICE_PNOR_ADDRESS(0, l_address));
+ DEVICE_PNOR_ADDRESS(0, l_address);
if (l_err)
{
TS_FAIL("testPnorDD2: PNORDD read fakeext: deviceRead() failed! Error committed.");
@@ -324,7 +834,6 @@ Leaving it commented out because the test-case will not dynamically find the ext
};
*/
-};
#endif
OpenPOWER on IntegriCloud