Exemple #1
0
fapi::ReturnCode mss_volt(std::vector<fapi::Target> & i_targets_memb)
{

    fapi::ReturnCode l_rc;
    uint8_t l_dimm_functionality=0;
    uint8_t l_spd_dramtype=0;
    uint8_t l_spd_volts=0;
    uint8_t l_spd_volts_all_dimms=0x06;  //start assuming all voltages supported
    uint8_t l_dram_ddr3_found_flag=0;
    uint8_t l_dram_ddr4_found_flag=0;
    uint8_t l_volt_override = 0x00;
    uint8_t l_volt_override_domain = 0x00;

    uint32_t l_selected_dram_voltage=0;  //this gets written into all centaurs when done.
    uint32_t l_selected_dram_voltage_vpp=0;
    uint32_t l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; //initially set to the max tolerated voltage

    do
    {
        // Iterate through the list of centaurs
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            std::vector<fapi::Target> l_mbaChiplets;
            // Get associated MBA's on this centaur
            l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
            if (l_rc) break;


	    l_rc = FAPI_ATTR_GET(ATTR_MSS_VOLT_OVERRIDE, &i_targets_memb[i], l_volt_override);
	    if (l_rc) break;

	    // Note if there is an overrride being applied on the domain
	    if ( (l_volt_override != fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE) && (l_volt_override_domain == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE) )
	    {
	    	l_volt_override_domain = l_volt_override;
	    }

	    // Error if our overides are not the same across the domain
	    if (l_volt_override_domain != l_volt_override)
	    {
                        // this just needs to callout the mismatching memb.
                        const uint8_t &OVERRIDE_TYPE = l_volt_override;
                        const uint8_t &OVERRIDE_DOMAIN_TYPE = l_volt_override_domain;
                        const fapi::Target &MEMB_TARGET = i_targets_memb[i];
                        FAPI_ERR("Mismatch volt override request.  Domain: 0x%x  Current Target Requests: 0x%x", l_volt_override_domain, l_volt_override);
                        FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_OVERIDE_MIXING);
                        fapiLogError(l_rc);
	    }

            // Loop through the 2 MBA's
            for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
            {
                std::vector<fapi::Target> l_dimm_targets;
                // Get a vector of DIMM targets
                l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                if (l_rc) break;

                for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                {
                    l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &l_dimm_targets[k], l_spd_dramtype);
                    if (l_rc) break;
                    l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE, &l_dimm_targets[k], l_spd_volts);
                    if (l_rc) break;
                    l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_dimm_targets[k], l_dimm_functionality);
                    if (l_rc) break;

                    // spd_volts:  bit0= NOT 1.5V bit1=1.35V bit2=1.25V, assume a 1.20V in future for DDR4
                    // check for supported voltage/dram type combo  DDR3=12, DDR4=13
                    if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
                    {
                        l_dram_ddr3_found_flag=1;
                    }
                    else if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                    {
                        l_dram_ddr4_found_flag=1;
                    }
                    else 
                    {
                        // this just needs to be deconfiged at the dimm level
                        const uint8_t &DEVICE_TYPE = l_spd_dramtype;
                        const fapi::Target &DIMM_TARGET = l_dimm_targets[k];
                        FAPI_ERR("Unknown DRAM Device Type 0x%x", l_spd_dramtype);
                        FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_UNRECOGNIZED_DRAM_DEVICE_TYPE);
                        fapiLogError(l_rc);
                    }

                    if(l_dimm_functionality == fapi::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
                    {
                        //AND dimm voltage capabilities together to find aggregate voltage support on all dimms
                        l_spd_volts_all_dimms = l_spd_volts_all_dimms & l_spd_volts;
                    }

                }//end of dimms loop
                if (l_rc)
                {
                    break;
                }
            }//end of mba loop
            if (l_rc)
            {
                break;
            }
        }//end of centaur (memb) loop      
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }

        // now we figure out if we have a supported ddr type and voltage
        // note: only support DDR3=1.35V and DDR4=1.2xV


        // Mixed Dimms, Deconfig the DDR4.
        if (l_dram_ddr3_found_flag && l_dram_ddr4_found_flag)
        {
            std::vector<fapi::Target> l_dimm_targets_deconfig;
            // Iterate through the list of centaurs
            for (uint32_t i=0; i < i_targets_memb.size(); i++)
            {
                std::vector<fapi::Target> l_mbaChiplets;
                // Get associated MBA's on this centaur
                l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
                if (l_rc) break;
                // Loop through the 2 MBA's
                for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
                {
                    std::vector<fapi::Target> l_dimm_targets;
                    // Get a vector of DIMM targets
                    l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                    if (l_rc) break;
                    for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                    {

                        l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &l_dimm_targets[k], l_spd_dramtype);
                        if (l_rc) break;

                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                        {
                            const fapi::Target &DIMM_DDR4_TARGET = l_dimm_targets[k];
                            const uint8_t &DEVICE_TYPE = l_spd_dramtype;
                            FAPI_ERR("mss_volt: DDR3 and DDR4 mixing not allowed");
                            FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_DDR_TYPE_MIXING_UNSUPPORTED);
                            fapiLogError(l_rc);
                        }

                    }//end of dimms loop
                    if (l_rc)
                    {
                        break;
                    }
                }//end of mba loop
                if (l_rc)
                {
                    break;
                }
            }//end of centaur (memb) loop 

        }
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }


	if (l_volt_override != fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_NONE)
	{
	    if (l_volt_override == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_VOLT_135)
	    {
		l_tolerated_dram_voltage = 1350;
		FAPI_INF( "mss_volt_overide being applied.  MSS_VOLT_OVERRIDE: 1.35V");
		FAPI_INF( "NOTE: Still checking for violations of tolerated voltage.  If DIMMs cannot tolerate, the override will not be applied.");
	    }
	    if (l_volt_override == fapi::ENUM_ATTR_MSS_VOLT_OVERRIDE_VOLT_120)
	    {
	        l_tolerated_dram_voltage = 1200;
		FAPI_INF( "mss_volt_overide being applied.  MSS_VOLT_OVERRIDE: 1.20V");
		FAPI_INF( "NOTE: Still checking for violations of tolerated voltage.  If DIMMs cannot tolerate, the override will not be applied.");
	    }
	    else
	    {
                const uint8_t &OVERRIDE_TYPE = l_volt_override;
                FAPI_ERR("Unknown volt override request.  Override Request: 0x%x", l_volt_override);
                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_OVERIDE_UKNOWN);
                fapiLogError(l_rc);
	    }

	}
        else if (l_dram_ddr3_found_flag && ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_35))
        {
            l_selected_dram_voltage=1350;
	    l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
        }
        else if (l_dram_ddr4_found_flag && ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2X) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_OP1_2X))
        {
            l_selected_dram_voltage=1200;
            l_selected_dram_voltage_vpp = DDR4_VPP_VOLT;
        }
        else if ((l_spd_volts_all_dimms & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) != fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5)
        {
            l_selected_dram_voltage=1500;
	    l_selected_dram_voltage_vpp = DDR3_VPP_VOLT;
        }
        else
        {

            std::vector<fapi::Target> l_dimm_targets_deconfig;
            // Iterate through the list of centaurs
            for (uint32_t i=0; i < i_targets_memb.size(); i++)
            {
                std::vector<fapi::Target> l_mbaChiplets;
                // Get associated MBA's on this centaur
                l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
                if (l_rc) break;
                // Loop through the 2 MBA's
                for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
                {
                    std::vector<fapi::Target> l_dimm_targets; 
                    // Get a vector of DIMM targets
                    l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                    if (l_rc) break;
                    for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                    {
                        l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_NOMINAL_VOLTAGE, &l_dimm_targets[k], l_spd_volts);
                        if (l_rc) break;

                        if((l_spd_volts & fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5) == fapi::ENUM_ATTR_SPD_MODULE_NOMINAL_VOLTAGE_NOTOP1_5)
                        {
                            const fapi::Target &DIMM_UV_TARGET = l_dimm_targets[k];
                            const uint8_t &DIMM_VOLTAGE = l_spd_volts;
                            FAPI_ERR("One or more DIMMs do not support required voltage for DIMM type");
                            FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_DDR_TYPE_REQUIRED_VOLTAGE);
                            fapiLogError(l_rc);
                        }

                    }//end of dimms loop
                    if (l_rc)
                    {
                        break;
                    }
                }//end of mba loop
                if (l_rc)
                {
                    break;
                }
            }//end of centaur (memb) loop  
        }
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }



        // Must check to see if we violate Tolerent voltages of Non-functional Dimms
        // If so we must error/deconfigure on the dimm level primarily then centaur level.
        // Iterate through the list of centaurs
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            std::vector<fapi::Target> l_dimm_targets_deconfig;

            l_tolerated_dram_voltage = MAX_TOLERATED_VOLT; // using 1.5 as this is the largest supported voltage
            std::vector<fapi::Target> l_mbaChiplets;
            // Get associated MBA's on this centaur
            l_rc=fapiGetChildChiplets(i_targets_memb[i], fapi::TARGET_TYPE_MBA_CHIPLET, l_mbaChiplets);
            if (l_rc) break;
            for (uint32_t j=0; j < l_mbaChiplets.size(); j++)
            {
                std::vector<fapi::Target> l_dimm_targets;
                // Get a vector of DIMM targets
                l_rc = fapiGetAssociatedDimms(l_mbaChiplets[j], l_dimm_targets, fapi::TARGET_STATE_PRESENT);
                if (l_rc) break;
                for (uint32_t k=0; k < l_dimm_targets.size(); k++)
                {
                    l_rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_dimm_targets[k], l_dimm_functionality);
                    if (l_rc) break;

                    if(l_dimm_functionality == fapi::ENUM_ATTR_FUNCTIONAL_NON_FUNCTIONAL)
                    {
                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3)
                        {
                            if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR3_VOLT)
                            {
                                l_tolerated_dram_voltage =  MAX_TOLERATED_DDR3_VOLT;
                            }

                            if (MAX_TOLERATED_DDR3_VOLT < l_selected_dram_voltage)
                            {
                                FAPI_ERR("One or more DIMMs classified non-functional has a"
                                         " tolerated voltage below selected voltage.");
                                const fapi::Target & CHIP_TARGET = l_dimm_targets[k];
                                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                                fapiLogError(l_rc);
                            }
                        }
                        if (l_spd_dramtype == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR4)
                        {
                            if (l_tolerated_dram_voltage > MAX_TOLERATED_DDR4_VOLT)
                            {
                                l_tolerated_dram_voltage =  MAX_TOLERATED_DDR4_VOLT;
                            }

                            if (MAX_TOLERATED_DDR4_VOLT < l_selected_dram_voltage)
                            {
                                FAPI_ERR("One or more DIMMs classified non-functional has a"
                                         " tolerated voltage below selected voltage.");
                                const fapi::Target & CHIP_TARGET = l_dimm_targets[k];
                                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                                fapiLogError(l_rc);
                            }
                        }

                    }//End of functional check
                }//End of Dimm loop
                if (l_rc)
                {
                    break;
                }
            }// End of MBA loop
            if (l_rc)
            {
                break;
            }
            if ( l_tolerated_dram_voltage < l_selected_dram_voltage )
            {

                FAPI_ERR("Deconfiguring the associated Centaur.");
                const fapi::Target & CHIP_TARGET = i_targets_memb[i];
                const uint8_t &DIMM_VOLTAGE = l_selected_dram_voltage;
                FAPI_SET_HWP_ERROR(l_rc, RC_MSS_VOLT_TOLERATED_VOLTAGE_VIOLATION);
                break;
            }
        }//End of Centaur (MEMB) loop
        if (l_rc)
        {
            // Break out of do...while(0)
            break;
        }

        // Iterate through the list of centaurs again, to update ATTR
        for (uint32_t i=0; i < i_targets_memb.size(); i++)
        {
            l_rc = FAPI_ATTR_SET(ATTR_MSS_VOLT, &i_targets_memb[i], l_selected_dram_voltage);
            FAPI_INF( "mss_volt calculation complete.  MSS_VOLT: %d", l_selected_dram_voltage);
            if (l_rc) break;

	    l_rc = FAPI_ATTR_SET(ATTR_MSS_VOLT_VPP, &i_targets_memb[i], l_selected_dram_voltage_vpp);
            FAPI_INF( "mss_volt calculation complete.  MSS_VOLT_VPP: %d", l_selected_dram_voltage_vpp);
            if (l_rc) break;

        }
    }while(0);
    return l_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;
  }
// 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;
}