diff options
author | Adam Muhle <armuhle@us.ibm.com> | 2012-11-26 12:32:49 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-12-07 14:54:43 -0600 |
commit | 2739f7bea4dd6919d00a85e0c511ae483179c96c (patch) | |
tree | e86fee5ac04b303ce3ae3fc005b18550cb042091 | |
parent | a6399f78deb2dde6e18749114df2881e37aca60a (diff) | |
download | talos-hostboot-2739f7bea4dd6919d00a85e0c511ae483179c96c.tar.gz talos-hostboot-2739f7bea4dd6919d00a85e0c511ae483179c96c.zip |
PNOR DD Micron NOR support
The current Micron parts require some special operations after a
read or write operation, otherwise future operations won't work.
Change-Id: I2d733da57cd0b05fa5a8ba962f87d7fabb3d5267
RTC: 53201
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2491
Tested-by: Jenkins Server
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/build/citest/etc/bbuild | 2 | ||||
-rwxr-xr-x | src/build/citest/etc/workarounds.postsimsetup | 11 | ||||
-rwxr-xr-x | src/build/citest/etc/workarounds.presimsetup | 33 | ||||
-rwxr-xr-x | src/build/simics/standalone.simics | 4 | ||||
-rw-r--r-- | src/include/usr/pnor/pnor_reasoncodes.H | 46 | ||||
-rw-r--r-- | src/usr/pnor/pnordd.C | 283 | ||||
-rw-r--r-- | src/usr/pnor/pnordd.H | 44 |
7 files changed, 350 insertions, 73 deletions
diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild index 28472dc7b..36a548773 100644 --- a/src/build/citest/etc/bbuild +++ b/src/build/citest/etc/bbuild @@ -1 +1 @@ -/esw/fips810/Builds/b1106a_1245.810 +/esw/fips810/Builds/b1201b_1249.810 diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup index e56c08ef5..0b7a91941 100755 --- a/src/build/citest/etc/workarounds.postsimsetup +++ b/src/build/citest/etc/workarounds.postsimsetup @@ -32,3 +32,14 @@ mkdir -p $sb/simu/data/cec-chip/ cp $bb/src/simu/data/cec-chip/centaur.act $sb/simu/data/cec-chip/centaur.act patch -p0 $sb/simu/data/cec-chip/centaur.act $HOSTBOOTROOT/src/build/citest/etc/patches/centaur.act.patch ### + +#### Update config file with new variables (Remove with RTC: 59984) #### +echo "+++ Forcing SBE header usage till Fips defaults to OFF" +mkdir -p $sb/simu/configs +mkdir -p $sb/simu/data/cec-chip +egrep -v "SETENV GFW_P8_MURANO_HB_BASE_IMG_USE_PNOR" $BACKING_BUILD/src/simu/configs/P8_MURANO.config> $sb/simu/configs/P8_MURANO.config +egrep -v "SETENV GFW_P8_VENICE_HB_BASE_IMG_USE_PNOR" $BACKING_BUILD/src/simu/configs/P8_VENICE.config> $sb/simu/configs/P8_VENICE.config +echo "SETENV GFW_P8_MURANO_HB_BASE_IMG_USE_PNOR no" >> $sb/simu/configs/P8_MURANO.config +echo "SETENV GFW_P8_VENICE_HB_BASE_IMG_USE_PNOR no" >> $sb/simu/configs/P8_VENICE.config +echo "SETENV GFW_P8_MURANO_HB_BASE_IMG_WITH_ECC no" >> $sb/simu/configs/P8_MURANO.config +echo "SETENV GFW_P8_VENICE_HB_BASE_IMG_WITH_ECC no" >> $sb/simu/configs/P8_VENICE.config diff --git a/src/build/citest/etc/workarounds.presimsetup b/src/build/citest/etc/workarounds.presimsetup index aff5cba43..85c0fc21d 100755 --- a/src/build/citest/etc/workarounds.presimsetup +++ b/src/build/citest/etc/workarounds.presimsetup @@ -1,26 +1,26 @@ #!/bin/sh -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. # -# $Source: src/build/citest/etc/workarounds.presimsetup $ +# $Source: src/build/citest/etc/workarounds.presimsetup $ # -# IBM CONFIDENTIAL +# IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011-2012 +# COPYRIGHT International Business Machines Corp. 2011,2012 # -# p1 +# p1 # -# Object Code Only (OCO) source materials -# Licensed Internal Code Source Materials -# IBM HostBoot Licensed Internal Code +# Object Code Only (OCO) source materials +# Licensed Internal Code Source Materials +# IBM HostBoot Licensed Internal Code # -# The source code for this program is not published or other- -# wise divested of its trade secrets, irrespective of what has -# been deposited with the U.S. Copyright Office. +# The source code for this program is not published or otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. # -# Origin: 30 +# Origin: 30 # -# IBM_PROLOG_END_TAG +# IBM_PROLOG_END_TAG ## ## Workarounds that are run before start_simics is executed for the first time ## to setup the sandbox @@ -33,3 +33,8 @@ #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 +####### Remove with RTC: 59984 +echo "+++ Override simics level to support Micron parts." +mkdir -p $sb/simu/data +egrep -v "WSALIAS DEFAULT FIPSLEVEL" $BACKING_BUILD/src/simu/data/simicsInfo > $sb/simu/data/simicsInfo +echo "WSALIAS DEFAULT FIPSLEVEL env/gfwf/simics-4.2.0/simics-4.2.98/fips/fld36/fi121205d800.42" >> $sb/simu/data/simicsInfo diff --git a/src/build/simics/standalone.simics b/src/build/simics/standalone.simics index 8ea2bdcee..7d6874cd9 100755 --- a/src/build/simics/standalone.simics +++ b/src/build/simics/standalone.simics @@ -1 +1,5 @@ p8Proc0.proc_fsi2host_mbox->responder_enable=1 + +#Trigger the SBE start +p8Proc0.proc_lbus_map.write 0x2870 0x50000000 #SBE Vital 0x281C +p8Proc0.proc_lbus_map.write 0x2870 0x90000000 #SBE Vital 0x281C diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H index 71d345873..a5b321b66 100644 --- a/src/include/usr/pnor/pnor_reasoncodes.H +++ b/src/include/usr/pnor/pnor_reasoncodes.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/usr/pnor/pnor_reasoncodes.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/pnor/pnor_reasoncodes.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __PNOR_REASONCODES_H #define __PNOR_REASONCODES_H @@ -50,6 +50,7 @@ namespace PNOR MOD_PNORDD_WRITELPC = 0x19, /**< pnordd.C : PnorDD::writeLPC */ MOD_PNORDD_ERASEFLASH = 0x1A, /**< pnordd.C : PnorDD::eraseFlash */ MOD_PNORDD_COMPAREANDWRITEBLOCK = 0x1B, /**< pnordd.C : PnorDD::compareAndWriteBlock */ + MOD_PNORDD_MICRONOPCOMPLETE = 0x1C, /**< pnordd.C : PnorDD::micronOpComplete */ }; @@ -65,6 +66,7 @@ namespace PNOR RC_LPC_ERROR = PNOR_COMP_ID | 0x08, RC_BAD_STARTUP_RC = PNOR_COMP_ID | 0x09, RC_UNSUPORTED_HARDWARE = PNOR_COMP_ID | 0x0A, + RC_MICRON_INCOMPLETE = PNOR_COMP_ID | 0x0B, }; }; diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C index 1f5c0b272..0f4f3e29d 100644 --- a/src/usr/pnor/pnordd.C +++ b/src/usr/pnor/pnordd.C @@ -400,6 +400,7 @@ PnorDD::~PnorDD() bool PnorDD::cv_sfcInitDone = false; //Static flag to ensure we only init the SFC one time. uint32_t PnorDD::cv_nor_chipid = 0; //Detected NOR Flash Type +uint32_t PnorDD::cv_hw_workaround = 0; //Hardware Workaround flags /** * STATIC @@ -449,15 +450,19 @@ void PnorDD::sfcInit( ) //Determine NOR Flash type, configure SFC and PNOR DD as needed l_err = getNORChipId(cv_nor_chipid); - TRACFCOMP(g_trac_pnor, "PnorDD::sfcInit: cv_nor_chipid=0x%.8x> ", cv_nor_chipid ); - - //TODO: Need to add support for VPO (RTC: 42325), Spansion NOR (RTC: 42326), - // Micron NOR (RTC: 42328), Macronix (RTC: 42330), and Simics (RTC: 42331) - // There will probably be some overlap between those stories, but keeping them - // all separate for now to ensure everything is covered. - if(SIMICS_NOR_ID == cv_nor_chipid) + TRACFCOMP(g_trac_pnor, + "PnorDD::sfcInit: cv_nor_chipid=0x%.8x> ", + cv_nor_chipid ); + + //TODO: Need to add support for VPO (RTC: 42325), + // Spansion NOR (RTC: 42326),, Macronix (RTC: 42330) + // There will probably be some overlap between those + // stories, but keeping them all separate for now to + // ensure everything is covered + if(MICRON_NOR_ID == cv_nor_chipid) /* Simics currently Micron */ { - TRACFCOMP(g_trac_pnor, "PnorDD::sfcInit: Configuring SFC for SIMICS NOR> " ); + TRACFCOMP(g_trac_pnor, + "PnorDD::sfcInit: Configuring SFC for SIMICS NOR> " ); uint32_t sm_erase_op = SPI_SIM_SM_ERASE_OP; iv_erasesize_bytes = SPI_SIM_SM_ERASE_SZ; @@ -473,7 +478,7 @@ void PnorDD::sfcInit( ) iv_erasesize_bytes); if(l_err) { break; } - //Enable 4-byte addressing for Macronix-type device + //Enable 4-byte addressing SfcCmdReg_t sfc_cmd; sfc_cmd.opcode = SPI_START4BA; sfc_cmd.length = 0; @@ -618,6 +623,7 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime) // the wait each time through //TODO tmp remove for VPO, need better polling strategy -- RTC43738 //nanosleep( 0, SFC_POLL_INCR_NS*(++loop) ); + ++loop; poll_time += SFC_POLL_INCR_NS*loop; } if( l_err ) { break; } @@ -626,7 +632,9 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime) // TODO: What errors do we check? if( (sfc_stat.done == 0) ) { - TRACFCOMP(g_trac_pnor, "PnorDD::pollSfcOpComplete> Error or timeout from LPC Status Register" ); + TRACFCOMP(g_trac_pnor, + "PnorDD::pollSfcOpComplete> Error or timeout from SFC Status Register" + ); /*@ * @errortype @@ -635,13 +643,14 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime) * @userdata1[0:31] NOR Flash Chip ID * @userdata1[32:63] Total poll time (ns) * @userdata2[0:31] ECCB Status Register - * @devdesc PnorDD::readLPC> Error or timeout from - * LPC Status Register + * @devdesc PnorDD::pollSfcOpComplete> Error or timeout from + * SFC Status Register */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_PNORDD_POLLSFCOPCOMPLETE, PNOR::RC_LPC_ERROR, - TWO_UINT32_TO_UINT64(cv_nor_chipid,poll_time), + TWO_UINT32_TO_UINT64(cv_nor_chipid, + poll_time), TWO_UINT32_TO_UINT64(sfc_stat.data32,0)); l_err->collectTrace("PNOR"); @@ -658,6 +667,135 @@ errlHndl_t PnorDD::pollSfcOpComplete(uint64_t i_pollTime) } /** + * @brief Poll for Op complete on Micron NOR chips + * The current version of Micron parts require a special + * form of checking for erase and write complete. + */ +errlHndl_t PnorDD::micronOpComplete(uint64_t i_pollTime) +{ + errlHndl_t l_err = NULL; + TRACFCOMP( g_trac_pnor, "PnorDD::micronOpComplete> i_pollTime=0x%.8x", + i_pollTime ); + + do { + + //Configure Get "Chip ID" command in SFC to check special + //Micron 'flag status' register + uint32_t confData = SPI_MICRON_FLAG_STAT << 24; + confData |= 0x00800001; // 8-> read, 1->1 bytes + TRACDCOMP( g_trac_pnor, "PnorDD::micronOpComplete> confData=0x%.8x", + confData ); + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CHIPIDCONF, + confData); + if(l_err) { break; } + + + //Poll for complete status + uint32_t opStatus; + uint64_t poll_time = 0; + uint64_t loop = 0; + while( poll_time < i_pollTime ) + { + //Issue Get Chip ID command (reading flag status) + SfcCmdReg_t sfc_cmd; + sfc_cmd.opcode = SFC_OP_CHIPID; + sfc_cmd.length = 0; + + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CMD, + sfc_cmd.data32); + if(l_err) { break; } + + //Read the Status from the Command Buffer + l_err = readRegSfc(SFC_CMDBUF_SPACE, + 0, //Offset into CMD BUFF space in bytes + opStatus); + if(l_err) { break; } + + //check for complete or error + // bit 0 = ready, bit 2=erase fail, bit 3=Program (Write) failure + if( (opStatus & 0xB0000000)) + { + 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 + //TODO tmp remove for VPO, need better polling strategy -- RTC43738 + //nanosleep( 0, SFC_POLL_INCR_NS*(++loop) ); + ++loop; + poll_time += SFC_POLL_INCR_NS*loop; + } + if( l_err ) { break; } + + // check for ready and no errors + // bit 0 = ready, bit 2=erase fail, bit 3=Program (Write) failure + if( (opStatus & 0xB0000000) != 0x80000000) + { + TRACFCOMP(g_trac_pnor, + "PnorDD::micronOpComplete> Error or timeout from Micron Flag Status Register (0x%.8X)", + opStatus); + + /*@ + * @errortype + * @moduleid PNOR::MOD_PNORDD_MICRONOPCOMPLETE + * @reasoncode PNOR::RC_MICRON_INCOMPLETE + * @userdata1[0:31] NOR Flash Chip ID + * @userdata1[32:63] Total poll time (ns) + * @userdata2[0:31] Micron Flag status register + * @devdesc PnorDD::micronOpComplete> Error or timeout from + * Micron Flag Status Register + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + PNOR::MOD_PNORDD_MICRONOPCOMPLETE, + PNOR::RC_MICRON_INCOMPLETE, + TWO_UINT32_TO_UINT64(cv_nor_chipid, + poll_time), + TWO_UINT32_TO_UINT64(opStatus,0)); + + l_err->collectTrace("PNOR"); + l_err->collectTrace("XSCOM"); + + //Erase & Program error bits are sticky, so they need to be cleared. + + //Configure Get "Chip ID" command in SFC to clear special + //Micron 'flag status' register. remaining bits are all zero + // since we just need to issue the SPI command. + uint32_t confData = SPI_MICRON_CLRFLAG_STAT << 24; + TRACDCOMP( g_trac_pnor, "PnorDD::micronOpComplete> confData=0x%.8x", + confData ); + errlHndl_t tmp_err = NULL; + tmp_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CHIPIDCONF, + confData); + if(tmp_err) { + //commit this error and return the original + ERRORLOG::errlCommit(tmp_err,PNOR_COMP_ID); + } + + //Issue Get Chip ID command (clearing flag status) + SfcCmdReg_t sfc_cmd; + sfc_cmd.opcode = SFC_OP_CHIPID; + sfc_cmd.length = 0; + + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CMD, + sfc_cmd.data32); + if(l_err) { break; } + + break; + } + + + }while(0); + + return l_err; + +} + +/** * @brief Read the NOR FLash ChipID */ errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId, @@ -668,10 +806,19 @@ errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId, i_spiOpcode ); do { + //Configure Get Chip ID opcode + uint32_t confData = i_spiOpcode << 24; + confData |= 0x00800003; // 8-> read, 3->3 bytes + TRACDCOMP( g_trac_pnor, "PnorDD::getNORChipId> confData=0x%.8x", + confData ); + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CHIPIDCONF, + confData); + if(l_err) { break; } //Issue Get Chip ID command SfcCmdReg_t sfc_cmd; - sfc_cmd.opcode = i_spiOpcode; + sfc_cmd.opcode = SFC_OP_CHIPID; sfc_cmd.length = 0; l_err = writeRegSfc(SFC_CMD_SPACE, @@ -694,6 +841,57 @@ errlHndl_t PnorDD::getNORChipId(uint32_t& o_chipId, // Only look at a portion of the data that is returned o_chipId &= ID_MASK; + //Some micron chips require a special workaround required + //so need to set a flag for later use + //We can't read all 6 bytes above because not all MFG + //support that operation. + if(o_chipId == MICRON_NOR_ID) + { + //Change ChipID command to read back 6 bytes. + //If bit 1 is set in 2nd word of cmd buffer data, then + //We must do the workaround. + //Ex: CCCCCCLL 40000000 + // CCCCCC -> Industry Standard Chip ID + // LL -> Lenght of Micron extended data + // 4 -> Bit to indicate we must to erase/write workaround + confData = i_spiOpcode << 24; + confData |= 0x00800006; // 8-> read, 6->6 bytes + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CHIPIDCONF, + confData); + if(l_err) { break; } + + //Issue Get Chip ID command + SfcCmdReg_t sfc_cmd; + sfc_cmd.opcode = SFC_OP_CHIPID; + sfc_cmd.length = 0; + + l_err = writeRegSfc(SFC_CMD_SPACE, + SFC_REG_CMD, + sfc_cmd.data32); + if(l_err) { break; } + + uint32_t extIdData = 0; + + //Read the Extended from the Command Buffer + l_err = readRegSfc(SFC_CMDBUF_SPACE, + 4, //Offset into CMD BUFF space in bytes + extIdData); + if(l_err) { + break; + } + if((extIdData & 0x40000000) == 0x00000000) + { + TRACFCOMP( g_trac_pnor, + "PnorDD::getNORChipId> Setting Micron workaround flag" + ); + //Set Micron workaround flag + cv_hw_workaround |= HWWK_MICRON_WRT_ERASE; + } + + } + + }while(0); return l_err; @@ -745,7 +943,8 @@ errlHndl_t PnorDD::flushSfcBuf(uint32_t i_addr, size_t i_size) { errlHndl_t l_err = NULL; - TRACDCOMP( g_trac_pnor, "PnorDD::flushSfcBuf> i_addr=0x%.8x, i_size=0x%.8x", + TRACDCOMP( g_trac_pnor, + "PnorDD::flushSfcBuf> i_addr=0x%.8x, i_size=0x%.8x", i_addr, i_size ); do { @@ -765,9 +964,18 @@ errlHndl_t PnorDD::flushSfcBuf(uint32_t i_addr, sfc_cmd.data32); if(l_err) { break; } - //Poll for complete status - l_err = pollSfcOpComplete(); - if(l_err) { break; } + //check for special Micron Op Complete + if(cv_hw_workaround & HWWK_MICRON_WRT_ERASE) + { + l_err = micronOpComplete(); + if(l_err) { break; } + } + else //Use Normal Op Complete + { + //Poll for complete status + l_err = pollSfcOpComplete(); + if(l_err) { break; } + } }while(0); @@ -1358,7 +1566,9 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address) if(iv_erases[idx].addr == i_address) { iv_erases[idx].count++; - TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", i_address, iv_erases[idx].count ); + TRACFCOMP(g_trac_pnor, + "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", + i_address, iv_erases[idx].count ); break; } @@ -1368,12 +1578,16 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address) { iv_erases[idx].addr = i_address; iv_erases[idx].count = 1; - TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", i_address, iv_erases[idx].count ); + TRACFCOMP(g_trac_pnor, + "PnorDD::eraseFlash> Block 0x%.8X has %d erasures", + i_address, iv_erases[idx].count ); break; } else if( idx == (ERASE_COUNT_MAX - 1)) { - TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erase counter full! Block 0x%.8X Erased", i_address ); + TRACFCOMP(g_trac_pnor, + "PnorDD::eraseFlash> Erase counter full! Block 0x%.8X Erased", + i_address ); break; } } @@ -1384,16 +1598,17 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address) break; //all done } - if(cv_nor_chipid != 0) + else if(cv_nor_chipid != 0) { - TRACDCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erasing flash for cv_nor_chipid=0x%.8x, iv_mode=0x%.8x", cv_nor_chipid, iv_mode); + TRACDCOMP(g_trac_pnor, + "PnorDD::eraseFlash> Erasing flash for cv_nor_chipid=0x%.8x, iv_mode=0x%.8x", + cv_nor_chipid, iv_mode); //Write erase address to ADR reg l_err = writeRegSfc(SFC_CMD_SPACE, SFC_REG_ADR, i_address); - //Issue Erase command SfcCmdReg_t sfc_cmd; sfc_cmd.opcode = SFC_OP_ERASM; @@ -1404,14 +1619,24 @@ errlHndl_t PnorDD::eraseFlash(uint32_t i_address) sfc_cmd.data32); if(l_err) { break; } - //Poll for complete status - l_err = pollSfcOpComplete(); - if(l_err) { break; } - + //check for special Micron Op Complete + if(cv_hw_workaround & HWWK_MICRON_WRT_ERASE) + { + l_err = micronOpComplete(); + if(l_err) { break; } + } + else //Use Normal Op Complete + { + //Poll for complete status + l_err = pollSfcOpComplete(); + if(l_err) { break; } + } } else { - TRACFCOMP(g_trac_pnor, "PnorDD::eraseFlash> Erase not supported for cv_nor_chipid=%d", cv_nor_chipid ); + TRACFCOMP(g_trac_pnor, + "PnorDD::eraseFlash> Erase not supported for cv_nor_chipid=%d", + cv_nor_chipid ); /*@ * @errortype diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H index f82b991a4..e118f12a6 100644 --- a/src/usr/pnor/pnordd.H +++ b/src/usr/pnor/pnordd.H @@ -121,6 +121,12 @@ class PnorDD SPI_GET_CHIPID_OP = 0x9F, /**< Default Op code for getting NOR ChipID */ SPI_START4BA = 0x37, /**< Enable Macronix 4-Byte addressing */ + /*This command is only use on Micron NOR chips which require special + * procedure to check write & erase op complete + */ + SPI_MICRON_FLAG_STAT = 0x70, /**< Check complete on Micron */ + SPI_MICRON_CLRFLAG_STAT = 0x50, /**< Clear Micron Flag Status reg */ + SPI_SIM_SM_ERASE_OP = 0x00000020, /**< Simics Op Code for Small Erase */ SPI_SIM_SM_ERASE_SZ = 0x1000, /**< Simics Small Erase Size */ }; @@ -131,8 +137,9 @@ class PnorDD */ enum NorChipIDs { - SIMICS_NOR_ID = 0x20ba2000, /**< CHIP ID returned by Simics NOR chip */ - VPO_NOR_ID = 0x20201800, /**< CHIP ID returned by VPO NOR chip */ + /* Note: Simics currently models Micron NOR */ + MICRON_NOR_ID = 0x20ba2000, /**< Micron NOR chip ID */ + VPO_NOR_ID = 0x20201800, /**< VPO NOR chip ID */ ID_MASK = 0xFFFFFF00, /**< Only look at 3 bytes */ }; @@ -163,8 +170,7 @@ class PnorDD SFC_REG_ADRCMS = 0x8C, /**< ADRCMS : Second Intf NOR Allocation */ SFC_REG_OADRNB = 0x90, /**< OADRNB : Direct Access OBP Window Base Address */ SFC_REG_OADRNS = 0x94, /**< OADRNS : DIrect Access OPB Window Size */ - - + SFC_REG_CHIPIDCONF = 0x9C, /**< CHIPIDCONF : config ChipId CMD */ }; /** @@ -195,6 +201,14 @@ class PnorDD }; + + /** + * Flags used to trigger Hardware workarounds + */ + enum { + HWWK_MICRON_WRT_ERASE = 0x00000001, /**< Micron Wrt/Erase workaround */ + }; + /** * @brief SFC Command Register Layout */ @@ -203,9 +217,9 @@ class PnorDD uint32_t data32; struct { - uint32_t reserved : 16; /**< 0:15 = Reserved */ - uint32_t opcode : 7; /**< 16:22 = OpCode */ - uint32_t length : 9; /**< 22:31 = Num bytes for ReadRaw/WriteRaw */ + uint32_t reserved : 16; /**< 0:15 = Reserved */ + uint32_t opcode : 7; /**< 16:22 = OpCode */ + uint32_t length : 9; /**< 22:31 = Num bytes for Read/Write Raw */ }; SfcCmdReg_t() : data32(0) {}; }; @@ -261,6 +275,16 @@ class PnorDD */ errlHndl_t pollSfcOpComplete(uint64_t i_pollTime = SFC_POLL_TIME_NS); + /** + * @brief Poll for Op complete on Micron NOR chips + * The current version of Micron parts require a special + * form of checking for erase and write complete. + * + * @parm i_pollTime Amount of time to Poll, default SFC_POLL_TIME_NS + * + * @return Error from operation + */ + errlHndl_t micronOpComplete(uint64_t i_pollTime = SFC_POLL_TIME_NS); /** * @brief Read the NOR FLash ChipID @@ -575,6 +599,12 @@ class PnorDD static uint32_t cv_nor_chipid; /** + * @brief Hardware workarounds + * + */ + static uint32_t cv_hw_workaround; + + /** * @brief indicates if SFC initialization has been performed. * */ |