// Function Specification // // Name: amec_slv_freq_smh // // Description: Slave OCC's frequency state machine. // This function will run every tick. // // Thread: RealTime Loop // // Task Flags: // // End Function Specification void amec_slv_freq_smh(void) { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ uint16_t k = 0; int8_t l_pstate = 0; /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ for (k=0; k<MAX_NUM_CORES; k++) { switch (g_amec->proc[0].core[k].f_sms) { case AMEC_CORE_FREQ_IDLE_STATE: // Translate frequency request into a Pstate l_pstate = proc_freq2pstate(g_amec->proc[0].core[k].f_request); // Fall through case AMEC_CORE_FREQ_PROCESS_STATE: if(G_sysConfigData.system_type.kvm) { // update core bounds on kvm systems proc_set_core_bounds(gpst_pmin(&G_global_pstate_table) + 1, (Pstate) l_pstate, k); } else { // update core pstate request on non-kvm systems proc_set_core_pstate((Pstate) l_pstate, k); } break; } } }
// Function Specification // // Name: populate_pstate_to_sapphire_tbl // // Description: // // End Function Specification void populate_pstate_to_sapphire_tbl() { uint8_t i = 0; GlobalPstateTable *l_gpst_ptr = NULL; uint16_t l_turboFreq = 0; uint16_t l_ultraturboFreq = 0; if(G_sysConfigData.sys_mode_freq.table[OCC_MODE_STURBO] == 0) { // In this case, there is no UltraTurbo frequency defined. For OPAL-OCC // interface, make UltraTurbo = Turbo frequency l_turboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]; l_ultraturboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]; } else { l_turboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_STURBO]; l_ultraturboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]; } memset(&G_sapphire_table, 0, sizeof(sapphire_table_t)); l_gpst_ptr = gpsm_gpst(); const int8_t l_pmax = (int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1; G_sapphire_table.config.valid = 0x01; // default 0x01 G_sapphire_table.config.version = 0x02; // default 0x02 G_sapphire_table.config.throttle = NO_THROTTLE; // default 0x00 G_sapphire_table.config.pmin = gpst_pmin(&G_global_pstate_table)+1; //Per David Du, we must use pmin+1 to avoid gpsa hang G_sapphire_table.config.pnominal = (int8_t)proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]); G_sapphire_table.config.turbo = (int8_t) proc_freq2pstate(l_turboFreq); G_sapphire_table.config.ultraTurbo = (int8_t) proc_freq2pstate(l_ultraturboFreq); int8_t l_tempPmax = gpst_pmax(&G_global_pstate_table); const uint16_t l_entries = l_tempPmax - G_sapphire_table.config.pmin + 1; const uint8_t l_idx = l_gpst_ptr->entries-1; for (i = 0; i < l_entries; i++) { G_sapphire_table.data[i].pstate = (int8_t) l_pmax - i; G_sapphire_table.data[i].flag = 0; // default 0x00 if (i < l_gpst_ptr->entries) { G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[i].fields.evid_vdd; G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[i].fields.evid_vcs; } else { // leave the VDD & VCS Vids the same as the "Pstate Table Pmin" G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[l_idx].fields.evid_vdd; G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[l_idx].fields.evid_vcs; } // extrapolate the frequency G_sapphire_table.data[i].freq_khz = l_gpst_ptr->pstate0_frequency_khz + (G_sapphire_table.data[i].pstate * l_gpst_ptr->frequency_step_khz); } uint8_t l_core = 0; uint16_t l_maxFreq = l_turboFreq; //Write the max pstate for each possible number of active cores. for (l_core = 1; l_core <= MAX_CORES; l_core++) { //If wof is enabled, then use the wof uplift table to find the max freq for given # of active cores. if (g_amec->wof.enable_parm != 0) { l_maxFreq = amec_wof_get_max_freq(l_core); } //If the l_core (# of Active cores) is greater than G_wof_max_cores_per_chip //then return 0x01 for Pstate. if (l_core > G_wof_max_cores_per_chip) { G_sapphire_table.activeCore_max_pstate[l_core - 1] = 0x01; } else { G_sapphire_table.activeCore_max_pstate[l_core - 1] = (int8_t)proc_freq2pstate((uint32_t)l_maxFreq); } } //For Version 0x02 of the interface, we need to make the first four reserved bytes //equal to 0x01 to prevent confusion for(i=0; i<4; i++) { G_sapphire_table.pad[i] = 0x01; } }
void gpst_print(FILE *stream, GlobalPstateTable *gpst) { // Endian-corrected scalar Pstate fields uint32_t options; uint32_t pstate0_frequency_khz, frequency_step_khz; uint8_t entries, pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value; // Pstate pmin, pvsafe, psafe; Pstate pvsafe, psafe; // Endian-corrected vector Pstate fields gpst_entry_t entry; // Other local variables int i; uint8_t evid_vdd, evid_vcs, evid_vdd_eff, evid_vcs_eff, maxreg_vdd, maxreg_vcs; int8_t pstate; char evid_vdd_str[FORMAT_10UV_STRLEN]; char evid_vcs_str[FORMAT_10UV_STRLEN]; char evid_vdd_eff_str[FORMAT_10UV_STRLEN]; char evid_vcs_eff_str[FORMAT_10UV_STRLEN]; char maxreg_vdd_str[FORMAT_10UV_STRLEN]; char maxreg_vcs_str[FORMAT_10UV_STRLEN]; char* ivrm_max_ps_str; char* ultraturbo_ps_str; char* turbo_ps_str; char* nominal_ps_str; char* powersave_ps_str; // Get endian-corrected scalars options = revle32(gpst->options.options); pstate0_frequency_khz = revle32(gpst->pstate0_frequency_khz); frequency_step_khz = revle32(gpst->frequency_step_khz); entries = gpst->entries; pstate_stepsize = gpst->pstate_stepsize; vrm_stepdelay_range = gpst->vrm_stepdelay_range; vrm_stepdelay_value = gpst->vrm_stepdelay_value; // pmin = gpst->pmin; pvsafe = gpst->pvsafe; psafe = gpst->psafe; fprintf(stream, "---------------------------------------------------------------------------------------------------------\n"); fprintf(stream, "Global Pstate Table @ %p\n", gpst); fprintf(stream, "---------------------------------------------------------------------------------------------------------\n"); fprintf(stream, "%d Entries from %+d to %+d\n", entries, gpst_pmin(gpst), gpst_pmax(gpst)); fprintf(stream, "Frequency Step = %u KHz\n", frequency_step_khz); fprintf(stream, "Pstate 0 Frequency = %u KHz\n", pstate0_frequency_khz); fprintf(stream, "Pstate 0 Frequency Code (per core) :"); for (i = 0; i < PGP_NCORES; i++) { if ((i != 0) && ((i % 4) == 0)) { fprintf(stream, "\n "); } fprintf(stream, " 0x%03x", revle16(gpst->pstate0_frequency_code[i])); } fprintf(stream, "\n"); fprintf(stream, "DPLL Fmax Bias (per core) :"); for (i = 0; i < PGP_NCORES; i++) { fprintf(stream, " %d", gpst->dpll_fmax_bias[i]); } fprintf(stream, "\n"); fprintf(stream, "Pstate Step Size %u, VRM Range %u, VRM Delay %u\n", pstate_stepsize, vrm_stepdelay_range, vrm_stepdelay_value); fprintf(stream, "Pvsafe %d, Psafe %d\n", pvsafe, psafe); fprintf(stream, "iVRM Maximum Pstate %d, Number of GPST entries (from Psafe) where iVRMs are enabled: %d\n", gpst->ivrm_max_ps, gpst->ivrm_entries); if (options == 0) { fprintf(stream, "No Options\n"); } else { fprintf(stream, "Options 0x%08x:\n", options); if (options & PSTATE_NO_COPY_GPST) { fprintf(stream, " PSTATE_NO_COPY_GPST\n"); } if (options & PSTATE_NO_INSTALL_GPST) { fprintf(stream, " PSTATE_NO_INSTALL_GPST\n"); } if (options & PSTATE_NO_INSTALL_LPSA) { fprintf(stream, " PSTATE_NO_INSTALL_LPSA\n"); } if (options & PSTATE_NO_INSTALL_RESCLK) { fprintf(stream, " PSTATE_NO_INSTALL_RESCLK\n"); } if (options & PSTATE_FORCE_INITIAL_PMIN) { fprintf(stream, " PSTATE_FORCE_INITIAL_PMIN\n"); } if (options & PSTATE_IDDQ_0P80V_VALID) { fprintf(stream, " PSTATE_IDDQ_0P80V_VALID\n"); } } fprintf(stream, "---------------------------------------------------------------------------------------------------------\n"); fprintf(stream, " I Pstate F(MHz) evid_vdd(V) evid_vcs(V) evid_vdd_eff(V) evid_vcs_eff(V) maxreg_vdd(V) maxreg_vcs(V)\n" "---------------------------------------------------------------------------------------------------------\n"); for (i = gpst->entries - 1; i >= 0; i--) { entry.value = revle64(gpst->pstate[i].value); evid_vdd = entry.fields.evid_vdd; sprintf_vrm11(evid_vdd_str, evid_vdd); evid_vcs = entry.fields.evid_vcs; sprintf_vrm11(evid_vcs_str, evid_vcs); evid_vdd_eff = entry.fields.evid_vdd_eff; sprintf_ivid(evid_vdd_eff_str, evid_vdd_eff); evid_vcs_eff = entry.fields.evid_vcs_eff; sprintf_ivid(evid_vcs_eff_str, evid_vcs_eff); maxreg_vdd = entry.fields.maxreg_vdd; sprintf_ivid(maxreg_vdd_str, maxreg_vdd); maxreg_vcs = entry.fields.maxreg_vcs; sprintf_ivid(maxreg_vcs_str, maxreg_vcs); pstate = gpst_pmin(gpst) + i; ultraturbo_ps_str = ""; if (pstate == 0 && gpst->turbo_ps != 0) ultraturbo_ps_str = " <--- UltraTurbo"; turbo_ps_str = ""; if (pstate == gpst->turbo_ps) turbo_ps_str = " <--- Turbo"; nominal_ps_str = ""; if (pstate == gpst->nominal_ps) nominal_ps_str = " <--- Nominal"; powersave_ps_str = ""; if (pstate == gpst->powersave_ps) powersave_ps_str = " <--- PowerSave"; ivrm_max_ps_str = ""; if (pstate == gpst->ivrm_max_ps) ivrm_max_ps_str = " <--- iVRM Maximum"; fprintf(stream, "%3d %+4d " "%4d " "0x%02x %s " "0x%02x %s " "0x%02x %s " "0x%02x %s " "0x%02x %s " "0x%02x %s " "%s%s%s%s%s\n", i, pstate, (pstate0_frequency_khz + (frequency_step_khz * pstate)) / 1000, evid_vdd, evid_vdd_str, evid_vcs, evid_vcs_str, evid_vdd_eff, evid_vdd_eff_str, evid_vcs_eff, evid_vcs_eff_str, maxreg_vdd, maxreg_vdd_str, maxreg_vcs, maxreg_vcs_str, ultraturbo_ps_str, turbo_ps_str, nominal_ps_str, powersave_ps_str, ivrm_max_ps_str); } fprintf(stream, "---------------------------------------------------------------------------------------------------------\n"); }
// Function Specification // // Name: proc_pstate_kvm_setup // // Description: Get everything set up for KVM mode // // End Function Specification void proc_pstate_kvm_setup() { int l_core; int l_rc = 0; uint32_t l_configured_cores; pcbs_pcbspm_mode_reg_t l_ppmr; pcbs_pmgp1_reg_t l_pmgp1; pcbs_power_management_bounds_reg_t l_pmbr; errlHndl_t l_errlHndl; do { //only run this in KVM mode if(!G_sysConfigData.system_type.kvm) { break; } l_configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG); // Do per-core configuration for(l_core = 0; l_core < PGP_NCORES; l_core++, l_configured_cores <<= 1) { if(!(l_configured_cores & 0x80000000)) continue; //do read-modify-write to allow pmax clip to also clip voltage (not just frequency) l_rc = getscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, l_core), &(l_ppmr.value), NULL); //commit errors internally if(l_rc) { TRAC_ERR("proc_pstate_kvm_setup: getscom(PCBS_PCBSPM_MODE_REG) failed. rc=%d, hw_core=%d", l_rc, l_core); break; } l_ppmr.fields.enable_clipping_of_global_pstate_req = 1; l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PCBSPM_MODE_REG, l_core), l_ppmr.value, NULL); //commit errors internally if(l_rc) { TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_PCBSPM_MODE_REG) failed. rc=%d, hw_core=%d", l_rc, l_core); break; } //per Vaidy Srinivasan, clear bit 11 in the Power Management GP1 register l_pmgp1.value = 0; l_pmgp1.fields.pm_spr_override_en = 1; l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, l_core), ~l_pmgp1.value, NULL); //commit errors internally if(l_rc) { TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_PMGB1_REG_OR) failed. rc=0x%08x, hw_core=%d", l_rc, l_core); break; } //set pmax/pmin clip initial settings l_pmbr.value = 0; l_pmbr.fields.pmin_clip = gpst_pmin(&G_global_pstate_table)+1; //Per David Du, we must use pmin+1 to avoid gpsa hang l_pmbr.fields.pmax_clip = gpst_pmax(&G_global_pstate_table); l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_POWER_MANAGEMENT_BOUNDS_REG, l_core), l_pmbr.value, NULL); //commit errors internally if(l_rc) { TRAC_ERR("proc_pstate_kvm_setup: putscom(PCBS_POWER_MANAGEMENT_BOUNDS_REG) failed. rc=0x%08x, hw_core=%d", l_rc, l_core); break; } }// end of per-core config if(l_rc) { break; } // Set the voltage clipping register to match the pmax/pmin clip values set above. pmc_rail_bounds_register_t prbr; prbr.value = in32(PMC_RAIL_BOUNDS_REGISTER); prbr.fields.pmin_rail = gpst_pmin(&G_global_pstate_table); prbr.fields.pmax_rail = gpst_pmax(&G_global_pstate_table); TRAC_IMP("pmin clip pstate = %d, pmax clip pstate = %d", prbr.fields.pmin_rail, prbr.fields.pmax_rail); out32(PMC_RAIL_BOUNDS_REGISTER, prbr.value); // Initialize the sapphire table in SRAM (sets valid bit) populate_pstate_to_sapphire_tbl(); // copy sram image into mainstore HOMER populate_sapphire_tbl_to_mem(); TRAC_IMP("proc_pstate_kvm_setup: RUNNING IN KVM MODE"); }while(0); if(l_rc) { // Create Error Log and request reset /* @ * @errortype * @moduleid PROC_PSTATE_KVM_SETUP_MOD * @reasoncode PROC_SCOM_ERROR * @userdata1 l_configured_cores * @userdata2 Return Code of call that failed * @userdata4 OCC_NO_EXTENDED_RC * @devdesc OCC failed to scom a core register */ l_errlHndl = createErrl( PROC_PSTATE_KVM_SETUP_MOD, //modId PROC_SCOM_ERROR, //reasoncode OCC_NO_EXTENDED_RC, //Extended reason code ERRL_SEV_PREDICTIVE, //Severity NULL, //Trace Buf DEFAULT_TRACE_SIZE, //Trace Size l_configured_cores, //userdata1 l_rc //userdata2 ); addCalloutToErrl(l_errlHndl, ERRL_CALLOUT_TYPE_HUID, G_sysConfigData.proc_huid, ERRL_CALLOUT_PRIORITY_HIGH); addCalloutToErrl(l_errlHndl, ERRL_CALLOUT_TYPE_COMPONENT_ID, ERRL_COMPONENT_ID_FIRMWARE, ERRL_CALLOUT_PRIORITY_MED); REQUEST_RESET(l_errlHndl); } }