Example #1
0
//------------------------------------------------------------------------------
// function: utility subroutine which writes AND/OR mask register to
//           set/clear desired bits
// parameters: i_target        => target
//             i_active_mask   => bit mask defining active bits to act on
//             i_set_not_clear => define desired operation
//                                (true=set, false=clear)
//             i_and_mask_addr => SCOM address for AND mask register
//             i_or_mask_addr  => SCOM address for OR mask register
// returns: FAPI_RC_SUCCESS if operation was successful, else error
//------------------------------------------------------------------------------
fapi::ReturnCode proc_fab_iovalid_write_active_mask(
    const fapi::Target& i_target,
    ecmdDataBufferBase& i_active_mask,
    bool i_set_not_clear,
    const uint32_t& i_and_mask_addr,
    const uint32_t& i_or_mask_addr)
{
    // data buffer to hold final bit mask
    ecmdDataBufferBase mask(64);

    // return codes
    uint32_t rc_ecmd = 0;
    fapi::ReturnCode rc;

    // mark function entry
    FAPI_DBG("proc_fab_iovalid_write_active_mask: Start");

    do
    {
        // copy input mask
        rc_ecmd = i_active_mask.copy(mask);
        // form final mask based on desired operation (set/clear)
        if (!i_set_not_clear)
        {
            FAPI_DBG("proc_fab_iovalid_write_active_mask: Inverting active mask");
            rc_ecmd |= mask.invert();
        }

        // check return code from buffer manipulation operations
        if (rc_ecmd)
        {
            FAPI_ERR("proc_fab_iovalid_write_active_mask: Error 0x%x setting up active mask data buffer",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }

        // write register (use OR mask address for set operation,
        // AND mask address for clear operation)
        rc = fapiPutScom(i_target,
                         i_set_not_clear?i_or_mask_addr:i_and_mask_addr,
                         mask);
        if (!rc.ok())
        {
            FAPI_ERR("proc_fab_iovalid_write_active_mask: fapiPutScom error (0x%08X)",
                     i_set_not_clear?i_or_mask_addr:i_and_mask_addr);
            break;
        }

    } while (0);

    // mark function exit
    FAPI_DBG("proc_fab_iovalid_write_active_mask: End");
    return rc;
}
Example #2
0
//------------------------------------------------------------------------------
// function: proc_tod_clear_error_reg
//
// parameters: i_tod_node  Reference to TOD topology (FAPI targets included within)
//
// returns: FAPI_RC_SUCCESS if every TOD node is cleared of errors
//          else FAPI or ECMD error is sent through
//------------------------------------------------------------------------------
fapi::ReturnCode proc_tod_clear_error_reg(const tod_topology_node* i_tod_node)
{
    fapi::ReturnCode rc;
    ecmdDataBufferBase data(64);
    uint32_t rc_ecmd = 0;
    fapi::Target* target = i_tod_node->i_target;

    FAPI_INF("proc_tod_clear_error_reg: Start");
    do
    {
        if (i_tod_node == NULL)
        {
            FAPI_ERR("proc_tod_clear_error_reg: null node passed into function!");
            FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_NULL_NODE);
            break;
        }

        FAPI_DBG("proc_tod_clear_error_reg: Clear any previous errors from TOD_ERROR_REG_00040030");
        rc_ecmd |= data.flushTo1();
        if (rc_ecmd)
        {
            FAPI_ERR("proc_tod_clear_error_reg: Error 0x%08X in ecmdDataBuffer setup for TOD_ERROR_REG_00040030.",  rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }
        rc = fapiPutScom(*target, TOD_ERROR_REG_00040030, data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_tod_clear_error_reg: Could not write TOD_ERROR_REG_00040030.");
            break;
        }

        for (std::list<tod_topology_node*>::const_iterator child = (i_tod_node->i_children).begin();
             child != (i_tod_node->i_children).end();
             ++child)
        {
            tod_topology_node* tod_node = *child;
            rc = proc_tod_clear_error_reg(tod_node);
            if (!rc.ok())
            {
                FAPI_ERR("proc_tod_clear_error_reg: Failure clearing errors from downstream node!");
                break;
            }
        }
        if (!rc.ok())
        {
            break;  // error in above for loop
        }
    } while (0);

    FAPI_INF("proc_tod_clear_error_reg: End");
    return rc;
}
  // parameters:
  // 'i_target' is chip target
  //
  // returns:
  // FAPI_RC_SUCCESS (success, EX chiplets entered fast winkle)
  //
  // getscom/putscom/getattribute fapi errors
  // fapi error assigned from eCMD function failure
  //
  //------------------------------------------------------------------------------
  fapi::ReturnCode proc_mpipl_ex_cleanup(const fapi::Target & i_target) {
    const char          *procedureName = "proc_mpipl_ex_cleanup";
    fapi::ReturnCode    rc; //fapi return code
    uint32_t            rc_ecmd = 0;    //ecmd return code value
    ecmdDataBufferBase  fsi_data(64); //64-bit data buffer
    uint8_t             attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units
    const uint64_t      EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet

    uint64_t            address;   // Varible for computed addresses
    uint64_t            offset;
    char                reg_name[32];  // Character array for register names


    // Relevant PMGP0 bits
//    const uint32_t      PM_DISABLE = 0;
    const uint32_t      BLOCK_REG_WKUP_SOURCE = 53;


    // Relevant PMGP1 bits  
    const uint32_t      WINKLE_POWER_OFF_SEL = 5;

    std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets


    do
    {
        //Entering fapi function
        FAPI_INF("Entering %s", procedureName);

        //Get vector of EX chiplets
        rc = fapiGetChildChiplets(  i_target, 
                                    fapi::TARGET_TYPE_EX_CHIPLET, 
                                    v_ex_chiplets, 
                                    fapi::TARGET_STATE_FUNCTIONAL); 
        if (rc) 
        {
             FAPI_ERR("%s: fapiGetChildChiplets error", procedureName);
             break;
        }

        FAPI_INF("Processing target %s", i_target.toEcmdString());
        
        //Parse thru EX chiplets and prepare fast-winkled cores for deep operations
        //Loop thru EX chiplets in vector
        for (uint32_t counter = 0; counter < v_ex_chiplets.size(); counter++)
        {

            // Get EX chiplet number
            rc = FAPI_ATTR_GET( ATTR_CHIP_UNIT_POS,
                                &(v_ex_chiplets[counter]),
                                attr_chip_unit_pos);
            if (rc)
            {
                FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName);
                break;
            }
            FAPI_INF("EX chiplet pos = 0x%02X", attr_chip_unit_pos);


            // Calculate the address offset based on chiplet number
            offset = EX_OFFSET_MULT * attr_chip_unit_pos;
                        
            // -----------------------------------------------------------------
            FAPI_DBG("\tOriginal register contents");
            address = EX_GP3_0x100F0012 + offset;
            strcpy(reg_name, "GP3");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            
            address = EX_PMGP0_0x100F0100 + offset;
            strcpy(reg_name, "PMGP0");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));

            address = EX_PMGP1_0x100F0103 + offset;
            strcpy(reg_name, "PMGP1");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            // -----------------------------------------------------------------

            // Clean up configuration remnants of the fast-winkle configuration
            // that  was used to flush the chiplets after checkstop.  EX chiplets
            // will have been through SBE EX Init with certain step skippled due 
            // to MPIPL.
            
            FAPI_INF("Re-establish Deep Winkle mode default");
            address = EX_PMGP1_OR_0x100F0105 + offset;
            strcpy(reg_name, "PMGP1 OR");

            rc_ecmd |= fsi_data.flushTo0();
            rc_ecmd |= fsi_data.setBit(WINKLE_POWER_OFF_SEL);
            if(rc_ecmd)
            {
                FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX) with rc %x", reg_name, address, rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(i_target, address, fsi_data);
            if (rc)
            {
                FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
                break;
            }

            FAPI_INF("Clear block wakeup sources to PM logic.  PM is NOT re-enabled");
            // (eg clear Block Interrrupt Sources)
            address = EX_PMGP0_AND_0x100F0101 + offset;
            strcpy(reg_name, "PMGP0 AND");

            rc_ecmd |= fsi_data.flushTo1();
//            rc_ecmd |= fsi_data.clearBit(PM_DISABLE);
            rc_ecmd |= fsi_data.clearBit(BLOCK_REG_WKUP_SOURCE);
            if(rc_ecmd)
            {
                FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX)", reg_name, address);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(i_target, address, fsi_data);
            if (rc)
            {
                 FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
                break;
            }
            
            // -----------------------------------------------------------------
            FAPI_DBG("\tUpdated register contents");
            address = EX_GP3_0x100F0012 + offset;
            strcpy(reg_name, "GP3");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            
            address = EX_PMGP0_0x100F0100 + offset;
            strcpy(reg_name, "PMGP0");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));

            address = EX_PMGP1_0x100F0103 + offset;
            strcpy(reg_name, "PMGP1");
            rc = fapiGetScom( i_target, address, fsi_data );
            if (rc)
            {
                FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
                break;
            }
            FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
            // -----------------------------------------------------------------
        } // chiplet loop

        // Error exit from above loop
        // Not really needed as outer while(0) is next but here for consistent structure
        if (!rc.ok())
        {
            break;
        }
    } while (0);

    //Exiting fapi function
    FAPI_INF("Exiting %s", procedureName);

    return rc;
  }
Example #4
0
// HWP entry point
fapi::ReturnCode proc_getecid(
    const fapi::Target& i_target,
    ecmdDataBufferBase& io_fuseString)
{
    // return code
    fapi::ReturnCode rc;
    uint32_t rc_ecmd = 0;
    uint64_t attr_data[2];

    // mark HWP entry
    FAPI_DBG("proc_getecid: Start");

    io_fuseString.setBitLength(112); // sets size and zeros out buffer
    ecmdDataBufferBase otprom_mode_data(64);
    ecmdDataBufferBase ecid_data(64);

    do
    {

      //
      // clear ECC enable before reading ECID data (read-modify-write OTPROM Mode register)
      //

      rc = fapiGetScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: fapiGetScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s",
                   i_target.toEcmdString());
          break;
      }

      rc_ecmd |= otprom_mode_data.clearBit(OTPC_M_MODE_REGISTER_ECC_ENABLE_BIT);
      if (rc_ecmd)
      {
          FAPI_ERR("proc_getecid: Error 0x%X setting up OTPROM Mode register data buffer",
                   rc_ecmd);
          rc.setEcmdError(rc_ecmd);
          break;
      }

      rc = fapiPutScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: fapiPutScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s",
                   i_target.toEcmdString());
          break;
      }


      //
      // extract and manipulate ECID data
      //

      rc = fapiGetScom(i_target, ECID_PART_0_0x00018000, ecid_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: fapiGetScom error (ECID_PART_0_0x00018000) for %s",
                   i_target.toEcmdString());
          break;
      }

      // 0:63 become 63:0
      rc_ecmd |= ecid_data.reverse();
      // copy bits 0:63 from the scom into 0:63 of the fuseString/attribute data
      rc_ecmd |= io_fuseString.insert(ecid_data,  0, 64);
      attr_data[0] = ecid_data.getDoubleWord(0);

      if (rc_ecmd)
      {
          FAPI_ERR("proc_getecid: Error 0x%X processing ECID (part 0) data buffer",
                   rc_ecmd);
          rc.setEcmdError(rc_ecmd);
          break;
      }

      rc = fapiGetScom(i_target, ECID_PART_1_0x00018001, ecid_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: fapiGetScom error (ECID_PART_1_0x00018001) for %s",
                   i_target.toEcmdString());
          break;
      }

      // 0:63 become 63:0
      rc_ecmd |= ecid_data.reverse();
      // copy bits 0:47 from the scom into 64:111 of the fuseString
      // all bits into attribute data
      rc_ecmd |= io_fuseString.insert(ecid_data, 64, 48);
      attr_data[1] = ecid_data.getDoubleWord(0);

      if (rc_ecmd)
      {
          FAPI_ERR("proc_getecid: Error 0x%X processing ECID (part 1) data buffer",
                   rc_ecmd);
          rc.setEcmdError(rc_ecmd);
          break;
      }

      // push fuse string into attribute
      rc = FAPI_ATTR_SET(ATTR_ECID,
                         &i_target,
                         attr_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: Error from FAPI_ATTR_SET (ATTR_ECID) for %s (attr_data[0] = %016llX, attr_data[1] = %016llX",
                   i_target.toEcmdString(), attr_data[0], attr_data[1]);
          break;
      }

      //
      // restore ECC enable setting
      //

      rc_ecmd |= otprom_mode_data.setBit(OTPC_M_MODE_REGISTER_ECC_ENABLE_BIT);
      if (rc_ecmd)
      {
          FAPI_ERR("proc_getecid: Error 0x%X setting up OTPROM Mode register data buffer",
                   rc_ecmd);
          rc.setEcmdError(rc_ecmd);
          break;
      }

      rc = fapiPutScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data);
      if (!rc.ok())
      {
          FAPI_ERR("proc_getecid: fapiPutScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s",
                   i_target.toEcmdString());
          break;
      }

    } while(0);

    // mark HWP exit
    FAPI_DBG("proc_getecid: End");
    return rc;
}
// HWP entry point, comments in header
fapi::ReturnCode proc_chiplet_scominit(const fapi::Target & i_target)
{
    fapi::ReturnCode rc;
    uint32_t rc_ecmd = 0;

    fapi::TargetType target_type;
    std::vector<fapi::Target> initfile_targets;
    std::vector<fapi::Target> ex_targets;
    std::vector<fapi::Target> mcs_targets;
    uint8_t nx_enabled;
    uint8_t mcs_pos;
    uint8_t ex_pos;
    uint8_t num_ex_targets;
    uint8_t master_mcs_pos = 0xFF;
    fapi::Target master_mcs;
    uint8_t enable_xbus_resonant_clocking = 0x0;
    uint8_t i2c_slave_address = 0x0;
    uint8_t dual_capp_present = 0x0;

    ecmdDataBufferBase data(64);
    ecmdDataBufferBase cfam_data(32);
    ecmdDataBufferBase mask(64);

    bool               is_master = false;

    // mark HWP entry
    FAPI_INF("proc_chiplet_scominit: Start");

    do
    {
        rc = proc_check_master_sbe_seeprom(i_target, is_master);
        if (!rc.ok())
        {
            FAPI_ERR("proc_cen_ref_clk_enable: Error from proc_check_master_sbe_seeprom");
            break;
        }

        // obtain target type to determine which initfile(s) to execute
        target_type = i_target.getType();

        // chip level target
        if (target_type == fapi::TARGET_TYPE_PROC_CHIP)
        {
            // execute FBC SCOM initfile
            initfile_targets.push_back(i_target);
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_FBC_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_FBC_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_FBC_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute PSI SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_PSI_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_PSI_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_PSI_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute TP bridge SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF,
                         i_target.toEcmdString());
                break;
            }

            // query NX partial good attribute
            rc = FAPI_ATTR_GET(ATTR_PROC_NX_ENABLE,
                               &i_target,
                               nx_enabled);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_PROC_NX_ENABLE");
                break;
            }

            // apply NX/AS SCOM initfiles only if partial good attribute is set
            if (nx_enabled == fapi::ENUM_ATTR_PROC_NX_ENABLE_ENABLE)
            {
                // execute NX SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_NX_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_NX_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_NX_IF,
                             i_target.toEcmdString());
                    break;
                }

                // execute CXA SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_CXA_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_CXA_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_CXA_IF,
                             i_target.toEcmdString());
                    break;
                }

                // configure CXA APC master LCO settings
                rc = fapiGetChildChiplets(i_target,
                                          fapi::TARGET_TYPE_EX_CHIPLET,
                                          ex_targets,
                                          fapi::TARGET_STATE_FUNCTIONAL);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (EX) on %s",
                             i_target.toEcmdString());
                    break;
                }

                // form valid LCO target list
                for (std::vector<fapi::Target>::iterator i = ex_targets.begin();
                     i != ex_targets.end();
                     i++)
                {
                    // determine EX chiplet number
                    rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), ex_pos);

                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s",
                                 i->toEcmdString());
                        break;
                    }

                    rc_ecmd |= data.setBit(ex_pos-((ex_pos < 8)?(1):(3)));
                }
                if (!rc.ok())
                {
                    break;
                }

                num_ex_targets = ex_targets.size();
                rc_ecmd |= data.insertFromRight(
                    num_ex_targets,
                    CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT,
                    (CAPP_APC_MASTER_LCO_TARGET_MIN_END_BIT-
                     CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT+1));

                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting APC Master LCO Target register data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                rc = fapiPutScom(i_target,
                                 CAPP_APC_MASTER_LCO_TARGET_0x02013021,
                                 data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP_APC_MASTER_LCO_TARGET_0x02013021) on %s",
                             i_target.toEcmdString());
                    break;
                }

                // get dual CAPP presence attribute
                FAPI_DBG("proc_chiplet_scominit: Querying dual CAPP feature attribute");
                rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT,
                                   &i_target,
                                   dual_capp_present);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT");
                    break;
                }
                
                if (dual_capp_present != 0)
                {
                    rc = fapiPutScom(i_target,
                                     CAPP1_APC_MASTER_LCO_TARGET_0x020131A1,
                                     data);
                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP1_APC_MASTER_LCO_TARGET_0x020131A1) on %s",
                                 i_target.toEcmdString());
                        break;
                    }
                }

                // execute AS SCOM initfile
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_AS_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_AS_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_AS_IF,
                             i_target.toEcmdString());
                    break;
                }
            }
            else
            {
                FAPI_DBG("proc_chiplet_scominit: Skipping execution of %s/%s/%s (partial good)",
                         PROC_CHIPLET_SCOMINIT_NX_IF, PROC_CHIPLET_SCOMINIT_CXA_IF, PROC_CHIPLET_SCOMINIT_AS_IF);
            }

            // conditionally enable I2C Slave
            rc = FAPI_ATTR_GET(ATTR_I2C_SLAVE_ADDRESS,
                               &i_target,
                               i2c_slave_address);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_I2C_SLAVE_ADDRESS on %s",
                         i_target.toEcmdString());
                break;
            }
            rc = fapiGetScom(i_target,
                             I2C_SLAVE_CONFIG_REG_0x000D0000,
                             data);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s",
                         i_target.toEcmdString());
                break;
            }
            if (i2c_slave_address)
            {
                FAPI_DBG("proc_chiplet_scominit: I2C Slave enabled (%s) address = %d",
                     i_target.toEcmdString(),i2c_slave_address);

                //set I2C address
                rc_ecmd |= data.insert(i2c_slave_address,0,7);

                // disable error state.  when this is enabled and there
                // is an error from I2CS it locks up the I2CS and no
                // more operations are allowed unless cleared
                // through FSI.  Not good for a FSPless system.
                rc_ecmd |= data.clearBit(23);

                // enable I2C interface
                rc_ecmd |= data.setBit(21);

            }
            else
            {
                FAPI_DBG("proc_chiplet_scominit: I2C Slave disabled (%s)",
                     i_target.toEcmdString());

                // disable I2C interface when attribute = 0x0
                rc_ecmd |= data.clearBit(21);
            }

            if (rc_ecmd)
            {
                FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting I2C Slave register data buffer",
                         rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }

            rc = fapiPutScom(i_target,
                             I2C_SLAVE_CONFIG_REG_0x000D0000,
                             data);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s",
                         i_target.toEcmdString());
                break;
            }

            // conditionally enable resonant clocking for XBUS
            rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID,
                               &i_target,
                               enable_xbus_resonant_clocking);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID on %s",
                         i_target.toEcmdString());
                break;
            }

            if (enable_xbus_resonant_clocking)
            {
                FAPI_DBG("proc_chiplet_scominit: Enabling XBUS resonant clocking");
                rc = fapiGetScom(i_target,
                                 MBOX_FSIGP6_0x00050015,
                                 data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (MBOX_FSIGP6_0x00050015) on %s",
                             i_target.toEcmdString());
                    break;
                }

                rc_ecmd |= data.insertFromRight(
                    XBUS_RESONANT_CLOCK_CONFIG,
                    MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT,
                    (MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_END_BIT-
                     MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT+1));

                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting FSI GP6 register data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                if (is_master) 
                {
                    rc = fapiPutScom(i_target,
                                 MBOX_FSIGP6_0x00050015,
                                 data);
                    if (!rc.ok())
                    {
                        FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (MBOX_FSIGP6_0x00050015) on %s",
                             i_target.toEcmdString());
                        break;
                    }
                }
                else 
                {
                    cfam_data.insert(data, 0, 32, 0);
                    rc = fapiPutCfamRegister(i_target, CFAM_FSI_GP6_0x00002815, cfam_data);
                    if (rc)
                    {
                        FAPI_ERR("proc_cen_ref_clk_enable: fapiPutCfamRegister error (CFAM_FSI_GP8_0x00001017)");
                        break;
                    }
                }
            }

            // execute A/X/PCI/DMI FIR init SCOM initfile
            FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                     PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF, i_target.toEcmdString());
            FAPI_EXEC_HWP(
                rc,
                fapiHwpExecInitFile,
                initfile_targets,
                PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF,
                         i_target.toEcmdString());
                break;
            }

            // execute NV scominit file
            uint8_t exist_NV = 0x00;
            rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_NV_PRESENT, &i_target, exist_NV);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error getting attribute value ATTR_CHIP_EC_FEATURE_NV_PRESENT");
                break;
            }
            if (exist_NV)
            {
                FAPI_INF("proc_chiplet_scominit: Executing  %s on %s",
                         PROC_CHIPLET_SCOMINIT_NPU_IF, i_target.toEcmdString());
                FAPI_EXEC_HWP(
                        rc,
                        fapiHwpExecInitFile,
                        initfile_targets,
                        PROC_CHIPLET_SCOMINIT_NPU_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_NPU_IF,
                             i_target.toEcmdString());
                    break;
                }

                // cleanup FIR bit (NPU FIR bit 27) caused by NDL/NTL parity error
                rc_ecmd = data.flushTo1();
                rc_ecmd = data.clearBit(NPU_FIR_NTL_DL2TL_PARITY_ERR_BIT);
                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%Xforming NPU FIR cleanup data buffer",
                  	   rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }
                rc = fapiPutScom(i_target, NPU_FIR_AND_0x08013D81, data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_AND_0x08013D81) on %s",
                             i_target.toEcmdString());
                    break;
                }
                rc = fapiPutScom(i_target, NPU_FIR_MASK_AND_0x08013D84, data);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_MASK_AND_0x08013D84) on %s",
                             i_target.toEcmdString());
                    break;
                }
            }
            else
            {
                FAPI_INF("proc_chiplet_scominit: NV link logic not present, scom initfile processing skipped");
            }

            // determine set of functional MCS chiplets
            rc = fapiGetChildChiplets(i_target,
                                      fapi::TARGET_TYPE_MCS_CHIPLET,
                                      mcs_targets,
                                      fapi::TARGET_STATE_FUNCTIONAL);
            if (!rc.ok())
            {
                FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (MCS) on %s",
                         i_target.toEcmdString());
                break;
            }

            // apply MCS SCOM initfile only for functional chiplets
            for (std::vector<fapi::Target>::iterator i = mcs_targets.begin();
                 (i != mcs_targets.end()) && rc.ok();
                 i++)
            {
                // execute MCS SCOM initfile
                initfile_targets.clear();
                initfile_targets.push_back(*i);
                initfile_targets.push_back(i_target);
                FAPI_INF("proc_chiplet_scominit: Executing %s on %s",
                         PROC_CHIPLET_SCOMINIT_MCS_IF, i->toEcmdString());
                FAPI_EXEC_HWP(
                    rc,
                    fapiHwpExecInitFile,
                    initfile_targets,
                    PROC_CHIPLET_SCOMINIT_MCS_IF);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s",
                             PROC_CHIPLET_SCOMINIT_MCS_IF,
                             i->toEcmdString());
                    break;
                }

                // determine MCS position
                rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), mcs_pos);

                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s",
                             i->toEcmdString());
                    break;
                }

                if (mcs_pos < master_mcs_pos)
                {
                    fapi::Target cen_target_unused;
                    rc = fapiGetOtherSideOfMemChannel(*i,
                                                      cen_target_unused,
                                                      fapi::TARGET_STATE_FUNCTIONAL);
                    // use return code only to indicate presence of connected Centaur,
                    // do not propogate/emit error if not connected
                    if (rc.ok())
                    {
                        FAPI_DBG("Updating master_mcs_pos to %d", mcs_pos);
                        FAPI_DBG("  Target: %s", cen_target_unused.toEcmdString());
                        master_mcs = *i;
                        master_mcs_pos = mcs_pos;
                    }
                    else
                    {
                        rc = fapi::FAPI_RC_SUCCESS;
                    }
                }

            }
            if (!rc.ok())
            {
                break;
            }

            if (master_mcs.getType() == fapi::TARGET_TYPE_MCS_CHIPLET)
            {
                // set MCMODE0Q_ENABLE_CENTAUR_SYNC on first target only
                // (this bit is required to be set on at most one MCS/chip)
                rc_ecmd |= data.flushTo0();
                rc_ecmd |= data.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT);
                rc_ecmd |= mask.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT);

                // check buffer manipulation return codes
                if (rc_ecmd)
                {
                    FAPI_ERR("proc_chiplet_scominit: Error 0x%X setting up MCSMODE0 data buffer",
                             rc_ecmd);
                    rc.setEcmdError(rc_ecmd);
                    break;
                }

                // write register with updated content
                rc = fapiPutScomUnderMask(master_mcs,
                                          MCS_MCSMODE0_0x02011807,
                                          data,
                                          mask);
                if (!rc.ok())
                {
                    FAPI_ERR("proc_chiplet_scominit: fapiPutScomUnderMask error (MCS_MCSMODE0_0x02011807) on %s",
                             master_mcs.toEcmdString());
                    break;
                }

            }
        }
        // unsupported target type
        else
        {
            FAPI_ERR("proc_chiplet_scominit: Unsupported target type");
            const fapi::Target & TARGET = i_target;
            FAPI_SET_HWP_ERROR(rc, RC_PROC_CHIPLET_SCOMINIT_INVALID_TARGET);
            break;
        }
    } while(0);

    // mark HWP exit
    FAPI_INF("proc_chiplet_scominit: End");
    return rc;
}
Example #6
0
//------------------------------------------------------------------------------
// function: init_tod_node
//
// parameters: i_tod_node  Reference to TOD topology (FAPI targets included within)
//
// returns: FAPI_RC_SUCCESS if TOD topology is successfully initialized
//          else FAPI or ECMD error is sent through
//------------------------------------------------------------------------------
fapi::ReturnCode init_tod_node(const tod_topology_node* i_tod_node)
{
    fapi::ReturnCode rc;
    ecmdDataBufferBase data(64);
    uint32_t rc_ecmd = 0;
    uint32_t tod_init_pending_count = 0; // Timeout counter for bits that are cleared by hardware
    fapi::Target* target = i_tod_node->i_target;

    FAPI_INF("configure_tod_node: Start: Configuring %s", target->toEcmdString());

    do
    {
        const bool is_mdmt = (i_tod_node->i_tod_master && i_tod_node->i_drawer_master);

        if (is_mdmt)
        {
            FAPI_INF("init_tod_node: Master: Chip TOD step checkers enable");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(0);
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Error 0x%08X in ecmdDataBuffer setup for TOD_TX_TTYPE_2_REG_00040013 SCOM.",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_TX_TTYPE_2_REG_00040013, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Could not write TOD_TX_TTYPE_2_REG_00040013.");
                break;
            }

            FAPI_INF("init_tod_node: Master: switch local Chip TOD to 'Not Set' state");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(TOD_LOAD_TOD_MOD_REG_FSM_LOAD_TOD_MOD_TRIG);
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Master: Error 0x%08X in ecmdDataBuffer setup for TOD_LOAD_TOD_MOD_REG_00040018 SCOM.",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_LOAD_TOD_MOD_REG_00040018, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Master: Could not write TOD_LOAD_TOD_MOD_REG_00040018");
                break;
            }
            FAPI_INF("init_tod_node: Master: switch all Chip TOD in the system to 'Not Set' state");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(0);
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Master: Error 0x%08X in ecmdDataBuffer setup for TOD_TX_TTYPE_5_REG_00040016 SCOM.",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_TX_TTYPE_5_REG_00040016, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Master: Could not write TOD_TX_TTYPE_5_REG_00040016");
                break;
            }
   
            FAPI_INF("init_tod_node: Master: Chip TOD load value (move TB to TOD)");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setWord(0,0x00000000);
            rc_ecmd |= data.setWord(1,0x00003FF0); // bits 51:59 must be 1s
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Master: Error 0x%08X in ecmdDataBuffer setup for TOD_LOAD_TOD_REG_00040021 SCOM.",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_LOAD_TOD_REG_00040021, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Master: Could not write TOD_LOAD_TOD_REG_00040021");
                break;
            }
            FAPI_INF("init_tod_node: Master: Chip TOD start_tod (switch local Chip TOD to 'Running' state)");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(TOD_START_TOD_REG_FSM_START_TOD_TRIGGER);
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Master: Error 0x%08X in ecmdDataBuffer setup for TOD_START_TOD_REG_00040022 SCOM.",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_START_TOD_REG_00040022, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Master: Could not write TOD_START_TOD_REG_00040022");
                break;
            }

            FAPI_INF("init_tod_node: Master: Send local Chip TOD value to all Chip TODs");
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(0);
            if (rc_ecmd)
            {
                FAPI_ERR("init_tod_node: Master: Error 0x%08X in ecmdDataBuffer setup for TOD_TX_TTYPE_4_REG_00040015",  rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(*target, TOD_TX_TTYPE_4_REG_00040015, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Master: Could not write TOD_TX_TTYPE_4_REG_00040015");
                break;
            }
        }

        FAPI_INF("init_tod_node: Check TOD is Running");
        tod_init_pending_count = 0;
        while (tod_init_pending_count < PROC_TOD_UTIL_TIMEOUT_COUNT)
        {
            FAPI_DBG("init_tod_node: Waiting for TOD to assert TOD_FSM_REG_TOD_IS_RUNNING...");
   
            rc = fapiDelay(PROC_TOD_UTILS_HW_NS_DELAY,
                           PROC_TOD_UTILS_SIM_CYCLE_DELAY);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: fapiDelay error");
                break;
            }
            rc = fapiGetScom(*target, TOD_FSM_REG_00040024, data);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Could not retrieve TOD_FSM_REG_00040024");
                break;
            }
            if (data.isBitSet(TOD_FSM_REG_TOD_IS_RUNNING))
            {
                FAPI_INF("init_tod_node: TOD is running!");
                break;
            }
            ++tod_init_pending_count;
        }
        if (!rc.ok())
        {
            break;  // error in above while loop
        }
        if (tod_init_pending_count>=PROC_TOD_UTIL_TIMEOUT_COUNT)
        {
                FAPI_ERR("init_tod_node: TOD is not running! (It should be)");
                const fapi::Target & CHIP_TARGET = *target;
                FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_INIT_NOT_RUNNING);
                break;
        }

        FAPI_INF("init_tod_node: clear TTYPE#2 and TTYPE#4 status");
        rc_ecmd |= data.flushTo0();
        rc_ecmd |= data.setBit(TOD_ERROR_REG_RX_TTYPE_2);
        rc_ecmd |= data.setBit(TOD_ERROR_REG_RX_TTYPE_4);
        if (rc_ecmd)
        {
            FAPI_ERR("init_tod_node: Error 0x%08X in ecmdDataBuffer setup for TOD_ERROR_REG_00040030.",  rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }
        rc = fapiPutScom(*target, TOD_ERROR_REG_00040030, data);
        if (!rc.ok())
        {
            FAPI_ERR("init_tod_node: Could not write TOD_ERROR_REG_00040030.");
            break;
        }

        FAPI_INF("init_tod_node: checking for TOD errors");
        rc = fapiGetScom(*target, TOD_ERROR_REG_00040030, data);
        if (!rc.ok())
        {
            FAPI_ERR("init_tod_node: Could not read TOD_ERROR_REG_00040030.");
            break;
        }
        if (data.getDoubleWord(0) != 0)
        {
            FAPI_ERR("init_tod_node: FIR bit active! (TOD_ERROR_REG = 0x%016llX)",data.getDoubleWord(0));
            const fapi::Target & CHIP_TARGET = *target;
            const uint64_t TOD_ERROR_REG = data.getDoubleWord(0);
            FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_INIT_ERROR);
            break;
        }

        // Finish configuring downstream nodes
        for (std::list<tod_topology_node*>::const_iterator child = (i_tod_node->i_children).begin();
             child != (i_tod_node->i_children).end();
             ++child)
        {
            tod_topology_node* tod_node = *child;
            rc = init_tod_node(tod_node);
            if (!rc.ok())
            {
                FAPI_ERR("init_tod_node: Failure configuring downstream node!");
                break;
            }
        }
        if (!rc.ok())
        {
            break;  // error in above for loop
        }

    } while(0);

    FAPI_INF("init_tod_node: End");
    return rc;
}
//------------------------------------------------------------------------------
// function:
//      Check if the SBE is still running
//      Wait 1 sec, then check again if still running
//      When stopped, check if the SBE halt code, istep, and substep are correct
//
// parameters: i_target           => slave chip target
//             i_pSEEPROM         => pointer to the seeprom image (for errors)
//             i_wait_in_ms       => pointer to the seeprom image (for errors)
//
// returns: FAPI_RC_SUCCESS if the slave SBE stopped with success at the correct
//          location, else error
//------------------------------------------------------------------------------
    fapi::ReturnCode proc_check_slave_sbe_seeprom_complete(
        const fapi::Target & i_target,
        const void         * i_pSEEPROM,
        const size_t       i_wait_in_ms)
    {
        // data buffer to hold register values
        ecmdDataBufferBase data(64);

        // return codes
        uint32_t rc_ecmd = 0;
        fapi::ReturnCode rc;

        // track if procedure has cleared I2C master bus fence
        bool i2cm_bus_fence_cleared = false;

        // mark function entry
        FAPI_INF("Entry");

        do
        {
            //Check if the SBE is still running.  Loop until stopped
            //or loop time is exceeded.  
            bool still_running = true;
            size_t loop_time = 0;
            rc = proc_check_slave_sbe_seeprom_complete_check_running(
                   i_target,
                   still_running );
            if( rc )
            {
                break;
            }

            while (still_running && (loop_time < i_wait_in_ms))
            {
                //Not done -- sleep 10ms, then check again
                loop_time += MS_TO_FINISH;
                rc = fapiDelay(NS_TO_FINISH, SIM_CYCLES_TO_FINISH);
                if( rc )
                {
                    FAPI_ERR("Error with delay\n");
                    break;
                }

                rc = proc_check_slave_sbe_seeprom_complete_check_running(
                       i_target,
                       still_running );
                if( rc )
                {
                    break;
                }
            }

            //Break if took an error
            if( rc )
            {
                break;
            }

            FAPI_INF("SBE is running [%d], wait time in ms[%zd]",
                     still_running, loop_time);

            //Give up if we're still running
            if( still_running )
            {
                FAPI_ERR(
                        "SBE still running after waiting (%zdns, %lld cycles)",
                        loop_time,
                        loop_time/MS_TO_FINISH*SIM_CYCLES_TO_FINISH );

                const fapi::Target & CHIP_IN_ERROR = i_target;
                FAPI_SET_HWP_ERROR(rc,
                      RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_STILL_RUNNING);
                break;
            } //end if(still_running)

            //SBE is stopped. Let's see where
            uint8_t  halt_code = 0;
            uint16_t istep_num = 0;
            uint8_t  substep_num = 0;

            // before analysis proceeds, make sure that I2C master bus fence is cleared
            FAPI_EXEC_HWP(rc, proc_reset_i2cm_bus_fence, i_target);
            if (!rc.ok())
            {
                FAPI_ERR("Error from proc_reset_i2cm_bus_fence");
                break;
            }
            // mark that fence has been cleared
            i2cm_bus_fence_cleared = true;

            //Get current location from SBE VITAL
            rc = proc_check_slave_sbe_seeprom_complete_get_location(
                i_target,
                halt_code,
                istep_num,
                substep_num );
            if( rc )
            {
                FAPI_ERR("Unable to get the current SBE location");
                break;
            }

            //Did it stop with success?
            if( halt_code != SBE_EXIT_SUCCESS_0xF )
            {
                FAPI_ERR(
                    "SBE halted with error %i (istep 0x%X, substep %i)", 
                    halt_code,
                    istep_num,
                    substep_num);
                //Get the error code from the SBE code
                FAPI_EXEC_HWP(rc, proc_extract_sbe_rc, i_target, NULL, i_pSEEPROM, SBE);
                break;
            }
            //Halt code was success

            //Did it stop in the correct istep?
            if(( istep_num != PROC_SBE_CHECK_MASTER_MAGIC_ISTEP_NUM ) &&
               ( istep_num != PROC_SBE_ENABLE_PNOR_MAGIC_ISTEP_NUM ) &&
               ( istep_num != PROC_SBE_EX_HOST_RUNTIME_SCOM_MAGIC_ISTEP_NUM ))
            {
                FAPI_ERR(
                    "SBE halted in wrong istep (istep 0x%X, substep %i)", 
                    istep_num,
                    substep_num);
                const fapi::Target & CHIP_IN_ERROR = i_target;
                uint16_t & ISTEP_NUM = istep_num;
                uint8_t & SUBSTEP_NUM = substep_num;
                FAPI_SET_HWP_ERROR(rc,
                        RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_BAD_ISTEP_NUM);
                break;
            }
            //Istep is correct

            //Did it stop in the correct substep?
            if( (( istep_num == PROC_SBE_CHECK_MASTER_MAGIC_ISTEP_NUM ) &&
                 ( substep_num != SUBSTEP_CHECK_MASTER_SLAVE_CHIP )) ||
                (( istep_num == PROC_SBE_ENABLE_PNOR_MAGIC_ISTEP_NUM ) &&
                 ( substep_num != SUBSTEP_ENABLE_PNOR_SLAVE_CHIP )))
            {
                FAPI_ERR(
                    "SBE halted in wrong substep (istep 0x%X, substep %i)", 
                    istep_num,
                    substep_num);
                const fapi::Target & CHIP_IN_ERROR = i_target;
                uint16_t & ISTEP_NUM = istep_num;
                uint8_t & SUBSTEP_NUM = substep_num;
                FAPI_SET_HWP_ERROR(rc,
                      RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_BAD_SUBSTEP_NUM);
                break;
            }
            //Substep is correct

            //Looks good!

            // Reset the SBE so it can be used for MPIPL if needed
            rc_ecmd |= data.flushTo0();
            rc_ecmd |= data.setBit(0);

            if(rc_ecmd)
            {
                FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }
            rc = fapiPutScom(i_target, PORE_SBE_RESET_0x000E0002, data);
            if(!rc.ok())
            {
                FAPI_ERR("Scom error resetting SBE\n");
                break;
            }
        } while (0);

        // if an error occurred prior to the I2C master bus fence
        // being cleared, attempt to clear it prior to exit
        if (!rc.ok() && !i2cm_bus_fence_cleared)
        {
            // discard rc, return that of original fail
            fapi::ReturnCode rc_unused;
            FAPI_EXEC_HWP(rc_unused, proc_reset_i2cm_bus_fence, i_target);
        }

        // mark function exit
        FAPI_INF("Exit");
        return rc;
    }
Example #8
0
//------------------------------------------------------------------------------
// function: initialize PBCQ FIRs
//             clear FIR/WOF
//             initialize FIR action settings
//             reset FIR masks
// parameters: i_target  => processor chip target
//             i_num_phb => number of PHB units
// returns: FAPI_RC_SUCCESS if all actions are successful,
//          else error
//------------------------------------------------------------------------------
fapi::ReturnCode proc_pcie_config_pbcq_fir(
    const fapi::Target & i_target,
    uint8_t i_num_phb)
{
    fapi::ReturnCode rc;
    uint32_t rc_ecmd = 0;

    ecmdDataBufferBase data(64);

    // mark function entry
    FAPI_INF("proc_pcie_config_pbcq_fir: Start");

    // loop over all PHBs
    for (size_t i = 0; i < i_num_phb; i++)
    {
        // clear FIR
        rc_ecmd |= data.flushTo0();
        if (rc_ecmd)
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error 0x%x setting up PCIE Nest FIR clear data buffer",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }
        rc = fapiPutScom(i_target,
                         PROC_PCIE_CONFIG_PCIE_NEST_FIR[i],
                         data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_0x%08X)",
                     i, PROC_PCIE_CONFIG_PCIE_NEST_FIR[i]);
            break;
        }

        // clear FIR WOF
        rc = fapiPutScom(i_target,
                         PROC_PCIE_CONFIG_PCIE_NEST_FIR_WOF[i],
                         data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_WOF_0x%08X)",
                     i, PROC_PCIE_CONFIG_PCIE_NEST_FIR_WOF[i]);
            break;
        }

        // set action0
        rc_ecmd |= data.setDoubleWord(0, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION0_VAL);
        if (rc_ecmd)
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error 0x%x setting up PCIE Nest FIR Action0 register data buffer",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }

        rc = fapiPutScom(i_target,
                         PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION0[i],
                         data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_ACTION0_0x%08X)",
                     i, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION0[i]);
            break;
        }

        // set action1
        rc_ecmd |= data.setDoubleWord(0, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION1_VAL);
        if (rc_ecmd)
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error 0x%x setting up PCIE Nest FIR Action1 register data buffer",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }

        rc = fapiPutScom(i_target,
                         PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION1[i],
                         data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_ACTION1_0x%08X)",
                     i, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION1[i]);
            break;
        }

        // set action2
        fapi::ATTR_CHIP_EC_FEATURE_PCI_NEST_FIR_ACTION2_PRESENT_Type action2_present = 0;
        rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_PCI_NEST_FIR_ACTION2_PRESENT, &i_target, action2_present);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: fapiGetAttribute of ATTR_CHIP_EC_FEATURE_PCI_NEST_FIR_ACTION2_PRESENT failed");
            break;
        }
        if (action2_present)
        {
            rc_ecmd |= data.setDoubleWord(0, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION2_VAL);
            if (rc_ecmd)
            {
                FAPI_ERR("proc_pcie_config_pbcq_fir: Error 0x%x setting up PCIE Nest FIR Action2 register data buffer",
                         rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }

            rc = fapiPutScom(i_target,
                             PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION2[i],
                             data);
            if (!rc.ok())
            {
                FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_ACTION2_0x%08X)",
                         i, PROC_PCIE_CONFIG_PCIE_NEST_FIR_ACTION2[i]);
                break;
            }
        }

        // set mask
        rc_ecmd |= data.setDoubleWord(0, PROC_PCIE_CONFIG_PCIE_NEST_FIR_MASK_VAL);
        if (rc_ecmd)
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error 0x%x setting up PCIE Nest FIR Mask register data buffer",
                     rc_ecmd);
            rc.setEcmdError(rc_ecmd);
            break;
        }

        rc = fapiPutScom(i_target,
                         PROC_PCIE_CONFIG_PCIE_NEST_FIR_MASK[i],
                         data);
        if (!rc.ok())
        {
            FAPI_ERR("proc_pcie_config_pbcq_fir: Error from fapiPutScom (PCIE%zd_FIR_MASK_0x%08X)",
                     i, PROC_PCIE_CONFIG_PCIE_NEST_FIR_MASK[i]);
            break;
        }
    }

    // mark function exit
    FAPI_INF("proc_pcie_config_pbcq_fir: End");
    return rc;
}
  //------------------------------------------------------------------------------
  // name: proc_mpipl_chip_cleanup
  //------------------------------------------------------------------------------
  // purpose: 
  // To enable MCD recovery
  //
  // Note: PHBs are left in ETU reset state after executing proc_mpipl_nest_cleanup, which runs before this procedure.  PHYP releases PHBs from ETU reset post HostBoot IPL.
  //
  // SCOM regs
  //
  // 1) MCD even recovery control register
  // 0000000002013410 (SCOM)
  // bit 0 (MCD_REC_EVEN_ENABLE): 0 to 1 transition needed to start, reset to 0 at end of request.
  // bit 5 (MCD_REC_EVEN_REQ_PEND)
  //
  //
  // 2) MCD odd recovery control register
  // 0000000002013411 (SCOM)
  // bit 0 (MCD_REC_ODD_ENABLE): 0 to 1 transition needed to start, reset to 0 at end of request.
  // bit 5 (MCD_REC_ODD_REQ_PEND)
  //
  // 3) Clear PCI Nest FIR registers
  // 02012000 (SCOM) 
  // 02012400 (SCOM) 
  // 02012800 (SCOM) 
  //
  // parameters: 
  // 'i_target' is reference to chip target
  //
  // returns:
  // FAPI_RC_SUCCESS (success, MCD recovery enabled for odd and even slices)
  //
  // RC_MCD_RECOVERY_NOT_DISABLED_RC (MCD recovery for even or odd slice is not disabled; therefore can't re-enable MCD recovery)
  // (Note: refer to file eclipz/chips/p8/working/procedures/xml/error_info/proc_mpipl_chip_cleanup_errors.xml)
  // 
  // getscom/putscom fapi errors
  // fapi error assigned from eCMD function failure
  // 
  //------------------------------------------------------------------------------
  fapi::ReturnCode proc_mpipl_chip_cleanup(const fapi::Target &i_target){
    const char *procedureName = "proc_mpipl_chip_cleanup"; //Name of this procedure
    fapi::ReturnCode rc; //fapi return code value
    uint32_t rc_ecmd = 0;    //ecmd return code value
    const uint32_t data_size = 64; //Size of data buffer
    const int MAX_MCD_DIRS = 2; //Max of 2 MCD Directories (even and odd)
    ecmdDataBufferBase fsi_data[MAX_MCD_DIRS];
    const uint64_t ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[MAX_MCD_DIRS] = {
      0x0000000002013410, //MCD even recovery control register address
      0x0000000002013411  //MCD odd recovery control register address
    };     
    const uint32_t MCD_RECOVERY_CTRL_REG_BIT_POS0 = 0; //Bit 0 of MCD even and odd recovery control regs
    const char *ARY_MCD_DIR_STRS[MAX_MCD_DIRS] = {
      "Even", //Ptr to char string "Even" for even MCD
      "Odd"   //Ptr to char string "Odd" for odd MCD
    }; 
    const int MAX_PHBS = 3;
    const uint64_t PCI_NEST_FIR_REG_ADDRS[MAX_PHBS] = {
      0x02012000,
      0x02012400,
      0x02012800
    };     
    
    do {
      //Set bit length for 64-bit buffers
      rc_ecmd = fsi_data[0].setBitLength(data_size);
      rc_ecmd |= fsi_data[1].setBitLength(data_size);
      if(rc_ecmd) {
        rc.setEcmdError(rc_ecmd);
        break;
      }
  
      //Verify MCD recovery was previously disabled for even and odd slices
      //If not, this is an error condition
      for (int counter = 0; counter < MAX_MCD_DIRS; counter++) {
        FAPI_DBG("Verifying MCD %s Recovery is disabled, target=%s", ARY_MCD_DIR_STRS[counter], i_target.toEcmdString());
        
        //Get data from MCD Even or Odd Recovery Ctrl reg
        rc = fapiGetScom(i_target, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], fsi_data[counter]);
        if (!rc.ok()) {
          FAPI_ERR("%s: fapiGetScom error (addr: 0x%08llX), target=%s", procedureName, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString());
          break;
        }
        
  
        //Check whether bit 0 is 0, meaning MCD recovery is disabled as expected
        if( fsi_data[counter].getBit(MCD_RECOVERY_CTRL_REG_BIT_POS0) ) {
          FAPI_ERR("%s: MCD %s Recovery not disabled as expected, target=%s", procedureName, ARY_MCD_DIR_STRS[counter], i_target.toEcmdString());
          const fapi::Target & CHIP_TARGET = i_target;
  	  const uint64_t & MCD_RECOV_CTRL_REG_ADDR = ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter];
          ecmdDataBufferBase & MCD_RECOV_CTRL_REG_DATA = fsi_data[counter];
          FAPI_SET_HWP_ERROR(rc, RC_MPIPL_MCD_RECOVERY_NOT_DISABLED_RC);
          break;
        }
      }
      if(!rc.ok()) {
        break;
      }
  
      //Assert bit 0 of MCD Recovery Ctrl regs to enable MCD recovery
      for (int counter = 0; counter < MAX_MCD_DIRS; counter++) {
        FAPI_DBG("Enabling MCD %s Recovery, target=%s", ARY_MCD_DIR_STRS[counter], i_target.toEcmdString());
        
        //Assert bit 0 of MCD Even or Odd Recovery Control reg to enable recovery
        rc_ecmd = fsi_data[counter].setBit(MCD_RECOVERY_CTRL_REG_BIT_POS0 );
        if(rc_ecmd) {
          FAPI_ERR("%s: Error (%u) asserting bit pos %u in ecmdDataBufferBase that stores value of MCD %s Recovery Control reg (addr: 0x%08llX), target=%s", procedureName, rc_ecmd, MCD_RECOVERY_CTRL_REG_BIT_POS0, ARY_MCD_DIR_STRS[counter], ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString());
          rc.setEcmdError(rc_ecmd);
          break;
        }
        
        //Write data to MCD Even or Odd Recovery Control reg
        rc = fapiPutScom(i_target, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], fsi_data[counter]);
        if (!rc.ok()) {
          FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX), target=%s", procedureName, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString());
          break;
        }
      }
      if(!rc.ok()) {
        break;
      }
  
      // SW227429: clear PCI Nest FIR registers
      // hostboot is blindly sending EOIs in order to ensure no interrupts are pending when  PHYP starts up again
      // with ETU held in reset, these get trapped in PCI and force a freeze to occur (PCI Nest FIR(14))
      // clearing the FIR should remove the freeze condition
      rc_ecmd = fsi_data[0].flushTo0();
      if (rc_ecmd) {
        FAPI_ERR("%s: Error (%u) forming PCI Nest FIR clear data buffer, target=%s", procedureName, rc_ecmd, i_target.toEcmdString());
        rc.setEcmdError(rc_ecmd);
        break;
      }
      
      for (int counter = 0; counter < MAX_PHBS; counter++) {
        FAPI_DBG("Clearing PCI%d Nest FIR, target=%s", counter, i_target.toEcmdString());
        rc = fapiPutScom(i_target, PCI_NEST_FIR_REG_ADDRS[counter], fsi_data[0]);
        if (!rc.ok()) {
          FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX), target=%s", procedureName, PCI_NEST_FIR_REG_ADDRS[counter], i_target.toEcmdString());
          break;
        }
      }
    } while(0);

    FAPI_IMP("Exiting %s", procedureName);

    return rc;
  }
//------------------------------------------------------------------------------
// function:
//      Stop SBE runtime scan service
//
// parameters: i_target => chip target
// returns: FAPI_RC_SUCCESS if operation was successful, else error
//------------------------------------------------------------------------------
fapi::ReturnCode proc_stop_sbe_scan_service(
    const fapi::Target& i_target,
    const void* i_pSEEPROM)
{
    // return codes
    fapi::ReturnCode rc;
    uint32_t rc_ecmd = 0;

    // track if procedure has cleared I2C master bus fence
    bool i2cm_bus_fence_cleared = false;

    // mark function entry
    FAPI_DBG("Start");

    do
    {
        // check SBE progress
        bool sbe_running = true;
        size_t loop_time = 0;
        uint8_t halt_code = 0;
        uint16_t istep_num = 0;
        uint8_t substep_num = 0;
        bool scan_service_loop_reached = false;

        // retrieve status
        rc = proc_sbe_utils_check_status(
            i_target,
            sbe_running,
            halt_code,
            istep_num,
            substep_num);
        if (!rc.ok())
        {
            FAPI_ERR("Error from proc_check_sbe_state_check_status");
            break;
        }

        // get HB->SBE request mailbox, check that it is clear
        ecmdDataBufferBase mbox_data(64);
        bool sbe_ready = false;
        rc = fapiGetScom(i_target, MBOX_SCRATCH_REG0_0x00050038, mbox_data);
        if (!rc.ok())
        {
            FAPI_ERR("Scom error reading SBE MBOX0 Register");
            break;
        }
        sbe_ready = (mbox_data.getDoubleWord(0) == 0);

        scan_service_loop_reached =
            sbe_running &&
            sbe_ready &&
            !halt_code &&
            (istep_num == PROC_SBE_SCAN_SERVICE_ISTEP_NUM) &&
            (substep_num == SUBSTEP_SBE_READY);

        FAPI_INF("SBE is running [%d], loop time [%zd], scan service loop reached [%d]",
                 sbe_running, loop_time, scan_service_loop_reached);

        if (!sbe_running)
        {
            FAPI_INF("SBE is stopped, exiting!");
            break;
        }
        else if (scan_service_loop_reached)
        {
            // format stop request
            rc_ecmd |= mbox_data.setBit(MBOX0_REQUEST_VALID_BIT);
            rc_ecmd |= mbox_data.insertFromRight(MBOX0_HALT_PATTERN,
                                                 MBOX0_HALT_PATTERN_START_BIT,
                                                 (MBOX0_HALT_PATTERN_END_BIT-
                                                  MBOX0_HALT_PATTERN_START_BIT)+1);
            if (rc_ecmd)
            {
                FAPI_ERR("Error 0x%x setting up SBE MBOX0 data buffer.", rc_ecmd);
                rc.setEcmdError(rc_ecmd);
                break;
            }

            // submit stop request to SBE
            FAPI_DBG("Submitting stop request to SBE");
            rc = fapiPutScom(i_target, MBOX_SCRATCH_REG0_0x00050038, mbox_data);
            if (!rc.ok())
            {
                FAPI_ERR("Error writing SBE MBOX0 Register");
                break;
            }

            // pause to allow request to be processed
            uint32_t loop_num = 0;
            while (sbe_running && (loop_num < SBE_HALT_POLL_MAX_LOOPS))
            {
                loop_num++;
                rc = fapiDelay(SBE_HALT_POLL_DELAY_HW, SBE_HALT_POLL_DELAY_SIM);
                if (!rc.ok())
                {
                    FAPI_ERR("Error from fapiDelay");
                    break;
                }

                // retrieve status
                rc = proc_sbe_utils_check_status(
                    i_target,
                    sbe_running,
                    halt_code,
                    istep_num,
                    substep_num);
                if (!rc.ok())
                {
                    FAPI_ERR("Error from proc_check_sbe_state_check_status");
                    break;
                }
            }
            if (rc)
            {
                break;
            }
            if (sbe_running)
            {
                FAPI_ERR("SBE is STILL running!");
                const fapi::Target & TARGET = i_target;
                FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_SBE_NOT_STOPPED);
                break;
            }

            // before analysis proceeds, make sure that I2C master bus fence is cleared
            FAPI_EXEC_HWP(rc, proc_reset_i2cm_bus_fence, i_target);
            if (!rc.ok())
            {
                FAPI_ERR("Error from proc_reset_i2cm_bus_fence");
                break;
            }
            // mark that fence has been cleared
            i2cm_bus_fence_cleared = true;

            //  ensure correct halt code is captured
            rc = proc_sbe_utils_check_status(
                i_target,
                sbe_running,
                halt_code,
                istep_num,
                substep_num);
            if (!rc.ok())
            {
                FAPI_ERR("Error from proc_check_sbe_state_check_status");
                break;
            }

            // confirm that expected halt point was reached
            if (halt_code != SBE_EXIT_SUCCESS_0xF)
            {
                FAPI_ERR("SBE halted with error 0x%X (istep 0x%03X, substep 0x%X)",
                         halt_code, istep_num, substep_num);
                // extract & return error code from analyzing SBE state
                FAPI_EXEC_HWP(rc, proc_extract_sbe_rc, i_target, NULL, i_pSEEPROM, SBE);
                break;
            }

            if ((istep_num != PROC_SBE_SCAN_SERVICE_ISTEP_NUM) ||
                (substep_num != SUBSTEP_HALT_SUCCESS))
            {
                FAPI_ERR("Expected SBE istep 0x%03llX, substep 0x%X but found istep 0x%03X, substep 0x%X",
                         PROC_SBE_SCAN_SERVICE_ISTEP_NUM, SUBSTEP_HALT_SUCCESS,
                         istep_num, substep_num);
                const fapi::Target & TARGET = i_target;
                const uint32_t & ISTEP_NUM = istep_num;
                const uint32_t & SUBSTEP_NUM = substep_num;
                FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_SBE_BAD_HALT);
                break;
            }

            // Reset the SBE so it can be used for MPIPL if needed
            ecmdDataBufferBase sbe_reset_data(64);
            rc = fapiPutScom(i_target, PORE_SBE_RESET_0x000E0002, sbe_reset_data);
            if (!rc.ok())
            {
                FAPI_ERR("Scom error resetting SBE\n");
                break;
            }
        }
        // error
        else
        {
            FAPI_ERR("SBE did not reach acceptable final state!");
            const fapi::Target & TARGET = i_target;
            const bool & SBE_RUNNING = sbe_running;
            const uint8_t & HALT_CODE = halt_code;
            const uint16_t & ISTEP_NUM = istep_num;
            const uint8_t & SUBSTEP_NUM = substep_num;
            FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_UNEXPECTED_FINAL_STATE);
            break;
        }

    } while(0);

    // if an error occurred prior to the I2C master bus fence
    // being cleared, attempt to clear it prior to exit
    if (!rc.ok() && !i2cm_bus_fence_cleared)
    {
        // discard rc, return that of original fail
        fapi::ReturnCode rc_unused;
        FAPI_EXEC_HWP(rc_unused, proc_reset_i2cm_bus_fence, i_target);
    }

    // mark function entry
    FAPI_DBG("End");
    return rc;
}