summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDean Sanner <dsanner@us.ibm.com>2017-07-19 06:47:47 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-07-20 09:44:50 -0400
commit76aa4662e398b137b5d775d9343d36db91622b75 (patch)
treeacc3e794c44b2e3b5ecc6e8ae39bc1f612516798 /src
parent5b3adbd548c7c1824145d2e890e2e8b31c24189a (diff)
downloadtalos-hostboot-76aa4662e398b137b5d775d9343d36db91622b75.tar.gz
talos-hostboot-76aa4662e398b137b5d775d9343d36db91622b75.zip
Support dynamic determination of powerbus freq
- Original code used ATTR_ASYNC_NEST_FREQ_MHZ to determine powerbus freq to a fixed value. This change allows the processor #V to control the powerbus freq if the MRW value for ATTR_ASYNC_NEST_FREQ_MHZ == 0xFFFF. Any other nest value will still allow the MRW to control the powerbus frequency Change-Id: I918c65a22e294d51c323ddd938f9149822016e15 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43312 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/util/utilmbox_scratch.H10
-rw-r--r--src/usr/isteps/istep06/call_host_voltage_config.C243
-rw-r--r--src/usr/isteps/istep07/call_mss_freq.C10
-rw-r--r--src/usr/util/makefile3
-rw-r--r--src/usr/util/utilmbox_scratch.C35
5 files changed, 254 insertions, 47 deletions
diff --git a/src/include/usr/util/utilmbox_scratch.H b/src/include/usr/util/utilmbox_scratch.H
index 31d67b8ee..ce4fd363d 100644
--- a/src/include/usr/util/utilmbox_scratch.H
+++ b/src/include/usr/util/utilmbox_scratch.H
@@ -97,6 +97,16 @@ namespace Util
* @return Data in mailbox scratch reg
*/
uint32_t readScratchReg(uint64_t i_addr);
+
+ /**
+ * @brief This uses the stashed away mbox scratch regs to
+ * determine the frequency the SBE booted the nest
+ * at
+ *
+ * @return uint32_t -- Nest freq SBE booted with
+ */
+ uint32_t getBootNestFreq( void);
+
};
#endif //UTILMEM_H
diff --git a/src/usr/isteps/istep06/call_host_voltage_config.C b/src/usr/isteps/istep06/call_host_voltage_config.C
index 2567d4bdc..72d5798e9 100644
--- a/src/usr/isteps/istep06/call_host_voltage_config.C
+++ b/src/usr/isteps/istep06/call_host_voltage_config.C
@@ -30,6 +30,8 @@
#include <initservice/isteps_trace.H>
#include <fapi2.H>
#include <fapi2/plat_hwp_invoker.H>
+#include <arch/pirformat.H>
+#include <sys/task.h>
//Targeting
#include <targeting/common/commontargeting.H>
@@ -37,11 +39,13 @@
#include <targeting/common/utilFilter.H>
#include <targeting/common/target.H>
+#include <p9_pm_get_poundv_bucket_attr.H>
#include <p9_pm_get_poundv_bucket.H>
#include <p9_setup_evid.H>
#include <p9_frequency_buckets.H>
-#include <initservice/mboxRegs.H>
+#include <util/utilmbox_scratch.H>
+#include <vpd/mvpdenums.H>
using namespace TARGETING;
@@ -49,49 +53,211 @@ using namespace TARGETING;
namespace ISTEP_06
{
-errlHndl_t getBootNestFreq( uint32_t & o_bootNestFreq )
+/**
+ * @brief This function will query MVPD and get the #V data for the
+ * master core
+ *
+ * @return uint32_t - Returns Indicates if half of cache is deconfigured or not.
+ * true - half cache deconfigured, only 4MB available
+ * false -> No Cache deconfigured, 8MB available.
+*/
+errlHndl_t get_first_valid_pdV_pbFreq(uint32_t& l_firstPBFreq)
{
- errlHndl_t l_err = nullptr;
-
- INITSERVICE::SPLESS::MboxScratch4_t l_scratch4;
-
- TARGETING::Target * l_sys = nullptr;
- (void) TARGETING::targetService().getTopLevelTarget( l_sys );
- assert( l_sys, "getBootNestFreq() system target is NULL");
+ //#V Keyword in LPRx Record of MVPD contains the info we need
+ //the x in LPRx is the EQ number.
+ errlHndl_t l_errl = NULL;
+ uint64_t theRecord = 0x0;
+ uint64_t theKeyword = MVPD::pdV;
+ uint8_t * theData = NULL;
+ size_t theSize = 0;
+ TARGETING::Target* l_procTarget = NULL;
+ uint64_t cpuid = task_getcpuid();
+ uint64_t l_masterCoreId = PIR_t::coreFromPir(cpuid);
+ l_firstPBFreq = 0;
+
+ do {
+ // Target: Find the Master processor
+ TARGETING::targetService().masterProcChipTargetHandle(l_procTarget);
+ assert(l_procTarget != NULL);
+
+ //Convert core number to LPRx Record ID.
+ //TODO: use a common utility function for conversion. RTC: 60552
+ switch (l_masterCoreId)
+ {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ default: // if not anything else try LRP0
+ theRecord = MVPD::LRP0;
+ break;
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ theRecord = MVPD::LRP1;
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ theRecord = MVPD::LRP2;
+ break;
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ theRecord = MVPD::LRP3;
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ theRecord = MVPD::LRP4;
+ break;
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ theRecord = MVPD::LRP5;
+ break;
+ }
+ //First call is just to get the Record size.
+ l_errl = deviceRead(l_procTarget,
+ NULL,
+ theSize,
+ DEVICE_MVPD_ADDRESS( theRecord,
+ theKeyword ) );
+
+ if (l_errl) { break; }
+
+ //2nd call is to get the actual data.
+ theData = static_cast<uint8_t*>(malloc( theSize ));
+ l_errl = deviceRead(l_procTarget,
+ theData,
+ theSize,
+ DEVICE_MVPD_ADDRESS( theRecord,
+ theKeyword ) );
+ if( l_errl ) { break; }
+
+
+ //Version 3:
+ //#V record is laid out as follows:
+ //Name: 0x2 byte
+ //Length: 0x2 byte
+ //Version: 0x1 byte **buffer starts here
+ //PNP: 0x3 byte
+ //bucket a: 0x3D byte
+ //bucket b: 0x3D byte
+ //bucket c: 0x3D byte
+ //bucket d: 0x3D byte
+ //bucket e: 0x3D byte
+ //bucket f: 0x3D byte
+ if( *theData == POUNDV_VERSION_3 )
+ {
+ //cast the voltage data into an array of buckets
+ fapi2::voltageBucketData_t* l_buckets = reinterpret_cast
+ <fapi2::voltageBucketData_t*>
+ (theData + POUNDV_BUCKET_OFFSET);
- TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- ENTER_MRK"Enter getBootNestFreq()");
- do
- {
- TARGETING::ATTR_MASTER_MBOX_SCRATCH_type l_scratchRegs;
- assert(l_sys->tryGetAttr
- <TARGETING::ATTR_MASTER_MBOX_SCRATCH>(l_scratchRegs),
- "getBootNestFreq() failed to get MASTER_MBOX_SCRATCH");
- l_scratch4.data32 = l_scratchRegs[INITSERVICE::SPLESS::SCRATCH_4];
+ for(int i = 0; i < NUM_BUCKETS; i++)
+ {
+ //To be valid the bucketId must be set (!=0) and pbFreq !=0
+ if((l_buckets[i].bucketId != 0) && (l_buckets[i].pbFreq != 0))
+ {
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "First valid #V bucket[%x], pbus_freq %d",
+ l_buckets[i].bucketId, l_buckets[i].pbFreq);
+ l_firstPBFreq = l_buckets[i].pbFreq;
+ break;
+ }
+ }
+ }
+ else
+ {
+ //emit trace for debug, but not finding pbus freq is not fatal
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "Invalid #V version, default powerbus freq to boot freq");
+ }
+ } while(0);
- TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "The nest PLL bucket id is %d",
- l_scratch4.nestPllBucket );
+ free(theData);
+ return l_errl;
+}
- size_t sizeOfPll = sizeof(NEST_PLL_FREQ_LIST)/
- sizeof(NEST_PLL_FREQ_LIST[0]);
- assert((uint8_t)(l_scratch4.nestPllBucket-1) < (uint8_t) sizeOfPll );
+errlHndl_t determineNestFreq( uint32_t& o_nestFreq )
+{
+ errlHndl_t l_err = nullptr;
+ o_nestFreq = 0x0;
- // The nest PLL bucket IDs are numbered 1 - 5. Subtract 1 to
- // take zero-based indexing into account.
- o_bootNestFreq = NEST_PLL_FREQ_LIST[l_scratch4.nestPllBucket-1];
+ TARGETING::Target * l_sys = nullptr;
+ (void) TARGETING::targetService().getTopLevelTarget( l_sys );
+ assert( l_sys, "determineNestFreq() system target is NULL");
- TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "getBootNestFreq::The boot frequency was %d: Bucket Id = %d",
- o_bootNestFreq,
- l_scratch4.nestPllBucket );
+ do
+ {
+ // Set the Nest frequency to whatever we boot with
+ // Note that all freq are supported in the nest pll buckets
+ // so we can safely customize to any -- however #V may only
+ // contain a subset. Instead of defaulting to the freq
+ // we booted with, target the freq we intend to run at:
+ //
+ // ATTR_REQUIRED_SYNCH_MODE == --> memory freq forces the nest freq,
+ // thus default to whatever we booted with
+ // ATTR_ASYNC_NEST_FREQ_MHZ != 0xFFFF --> System owner wants
+ // specified ASYNC freq to be the default
+ // ATTR_ASYNC_NEST_FREQ_MHZ == 0xFFFF --> System owner wants
+ // Nest freq to be determined by 1st valid #V
+ // bucket
+ //
+
+ //Default to the boot freq
+ o_nestFreq = Util::getBootNestFreq();
+
+ if(l_sys->getAttr<ATTR_REQUIRED_SYNCH_MODE>() == 0x1) //ALWAYS
+ {
+ //Leave nest freq as is, istep 7 will handle
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_voltage_config.C::"
+ "REQUIRED_SYNCH_MODE = 0x1, nest at boot %d Mhz",
+ o_nestFreq);
+ }
+ else if (l_sys->getAttr<ATTR_ASYNC_NEST_FREQ_MHZ>() != 0xFFFF)
+ {
+ o_nestFreq = l_sys->getAttr<ATTR_ASYNC_NEST_FREQ_MHZ>();
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_voltage_config.C::"
+ "ASYNC Freq specified by MRW, using %d Mhz",
+ o_nestFreq);
+ }
+ else
+ {
+ uint32_t l_pdV_nestFreq = 0x0;
+ l_err = get_first_valid_pdV_pbFreq( l_pdV_nestFreq );
+ if( l_err )
+ {
+ //Fatal error on VPD access
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_voltage_config.C::"
+ "Failed to get nest freq from VPD");
+ break;
+ }
+ else if (l_pdV_nestFreq != 0)
+ {
+ //got a valid freq
+ o_nestFreq = l_pdV_nestFreq;
+ TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
+ "call_host_voltage_config.C::"
+ "First valid #V controls freq, found %d Mhz",
+ o_nestFreq);
+ }
+ }
+ l_sys->setAttr<TARGETING::ATTR_FREQ_PB_MHZ>(o_nestFreq);
}while( 0 );
- TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- EXIT_MRK "Exit getBootNestFreq()");
return l_err;
}
@@ -134,19 +300,16 @@ void* call_host_voltage_config( void *io_pArgs )
// Get the system target
targetService().getTopLevelTarget(l_sys);
- // Set the Nest frequency to whatever we boot with
- l_err = getBootNestFreq( l_nestFreq );
-
+ // Set the Nest frequency based on ATTR
+ l_err = determineNestFreq(l_nestFreq);
if( l_err )
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
- "call_host_voltage_config.C::"
- "Failed getting the boot nest frequency");
+ "call_host_voltage_config.C::"
+ "Failed setting the nest frequency");
break;
}
- l_sys->setAttr<TARGETING::ATTR_FREQ_PB_MHZ>( l_nestFreq );
-
// Get the child proc chips
getChildAffinityTargets( l_procList,
l_sys,
diff --git a/src/usr/isteps/istep07/call_mss_freq.C b/src/usr/isteps/istep07/call_mss_freq.C
index 252c82d43..afa64885c 100644
--- a/src/usr/isteps/istep07/call_mss_freq.C
+++ b/src/usr/isteps/istep07/call_mss_freq.C
@@ -48,6 +48,7 @@
#include <config.h>
#include <fapi2.H>
#include <fapi2/plat_hwp_invoker.H>
+#include <util/utilmbox_scratch.H>
// SBE
@@ -114,15 +115,12 @@ void* call_mss_freq( void *io_pArgs )
}
} // End memBuf loop
- // Set PB frequency to ASYNC_FREQ_MHZ
+ // PB frequency was set in istep 6 for non MC SYNC mode
+ // allow it to change here
TARGETING::Target * l_sys = nullptr;
TARGETING::targetService().getTopLevelTarget( l_sys );
- uint32_t l_originalNest = l_sys->getAttr<TARGETING::ATTR_FREQ_PB_MHZ>();
- uint32_t l_asyncFreq =
- l_sys->getAttr<TARGETING::ATTR_ASYNC_NEST_FREQ_MHZ>();
-
- l_sys->setAttr<TARGETING::ATTR_FREQ_PB_MHZ>(l_asyncFreq);
+ uint32_t l_originalNest = Util::getBootNestFreq();
// Read MC_SYNC_MODE from SBE itself and set the attribute
uint8_t l_bootSyncMode = 0;
diff --git a/src/usr/util/makefile b/src/usr/util/makefile
index d2c86d816..d0e4659cf 100644
--- a/src/usr/util/makefile
+++ b/src/usr/util/makefile
@@ -44,4 +44,7 @@ OBJS += utilxipimage.o
SUBDIRS += test.d
SUBDIRS += runtime.d
+#Add all the extra include paths
+EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/common/include
+
include ${ROOTPATH}/config.mk
diff --git a/src/usr/util/utilmbox_scratch.C b/src/usr/util/utilmbox_scratch.C
index 6d2c57174..ff0b44589 100644
--- a/src/usr/util/utilmbox_scratch.C
+++ b/src/usr/util/utilmbox_scratch.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016 */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -41,6 +41,7 @@
#include <sys/task.h>
#include <sys/misc.h>
#include <util/utilmbox_scratch.H>
+#include <p9_frequency_buckets.H>
#include "utilbase.H"
@@ -117,4 +118,36 @@ namespace Util
mutex_unlock(&g_mutex);
}
+ uint32_t getBootNestFreq()
+ {
+ uint32_t l_bootNestFreq;
+ INITSERVICE::SPLESS::MboxScratch4_t l_scratch4;
+
+ TARGETING::Target * l_sys = nullptr;
+ (void) TARGETING::targetService().getTopLevelTarget( l_sys );
+ assert( l_sys, "getBootNestFreq() system target is NULL");
+
+ TARGETING::ATTR_MASTER_MBOX_SCRATCH_type l_scratchRegs;
+ assert(l_sys->tryGetAttr
+ <TARGETING::ATTR_MASTER_MBOX_SCRATCH>(l_scratchRegs),
+ "getBootNestFreq() failed to get MASTER_MBOX_SCRATCH");
+ l_scratch4.data32 = l_scratchRegs[INITSERVICE::SPLESS::SCRATCH_4];
+
+ size_t sizeOfPll = sizeof(NEST_PLL_FREQ_LIST)/
+ sizeof(NEST_PLL_FREQ_LIST[0]);
+
+ assert((uint8_t)(l_scratch4.nestPllBucket-1) < (uint8_t) sizeOfPll );
+
+ // The nest PLL bucket IDs are numbered 1 - 5. Subtract 1 to
+ // take zero-based indexing into account.
+ l_bootNestFreq = NEST_PLL_FREQ_LIST[l_scratch4.nestPllBucket-1];
+
+ UTIL_FT("getBootNestFreq::The boot frequency was %d: Bucket Id = %d",
+ l_bootNestFreq,
+ l_scratch4.nestPllBucket );
+
+ return l_bootNestFreq;
+ }
+
+
};
OpenPOWER on IntegriCloud