summaryrefslogtreecommitdiffstats
path: root/src/usr/pnor
diff options
context:
space:
mode:
authorStephen Cprek <smcprek@us.ibm.com>2014-12-15 14:18:37 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2015-01-22 17:31:04 -0600
commit38cfbf78f1b0393131bb6d7772d7e9948b03096e (patch)
tree6574127229c0d0816606628f2b8fa9d8bc22e301 /src/usr/pnor
parent3443aa895cfc6ad9acaed6f26622ce540f96e30d (diff)
downloadtalos-hostboot-38cfbf78f1b0393131bb6d7772d7e9948b03096e.tar.gz
talos-hostboot-38cfbf78f1b0393131bb6d7772d7e9948b03096e.zip
Add API to clear PNOR data with good ECC
Change-Id: I368da631657016e7d44162f33e34c5afc194c222 RTC: 119898 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14930 Tested-by: Jenkins Server Reviewed-by: Brian H. Horton <brianh@linux.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/pnor')
-rw-r--r--src/usr/pnor/pnorrp.C95
-rw-r--r--src/usr/pnor/pnorrp.H10
2 files changed, 102 insertions, 3 deletions
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index 3c1ce4a99..03f1a74d6 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -79,6 +79,14 @@ errlHndl_t PNOR::getSectionInfo( PNOR::SectionId i_section,
}
/**
+ * @brief Clear pnor section
+ */
+errlHndl_t PNOR::clearSection(PNOR::SectionId i_section)
+{
+ return Singleton<PnorRP>::instance().clearSection(i_section);
+}
+
+/**
* @brief Write the data for a given sectino into PNOR
*/
errlHndl_t PNOR::flush( PNOR::SectionId i_section)
@@ -257,8 +265,6 @@ void PnorRP::initDaemon()
rc = mm_set_permission((void*) BASE_VADDR,TOTAL_SIZE,
WRITABLE | WRITE_TRACKED);
-
-
// start task to wait on the queue
task_create( wait_for_message, NULL );
@@ -832,3 +838,88 @@ errlHndl_t PnorRP::computeSection( uint64_t i_vaddr,
return errhdl;
}
+errlHndl_t PnorRP::clearSection(PNOR::SectionId i_section)
+{
+ TRACFCOMP(g_trac_pnor, "PnorRP::clearSection Section id = %d", i_section);
+ errlHndl_t l_errl = NULL;
+ const uint64_t CLEAR_BYTE = 0xFF;
+ uint8_t* l_buf = new uint8_t[PAGESIZE];
+ uint8_t* l_eccBuf = NULL;
+
+ do
+ {
+ // Flush pages of pnor section we are trying to clear
+ l_errl = flush(i_section);
+ if (l_errl)
+ {
+ TRACFCOMP( g_trac_pnor, ERR_MRK"PnorRP::clearSection: flush() failed on section",
+ i_section);
+ break;
+ }
+
+ // Get PNOR section info
+ uint64_t l_address = iv_TOC[i_section].flashAddr;
+ uint64_t l_chipSelect = iv_TOC[i_section].chip;
+ uint32_t l_size = iv_TOC[i_section].size;
+ bool l_ecc = iv_TOC[i_section].integrity & FFS_INTEG_ECC_PROTECT;
+
+ // Number of pages needed to cycle proper ECC
+ // Meaning every 9th page will copy the l_eccBuf at offset 0
+ const uint64_t l_eccCycleNum = 9;
+
+ // Boundaries for properly splitting up an ECC page for 4K writes.
+ // Subtract 1 from l_eccCycleNum because we start writing with offset 0
+ // and add this value 8 times to complete a cycle.
+ const uint64_t l_sizeOfOverlapSection = (PAGESIZE_PLUS_ECC - PAGESIZE) /
+ (l_eccCycleNum - 1);
+
+ // Create clear section buffer
+ memset(l_buf, CLEAR_BYTE, PAGESIZE);
+
+ // apply ECC to data if needed
+ if(l_ecc)
+ {
+ l_eccBuf = new uint8_t[PAGESIZE_PLUS_ECC];
+ PNOR::ECC::injectECC( reinterpret_cast<uint8_t*>(l_buf),
+ PAGESIZE,
+ reinterpret_cast<uint8_t*>(l_eccBuf) );
+ l_size = (l_size*9)/8;
+ }
+
+ // Write clear section page to PNOR
+ for (uint64_t i = 0; i < l_size; i+=PAGESIZE)
+ {
+ if(l_ecc)
+ {
+ // Take (current page) mod (l_eccCycleNum) to get cycle position
+ uint8_t l_bufPos = ( (i/PAGESIZE) % l_eccCycleNum );
+ uint64_t l_bufOffset = l_sizeOfOverlapSection * l_bufPos;
+ memcpy(l_buf, (l_eccBuf + l_bufOffset), PAGESIZE);
+ }
+
+ // Set ecc parameter to false to avoid double writes will only write
+ // 4k at a time, even if the section is ecc protected.
+ l_errl = writeToDevice((l_address + i), l_chipSelect,
+ false, l_buf);
+ if (l_errl)
+ {
+ TRACFCOMP( g_trac_pnor, ERR_MRK"PnorRP::clearSection: writeToDevice fail: eid=0x%X, rc=0x%X",
+ l_errl->eid(), l_errl->reasonCode());
+ break;
+ }
+ }
+ if (l_errl)
+ {
+ break;
+ }
+ } while(0);
+
+ // Free allocated memory
+ if(l_eccBuf)
+ {
+ delete[] l_eccBuf;
+ }
+ delete [] l_buf;
+
+ return l_errl;
+}
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index 54f3e364e..9f9284290 100644
--- a/src/usr/pnor/pnorrp.H
+++ b/src/usr/pnor/pnorrp.H
@@ -58,6 +58,15 @@ class PnorRP
errlHndl_t getSectionInfo( PNOR::SectionId i_section,
PNOR::SectionInfo_t& o_info );
+ /**
+ * @brief Clears the specified PNOR section with all FF's (w/ good ECC)
+ *
+ * @param[in] i_id PNOR section to clear
+ *
+ * @return Error if fails
+ */
+ errlHndl_t clearSection(PNOR::SectionId i_section);
+
protected:
/**
* @brief Constructor
@@ -222,7 +231,6 @@ class PnorRP
* @brief Static instance function for testcase only
*/
static PnorRP& getInstance();
-
};
OpenPOWER on IntegriCloud