diff options
-rwxr-xr-x | src/lib/gpsm_init.c | 199 | ||||
-rwxr-xr-x | src/lib/pstates.h | 254 | ||||
-rwxr-xr-x | src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c | 12 | ||||
-rwxr-xr-x | src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h | 5 |
4 files changed, 358 insertions, 112 deletions
diff --git a/src/lib/gpsm_init.c b/src/lib/gpsm_init.c index 02ac786..ff0f68b 100755 --- a/src/lib/gpsm_init.c +++ b/src/lib/gpsm_init.c @@ -1,4 +1,4 @@ -// $Id: gpsm_init.c,v 1.9 2014/06/10 19:14:57 daviddu Exp $ +// $Id: gpsm_init.c,v 1.10 2015/05/16 17:43:12 daviddu Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/gpsm_init.c,v $ //----------------------------------------------------------------------------- // *! (C) Copyright International Business Machines Corp. 2013 @@ -25,7 +25,7 @@ /// GlobalPstateTable *gpst; /// GpsmEnablePstatesMasterInfo info; /// Pstate voltage_pstate, frequency_pstate; -/// +/// /// gpsm_initialize(pss, gpst); /// gpsm_enable_pstates_master(&info, &voltage_pstate, &frequency_pstate); /// gpsm_enable_pstates_slave(&info, voltage_pstate, frequency_pstate); @@ -48,12 +48,12 @@ /// GlobalPstateTable *gpst; /// GpsmEnablePstatesMasterInfo info; /// Pstate voltage_pstate, frequency_pstate; -/// +/// /// gpsm_initialize(pss, gpst); /// gpsm_enable_pstates_master(&info, &voltage_pstate, &frequency_pstate); /// /// <em> Send voltage_pstate and frequency_pstate to the slave and wait for -/// confirmation that the procedure has completed. </em> +/// confirmation that the procedure has completed. </em> /// /// gpsm_enable_pstates_slave(&info, voltage_pstate, frequency_pstate); /// gpsm_hw_mode(); @@ -67,11 +67,11 @@ /// PstateSuperStructure* pss; /// GlobalPstateTable *gpst; /// Pstate voltage_pstate, frequency_pstate; -/// +/// /// gpsm_initialize(pss, gpst); /// /// <em> Receive voltage_pstate and frequency_pstate from the masterand wait for -/// confirmation that the procedure has completed. </em> +/// confirmation that the procedure has completed. </em> /// /// gpsm_enable_pstates_slave(0, voltage_pstate, frequency_pstate); /// @@ -91,7 +91,7 @@ /// /// - CPM-DPLL mode should be disabled, and all undervolting controls are /// assumed to be at their nominal values. Correctness can not guaranteed -/// otherwise. +/// otherwise. /// /// - iVRM mode should be disabled prior to calling this procedure. /// Correctness can not be guaranteed otherwise. @@ -106,7 +106,7 @@ /// 'nominal_frequency_khz' field of the Global Pstate table. /// /// - All core chiplet frequencies will be under the control of the PMCR Local -/// Pstate. +/// Pstate. /// /// - The Global Actual Pstate immediately prior to the final entry of Pstate /// mode is the Pstate that most closely matches an arbitrary snapshot of the @@ -115,7 +115,7 @@ /// - The PMCR and PMICR are not modified, therefore the Global Pstate /// subsequent to the release of Hardware Pstate mode is arbitrary. /// -/// - The PMC_RAIL_BOUNDS register is set to the maximum legal bounds allowed +/// - The PMC_RAIL_BOUNDS register is set to the maximum legal bounds allowed /// by Global Pstate Table /// /// - IVRM is setup and enabled if Local Pstate Table is installed. @@ -180,7 +180,7 @@ uint8_t G_gpsm_initialized = 0; /// /// - Installs a pointer to the Global Pstate Table in the PMC hardware. /// -/// - Sets up the PMC Pstate clipping bounds. +/// - Sets up the PMC Pstate clipping bounds. /// /// - Sets up the Pstate stepping parameters from the GlobalPstateTable /// @@ -202,7 +202,7 @@ uint8_t G_gpsm_initialized = 0; /// \retval -GPSM_INVALID_ARGUMENT_GPST_INSTALL The Global Pstate table argument /// was either NULL (0) or improperly aligned, or the \a source was NULL (0). /// -/// \retval -GPSM_ILLEGAL_MODE_GPST_INSTALL The PMC does not indicate that the +/// \retval -GPSM_ILLEGAL_MODE_GPST_INSTALL The PMC does not indicate that the // system is in Firmware Pstate Mode, or the heartbeat is enabled. int @@ -226,13 +226,13 @@ gpsm_gpst_install(GlobalPstateTable* o_gpst, // Optional bypass of the procedure if (i_source->options.options & PSTATE_NO_INSTALL_GPST) { - + rc = 0; break; } // Check presence and alignment of the Pstate table, and proper Pstate - // and heartbeat modes. + // and heartbeat modes. if ((o_gpst == 0) || ((unsigned long)o_gpst % POW2_32(GLOBAL_PSTATE_TABLE_ALIGNMENT))) { @@ -369,7 +369,7 @@ gpsm_gpst_install(GlobalPstateTable* o_gpst, /// then only as part of the gpsm_initialize() procedure. The procedure: /// /// - Power on PFET Voltage Reference Circuit -/// +/// /// - Perform the binary search for IVRM Calibration /// /// - Uploads the LocalPstateArray to every core using multicast. @@ -394,13 +394,13 @@ gpsm_gpst_install(GlobalPstateTable* o_gpst, /// /// \retval 0 Success /// -/// \retval -GPSM_INVALID_ARGUMENT_LPST_INSTALL The Local Pstate array argument +/// \retval -GPSM_INVALID_ARGUMENT_LPST_INSTALL The Local Pstate array argument /// was NULL (0). /// -/// \retval -GPSM_ILLEGAL_MODE_LPST_INSTALL iVRM mode, CPM-DPLL mode, or the +/// \retval -GPSM_ILLEGAL_MODE_LPST_INSTALL iVRM mode, CPM-DPLL mode, or the /// local heartbeat appears to be enabled in at least one core. /// -/// \retval -GPSM_IVRM_CALIBRATION_TIMEOUT, if IVRM Calibration does not +/// \retval -GPSM_IVRM_CALIBRATION_TIMEOUT, if IVRM Calibration does not /// complete in time. /// /// \retval -GPSM_IVRM_GROSS_OR_FINE, if ivrm_gross_or_fine_err is set @@ -408,7 +408,7 @@ gpsm_gpst_install(GlobalPstateTable* o_gpst, /// \retval -GPSM_PSTATE_ENABLED, if pstate is enabled before enabling IVRM /// /// \retval others This API may also return non-0 codes from -/// getscom()/putscom() +/// getscom()/putscom() int gpsm_lpsa_install(const LocalPstateArray* i_lpsa, @@ -435,7 +435,7 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, // Optional bypass of this procedure - if ((i_options != 0) && + if ((i_options != 0) && (i_options->options & PSTATE_NO_INSTALL_LPSA)) { rc = 0; @@ -454,7 +454,7 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, rc = 0; break; } - + // Check the array for existence. Do an OR-combining multicast read // to see if any of the cores have iVRM enabled, have the heartbeat // enabled, or any cores are running in CPM-DPLL mode. @@ -472,13 +472,13 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, &(pdcpr.value)); if (rc) _BREAK; - if (picsr.fields.ivrm_fsm_enable || + if (picsr.fields.ivrm_fsm_enable || pdcpr.fields.cpm_filter_enable) { rc = -GPSM_ILLEGAL_MODE_LPST_INSTALL; _BREAK; } - // In case cores are in deep winkle so that ivrm caliburation + // In case cores are in deep winkle so that ivrm caliburation // will fail, insert special wakeup first pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG); cores = ~pcdr.fields.core_chiplet_deconf_vector; @@ -505,7 +505,7 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, // Check IVRM Calibration is completed // Poll for up to 100us for done before erroring out - timeout_rc = -GPSM_IVRM_CALIBRATION_TIMEOUT; + timeout_rc = -GPSM_IVRM_CALIBRATION_TIMEOUT; timeout = ssx_timebase_get() + SSX_MICROSECONDS(100); while (ssx_timebase_get() < timeout) { rc = getscom(MC_ADDRESS(PCBS_IVRM_CONTROL_STATUS_REG, @@ -533,17 +533,17 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, if (rc) _BREAK; if (ppr.fields.pcbs_ivrm_gross_or_fine_err) { rc = -GPSM_IVRM_GROSS_OR_FINE; - _BREAK; + _BREAK; } // Deassert Special Wakeup rc = occ_special_wakeup(0, cores, 25, &wakedup); if (rc) _BREAK; - + // Upload the Local Pstate Array. The array is loaded via multicast, // using the built-in auto-increment mechanism. Then upload the // Pstate bounds register via multicast. Pstate clipping is not - // modified. + // modified. rc = putscom(MC_ADDRESS(PCBS_PSTATE_TABLE_CTRL_REG, MC_GROUP_EX, PCB_MULTICAST_WRITE), @@ -580,14 +580,14 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, pivcr0.value = 0; if (i_lpsa->stepdelay_rising) - pivcr0.fields.ivrm_req_pstate_stepdelay_rising = + pivcr0.fields.ivrm_req_pstate_stepdelay_rising = i_lpsa->stepdelay_rising; - else + else pivcr0.fields.ivrm_req_pstate_stepdelay_rising = 0xFF; if (i_lpsa->stepdelay_lowering) - pivcr0.fields.ivrm_req_pstate_stepdelay_lowering = + pivcr0.fields.ivrm_req_pstate_stepdelay_lowering = i_lpsa->stepdelay_lowering; - else + else pivcr0.fields.ivrm_req_pstate_stepdelay_lowering = 0XFF; rc = putscom(MC_ADDRESS(PCBS_IVRM_VID_CONTROL_REG0, MC_GROUP_EX, PCB_MULTICAST_WRITE), @@ -653,9 +653,9 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, } while (0); - if (timeout_rc && !rc) + if (timeout_rc && !rc) return timeout_rc; - else + else return rc; } @@ -674,7 +674,7 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, /// - Initializes the Pstate resonance range limits in the register /// PCBS_RESONANT_CLOCK_CONTROL_REG1 by multicast. /// -/// - Setup parameters in PCBS_RESONANT_CLOCK_CONTROL_REG0 and turn on +/// - Setup parameters in PCBS_RESONANT_CLOCK_CONTROL_REG0 and turn on /// Resonant Clock in Hardware Pstate Mode. /// /// \note The caller is responsible for the mode-correctness of this @@ -686,14 +686,14 @@ gpsm_lpsa_install(const LocalPstateArray* i_lpsa, /// /// \retval 0 Success /// -/// \retval -GPSM_INVALID_ARGUMENT_RCLK_INSTALL The ResonantClockingSetup +/// \retval -GPSM_INVALID_ARGUMENT_RCLK_INSTALL The ResonantClockingSetup /// argument was NULL (0). /// -/// \retval -GPSM_ILLEGAL_MODE_RCLK_INSTALL Resonant clocking appears to be +/// \retval -GPSM_ILLEGAL_MODE_RCLK_INSTALL Resonant clocking appears to be /// enabled or not in manual mode in at least one configured core. /// /// \retval others This API may also return non-0 codes from -/// getscom()/putscom() +/// getscom()/putscom() int gpsm_resclk_install(const ResonantClockingSetup* i_resclk, @@ -751,7 +751,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, _BREAK; } - + // Resonant clocking is specified such that it must be enabled (in a // benign manual mode) in order to be set up. @@ -761,7 +761,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, if (!SIMICS_ENVIRONMENT) { - rc = putscom(MC_ADDRESS(0x100f0013, MC_GROUP_EX, + rc = putscom(MC_ADDRESS(0x100f0013, MC_GROUP_EX, PCB_MULTICAST_WRITE), ~0x0000020000000000ull); if (rc) _BREAK; @@ -769,7 +769,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, // Write the PCBS_RESONANT_CLOCK_CONTROL_REG1 with the // Pstate setup, clearing all manual fields. - + // If at least one resonant clocking parm was 0 in PstateSuperStructure // write the register with default values // Low Band : 2 GHZ to 3.2 GHz @@ -782,9 +782,9 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, gpst_frequency2pstate(i_gpst, 9999999, &(d_resclk.res_high_upper_ps)); prccr1.value = 0; - if (!(i_resclk->full_csb_ps && + if (!(i_resclk->full_csb_ps && i_resclk->res_low_lower_ps && - i_resclk->res_low_upper_ps && + i_resclk->res_low_upper_ps && i_resclk->res_high_lower_ps && i_resclk->res_high_upper_ps)) { prccr1.fields.full_csb_ps = d_resclk.full_csb_ps; @@ -814,7 +814,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, if (!SIMICS_ENVIRONMENT) { - rc = putscom(MC_ADDRESS(0x100f0014, MC_GROUP_EX, + rc = putscom(MC_ADDRESS(0x100f0014, MC_GROUP_EX, PCB_MULTICAST_WRITE), 0x0000020000000000ull); if (rc) _BREAK; @@ -851,7 +851,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, return rc; } - + /// Initialize the GPSM procedure mechanism /// /// \param[in] i_pss A pointer to the PstateSuperStructure containing the @@ -888,7 +888,7 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, /// master. /// /// The GPSM driver makes few assumptions about how the system firmware has -/// set up the PMC, but does require some critical setup. +/// set up the PMC, but does require some critical setup. /// /// - It is assumed that for DCM configurations the system firmware will have /// set the PMC_MODE_REG.enable_interchip_interface (to indicate a DCM @@ -915,15 +915,15 @@ gpsm_resclk_install(const ResonantClockingSetup* i_resclk, /// \retval -GPSM_INVALID_MAGIC The 'magic number' of the PstateSuperStructure /// is different from that expected. /// -/// \retval -GPSM_ILLEGAL_MODE_GPSM_INIT Either the PMC indicates a Pstate mode -/// is active, one or more cores appear to have iVRM enabled, or one or more +/// \retval -GPSM_ILLEGAL_MODE_GPSM_INIT Either the PMC indicates a Pstate mode +/// is active, one or more cores appear to have iVRM enabled, or one or more /// cores appear to have resonant clocking enabled. /// /// \retval others This API may also return codes from gpsm_gpst_install(), /// gpsm_lpsa_install() and gpsm_resclk_install(). int -gpsm_initialize(const PstateSuperStructure* i_pss, +gpsm_initialize(const PstateSuperStructure* i_pss, GlobalPstateTable* o_gpst) { pmc_mode_reg_t pmr; @@ -942,8 +942,9 @@ gpsm_initialize(const PstateSuperStructure* i_pss, } if (i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD1 && - i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD2 && - i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD3 ) { + i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD2 && + i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD3 && + i_pss->magic != PSTATE_SUPERSTRUCTURE_GOOD4) { rc = -GPSM_INVALID_MAGIC; _BREAK; @@ -959,7 +960,7 @@ gpsm_initialize(const PstateSuperStructure* i_pss, _BREAK; } if (!pmr.fields.enable_fw_pstate_mode) { - + pmr.fields.enable_fw_pstate_mode = 1; out32(PMC_MODE_REG, pmr.value); } @@ -968,7 +969,7 @@ gpsm_initialize(const PstateSuperStructure* i_pss, pmr.fields.halt_pstate_master_fsm = 0; out32(PMC_MODE_REG, pmr.value); - + // Initialize interrupt handling ssx_semaphore_create(&G_gpsm_protocol_semaphore, 0, 1); @@ -1011,12 +1012,12 @@ gpsm_initialize(const PstateSuperStructure* i_pss, rc = gpsm_gpst_install(o_gpst, &(i_pss->gpst)); if (rc) _BREAK; - rc = gpsm_lpsa_install(&i_pss->lpsa, + rc = gpsm_lpsa_install(&i_pss->lpsa, &(i_pss->gpst.options)); if (rc) _BREAK; rc = gpsm_resclk_install(&i_pss->resclk, - &(i_pss->gpst), + &(i_pss->gpst), &(i_pss->gpst.options)); if (rc) _BREAK; @@ -1050,9 +1051,9 @@ gpsm_initialize(const PstateSuperStructure* i_pss, // Racall that the inputs are VID codes (lower VID --> higher voltage) static int -_manual_step_voltage(const uint8_t i_currentVdd, +_manual_step_voltage(const uint8_t i_currentVdd, const uint8_t i_currentVcs, - const uint8_t i_targetVdd, + const uint8_t i_targetVdd, const uint8_t i_targetVcs) { int rc, parity; @@ -1110,12 +1111,12 @@ _manual_step_voltage(const uint8_t i_currentVdd, out32(PMC_GLOBAL_ACTUAL_VOLTAGE_REG, pgavr.value); } if (rc) _BREAK; - + rc = gpsm_quiesce(); if (rc) _BREAK; } while (0); - + return rc; } @@ -1124,8 +1125,8 @@ _manual_step_voltage(const uint8_t i_currentVdd, // initialization of Pstates. The set of cores to operate on is taken from // the current value of the PMC_CORE_DECONFIGURATION_REG. // -// At entry it assumed that iVRM and CPM-DPLL are disabled. It also clears -// possible safe mode dails before enable pstate. +// At entry it assumed that iVRM and CPM-DPLL are disabled. It also clears +// possible safe mode dails before enable pstate. // // At exit, the following will be true for all configured cores: // @@ -1146,7 +1147,7 @@ _manual_step_voltage(const uint8_t i_currentVdd, // in the PMCR are not modified. static int -_enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, +_enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, const Pstate i_frequency_pstate, const gpst_entry_t i_entry) { @@ -1167,7 +1168,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, /* In the event of no configured cores, FW requested to not error out */ //rc = -GPSM_CONFIGURATION_ERROR; - rc = 0; + rc = 0; // Do for each core chiplet... configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG); @@ -1175,7 +1176,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, // Turn off possible safe mode so we can move pstate pcbs_hb_config(0, configured_cores, 0, 0, 0, &bogus); pmc_hb_config(0, 0, 0, &bogus); - + for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) { if (!(configured_cores & 0x80000000)) continue; @@ -1209,7 +1210,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, // Update Fmin, Fmax, Fmax bias and Pstate0 frequency. - + pfcr.value = 0; pfcr.fields.dpll_fmin = fPstate; pfcr.fields.dpll_fmax = fPstate; @@ -1234,29 +1235,29 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, // _local_ pstate table. // \bug Workaround, since pre_vret_pstate is set to pmin currently - // until pstate super structure and pstate data block procedure + // until pstate super structure and pstate data block procedure // support an entry as non-functional pstate, need to set lower - // clip bound to be the pstate one above pmin to make pmin + // clip bound to be the pstate one above pmin to make pmin // essentially a non-functional pstate for now - + ppmbr.value = 0; ppmbr.fields.pmin_clip = gpst_pmin(i_gpst)+1; ppmbr.fields.pmax_clip = gpst_pmax(i_gpst); // This fix is added per SW260911 // Minimum Frequency in the system is given by MRW attribute - // PState Datablock procedure will read the attribute then - // convert it into pstate _pfloor_ and put it into - // Global Pstate Table. GPSM here consumes the value + // PState Datablock procedure will read the attribute then + // convert it into pstate _pfloor_ and put it into + // Global Pstate Table. GPSM here consumes the value // and set both lower bounds: pmin_rail(PMC) and pmin_clip(PCBS) // and two safe pstates: pvsafe(PMc) and psafe(PCBS) to be // _pfloor_ if _pfloor_ is higher than their default(gpst_pmin) - // so that we should never run with frequency below the floor + // so that we should never run with frequency below the floor // even in safe mode if (ppmbr.fields.pmin_clip < i_gpst->pfloor && i_gpst->pfloor != 0) ppmbr.fields.pmin_clip = i_gpst->pfloor; - rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_BOUNDS_REG, + rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_BOUNDS_REG, core), ppmbr.value); if (rc) _BREAK; @@ -1284,7 +1285,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, &(ppvcr.value)); if (rc) _BREAK; - ppvcr.fields.pglobal_actual = i_frequency_pstate; + ppvcr.fields.pglobal_actual = i_frequency_pstate; ppvcr.fields.maxregvcs = i_entry.fields.maxreg_vdd; ppvcr.fields.maxregvdd = i_entry.fields.maxreg_vcs; ppvcr.fields.evidvcs_eff = i_entry.fields.evid_vdd_eff; @@ -1294,7 +1295,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, ppvcr.value); if (rc) _BREAK; - + // Enable Pstate in PCB Slave rc = getscom(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, core), @@ -1341,7 +1342,7 @@ _enable_pstates_core_prologue(const GlobalPstateTable* i_gpst, // Actual. This procedure releases frequency override mode and core-level // Pstate operations commence. // -// retval -GPSM_BABYSTEPPER_SYNC_TIMEOUT, if baby stepper sync +// retval -GPSM_BABYSTEPPER_SYNC_TIMEOUT, if baby stepper sync // local_pstate_actual times out // static int @@ -1359,21 +1360,21 @@ _enable_pstates_core_epilogue(void) configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG); for (core = 0; core < PGP_NCORES; core++, configured_cores <<= 1) { - + if (!(configured_cores & 0x80000000)) continue; - + pmgp1.value = 0; pmgp1.fields.dpll_freq_override_enable = 1; - + rc = putscom(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, core), ~pmgp1.value); if (rc) _BREAK; } if (rc) _BREAK; - + // For Babystepper to catch up sync the local_pstate_actual // Poll for up to 300us for done before erroring out - + timeout_rc = -GPSM_BABYSTEPPER_SYNC_TIMEOUT; timeout = ssx_timebase_get() + SSX_MICROSECONDS(300); while (ssx_timebase_get() < timeout) { @@ -1381,7 +1382,7 @@ _enable_pstates_core_epilogue(void) MC_GROUP_EX, PCB_MULTICAST_AND), &(ppmsr.value)); if (rc) _BREAK; - if (ppmsr.fields.local_pstate_actual == + if (ppmsr.fields.local_pstate_actual == ppmsr.fields.global_pstate_actual) { timeout_rc = 0; break; @@ -1391,9 +1392,9 @@ _enable_pstates_core_epilogue(void) } while(0); - if (timeout_rc && !rc) + if (timeout_rc && !rc) return timeout_rc; - else + else return rc; } @@ -1457,16 +1458,16 @@ gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info, // the PMIN frequency prior to starting Pstate operations. It is // always safe to change the Pstate from "PMIN", regardless of the // actual external voltage, since the PMIN frequency is safe at any - // voltage. + // voltage. if (!(gpst->options.options & PSTATE_FORCE_INITIAL_PMIN)) { - rc = vrm_voltage_read(SPIVRM_PORT(0), - VRM_RD_VDD_RAIL, + rc = vrm_voltage_read(SPIVRM_PORT(0), + VRM_RD_VDD_RAIL, &(o_info->currentVdd)); if (rc) _BREAK; - rc = vrm_voltage_read(SPIVRM_PORT(0), - VRM_RD_VCS_RAIL, + rc = vrm_voltage_read(SPIVRM_PORT(0), + VRM_RD_VCS_RAIL, &(o_info->currentVcs)); if (rc) _BREAK; @@ -1476,14 +1477,14 @@ gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info, if (rc) { SSX_PANIC(GPSM_BUG); /* This can't happen */ } - + o_info->currentVdd = voltage_entry.fields.evid_vdd; o_info->currentVcs = voltage_entry.fields.evid_vcs; } - - search_rc = gpst_vdd2pstate(gpst, o_info->currentVdd, + + search_rc = gpst_vdd2pstate(gpst, o_info->currentVdd, o_voltage_pstate, &voltage_entry); - if (search_rc && + if (search_rc && (search_rc != -GPST_PSTATE_CLIPPED_LOW_GPST_V2P) && (search_rc != -GPST_PSTATE_CLIPPED_HIGH_GPST_V2P)) { rc = search_rc; @@ -1506,7 +1507,7 @@ gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info, if ((search_rc == 0)||(search_rc = -GPST_PSTATE_CLIPPED_LOW_GPST_V2P)) { - rc = _manual_step_voltage(o_info->currentVdd, o_info->currentVcs, + rc = _manual_step_voltage(o_info->currentVdd, o_info->currentVcs, o_info->targetVdd, o_info->targetVcs); if (rc) _BREAK; @@ -1532,7 +1533,7 @@ gpsm_enable_pstates_master(GpsmEnablePstatesMasterInfo* o_info, /// \param[in] i_info This structure is populated by /// gpsm_enable_pstates_master(), and only required in an SCM or DCM master. /// When this API is called on a DCM slave the parameter may be passed as NULL -/// (0). +/// (0). /// /// \param[in] i_voltage_pstate This parameter is computed by /// gpsm_enable_pstates_master(), and is required in every case. @@ -1565,7 +1566,7 @@ gpsm_enable_pstates_slave(const GpsmEnablePstatesMasterInfo* i_info, // guarantees that the GPSM is quiesced at this point for the slave; // the master must already be quiesced. Recover a pointer to the // Pstate table from PMC. - + if (gpsm_dcm_slave_p()) { rc = gpsm_fw_mode(); @@ -1587,28 +1588,28 @@ gpsm_enable_pstates_slave(const GpsmEnablePstatesMasterInfo* i_info, gpst = gpsm_gpst(); gpst_entry(gpst, i_voltage_pstate, 0, &voltage_entry); - + // Execute the core prologue. An SCM or DCM master may need to move // voltage after the frequency move. Since this is guaranteed to be a // safe downward move (otherwise we would have moved voltage already), // it is safe for the DCM slave to go ahead and finish its Pstate // setup before the master has moved the voltage. - rc = _enable_pstates_core_prologue(gpst, i_frequency_pstate, + rc = _enable_pstates_core_prologue(gpst, i_frequency_pstate, voltage_entry); if (rc) _BREAK; if (!gpsm_dcm_slave_p()) { - rc = _manual_step_voltage(i_info->currentVdd, i_info->currentVcs, + rc = _manual_step_voltage(i_info->currentVdd, i_info->currentVcs, i_info->targetVdd, i_info->targetVcs); if (rc) _BREAK; } - + // The Voltage and Frequency state is now consistent in the cores and // in PMC. Make sure that PMC modes are set correctly for Hardware - // Pstate Mode. + // Pstate Mode. pmr.value = in32(PMC_MODE_REG); pmr.fields.enable_pstate_voltage_changes = 1; diff --git a/src/lib/pstates.h b/src/lib/pstates.h index 3e4b1c9..2aeb52c 100755 --- a/src/lib/pstates.h +++ b/src/lib/pstates.h @@ -1,7 +1,7 @@ #ifndef __PSTATES_H__ #define __PSTATES_H__ -// $Id: pstates.h,v 1.3 2014/05/27 15:35:05 daviddu Exp $ +// $Id: pstates.h,v 1.5 2015/05/18 15:56:07 daviddu Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pstates.h,v $ //----------------------------------------------------------------------------- // *! (C) Copyright International Business Machines Corp. 2013 @@ -46,6 +46,42 @@ /// CPM Inflection Points #define CPM_RANGES 8 +/// VPD #V Operating Points +#define VPD_PV_POINTS 4 +#define VPD_PV_ORDER_STR {"PowerSave", "Nominal ", "Turbo ", "UltraTurbo"} +#define POWERSAVE 0 +#define NOMINAL 1 +#define TURBO 2 +#define ULTRA 3 + +/// IDDQ readings +#define CORE_IDDQ_MEASUREMENTS 6 +#define CHIP_IDDQ_MEASUREMENTS 1 + +#define CORE_IDDQ_ARRAY_VOLTAGES {0.80, 0.90, 1.00, 1.10, 1.20, 1.25} +#define CHIP_IDDQ_ARRAY_VOLTAGES {1.10} + +/// Iddq LRPx and CRPx elements +#define LRP_IDDQ_RECORDS CORE_IDDQ_MEASUREMENTS +#define CRP_IDDQ_RECORDS CHIP_IDDQ_MEASUREMENTS +#define IDDQ_READINGS_PER_IQ 2 + +/// LRPx mapping to Core measurements 1 2 3 4 5 6 +/// Index 0 1 2 3 4 5 +#define CORE_IDDQ_MEASUREMENTS_ORDER { 1, 2, 3, 4, 5, 0} +#define CORE_IDDQ_MEASUREMENT_VOLTAGES {"0.90", "1.00", "1.10", "1.20", "1.25", "0.80"} +#define CORE_IDDQ_VALIDITY_CHECK { 1, 1, 1, 1, 1, 0} +#define CORE_IDDQ_VALID_SECOND { 1, 1, 1, 1, 1, 0} + +// CRPx mapping to Chip measurements 0 +#define CHIP_IDDQ_MEASUREMENTS_ORDER { 0 } +#define CHIP_IDDQ_MEASUREMENT_VOLTAGES {"1.10"} +#define CHIP_IDDQ_VALID_SECOND { 0 } + +/// WOF Items +#define NUM_ACTIVE_CORES 12 +#define MAX_UT_PSTATES 64 // Oversized + // Error/Panic codes for support routines #define VRM11_INVALID_VOLTAGE 0x00876101 @@ -89,12 +125,13 @@ /// This magic number identifies a particular version of the /// PstateSuperStructure and its substructures. The version number should be /// kept up to date as changes are made to the layout or contents of the -/// structure. +/// structure. -#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453033ull /* PSTATE03 */ +#define PSTATE_SUPERSTRUCTURE_MAGIC 0x5053544154453034ull /* PSTATE04 */ #define PSTATE_SUPERSTRUCTURE_GOOD1 0x5053544154453031ull /* PSTATE01 */ #define PSTATE_SUPERSTRUCTURE_GOOD2 0x5053544154453032ull /* PSTATE02 */ #define PSTATE_SUPERSTRUCTURE_GOOD3 0x5053544154453033ull /* PSTATE03 */ +#define PSTATE_SUPERSTRUCTURE_GOOD4 0x5053544154453034ull /* PSTATE03 */ /// \defgroup pstate_options Pstate Options @@ -125,6 +162,10 @@ /// to come up at a low frequency. #define PSTATE_FORCE_INITIAL_PMIN 0x10 +/// Flag to indicated that the 0.8V readings in the IDDQ Table are valid +#define PSTATE_IDDQ_0P80V_VALID 0x20 +#define PSTATE_IDDQ_0P80V_INVALID ~PSTATE_IDDQ_0P80V_VALID + /// @} #ifndef __ASSEMBLER__ @@ -208,7 +249,7 @@ typedef union lpst_entry { uint64_t vdd_eco_pwrratio : 6; uint64_t vcs_eco_pwrratio : 6; uint64_t ps1_vid_incr : 3; - uint64_t ps2_vid_incr : 3; + uint64_t ps2_vid_incr : 3; uint64_t ps3_vid_incr : 3; uint64_t reserved47 : 7; uint64_t inc_step : 3; @@ -220,7 +261,7 @@ typedef union lpst_entry { uint64_t inc_step : 3; uint64_t reserved47 : 7; uint64_t ps3_vid_incr : 3; - uint64_t ps2_vid_incr : 3; + uint64_t ps2_vid_incr : 3; uint64_t ps1_vid_incr : 3; uint64_t vcs_eco_pwrratio : 6; uint64_t vdd_eco_pwrratio : 6; @@ -386,11 +427,29 @@ typedef struct { /// The Pstate for minimum core frequency in the system, defined by MRW uint8_t pfloor; + /// The Pstate representing the Turbo VPD point + Pstate turbo_ps; + + /// The Pstate representing the Nominal VPD point + Pstate nominal_ps; + + /// The Pstate representing the PowerSave VPD point + Pstate powersave_ps; + + /// The Pstate within the GPST which is the maximum for which iVRMs are + /// defined. This allows WOF Pstate and iVRM Pstates to be non-overlapping + /// to simplify characterization. + Pstate ivrm_max_ps; + + /// The number of entries over which iVRM enablement is possible. The + /// starting entry is PMin. + uint8_t ivrm_entries; + } GlobalPstateTable; /// This macro creates a properly-aligned Global Pstate table structure as a -/// static initialization. +/// static initialization. #define GLOBAL_PSTATE_TABLE(x) \ GlobalPstateTable x \ @@ -505,6 +564,175 @@ typedef union { } CpmPstateModeRanges; +/// A VPD operating point +/// +/// VPD operating points are stored without load-line correction. Frequencies +/// are in MHz, voltages are specified in units of 5mV, and characterization +/// currents are specified in units of 500mA. +/// +/// \bug The assumption is that the 'maxreg' points for the iVRM will also be +/// supplied in the VPD in units of 5mv. If they are supplied in some other +/// form then chip_characterization_create() will need to be modified. + +typedef struct { + + uint32_t vdd_5mv; + uint32_t vcs_5mv; + uint32_t vdd_maxreg_5mv; + uint32_t vcs_maxreg_5mv; + uint32_t idd_500ma; + uint32_t ics_500ma; + uint32_t frequency_mhz; + +} VpdOperatingPoint; + +/// System Power Distribution Paramenters +/// +/// Parameters set by system design that influence the power distribution +/// for a rail to the processor module. This values are typically set in the +/// system machine readable workbook and are used in the generation of the +/// Global Pstate Table. This values are carried in the Pstate SuperStructure +/// for use and/or reference by OCC firmware (eg the WOF algorithm) + +typedef struct { + + /// Loadline + /// Impedance (binary microOhms) of the load line from a processor VDD VRM + /// to the Processor Module pins. + uint32_t loadline_uohm; + + /// Distribution Loss + /// Impedance (binary in microOhms) of the VDD distribution loss sense point + /// to the circuit. + uint32_t distloss_uohm; + + /// Distribution Offset + /// Offset voltage (binary in microvolts) to apply to the rail VRM + /// distribution to the processor module. + uint32_t distoffset_uv; + +} SysPowerDistParms; + + + +/// IDDQ Reading Type +/// Each entry is 2 bytes. The values are in 10mA units; this allow for a +/// maximum value of 655.36A represented. +/// +typedef uint16_t iddq_entry_t; + +/// IDDQ Reading +/// +/// Structure with "raw" and "temperature corrected" values. See VPD +/// documentation for the correction function that is applied to the raw +/// value to load the corrected value. +/// +typedef union { + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + iddq_entry_t iddq_raw_value; + iddq_entry_t iddq_corrected_value; +#else + iddq_entry_t iddq_corrected_value; + iddq_entry_t iddq_raw_value; +#endif // _BIG_ENDIAN + } fields; + +} IddqReading; + +/// Iddq Table +/// +/// A set of arrays of leakage values (Iddq) collected at various voltage +/// conditions during manufacturing test that will feed into the Workload +/// Optimized Frequency algorithms on the OCC. These values are not installed +/// in any hardware facilities. +/// +typedef struct { + + /// IDDQ version + uint8_t iddq_version; + + /// VDD IDDQ readings + IddqReading iddq_vdd[CORE_IDDQ_MEASUREMENTS]; + + /// VCS IDDQ readings + IddqReading iddq_vcs[CORE_IDDQ_MEASUREMENTS]; + + /// VIO IDDQ readings + IddqReading iddq_vio[CHIP_IDDQ_MEASUREMENTS]; + +} IddqTable; + + + +/// UltraTurbo Segment VIDs by Core Count +typedef struct { + + /// Number of Segment Pstates + uint8_t ut_segment_pstates; + + /// Maximum number of core possibly active + uint8_t ut_max_cores; + + /// VDD VID modification + /// 1 core active = offset 0 + /// 2 cores active = offset 1 + /// ... + /// 12 cores active = offset 11 + uint8_t ut_segment_vdd_vid[MAX_UT_PSTATES][NUM_ACTIVE_CORES]; + + /// VCS VID modification + /// 1 core active = offset 0 + /// 2 cores active = offset 1 + /// ... + /// 12 cores active = offset 11 + uint8_t ut_segment_vcs_vid[MAX_UT_PSTATES][NUM_ACTIVE_CORES]; + +} VIDModificationTable; + +/// Workload Optimized Frequency (WOF) Elements +/// +/// Structure defining various control elements needed by the WOF algorithm +/// firmware running on the OCC. +/// +typedef struct { + + /// WOF Enablement + uint8_t wof_enabled; + + /// Operating points + /// + /// VPD operating points are stored without load-line correction. Frequencies + /// are in MHz, voltages are specified in units of 5mV, and currents are + /// in units of 500mA. + VpdOperatingPoint operating_points[VPD_PV_POINTS]; + + /// Loadlines and Distribution values for the VDD rail + SysPowerDistParms vdd_sysparm; + + /// Loadlines and Distribution values for the VCS rail + SysPowerDistParms vcs_sysparm; + + /// TDP<>RDP Current Factor + /// Value read from ??? VPD + /// Defines the scaling factor that converts current (amperage) value from + /// the Thermal Design Point to the Regulator Design Point (RDP) as input + /// to the Workload Optimization Frequency (WOF) OCC algorithm. + /// + /// This is a ratio value and has a granularity of 0.01 decimal. Data + /// is held in hexidecimal (eg 1.22 is represented as 122 and then converted + /// to hex 0x7A). + uint32_t tdp_rdp_factor; + + /// UltraTurbo Segment VIDs by Core Count + VIDModificationTable ut_vid_mod; + + uint8_t pad[4]; + +} WOFElements; + + /// The layout of the data created by the Pstate table creation firmware /// /// This structure is only used for passing Pstate data from the FSP into OCC, @@ -533,6 +761,12 @@ typedef struct { /// CPM Pstate ranges CpmPstateModeRanges cpmranges; + /// Iddq Table + IddqTable iddq; + + /// WOF Controls + WOFElements wof; + } PstateSuperStructure; @@ -549,8 +783,8 @@ int bias_vid11(Vid11 vid, int bias, Vid11* biased_fcode); int -gpst_entry(const GlobalPstateTable* gpst, - const Pstate pstate, +gpst_entry(const GlobalPstateTable* gpst, + const Pstate pstate, const int bias, gpst_entry_t* entry); @@ -560,8 +794,8 @@ gpst_frequency2pstate(const GlobalPstateTable* gpst, Pstate* pstate); int -gpst_vdd2pstate(const GlobalPstateTable* gpst, - const uint8_t vdd, +gpst_vdd2pstate(const GlobalPstateTable* gpst, + const uint8_t vdd, Pstate* pstate, gpst_entry_t* entry); diff --git a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c index 274f028..a6719ac 100755 --- a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c +++ b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.c @@ -1067,10 +1067,11 @@ errlHndl_t data_store_pstate_super(const cmdh_fsp_cmd_t * i_cmd_ptr, do { // Command Length Check - make sure we have all the data - if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) < CMDH_CNFGDATA_PSTATESS_DATALEN) + // Lenght check depends on the version of the Pstate Superstructure + if( CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) < CMDH_CNFGDATA_PSTATESS_MIN_DATALEN) { TRAC_ERR("data_store_pstate_super: Invalid command length! expected[%u] received[%u]", - CMDH_CNFGDATA_PSTATESS_DATALEN, + CMDH_CNFGDATA_PSTATESS_MIN_DATALEN, CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr)); // Build Error Response packet, it will get 'rebuilt' later, but @@ -1082,7 +1083,7 @@ errlHndl_t data_store_pstate_super(const cmdh_fsp_cmd_t * i_cmd_ptr, // Only initialize Pstate once if( G_gpsm_initialized == 0 ) { - // Initialze Pstate Table from PstateSuperStructure passed in + // Initialize Pstate Table from PstateSuperStructure passed in // via the DATA in this command. l_errlHndl = proc_gpsm_pstate_initialize(&l_cmd_ptr->pstatess); } @@ -1091,6 +1092,11 @@ errlHndl_t data_store_pstate_super(const cmdh_fsp_cmd_t * i_cmd_ptr, { // Change Data Request Mask to indicate we got this data G_data_cnfg->data_mask |= DATA_MASK_PSTATE_SUPERSTRUCTURE; + + TRAC_IMP("Pstate SuperStructure is valid: Magic_number[0x%08X%08X] Size[%d]", + (uint32_t)(l_cmd_ptr->pstatess.magic >> 32), + (uint32_t)(l_cmd_ptr->pstatess.magic & 0x00000000ffffffffull), + CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr) - 4); } } while(0); diff --git a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h index ce8131b..6affe10 100755 --- a/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h +++ b/src/occ/cmdh/cmdh_fsp_cmds_datacnfg.h @@ -98,8 +98,13 @@ typedef struct __attribute__ ((packed)) uint8_t reserved[3]; PstateSuperStructure pstatess; }cmdh_store_cnfgdata_pstatess_t; + #define CMDH_CNFGDATA_PSTATESS_DATALEN (sizeof(PstateSuperStructure) + 4) +//At a minimum, OCC expects this size: Pstate superstructure for versions +//PSTATE01, PSTATE02, or PSTATE03, plus 4 bytes (from format and reserved bytes) +#define CMDH_CNFGDATA_PSTATESS_MIN_DATALEN (1904 + 4) + // Used by TMGT to send OCC the frequencies for each mode. typedef struct __attribute__ ((packed)) { |