summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Crowell <dcrowell@us.ibm.com>2012-02-07 09:49:21 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2012-02-28 13:06:28 -0600
commitca733abd8cc5ff4e05e1bf958239c9b06710632c (patch)
tree34c3f527282e31cf3b9ba8bc46648a4f84762dad /src
parentdf05b815a80fc2475aa0396ae140903beaa9dde1 (diff)
downloadtalos-hostboot-ca733abd8cc5ff4e05e1bf958239c9b06710632c.tar.gz
talos-hostboot-ca733abd8cc5ff4e05e1bf958239c9b06710632c.zip
RTC Story 36901 - Use LPC Memory
This includes a hack to allow access to our fake PNOR data via the ECCB scom registers. This hack will be removed once Simics provides a real ECCB model. Changes to INTR testcase were needed due to bugs exposed by the timing changes when enabling this new code. Note that the default operating mode will remain LPC_MEM because the current version of the ECCB model causes the IPL to take close to 10 minutes to complete. Change-Id: Icc236bffd52ba8214ec920f9a496adec138e54d9 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/692 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-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