diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/fsi/fsi_reasoncodes.H | 6 | ||||
-rw-r--r-- | src/makefile | 1 | ||||
-rw-r--r-- | src/usr/fsi/errlud_fsi.C | 7 | ||||
-rw-r--r-- | src/usr/fsi/fsi_common.C | 65 | ||||
-rw-r--r-- | src/usr/fsi/fsi_common.H | 155 | ||||
-rw-r--r-- | src/usr/fsi/fsidd.C | 167 | ||||
-rw-r--r-- | src/usr/fsi/fsidd.H | 154 | ||||
-rw-r--r-- | src/usr/fsi/makefile | 6 | ||||
-rw-r--r-- | src/usr/fsi/runtime/makefile | 35 | ||||
-rw-r--r-- | src/usr/fsi/runtime/rt_fsi.C | 476 | ||||
-rw-r--r-- | src/usr/fsi/runtime/rt_fsi.H | 118 | ||||
-rw-r--r-- | src/usr/pnor/runtime/rt_pnor.C | 111 | ||||
-rw-r--r-- | src/usr/pnor/runtime/rt_pnor.H | 11 |
13 files changed, 1070 insertions, 242 deletions
diff --git a/src/include/usr/fsi/fsi_reasoncodes.H b/src/include/usr/fsi/fsi_reasoncodes.H index de8930940..32844e5e4 100644 --- a/src/include/usr/fsi/fsi_reasoncodes.H +++ b/src/include/usr/fsi/fsi_reasoncodes.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +46,8 @@ namespace FSI MOD_FSIPRES_PROCPRESENCEDETECT = 0x20, /**< fsipres.C : procPresenceDetect */ MOD_FSIPRES_MEMBPRESENCEDETECT = 0x21, /**< fsipres.C : membPresenceDetect */ + + MOD_RTFSI_GENFULLFSIADDR = 0x22, /**< rt_fsi.C : genFullFsiAddr */ }; enum FSIReasonCode @@ -69,6 +71,8 @@ namespace FSI RC_FSI_CVPD_MISMATCH = FSI_COMP_ID | 0x10, RC_ERROR_IN_MAEB = FSI_COMP_ID | 0x11, RC_BAD_ATTRIBUTES = FSI_COMP_ID | 0x12, + + }; enum UserDetailsTypes diff --git a/src/makefile b/src/makefile index 586c01879..6d1b1246d 100644 --- a/src/makefile +++ b/src/makefile @@ -293,6 +293,7 @@ RUNTIME_MODULES += pnor_rt RUNTIME_MODULES += fapi2_rt RUNTIME_MODULES += secureboot_rt RUNTIME_MODULES += p9_cpuWkup +RUNTIME_MODULES += fsi_rt RUNTIME_DATA_MODULES += RUNTIME_TESTCASE_MODULES += cxxtest_rt diff --git a/src/usr/fsi/errlud_fsi.C b/src/usr/fsi/errlud_fsi.C index c9647e444..f00530d22 100644 --- a/src/usr/fsi/errlud_fsi.C +++ b/src/usr/fsi/errlud_fsi.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -29,6 +31,7 @@ #include <fsi/fsi_reasoncodes.H> #include <string.h> #include "fsidd.H" +#include "fsi_common.H" namespace FSI { @@ -44,7 +47,7 @@ UdPresence::UdPresence( TARGETING::Target* i_target ) iv_SubSection = FSI_UDT_PRESENCE; FsiDD& fsidd = Singleton<FsiDD>::instance(); - FsiDD::FsiChipInfo_t l_chip_info = fsidd.getFsiInfo(i_target); + FSI::FsiChipInfo_t l_chip_info = fsidd.getFsiInfo(i_target); uint64_t l_slaveIndex = fsidd.getSlaveEnableIndex(l_chip_info.master, l_chip_info.type); diff --git a/src/usr/fsi/fsi_common.C b/src/usr/fsi/fsi_common.C new file mode 100644 index 000000000..ca4f5c5a7 --- /dev/null +++ b/src/usr/fsi/fsi_common.C @@ -0,0 +1,65 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/fsi/fsi_common.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include "fsi_common.H" +#include <fsi/fsiif.H> + +/** + * @brief Convert a type/port pair into a FSI address offset + */ +uint64_t FSI::getPortOffset(TARGETING::FSI_MASTER_TYPE i_type, + uint8_t i_port) +{ + uint64_t offset = 0; + if( TARGETING::FSI_MASTER_TYPE_MFSI == i_type ) + { + switch(i_port) + { + case(0): offset = FSI::MFSI_PORT_0; break; + case(1): offset = FSI::MFSI_PORT_1; break; + case(2): offset = FSI::MFSI_PORT_2; break; + case(3): offset = FSI::MFSI_PORT_3; break; + case(4): offset = FSI::MFSI_PORT_4; break; + case(5): offset = FSI::MFSI_PORT_5; break; + case(6): offset = FSI::MFSI_PORT_6; break; + case(7): offset = FSI::MFSI_PORT_7; break; + } + } + else if( TARGETING::FSI_MASTER_TYPE_CMFSI == i_type ) + { + switch(i_port) + { + case(0): offset = FSI::CMFSI_PORT_0; break; + case(1): offset = FSI::CMFSI_PORT_1; break; + case(2): offset = FSI::CMFSI_PORT_2; break; + case(3): offset = FSI::CMFSI_PORT_3; break; + case(4): offset = FSI::CMFSI_PORT_4; break; + case(5): offset = FSI::CMFSI_PORT_5; break; + case(6): offset = FSI::CMFSI_PORT_6; break; + case(7): offset = FSI::CMFSI_PORT_7; break; + } + } + + return offset; +} diff --git a/src/usr/fsi/fsi_common.H b/src/usr/fsi/fsi_common.H new file mode 100644 index 000000000..302cea570 --- /dev/null +++ b/src/usr/fsi/fsi_common.H @@ -0,0 +1,155 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/fsi/fsi_common.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef FSI_COMMON_H +#define FSI_COMMON_H + +#include <fsi/fsiif.H> + +namespace FSI{ + + /** + * FSI Address Space + */ + enum FsiAddressSpace { + // Master control registers + CMFSI_CONTROL_REG = 0x003000, /**< cMFSI Control Register */ + MFSI_CONTROL_REG = 0x003400, /**< MFSI Control Register */ + + // cMFSI Ports (32KB each) + CMFSI_PORT_0 = 0x040000, /**< cMFSI port 0 */ + CMFSI_PORT_1 = 0x048000, /**< cMFSI port 1 */ + CMFSI_PORT_2 = 0x050000, /**< cMFSI port 2 */ + CMFSI_PORT_3 = 0x058000, /**< cMFSI port 3 */ + CMFSI_PORT_4 = 0x060000, /**< cMFSI port 4 */ + CMFSI_PORT_5 = 0x068000, /**< cMFSI port 5 */ + CMFSI_PORT_6 = 0x070000, /**< cMFSI port 6 */ + CMFSI_PORT_7 = 0x078000, /**< cMFSI port 7 */ + CMFSI_PORT_MASK = 0x078000, + /**< Mask to look for a valid cMFSI port */ + + // Offsets to cascaded slaves within a cMFSI port + CMFSI_SLAVE_0 = 0x000000, /**< cMFSI - Slave 0 */ + CMFSI_SLAVE_1 = 0x002000, /**< cMFSI - Slave 1 */ + CMFSI_SLAVE_2 = 0x004000, /**< cMFSI - Slave 2 */ + CMFSI_SLAVE_3 = 0x006000, /**< cMFSI - Slave 3 */ + + // MFSI Ports (512KB each) + MFSI_PORT_LOCAL = 0x000000, /**< Local master (for local cMFSI) */ + MFSI_PORT_0 = 0x080000, /**< MFSI port 0 */ + MFSI_PORT_1 = 0x100000, /**< MFSI port 1 */ + MFSI_PORT_2 = 0x180000, /**< MFSI port 2 */ + MFSI_PORT_3 = 0x200000, /**< MFSI port 3 */ + MFSI_PORT_4 = 0x280000, /**< MFSI port 4 */ + MFSI_PORT_5 = 0x300000, /**< MFSI port 5 */ + MFSI_PORT_6 = 0x380000, /**< MFSI port 6 */ + MFSI_PORT_7 = 0x400000, /**< MFSI port 7 */ + MFSI_PORT_MASK = 0x780000, + /**< Mask to look for a valid MFSI port */ + + // Offsets to cascaded slaves within a MFSI port + MFSI_SLAVE_0 = 0x000000, /**< MFSI - Slave 0 */ + MFSI_SLAVE_1 = 0x020000, /**< MFSI - Slave 1 */ + MFSI_SLAVE_2 = 0x040000, /**< MFSI - Slave 2 */ + MFSI_SLAVE_3 = 0x060000, /**< MFSI - Slave 3 */ + }; + + /** + * Common id to identify a FSI position to use in error logs and traces + */ + union FsiLinkId_t + { + uint32_t id; + struct + { + uint8_t node; ///< Physical Node of FSI Master processor + uint8_t proc; ///< Physical Position of FSI Master processor + uint8_t type; ///< FSI Master type (FSI_MASTER_TYPE) + uint8_t port; ///< Slave link/port number + }; + }; + + /** + * @brief Structure which defines info necessary to access a chip via FSI + */ + struct FsiChipInfo_t + { + TARGETING::Target* slave; //< FSI Slave chip + TARGETING::Target* master; ///< FSI Master + TARGETING::FSI_MASTER_TYPE type; ///< Master or Cascaded Master + uint8_t port; ///< Which port is this chip hanging off of + uint8_t cascade; ///< Slave cascade position + union { + TARGETING::FsiOptionFlags flagbits; ///< Special flags + uint16_t flags; ///< Special flags + }; + FsiLinkId_t linkid; ///< Id for traces and error logs + + FsiChipInfo_t() : + slave(NULL), master(NULL), + type(TARGETING::FSI_MASTER_TYPE_NO_MASTER), + port(UINT8_MAX), cascade(0), flags(0) + { linkid.id = 0; }; + }; + + /** + * @brief Holds a set of addressing information to describe the + * current FSI operation + */ + struct FsiAddrInfo_t { + TARGETING::Target* fsiTarg; ///< Target of FSI operation + TARGETING::Target* opbTarg; ///< OPB control reg target + uint32_t relAddr; ///< Input FSI address (relative to fsiTarg) + uint32_t absAddr; ///< Absolute FSI address (relative to opbTarg) + FsiChipInfo_t accessInfo; ///< FSI Access Info + + /** Input Arg Constructor */ + FsiAddrInfo_t( TARGETING::Target* i_target, + uint64_t i_address ) : + fsiTarg(i_target), opbTarg(NULL), + relAddr(i_address), absAddr(UINT32_MAX) + {}; + + private: + /** Default Constructor is not allowed */ + FsiAddrInfo_t() : + fsiTarg(NULL), opbTarg(NULL), + relAddr(UINT32_MAX),absAddr(UINT32_MAX) + {}; + }; + + /** + * @brief Convert a type/port pair into a FSI address offset + * + * @param[in] i_type Type of FSI interface + * @param[in] i_port FSI link number + * @return uint64_t FSI address offset + */ + uint64_t getPortOffset(TARGETING::FSI_MASTER_TYPE i_type, + uint8_t i_port); +} + + + +#endif diff --git a/src/usr/fsi/fsidd.C b/src/usr/fsi/fsidd.C index db2811f82..9f651f173 100644 --- a/src/usr/fsi/fsidd.C +++ b/src/usr/fsi/fsidd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -387,7 +387,7 @@ errlHndl_t FsiDD::read(TARGETING::Target* i_target, } // prefix the appropriate MFSI/cMFSI slave port offset - FsiAddrInfo_t addr_info( i_target, i_address ); + FSI::FsiAddrInfo_t addr_info( i_target, i_address ); l_err = genFullFsiAddr( addr_info ); if(l_err) { @@ -429,7 +429,7 @@ errlHndl_t FsiDD::write(TARGETING::Target* i_target, } // prefix the appropriate MFSI/cMFSI slave port offset - FsiAddrInfo_t addr_info( i_target, i_address ); + FSI::FsiAddrInfo_t addr_info( i_target, i_address ); l_err = genFullFsiAddr( addr_info ); if(l_err) { @@ -503,7 +503,7 @@ errlHndl_t FsiDD::initializeHardware() typedef struct { TARGETING::Target* targ; - FsiDD::FsiChipInfo_t info; + FSI::FsiChipInfo_t info; } target_chipInfo_t ; // list of ports off of local MFSI @@ -518,7 +518,7 @@ errlHndl_t FsiDD::initializeHardware() target_chipInfo_t remote_cmfsi[MAX_SLAVE_PORTS][MAX_SLAVE_PORTS]; // = {}; memset(remote_cmfsi, '\0', sizeof(remote_cmfsi)); // TODO: GCC ICE. - FsiChipInfo_t info; + FSI::FsiChipInfo_t info; // loop through every CHIP target TARGETING::PredicateCTM l_chipClass(TARGETING::CLASS_CHIP, @@ -549,7 +549,7 @@ errlHndl_t FsiDD::initializeHardware() } else { - FsiChipInfo_t info2 = getFsiInfo(info.master); + FSI::FsiChipInfo_t info2 = getFsiInfo(info.master); if( info2.master == NULL ) { TRACFCOMP( g_trac_fsi, "Problem with attribute data for master %.8X for slave %.8X", TARGETING::get_huid(info.master), TARGETING::get_huid(*t_itr) ); @@ -771,7 +771,7 @@ void FsiDD::getFsiFFDC(FSI::fsiFFDCType_t i_ffdc_type, errlHndl_t tmp_err = NULL; // Use this call to find the OPB Master to read - FsiAddrInfo_t addr_info( i_target, 0x12345678 ); + FSI::FsiAddrInfo_t addr_info( i_target, 0x12345678 ); tmp_err = genFullFsiAddr( addr_info ); if( tmp_err ) { @@ -835,7 +835,7 @@ void FsiDD::getFsiFFDC(FSI::fsiFFDCType_t i_ffdc_type, else if( FSI::FFDC_PIB_FAIL == i_ffdc_type ) { errlHndl_t tmp_err = NULL; - FsiChipInfo_t fsi_info = getFsiInfo( i_target ); + FSI::FsiChipInfo_t fsi_info = getFsiInfo( i_target ); // Grab the FSI GP regs since they have fencing information ERRORLOG::ErrlUserDetailsLogRegister regdata2(i_target); @@ -912,7 +912,7 @@ void FsiDD::getFsiFFDC(FSI::fsiFFDCType_t i_ffdc_type, { errlHndl_t tmp_err = NULL; // Find the OPB Master and then collect FFDC_OPB_FAIL - FsiAddrInfo_t addr_info( i_target, 0x12345678 ); + FSI::FsiAddrInfo_t addr_info( i_target, 0x12345678 ); tmp_err = genFullFsiAddr( addr_info ); if( tmp_err ) { @@ -1036,7 +1036,7 @@ FsiDD::FsiDD() TRACFCOMP(g_trac_fsi,"Master=%.8X",TARGETING::get_huid(iv_master)); // add a dummy value to catch NULL - FsiChipInfo_t info; + FSI::FsiChipInfo_t info; iv_fsiInfoMap[NULL] = info; mutex_init(&iv_dataMutex); @@ -1063,7 +1063,7 @@ errlHndl_t FsiDD::read(uint64_t i_address, // generate a set of address info for this manual operation // note that relAddr==absAddr in this case - FsiAddrInfo_t addr_info( iv_master, i_address ); + FSI::FsiAddrInfo_t addr_info( iv_master, i_address ); addr_info.opbTarg = iv_master; addr_info.absAddr = i_address; @@ -1086,7 +1086,7 @@ errlHndl_t FsiDD::write(uint64_t i_address, // generate a set of address info for this manual operation // note that relAddr==absAddr in this case - FsiAddrInfo_t addr_info( iv_master, i_address ); + FSI::FsiAddrInfo_t addr_info( iv_master, i_address ); addr_info.opbTarg = iv_master; addr_info.absAddr = i_address; @@ -1100,7 +1100,7 @@ errlHndl_t FsiDD::write(uint64_t i_address, /** * @brief Performs an FSI Read Operation */ -errlHndl_t FsiDD::read(FsiAddrInfo_t& i_addrInfo, +errlHndl_t FsiDD::read(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* o_buffer, uint64_t i_buflen ) { @@ -1202,7 +1202,7 @@ errlHndl_t FsiDD::read(FsiAddrInfo_t& i_addrInfo, /** * @brief Write FSI Register */ -errlHndl_t FsiDD::write(FsiAddrInfo_t& i_addrInfo, +errlHndl_t FsiDD::write(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* i_buffer, uint64_t i_buflen ) { @@ -1308,7 +1308,7 @@ errlHndl_t FsiDD::write(FsiAddrInfo_t& i_addrInfo, /** * @brief Analyze error bits and recover hardware as needed */ -errlHndl_t FsiDD::handleOpbErrors(FsiAddrInfo_t& i_addrInfo, +errlHndl_t FsiDD::handleOpbErrors(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t i_opbStatAddr, uint32_t i_opbStatData) { @@ -1385,10 +1385,10 @@ errlHndl_t FsiDD::handleOpbErrors(FsiAddrInfo_t& i_addrInfo, if( (l_opb_stat & OPB_STAT_ERRACK) && ( ((i_addrInfo.relAddr & ~FSI_CTLREG_MASK) - == MFSI_CONTROL_REG) + == FSI::MFSI_CONTROL_REG) || ((i_addrInfo.relAddr & ~FSI_CTLREG_MASK) - == CMFSI_CONTROL_REG) + == FSI::CMFSI_CONTROL_REG) ) ) { @@ -1439,7 +1439,7 @@ errlHndl_t FsiDD::handleOpbErrors(FsiAddrInfo_t& i_addrInfo, if( !root_cause_found ) { // read the Status Bridge0 Register - FsiChipInfo_t fsi_info = getFsiInfo( i_addrInfo.fsiTarg ); + FSI::FsiChipInfo_t fsi_info = getFsiInfo( i_addrInfo.fsiTarg ); uint64_t ctl_reg = getControlReg(fsi_info.type); uint32_t mesrb0_data = 0; @@ -1574,7 +1574,7 @@ errlHndl_t FsiDD::handleOpbErrors(FsiAddrInfo_t& i_addrInfo, /** * @brief Poll for completion of a FSI operation, return data on read */ -errlHndl_t FsiDD::pollForComplete(FsiAddrInfo_t& i_addrInfo, +errlHndl_t FsiDD::pollForComplete(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* o_readData) { errlHndl_t l_err = NULL; @@ -1790,7 +1790,7 @@ errlHndl_t FsiDD::pollForComplete(FsiAddrInfo_t& i_addrInfo, * @brief Generate a complete FSI address based on the target and the * FSI offset within that target */ -errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) +errlHndl_t FsiDD::genFullFsiAddr(FSI::FsiAddrInfo_t& io_addrInfo) { errlHndl_t l_err = NULL; @@ -1815,7 +1815,7 @@ errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) if( io_addrInfo.accessInfo.master == iv_master ) { //append the appropriate offset - io_addrInfo.absAddr += getPortOffset(io_addrInfo.accessInfo.type, + io_addrInfo.absAddr += FSI::getPortOffset(io_addrInfo.accessInfo.type, io_addrInfo.accessInfo.port); } //verify this target has a valid FSI master @@ -1848,11 +1848,12 @@ errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) else { //append the CMFSI portion first - io_addrInfo.absAddr += getPortOffset(io_addrInfo.accessInfo.type, + io_addrInfo.absAddr += FSI::getPortOffset(io_addrInfo.accessInfo.type, io_addrInfo.accessInfo.port); //find this port's master and then get its port information - FsiChipInfo_t mfsi_info = getFsiInfo(io_addrInfo.accessInfo.master); + FSI::FsiChipInfo_t mfsi_info = + getFsiInfo(io_addrInfo.accessInfo.master); //check for invalid topology if( mfsi_info.master != iv_master ) @@ -1937,7 +1938,8 @@ errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) // a flipped cmfsi port //using the master chip so we need to append the MFSI port - io_addrInfo.absAddr += getPortOffset(mfsi_info.type,mfsi_info.port); + io_addrInfo.absAddr += FSI::getPortOffset(mfsi_info.type, + mfsi_info.port); } else if( (io_addrInfo.accessInfo.master)-> getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useXscom @@ -1959,7 +1961,8 @@ errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) else { //using the master chip so we need to append the MFSI port - io_addrInfo.absAddr += getPortOffset(mfsi_info.type,mfsi_info.port); + io_addrInfo.absAddr += FSI::getPortOffset(mfsi_info.type, + mfsi_info.port); } } @@ -1970,7 +1973,7 @@ errlHndl_t FsiDD::genFullFsiAddr(FsiAddrInfo_t& io_addrInfo) * @brief Generate a valid SCOM address to access the OPB, this will * choose the correct master */ -uint64_t FsiDD::genOpbScomAddr(FsiAddrInfo_t& i_addrInfo, +uint64_t FsiDD::genOpbScomAddr(FSI::FsiAddrInfo_t& i_addrInfo, uint64_t i_opbOffset) { uint64_t opbaddr = FSI2OPB_OFFSET_0; @@ -1986,7 +1989,7 @@ uint64_t FsiDD::genOpbScomAddr(FsiAddrInfo_t& i_addrInfo, else if( (TARGETING::FSI_MASTER_TYPE_CMFSI == i_addrInfo.accessInfo.type) ) { - FsiChipInfo_t chipinfo = getFsiInfo(i_addrInfo.opbTarg); + FSI::FsiChipInfo_t chipinfo = getFsiInfo(i_addrInfo.opbTarg); if( chipinfo.flagbits.flipPort ) { opbaddr = FSI2OPB_OFFSET_1; @@ -2001,7 +2004,7 @@ uint64_t FsiDD::genOpbScomAddr(FsiAddrInfo_t& i_addrInfo, /** * @brief Initializes the FSI link to allow slave access */ -errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, +errlHndl_t FsiDD::initPort(FSI::FsiChipInfo_t i_fsiInfo, bool& o_enabled) { errlHndl_t l_err = NULL; @@ -2019,10 +2022,11 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, && (i_fsiInfo.master != iv_master) ) { // look up the FSI information for this target's master - FsiChipInfo_t mfsi_info = getFsiInfo(i_fsiInfo.master); + FSI::FsiChipInfo_t mfsi_info = getFsiInfo(i_fsiInfo.master); // append the master's port offset to the slave's - master_offset = getPortOffset( TARGETING::FSI_MASTER_TYPE_MFSI, mfsi_info.port ); + master_offset = FSI::getPortOffset(TARGETING::FSI_MASTER_TYPE_MFSI, + mfsi_info.port ); } // control register is determined by the type of port @@ -2030,7 +2034,8 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, master_ctl_reg += master_offset; // slave offset is determined by which port it is on - uint64_t slave_offset = getPortOffset( i_fsiInfo.type, i_fsiInfo.port ); + uint64_t slave_offset = FSI::getPortOffset( i_fsiInfo.type, + i_fsiInfo.port ); slave_offset += master_offset; // nothing was detected on this port so this is just a NOOP @@ -2056,7 +2061,7 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, //Reset the port to clear up any previous error state // (using idec reg as arbitrary address for lookups) - FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); + FSI::FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); l_err = genFullFsiAddr( addr_info ); if( l_err ) { break; } l_err = errorCleanup( addr_info, FSI::RC_ERROR_IN_MAEB ); @@ -2076,7 +2081,7 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, //Reset the port to clear up any previous error state // (using idec reg as arbitrary address for lookups) - FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); + FSI::FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); l_err = genFullFsiAddr( addr_info ); if( l_err ) { break; } l_err = errorCleanup( addr_info, FSI::RC_ERROR_IN_MAEB ); @@ -2118,11 +2123,11 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, uint32_t tmp_slave_offset = slave_offset; if( TARGETING::FSI_MASTER_TYPE_CMFSI == i_fsiInfo.type ) { - slave_offset |= CMFSI_SLAVE_0; + slave_offset |= FSI::CMFSI_SLAVE_0; } else if( TARGETING::FSI_MASTER_TYPE_MFSI == i_fsiInfo.type ) { - slave_offset |= MFSI_SLAVE_0; + slave_offset |= FSI::MFSI_SLAVE_0; } //Setup the FSI slave to enable HW recovery, lbus ratio @@ -2164,7 +2169,7 @@ errlHndl_t FsiDD::initPort(FsiChipInfo_t i_fsiInfo, // (using idec reg as arbitrary address for lookups) //Note, initial cfam reset should have cleaned up everything // but this makes sure we're in a consistent state - FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); + FSI::FsiAddrInfo_t addr_info( i_fsiInfo.slave, 0x1028 ); l_err = genFullFsiAddr( addr_info ); if( l_err ) { break; } l_err = errorCleanup( addr_info, FSI::RC_ERROR_IN_MAEB ); @@ -2217,12 +2222,13 @@ errlHndl_t FsiDD::initMasterControl(TARGETING::Target* i_master, // append the master port offset to get to te remote master if( i_master != iv_master ) { - FsiChipInfo_t m_info = getFsiInfo(i_master); - ctl_reg += getPortOffset(TARGETING::FSI_MASTER_TYPE_MFSI,m_info.port); + FSI::FsiChipInfo_t m_info = getFsiInfo(i_master); + ctl_reg += FSI::getPortOffset(TARGETING::FSI_MASTER_TYPE_MFSI, + m_info.port); } //Always clear out any pending errors before we start anything - FsiAddrInfo_t addr_info( i_master, 0 ); + FSI::FsiAddrInfo_t addr_info( i_master, 0 ); l_err = genFullFsiAddr(addr_info); if( l_err ) { break; } @@ -2325,7 +2331,7 @@ errlHndl_t FsiDD::initMasterControl(TARGETING::Target* i_master, if( i_master != iv_master ) { // get the data via FSI (scom engine) - FsiAddrInfo_t addr_info( i_master, 0x1028 ); + FSI::FsiAddrInfo_t addr_info( i_master, 0x1028 ); l_err = genFullFsiAddr( addr_info ); if( l_err ) { break; } @@ -2453,45 +2459,6 @@ errlHndl_t FsiDD::initMasterControl(TARGETING::Target* i_master, /** - * @brief Convert a type/port pair into a FSI address offset - */ -uint64_t FsiDD::getPortOffset(TARGETING::FSI_MASTER_TYPE i_type, - uint8_t i_port) -{ - uint64_t offset = 0; - if( TARGETING::FSI_MASTER_TYPE_MFSI == i_type ) - { - switch(i_port) - { - case(0): offset = MFSI_PORT_0; break; - case(1): offset = MFSI_PORT_1; break; - case(2): offset = MFSI_PORT_2; break; - case(3): offset = MFSI_PORT_3; break; - case(4): offset = MFSI_PORT_4; break; - case(5): offset = MFSI_PORT_5; break; - case(6): offset = MFSI_PORT_6; break; - case(7): offset = MFSI_PORT_7; break; - } - } - else if( TARGETING::FSI_MASTER_TYPE_CMFSI == i_type ) - { - switch(i_port) - { - case(0): offset = CMFSI_PORT_0; break; - case(1): offset = CMFSI_PORT_1; break; - case(2): offset = CMFSI_PORT_2; break; - case(3): offset = CMFSI_PORT_3; break; - case(4): offset = CMFSI_PORT_4; break; - case(5): offset = CMFSI_PORT_5; break; - case(6): offset = CMFSI_PORT_6; break; - case(7): offset = CMFSI_PORT_7; break; - } - } - - return offset; -} - -/** * @brief Retrieve the slave enable index */ uint64_t FsiDD::getSlaveEnableIndex( TARGETING::Target* i_master, @@ -2506,7 +2473,7 @@ uint64_t FsiDD::getSlaveEnableIndex( TARGETING::Target* i_master, uint64_t slave_index = MAX_SLAVE_PORTS+i_type; if( i_master != iv_master ) { - FsiChipInfo_t m_info = getFsiInfo(i_master); + FSI::FsiChipInfo_t m_info = getFsiInfo(i_master); if( m_info.type == TARGETING::FSI_MASTER_TYPE_NO_MASTER ) { slave_index = INVALID_SLAVE_INDEX; @@ -2523,9 +2490,9 @@ uint64_t FsiDD::getSlaveEnableIndex( TARGETING::Target* i_master, * @brief Retrieve the connection information needed to access FSI * registers within the given chip target */ -FsiDD::FsiChipInfo_t FsiDD::getFsiInfoFromAttr( TARGETING::Target* i_target ) +FSI::FsiChipInfo_t FsiDD::getFsiInfoFromAttr( TARGETING::Target* i_target ) { - FsiChipInfo_t info; + FSI::FsiChipInfo_t info; info.slave = i_target; using namespace TARGETING; @@ -2665,14 +2632,14 @@ bool FsiDD::isSlavePresent( TARGETING::Target* i_target, uint8_t& o_detected ) { // look up the FSI information for this target - FsiChipInfo_t info = getFsiInfo(i_target); + FSI::FsiChipInfo_t info = getFsiInfo(i_target); return isSlavePresent( info.master, info.type, info.port, o_detected ); } /** * @brief Clear out the error indication so that we can do more FSI ops */ -errlHndl_t FsiDD::errorCleanup( FsiAddrInfo_t& i_addrInfo, +errlHndl_t FsiDD::errorCleanup( FSI::FsiAddrInfo_t& i_addrInfo, FSI::FSIReasonCode i_errType ) { errlHndl_t l_err = NULL; @@ -2736,7 +2703,7 @@ errlHndl_t FsiDD::errorCleanup( FsiAddrInfo_t& i_addrInfo, { // 0=Bridge: General reset data = 0x80000000; - mesrb0_reg = MFSI_CONTROL_REG | FSI_MESRB0_1D0; + mesrb0_reg = FSI::MFSI_CONTROL_REG | FSI_MESRB0_1D0; l_err = write( iv_master, mesrb0_reg, &data ); if(l_err) break; } @@ -2761,17 +2728,17 @@ errlHndl_t FsiDD::errorCleanup( FsiAddrInfo_t& i_addrInfo, //Trace some values for FFDC in case this cleanup // didn't really work uint32_t grabregs[] = { - MFSI_CONTROL_REG|FSI_MSIEP0_030, - CMFSI_CONTROL_REG|FSI_MSIEP0_030, - MFSI_CONTROL_REG|FSI_MAEB_070, - CMFSI_CONTROL_REG|FSI_MAEB_070 + FSI::MFSI_CONTROL_REG|FSI_MSIEP0_030, + FSI::CMFSI_CONTROL_REG|FSI_MSIEP0_030, + FSI::MFSI_CONTROL_REG|FSI_MAEB_070, + FSI::CMFSI_CONTROL_REG|FSI_MAEB_070 }; for( size_t r = 0; r < (sizeof(grabregs)/sizeof(grabregs[0])); r++ ) { l_err = read( i_addrInfo.accessInfo.master, - MFSI_CONTROL_REG|FSI_MSIEP0_030, &data ); + FSI::MFSI_CONTROL_REG|FSI_MSIEP0_030, &data ); if(l_err) break; TRACFCOMP( g_trac_fsi, "errorCleanup> %.8X->%.6X = %.8X", TARGETING::get_huid(i_addrInfo.accessInfo.master), grabregs[r], data ); } @@ -2786,9 +2753,9 @@ errlHndl_t FsiDD::errorCleanup( FsiAddrInfo_t& i_addrInfo, /** * @brief Check for FSI errors anywhere in the system */ -errlHndl_t FsiDD::checkForErrors( FsiChipInfo_t& i_chipInfo ) +errlHndl_t FsiDD::checkForErrors( FSI::FsiChipInfo_t& i_chipInfo ) { - FsiAddrInfo_t addr_info( i_chipInfo.slave, 0xFFFFFFFF ); + FSI::FsiAddrInfo_t addr_info( i_chipInfo.slave, 0xFFFFFFFF ); errlHndl_t errhdl = genFullFsiAddr( addr_info ); if( !errhdl ) { @@ -2801,7 +2768,7 @@ errlHndl_t FsiDD::checkForErrors( FsiChipInfo_t& i_chipInfo ) /** * @brief Check for FSI errors anywhere in the system */ -errlHndl_t FsiDD::checkForErrors( FsiAddrInfo_t& i_addrInfo ) +errlHndl_t FsiDD::checkForErrors( FSI::FsiAddrInfo_t& i_addrInfo ) { errlHndl_t l_err = NULL; @@ -2910,7 +2877,7 @@ errlHndl_t FsiDD::verifyPresent( TARGETING::Target* i_target ) { TRACFCOMP( g_trac_fsi, "FsiDD::verifyPresent> Requested target was never detected during FSI Init : i_target=%.8X", TARGETING::get_huid(i_target) ); - FsiChipInfo_t chipinfo = getFsiInfo(i_target); + FSI::FsiChipInfo_t chipinfo = getFsiInfo(i_target); /*@ * @errortype @@ -2973,14 +2940,14 @@ errlHndl_t FsiDD::verifyPresent( TARGETING::Target* i_target ) * @brief Retrieve the connection information needed to access FSI * registers within the given chip target */ -FsiDD::FsiChipInfo_t FsiDD::getFsiInfo( TARGETING::Target* i_target ) +FSI::FsiChipInfo_t FsiDD::getFsiInfo( TARGETING::Target* i_target ) { - FsiChipInfo_t info; + FSI::FsiChipInfo_t info; mutex_lock(&iv_dataMutex); // Check if we have a cached version first - std::map<TARGETING::Target*,FsiChipInfo_t>::iterator itr + std::map<TARGETING::Target*,FSI::FsiChipInfo_t>::iterator itr = iv_fsiInfoMap.find(i_target); if( itr != iv_fsiInfoMap.end() ) { @@ -3005,7 +2972,7 @@ FsiDD::FsiChipInfo_t FsiDD::getFsiInfo( TARGETING::Target* i_target ) void FsiDD::getFsiLinkInfo( TARGETING::Target* i_slave, FSI::FsiLinkInfo_t& o_info ) { - FsiAddrInfo_t addr_info( i_slave, 0x0 ); + FSI::FsiAddrInfo_t addr_info( i_slave, 0x0 ); errlHndl_t tmp_err = genFullFsiAddr( addr_info ); if( tmp_err ) { @@ -3031,8 +2998,8 @@ void FsiDD::getFsiLinkInfo( TARGETING::Target* i_slave, o_info.baseAddr = addr_info.absAddr; if( addr_info.opbTarg != iv_master ) { - FsiChipInfo_t mfsi_info = getFsiInfo(addr_info.accessInfo.master); - o_info.baseAddr |= getPortOffset(mfsi_info.type,mfsi_info.port); + FSI::FsiChipInfo_t mfsi_info = getFsiInfo(addr_info.accessInfo.master); + o_info.baseAddr |= FSI::getPortOffset(mfsi_info.type,mfsi_info.port); } } diff --git a/src/usr/fsi/fsidd.H b/src/usr/fsi/fsidd.H index 999b38d02..b794b4273 100644 --- a/src/usr/fsi/fsidd.H +++ b/src/usr/fsi/fsidd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,6 +35,8 @@ #include <usr/fsi/fsiif.H> #include <usr/fsi/fsi_reasoncodes.H> #include <map> +#include "fsi_common.H" + namespace FSI { class UdPresence; } /** @file fsidd.H @@ -190,70 +192,6 @@ class FsiDD size_t i_buflen = 4); /** - * Common id to identify a FSI position to use in error logs and traces - */ - union FsiLinkId_t - { - uint32_t id; - struct - { - uint8_t node; ///< Physical Node of FSI Master processor - uint8_t proc; ///< Physical Position of FSI Master processor - uint8_t type; ///< FSI Master type (FSI_MASTER_TYPE) - uint8_t port; ///< Slave link/port number - }; - }; - - /** - * @brief Structure which defines info necessary to access a chip via FSI - */ - struct FsiChipInfo_t - { - TARGETING::Target* slave; //< FSI Slave chip - TARGETING::Target* master; ///< FSI Master - TARGETING::FSI_MASTER_TYPE type; ///< Master or Cascaded Master - uint8_t port; ///< Which port is this chip hanging off of - uint8_t cascade; ///< Slave cascade position - union { - TARGETING::FsiOptionFlags flagbits; ///< Special flags - uint16_t flags; ///< Special flags - }; - FsiLinkId_t linkid; ///< Id for traces and error logs - - FsiChipInfo_t() : - slave(NULL), master(NULL), - type(TARGETING::FSI_MASTER_TYPE_NO_MASTER), - port(UINT8_MAX), cascade(0), flags(0) - { linkid.id = 0; }; - }; - - /** - * @brief Holds a set of addressing information to describe the - * current FSI operation - */ - struct FsiAddrInfo_t { - TARGETING::Target* fsiTarg; ///< Target of FSI operation - TARGETING::Target* opbTarg; ///< OPB control reg target - uint32_t relAddr; ///< Input FSI address (relative to fsiTarg) - uint32_t absAddr; ///< Absolute FSI address (relative to opbTarg) - FsiChipInfo_t accessInfo; ///< FSI Access Info - - /** Input Arg Constructor */ - FsiAddrInfo_t( TARGETING::Target* i_target, - uint64_t i_address ) : - fsiTarg(i_target), opbTarg(NULL), - relAddr(i_address), absAddr(UINT32_MAX) - {}; - - private: - /** Default Constructor is not allowed */ - FsiAddrInfo_t() : - fsiTarg(NULL), opbTarg(NULL), - relAddr(UINT32_MAX),absAddr(UINT32_MAX) - {}; - }; - - /** * @brief Performs an FSI Read Operation * * @param[in] i_addrInfo Addressing information @@ -262,7 +200,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t read(FsiAddrInfo_t& i_addrInfo, + errlHndl_t read(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* o_buffer, size_t i_buflen = 4); @@ -275,7 +213,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t write(FsiAddrInfo_t& i_addrInfo, + errlHndl_t write(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* i_buffer, size_t i_buflen = 4); @@ -298,7 +236,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t initPort(FsiChipInfo_t i_fsiInfo, + errlHndl_t initPort(FSI::FsiChipInfo_t i_fsiInfo, bool& o_enabled); /** @@ -310,7 +248,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t handleOpbErrors(FsiAddrInfo_t& i_addrInfo, + errlHndl_t handleOpbErrors(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t i_opbStatAddr, uint32_t i_opbStatData); @@ -323,7 +261,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t pollForComplete(FsiAddrInfo_t& i_addrInfo, + errlHndl_t pollForComplete(FSI::FsiAddrInfo_t& i_addrInfo, uint32_t* o_readData); /** @@ -336,7 +274,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t genFullFsiAddr(FsiAddrInfo_t& io_addrInfo); + errlHndl_t genFullFsiAddr(FSI::FsiAddrInfo_t& io_addrInfo); /** * @brief Generate a valid SCOM address to access the OPB, this will @@ -349,67 +287,11 @@ class FsiDD * * @return uint64_t Fully qualified OPB SCOM address */ - uint64_t genOpbScomAddr(FsiAddrInfo_t& i_addrInfo, + uint64_t genOpbScomAddr(FSI::FsiAddrInfo_t& i_addrInfo, uint64_t i_opbOffset); /** - * @brief Convert a type/port pair into a FSI address offset - * - * @param[in] i_type Type of FSI interface - * @param[in] i_port FSI link number - * @return uint64_t FSI address offset - */ - uint64_t getPortOffset(TARGETING::FSI_MASTER_TYPE i_type, - uint8_t i_port); - - - /** - * FSI Address Space - */ - enum FsiAddressSpace { - // Master control registers - CMFSI_CONTROL_REG = 0x003000, /**< cMFSI Control Register */ - MFSI_CONTROL_REG = 0x003400, /**< MFSI Control Register */ - - // cMFSI Ports (32KB each) - CMFSI_PORT_0 = 0x040000, /**< cMFSI port 0 */ - CMFSI_PORT_1 = 0x048000, /**< cMFSI port 1 */ - CMFSI_PORT_2 = 0x050000, /**< cMFSI port 2 */ - CMFSI_PORT_3 = 0x058000, /**< cMFSI port 3 */ - CMFSI_PORT_4 = 0x060000, /**< cMFSI port 4 */ - CMFSI_PORT_5 = 0x068000, /**< cMFSI port 5 */ - CMFSI_PORT_6 = 0x070000, /**< cMFSI port 6 */ - CMFSI_PORT_7 = 0x078000, /**< cMFSI port 7 */ - CMFSI_PORT_MASK = 0x078000, /**< Mask to look for a valid cMFSI port */ - - // Offsets to cascaded slaves within a cMFSI port - CMFSI_SLAVE_0 = 0x000000, /**< cMFSI - Slave 0 */ - CMFSI_SLAVE_1 = 0x002000, /**< cMFSI - Slave 1 */ - CMFSI_SLAVE_2 = 0x004000, /**< cMFSI - Slave 2 */ - CMFSI_SLAVE_3 = 0x006000, /**< cMFSI - Slave 3 */ - - // MFSI Ports (512KB each) - MFSI_PORT_LOCAL = 0x000000, /**< Local master (used for local cMFSI) */ - MFSI_PORT_0 = 0x080000, /**< MFSI port 0 */ - MFSI_PORT_1 = 0x100000, /**< MFSI port 1 */ - MFSI_PORT_2 = 0x180000, /**< MFSI port 2 */ - MFSI_PORT_3 = 0x200000, /**< MFSI port 3 */ - MFSI_PORT_4 = 0x280000, /**< MFSI port 4 */ - MFSI_PORT_5 = 0x300000, /**< MFSI port 5 */ - MFSI_PORT_6 = 0x380000, /**< MFSI port 6 */ - MFSI_PORT_7 = 0x400000, /**< MFSI port 7 */ - MFSI_PORT_MASK = 0x780000, /**< Mask to look for a valid MFSI port */ - - // Offsets to cascaded slaves within a MFSI port - MFSI_SLAVE_0 = 0x000000, /**< MFSI - Slave 0 */ - MFSI_SLAVE_1 = 0x020000, /**< MFSI - Slave 1 */ - MFSI_SLAVE_2 = 0x040000, /**< MFSI - Slave 2 */ - MFSI_SLAVE_3 = 0x060000, /**< MFSI - Slave 3 */ - }; - - - /** * PIB2OPB Registers */ enum Pib2OpbRegisters { @@ -501,10 +383,10 @@ class FsiDD */ uint64_t getControlReg(TARGETING::FSI_MASTER_TYPE i_type) { - uint64_t ctl_reg = MFSI_CONTROL_REG; + uint64_t ctl_reg = FSI::MFSI_CONTROL_REG; if( TARGETING::FSI_MASTER_TYPE_CMFSI == i_type ) { - ctl_reg = CMFSI_CONTROL_REG; + ctl_reg = FSI::CMFSI_CONTROL_REG; } return ctl_reg; }; @@ -526,7 +408,7 @@ class FsiDD * * @return FsiChipInfo_t FSI Chip Information */ - FsiChipInfo_t getFsiInfo( TARGETING::Target* i_target ); + FSI::FsiChipInfo_t getFsiInfo( TARGETING::Target* i_target ); /** * @brief Clear out the error indication so that we can do more FSI ops @@ -536,7 +418,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t errorCleanup( FsiAddrInfo_t& i_addrInfo, + errlHndl_t errorCleanup( FSI::FsiAddrInfo_t& i_addrInfo, FSI::FSIReasonCode i_errType ); /** @@ -546,7 +428,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t checkForErrors( FsiChipInfo_t& i_chipInfo ); + errlHndl_t checkForErrors( FSI::FsiChipInfo_t& i_chipInfo ); /** * @brief Check for FSI errors anywhere in the system @@ -555,7 +437,7 @@ class FsiDD * * @return errlHndl_t NULL on success */ - errlHndl_t checkForErrors( FsiAddrInfo_t& i_addrInfo ); + errlHndl_t checkForErrors( FSI::FsiAddrInfo_t& i_addrInfo ); /** * @brief Verify that the slave target was detected @@ -574,7 +456,7 @@ class FsiDD * * @return FsiChipInfo_t FSI Chip Information */ - FsiChipInfo_t getFsiInfoFromAttr( TARGETING::Target* i_target ); + FSI::FsiChipInfo_t getFsiInfoFromAttr( TARGETING::Target* i_target ); /******************************************** @@ -616,7 +498,7 @@ class FsiDD * Cache of FSI connection information gleaned from attributes * Indexed by Target*, returns FsiChipInfo_t */ - std::map<TARGETING::Target*,FsiChipInfo_t> iv_fsiInfoMap; + std::map<TARGETING::Target*,FSI::FsiChipInfo_t> iv_fsiInfoMap; /** * Mutex to protect the internal maps diff --git a/src/usr/fsi/makefile b/src/usr/fsi/makefile index 437d99f35..df88c4fb5 100644 --- a/src/usr/fsi/makefile +++ b/src/usr/fsi/makefile @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2011,2014 +# Contributors Listed Below - COPYRIGHT 2011,2017 +# [+] International Business Machines Corp. +# # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,7 +28,9 @@ MODULE = fsi OBJS += fsidd.o OBJS += fsipres.o OBJS += errlud_fsi.o +OBJS += fsi_common.o SUBDIRS += test.d +SUBDIRS += runtime.d include ${ROOTPATH}/config.mk diff --git a/src/usr/fsi/runtime/makefile b/src/usr/fsi/runtime/makefile new file mode 100644 index 000000000..10d4d5ae3 --- /dev/null +++ b/src/usr/fsi/runtime/makefile @@ -0,0 +1,35 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/fsi/runtime/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +HOSTBOOT_RUNTIME = 1 +ROOTPATH = ../../../.. +MODULE = fsi_rt + +OBJS += rt_fsi.o +OBJS += fsi_common.o + +EXTRAINCDIR += ${ROOTPATH}/src/usr/fsi + +VPATH += ../ +include $(ROOTPATH)/config.mk diff --git a/src/usr/fsi/runtime/rt_fsi.C b/src/usr/fsi/runtime/rt_fsi.C new file mode 100644 index 000000000..75103cc4b --- /dev/null +++ b/src/usr/fsi/runtime/rt_fsi.C @@ -0,0 +1,476 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/fsi/runtime/rt_fsi.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <stdlib.h> +#include <runtime/rt_targeting.H> +#include <runtime/interface.h> + +#include <targeting/common/targetservice.H> + +#include <fsi/fsiif.H> +#include "rt_fsi.H" +#include <util/misc.H> +#include <fsi/fsi_reasoncodes.H> + +// Trace definition +trace_desc_t* g_trac_fsi = NULL; +TRAC_INIT(&g_trac_fsi, FSI_COMP_NAME, KILOBYTE); // 1K + + +/** + * @brief Retrieve some FSI attribute information + */ +void FSI::getFsiLinkInfo( TARGETING::Target* i_slave, + FSI::FsiLinkInfo_t& o_info ) +{ + Singleton<RtFsi>::instance().getFsiLinkInfo( i_slave,o_info ); +} + +/* Protected Methods */ + +/** + * @brief Constructor + */ +RtFsi::RtFsi() +:iv_master(NULL) +,iv_useAlt(0) +{ + TRACFCOMP(g_trac_fsi, "RtFsi::RtFsi()>"); + + // save away the master processor target + TARGETING::TargetService& targetService = TARGETING::targetService(); + iv_master = NULL; + targetService.masterProcChipTargetHandle( iv_master ); + TRACFCOMP(g_trac_fsi, "Master=%.8X",TARGETING::get_huid(iv_master)); + +} + +/** + * @brief Destructor + */ +RtFsi::~RtFsi() +{ + +} + +/* Public Methods */ + +/** + * @brief Retrieve the connection information needed to access FSI + * registers within the given chip target + */ +FSI::FsiChipInfo_t RtFsi::getFsiInfo( TARGETING::Target* i_target ) +{ + FSI::FsiChipInfo_t info; + + mutex_lock(&iv_dataMutex); + + // Check if we have a cached version first + std::map<TARGETING::Target*,FSI::FsiChipInfo_t>::iterator itr + = iv_fsiInfoMap.find(i_target); + if( itr != iv_fsiInfoMap.end() ) + { + info = itr->second; + } + else + { + // fetch the data from the attributes + info = getFsiInfoFromAttr( i_target ); + // then cache it for next time + iv_fsiInfoMap[i_target] = info; + } + + mutex_unlock(&iv_dataMutex); + + return info; +} + +/** + * @brief Retrieve some FSI attribute information + */ +void RtFsi::getFsiLinkInfo( TARGETING::Target* i_slave, + FSI::FsiLinkInfo_t& o_info ) +{ + FSI::FsiAddrInfo_t addr_info( i_slave, 0x0 ); + errlHndl_t tmp_err = RtFsi::genFullFsiAddr( addr_info ); + if( tmp_err ) + { + TRACFCOMP( g_trac_fsi, "Error getting FsiLinkInfo fo %.8X", + TARGETING::get_huid(i_slave)); + delete tmp_err; + return; + } + + o_info.master = addr_info.accessInfo.master; + o_info.type = addr_info.accessInfo.type; + o_info.link = addr_info.accessInfo.port; + o_info.cascade = addr_info.accessInfo.cascade; + o_info.mPort = 0; + if( addr_info.accessInfo.master && + (addr_info.accessInfo.master != iv_master) && + (getFsiInfo(addr_info.accessInfo.master).flagbits.flipPort) ) + { + o_info.mPort = 1; + } + + // if this chip is not off the master, need to include its + // master's offset oo + o_info.baseAddr = addr_info.absAddr; + if( addr_info.opbTarg != iv_master ) + { + FSI::FsiChipInfo_t mfsi_info = getFsiInfo(addr_info.accessInfo.master); + o_info.baseAddr |= FSI::getPortOffset(mfsi_info.type,mfsi_info.port); + } +} + +/** + * @brief Generate a complete FSI address based on the target and the + * FSI offset within that target + */ +errlHndl_t RtFsi::genFullFsiAddr(FSI::FsiAddrInfo_t& io_addrInfo) +{ + errlHndl_t l_err = NULL; + + //default to using the master chip for OPB XSCOM ops + io_addrInfo.opbTarg = iv_master; + + //start off with the addresses being the same + io_addrInfo.absAddr = io_addrInfo.relAddr; + + //pull the FSI info out for this target + io_addrInfo.accessInfo = getFsiInfo( io_addrInfo.fsiTarg ); + + //target matches master so the address is correct as-is + if( io_addrInfo.fsiTarg == iv_master ) + { + return NULL; + } + + TRACFCOMP( g_trac_fsi, "target=%.8X : Link Id=%.8X", + TARGETING::get_huid(io_addrInfo.fsiTarg), + io_addrInfo.accessInfo.linkid.id ); + + //FSI master is the master proc, find the port + if( io_addrInfo.accessInfo.master == iv_master ) + { + //append the appropriate offset + io_addrInfo.absAddr += FSI::getPortOffset(io_addrInfo.accessInfo.type, + io_addrInfo.accessInfo.port); + } + //verify this target has a valid FSI master + else if( TARGETING::FSI_MASTER_TYPE_CMFSI != io_addrInfo.accessInfo.type ) + { + TRACFCOMP( g_trac_fsi,"target=%.8X : Master Type isn't supported = %d", + TARGETING::get_huid(io_addrInfo.fsiTarg), + io_addrInfo.accessInfo.type ); + /*@ + * @errortype + * @moduleid FSI::MOD_RTFSI_GENFULLFSIADDR + * @reasoncode FSI::RC_FSI_NOT_SUPPORTED + * @userdata1 Target of FSI Operation + * @userdata2[32:39] Physical Node of FSI Master processor + * @userdata2[40:47] Physical Position of FSI Master processor + * @userdata2[48:55] FSI Master type (0=MFSI,1=CMFSI,2=NO_MASTER) + * @userdata2[56:63] Slave link/port number + * @devdesc FsiDD::genFullFsiAddr> Master Type is not supported + * @custdesc A problem occurred during the + * IPL of the system. + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + FSI::MOD_RTFSI_GENFULLFSIADDR, + FSI::RC_FSI_NOT_SUPPORTED, + TARGETING::get_huid(io_addrInfo.fsiTarg), + io_addrInfo.accessInfo.linkid.id, + true /*SW error*/); + l_err->collectTrace(FSI_COMP_NAME); + return l_err; + } + //target is behind another proc + else + { + //append the CMFSI portion first + io_addrInfo.absAddr += FSI::getPortOffset(io_addrInfo.accessInfo.type, + io_addrInfo.accessInfo.port); + + //find this port's master and then get its port information + FSI::FsiChipInfo_t mfsi_info = + getFsiInfo(io_addrInfo.accessInfo.master); + + //check for invalid topology + if( mfsi_info.master != iv_master ) + { + TRACFCOMP( g_trac_fsi, + "target=%.8X : master=%.8X : master's master=%.8X :" + " Cannot chain 2 masters", + TARGETING::get_huid(io_addrInfo.fsiTarg), + TARGETING::get_huid(io_addrInfo.accessInfo.master), + TARGETING::get_huid(mfsi_info.master), + io_addrInfo.accessInfo.type ); + /*@ + * @errortype + * @moduleid FSI::MOD_RTFSI_GENFULLFSIADDR + * @reasoncode FSI::RC_INVALID_FSI_PATH_1 + * @userdata1[0:31] Target of FSI Operation + * @userdata1[32:63] Target's FSI Master Chip + * @userdata2[0:7] Physical Node of FSI Master processor + * [target's master] + * @userdata2[8:15] Physical Position of FSI Master processor + * [target's master] + * @userdata2[16:23] FSI Master type (0=MFSI,1=CMFSI,2=NO_MASTER) + * [target's master] + * @userdata2[24:31] Slave link/port number [target's master] + * @userdata2[32:39] Physical Node of FSI Master processor + * [master's master] + * @userdata2[40:47] Physical Position of FSI Master processor + * [master's master] + * @userdata2[48:55] FSI Master type (0=MFSI,1=CMFSI,2=NO_MASTER) + * [master's master] + * @userdata2[56:63] Slave link/port number [master's master] + * @devdesc FsiDD::genFullFsiAddr> Cannot chain 2 masters + * @custdesc A problem occurred during the + * IPL of the system. + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + FSI::MOD_RTFSI_GENFULLFSIADDR, + FSI::RC_INVALID_FSI_PATH_1, + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(io_addrInfo.fsiTarg), + TARGETING::get_huid(io_addrInfo.accessInfo.master)), + TWO_UINT32_TO_UINT64( + io_addrInfo.accessInfo.linkid.id, + mfsi_info.linkid.id), + true /*SW error*/); + l_err->collectTrace(FSI_COMP_NAME); + return l_err; + } + else if( TARGETING::FSI_MASTER_TYPE_MFSI != mfsi_info.type ) + { + TRACFCOMP( g_trac_fsi, "target=%.8X:master=%.8X, type=%d, port=%d", + TARGETING::get_huid(io_addrInfo.fsiTarg), + TARGETING::get_huid(io_addrInfo.accessInfo.master), + io_addrInfo.accessInfo.type, + io_addrInfo.accessInfo.port ); + TRACFCOMP( g_trac_fsi, + "Master: target=%.8X : master=%.8X, type=%d, port=%d", + TARGETING::get_huid(io_addrInfo.accessInfo.master), + TARGETING::get_huid(mfsi_info.master), + mfsi_info.type, mfsi_info.port ); + /*@ + * @errortype + * @moduleid FSI::MOD_RTFSI_GENFULLFSIADDR + * @reasoncode FSI::RC_INVALID_FSI_PATH_2 + * @userdata1[0:31] Target of FSI Operation + * @userdata1[32:63] Target's FSI Master Chip + * @userdata2[0:7] Physical Node of FSI Master processor + * [target's master] + * @userdata2[8:15] Physical Position of FSI Master processor + * [target's master] + * @userdata2[16:23] FSI Master type (0=MFSI,1=CMFSI,2=NO_MASTER) + * [target's master] + * @userdata2[24:31] Slave link/port number [target's master] + * @userdata2[32:39] Physical Node of FSI Master processor + * [master's master] + * @userdata2[40:47] Physical Position of FSI Master processor + * [master's master] + * @userdata2[48:55] FSI Master type (0=MFSI,1=CMFSI,2=NO_MASTER) + * [master's master] + * @userdata2[56:63] Slave link/port number [master's master] + * @devdesc FsiDD::genFullFsiAddr> Invalid master type for the + * target's master + * @custdesc A problem occurred during the + * IPL of the system. + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + FSI::MOD_RTFSI_GENFULLFSIADDR, + FSI::RC_INVALID_FSI_PATH_2, + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(io_addrInfo.fsiTarg), + TARGETING::get_huid(io_addrInfo.accessInfo.master)), + TWO_UINT32_TO_UINT64( + io_addrInfo.accessInfo.linkid.id, + mfsi_info.linkid.id), + true /*SW error*/); + l_err->collectTrace(FSI_COMP_NAME); + return l_err; + } + + // If powerbus is alive, we can use the local master + // + if( Util::isSimicsRunning() + && (mfsi_info.flagbits.flipPort) ) + { + //@fixme - RTC:99928 : Simics is wired wrong on Brazos + // so always use indirect path when talking through + // a flipped cmfsi port + + //using the master chip so we need to append the MFSI port + io_addrInfo.absAddr += FSI::getPortOffset(mfsi_info.type, + mfsi_info.port); + } + else if( (io_addrInfo.accessInfo.master)-> + getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useXscom + ) + { + //use the local proc to drive the operation instead of + // going through the master proc indirectly + io_addrInfo.opbTarg = io_addrInfo.accessInfo.master; + // Note: no need to append the MFSI port since it is now local + + // set a flag to flip the OPB port if this slave's master + // is reversed and it isn't the acting master + if( io_addrInfo.accessInfo.master != iv_master ) + { + io_addrInfo.accessInfo.flagbits.flipPort + = mfsi_info.flagbits.flipPort; + } + } + else + { + //using the master chip so we need to append the MFSI port + io_addrInfo.absAddr += FSI::getPortOffset(mfsi_info.type, + mfsi_info.port); + } + } + + return NULL; +} + +/** + * @brief Retrieve the connection information needed to access FSI + * registers within the given chip target + */ +FSI::FsiChipInfo_t RtFsi::getFsiInfoFromAttr( TARGETING::Target* i_target ) +{ + FSI::FsiChipInfo_t info; + info.slave = i_target; + + using namespace TARGETING; + + EntityPath epath; + + if( (i_target != NULL) && + i_target->tryGetAttr<ATTR_FSI_MASTER_TYPE>(info.type) ) + { + if( info.type != FSI_MASTER_TYPE_NO_MASTER ) + { + if( !iv_useAlt + && i_target->tryGetAttr<ATTR_FSI_MASTER_CHIP>(epath) ) + { + info.master = targetService().toTarget(epath); + + if( i_target->tryGetAttr<ATTR_FSI_MASTER_PORT>(info.port) ) + { + if( i_target->tryGetAttr<ATTR_FSI_SLAVE_CASCADE> + (info.cascade) ) + { + if( !i_target->tryGetAttr<ATTR_FSI_OPTION_FLAGS> + (info.flagbits) ) + { + info.master = NULL; + } + } + else + { + info.master = NULL; + } + } + else + { + info.master = NULL; + } + } + else if( iv_useAlt + && i_target->tryGetAttr<ATTR_ALTFSI_MASTER_CHIP>(epath) ) + { + TRACFCOMP(g_trac_fsi,"Using alt path for %.8X",i_target); + info.master = targetService().toTarget(epath); + + if( i_target->tryGetAttr<ATTR_ALTFSI_MASTER_PORT>(info.port) ) + { + if( i_target->tryGetAttr<ATTR_FSI_SLAVE_CASCADE> + (info.cascade) ) + { + if( !i_target->tryGetAttr<ATTR_FSI_OPTION_FLAGS> + (info.flagbits) ) + { + info.master = NULL; + } + } + else + { + info.master = NULL; + } + } + else + { + info.master = NULL; + } + } + else + { + info.master = NULL; + } + } + } + + + if( (info.master == NULL) + || (info.type == FSI_MASTER_TYPE_NO_MASTER) + || (info.port == UINT8_MAX) ) + { + info.master = NULL; + info.type = FSI_MASTER_TYPE_NO_MASTER; + info.port = UINT8_MAX; + info.cascade = 0; + info.flags = 0; + info.linkid.id = 0; + } + else + { + TARGETING::EntityPath master_phys; + if( info.master->tryGetAttr<TARGETING::ATTR_PHYS_PATH>(master_phys) ) + { + info.linkid.node = + master_phys.pathElementOfType(TARGETING::TYPE_NODE).instance; + info.linkid.proc = + master_phys.pathElementOfType(TARGETING::TYPE_PROC).instance; + info.linkid.type = static_cast<uint8_t>(info.type); + info.linkid.port = info.port; + } + } + + TRACDCOMP( g_trac_fsi, + "getFsiInfoFromAttr> i_target=%.8X : master=%.8X, type=%X", + TARGETING::get_huid(i_target), + TARGETING::get_huid(info.master), info.type ); + TRACDCOMP( g_trac_fsi, + "getFsiInfoFromAttr> port=%X, cascade=%X, flags=%X, linkid=%.8X", + info.port, info.cascade, info.flags, info.port ); + return info; +} + + diff --git a/src/usr/fsi/runtime/rt_fsi.H b/src/usr/fsi/runtime/rt_fsi.H new file mode 100644 index 000000000..d8efa6f56 --- /dev/null +++ b/src/usr/fsi/runtime/rt_fsi.H @@ -0,0 +1,118 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/fsi/runtime/rt_fsi.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef _RT_FSI_H_ +#define _RT_FSI_H_ + +#include <fsi/fsiif.H> +#include <map> +#include "fsi_common.H" + +class RtFsi +{ + + public: + /** + * @brief Retrieve some FSI attribute information + * + * @param[in] i_slave Slave Chip Target to query + * @param[out] o_info FSI Link Information + * + */ + void getFsiLinkInfo( TARGETING::Target* i_slave, + FSI::FsiLinkInfo_t& o_info); + + protected: + /** + * @brief Constructor + */ + RtFsi(); + + /** + * @brief Destructor + */ + ~RtFsi(); + + /** + * @brief Figure out the optimal OPB Master to use and generate a + * complete FSI address relative to that master based on the target + * and the FSI offset within that target + * + * @param[inout] io_addrInfo FSI addressing information, + * expects fsiTarg and relAddr to be populated as input + * + * @return errlHndl_t NULL on success + */ + errlHndl_t genFullFsiAddr(FSI::FsiAddrInfo_t& io_addrInfo); + + + /** + * @brief Retrieve the connection information needed to access FSI + * registers within the given chip target + * + * @param[in] i_target Target of FSI Slave to access + * + * @return FsiChipInfo_t FSI Chip Information + */ + FSI::FsiChipInfo_t getFsiInfo( TARGETING::Target* i_target ); + + /** + * @brief Retrieve the connection information needed to access FSI + * registers within the given chip target from attributes + * + * @param[in] i_target Target of FSI Slave to access + * + * @return FsiChipInfo_t FSI Chip Information + */ + FSI::FsiChipInfo_t getFsiInfoFromAttr( TARGETING::Target* i_target ); + + + /************************ + * VARIABLES + ************************/ + + /** + * Master processor target + */ + TARGETING::Target* iv_master; + + /** + * Cache of FSI connection information gleaned from attributes + * Indexed by Target*, returns FsiChipInfo_t + */ + std::map<TARGETING::Target*,FSI::FsiChipInfo_t> iv_fsiInfoMap; + + /** + * Mutex to protect the internal maps + */ + mutex_t iv_dataMutex; + + /** + * Using alternate master + */ + uint8_t iv_useAlt; + +}; + +#endif diff --git a/src/usr/pnor/runtime/rt_pnor.C b/src/usr/pnor/runtime/rt_pnor.C index 33c1a2439..5d3ec698a 100644 --- a/src/usr/pnor/runtime/rt_pnor.C +++ b/src/usr/pnor/runtime/rt_pnor.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* Contributors Listed Below - COPYRIGHT 2014,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -79,6 +79,14 @@ errlHndl_t PNOR::getSideInfo( PNOR::SideId i_side, return Singleton<RtPnor>::instance().getSideInfo(i_side,o_info); } +/** + * @brief Clear pnor section + */ +errlHndl_t PNOR::clearSection(PNOR::SectionId i_section) +{ + return Singleton<RtPnor>::instance().clearSection(i_section); +} + /****************Public Methods***************************/ /** * STATIC @@ -723,3 +731,104 @@ errlHndl_t RtPnor::getSideInfo( PNOR::SideId i_side, return l_err; } + + +errlHndl_t RtPnor::clearSection(PNOR::SectionId i_section) +{ + TRACFCOMP(g_trac_pnor, "RtPnor::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"RtPnor::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 = + (PNOR::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[PNOR::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; + } + + //find proc id + uint64_t l_procId; + TARGETING::Target* l_masterProc = NULL; + TARGETING::targetService().masterProcChipTargetHandle( l_masterProc ); + l_errl = RT_TARG::getRtTarget (l_masterProc, l_procId); + if (l_errl) + { + TRACFCOMP(g_trac_pnor, "RtPnor::clearSection: getRtTarget failed"); + break; + } + + // 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_procId,i_section, + (l_address + i), l_chipSelect, + false, l_buf); + if (l_errl) + { + TRACFCOMP( g_trac_pnor, ERR_MRK"RtPnor::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/runtime/rt_pnor.H b/src/usr/pnor/runtime/rt_pnor.H index 54c1ac9af..e2f390afd 100644 --- a/src/usr/pnor/runtime/rt_pnor.H +++ b/src/usr/pnor/runtime/rt_pnor.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -77,6 +77,15 @@ class RtPnor errlHndl_t getSideInfo( PNOR::SideId i_side, PNOR::SideInfo_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 |