diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h index 72193b58..da2285e2 100644 --- a/src/common/ipc_func_ids.h +++ b/src/common/ipc_func_ids.h @@ -73,12 +73,12 @@ IPC_FUNCIDS_TABLE_START //Functions that are only supported by GPE2 should be defined here //These function ID's can only be sent to GPE2 (PGPE) IPC_FUNCIDS_ST_START(OCCHW_INST_ID_GPE2) - IPC_FUNC_ID(IPC_PGPE_INVALID_FUNCID) - IPC_FUNC_ID(IPC_PGPE_START_SUSPEND_FUNCID) - IPC_FUNC_ID(IPC_PGPE_CLIPS_FUNCID) - IPC_FUNC_ID(IPC_PGPE_SET_PMCR_FUNCID) - IPC_FUNC_ID(IPC_PGPE_WOF_CONTROL_FUNCID) - IPC_FUNC_ID(IPC_PGPE_WOF_VFRT_FUNCID) + IPC_FUNC_ID(IPC_MSGID_405_INVALID) + IPC_FUNC_ID(IPC_MSGID_405_START_SUSPEND) + IPC_FUNC_ID(IPC_MSGID_405_CLIPS) + IPC_FUNC_ID(IPC_MSGID_405_SET_PMCR) + IPC_FUNC_ID(IPC_MSGID_405_WOF_CONTROL) + IPC_FUNC_ID(IPC_MSGID_405_WOF_VFRT) IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE2) //Functions that are only supported by GPE3 should be defined here diff --git a/src/include/p9_pstates_occ.h b/src/include/p9_pstates_occ.h index d3fa62b6..e69e5008 100644 --- a/src/include/p9_pstates_occ.h +++ b/src/include/p9_pstates_occ.h @@ -168,6 +168,8 @@ typedef struct // Minimum Pstate; Maximum is always 0. uint32_t pstate_min; // Comes from PowerSave #V point after biases + // TODO: Temporary hack untill interface is finalized. + uint8_t pad[88]; // total size = 0xE00, devisible by 128 } OCCPstateParmBlock; diff --git a/src/occ_405/Makefile b/src/occ_405/Makefile index 3fb12501..f64a3196 100755 --- a/src/occ_405/Makefile +++ b/src/occ_405/Makefile @@ -69,7 +69,8 @@ LIB_DIRS = -L$(OBJDIR) \ -L$(OBJDIR)/firdata \ -L$(OBJDIR)/cent \ -L$(OBJDIR)/mem \ - -L$(OBJDIR)/wof + -L$(OBJDIR)/wof \ + -L$(OBJDIR)/pgpe #default target is to make a binary application image .PHONY : all diff --git a/src/occ_405/amec/amec_data.c b/src/occ_405/amec/amec_data.c index 6663cdc9..05d60b95 100755 --- a/src/occ_405/amec/amec_data.c +++ b/src/occ_405/amec/amec_data.c @@ -47,6 +47,8 @@ #include #include #include +#include +#include //************************************************************************* // Externs @@ -64,8 +66,9 @@ // Globals //************************************************************************* extern uint8_t G_occ_interrupt_type; -extern uint32_t G_proc_fmin; -extern uint32_t G_proc_fmax; + +//max(fturbo,futurbo) +extern uint16_t G_proc_fmax_mhz; //************************************************************************* // Function Prototypes @@ -98,16 +101,13 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode) /* Code */ /*------------------------------------------------------------------------*/ - // If we're active we need to load this new range into DVFS MIN/MAX - if(CURRENT_STATE() == OCC_STATE_ACTIVE) - { - // Use i_mode here since this function understands turbo - l_err = amec_set_freq_range(i_mode); + // Load new range into DVFS MIN/MAX, + // Use i_mode here since this function understands turbo + l_err = amec_set_freq_range(i_mode); - if(l_err) - { - //break; - } + if(l_err) + { + //break; } // If we are in OpenPower environment with OPAL, load this new range into DVFS @@ -115,14 +115,25 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode) // in amec_set_freq_range() based on mode if((G_occ_interrupt_type != FSP_SUPPORTED_OCC) && (G_sysConfigData.system_type.kvm)) { - g_amec->sys.fmax = G_proc_fmax; - g_amec->sys.fmin = G_proc_fmin; // = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY] + g_amec->sys.fmax = G_proc_fmax_mhz; + g_amec->sys.fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; TRAC_INFO("AMEC_data_write_fcurr: New frequency range Fmin[%u] Fmax[%u]", g_amec->sys.fmin, g_amec->sys.fmax); } + if(!l_err) + { + // set the clip bounds wide open (if not in active state) + // if not already in active mode, send IPC command to PGPE to set + // pStates clips wide open (pmin - pmax) + if(!IS_OCC_STATE_ACTIVE()) + { + l_err = pgpe_widen_clip_ranges(); + } + } + return l_err; } diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c index 7115b376..5dadfa71 100755 --- a/src/occ_405/amec/amec_freq.c +++ b/src/occ_405/amec/amec_freq.c @@ -56,6 +56,11 @@ extern uint8_t G_cent_temp_expired_bitmap; extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap; +extern uint16_t G_proc_fmax_mhz; + +extern GPE_BUFFER(PstatesClips* G_core_data_control_occwrite_ptr); + + //************************************************************************* // Defines/Enums //************************************************************************* @@ -67,12 +72,12 @@ extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap; //************************************************************************* // Globals //************************************************************************* -BOOLEAN G_non_dps_power_limited = FALSE; +BOOLEAN G_non_dps_power_limited = FALSE; opal_proc_voting_reason_t G_amec_opal_proc_throt_reason = NO_THROTTLE; opal_mem_voting_reason_t G_amec_opal_mem_throt_reason = NO_MEM_THROTTLE; -uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME; +uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME; //FFDC SCOM addresses as requested by Greg Still in defect SW247927 //If new SCOM addresses are added, update the size of the array. @@ -162,7 +167,15 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode) /*------------------------------------------------------------------------*/ // First set to Max Freq Range for this mode - if( VALID_MODE(i_mode) ) + // if no mode set yet default to the full range + if(i_mode == OCC_MODE_NOCHANGE) + { + l_freq_min = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; + + // Set Max frequency (ultra turbo freq if wof enabled, to turbo freq otherwise) + l_freq_max = G_proc_fmax_mhz; + } + else if( VALID_MODE(i_mode) ) // Set to Max Freq Range for this mode { l_freq_min = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]; l_freq_max = G_sysConfigData.sys_mode_freq.table[i_mode]; @@ -573,39 +586,54 @@ void amec_slv_proc_voting_box(void) // End Function Specification void amec_slv_freq_smh(void) { -// RTC:130201 -// TODO/TEMP: Remove '#if 0' when/if needed. Currently does nothing and -// causes warning of set but not used.. -#if 0 - /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ - uint16_t k = 0; - Pstate l_pstate[MAX_NUM_CORES]; + uint8_t quad = 0; // loop through quads + uint8_t core_num = 0; // core ID + uint8_t core_idx = 0; // loop through cores within each quad + Pstate pmax = 0; // select the maximum pstate (minimum frequency) + // within each quad, initialize to 0 /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ - for (k=0; kproc[0].core[k].f_request); - } + for (core_idx=0; core_idxproc[0].core[core_num].f_request)) + { + pmax = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request); + } + } - if(G_sysConfigData.system_type.kvm) - { - // Send IPC with G_proc_pmin and l_pstate to set pmin and pmax clips - } - else - { - // send an IPC with l_pstate to set pstates for all Cores + // set quad clip bounds/pstates based on system type + if(G_sysConfigData.system_type.kvm) + { + // update quad bounds on OPAL systems + G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] = + G_opal_static_table.config.pmin; + G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax; + + PROC_DBG("Setting Quad %d's min-max clip bounds to %d-%d\n", + quad, G_opal_static_table.config.pmin, pmax); + } + else + { + // update quad pstate request on non-OPAL systems + G_core_data_control_occwrite_ptr->pstates.pmcr[quad] = + ((uint64_t) pmax << 48) +1; // Version 1 (Power9 format) + + PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax); + } + + pmax = 0; // initialize for next loop iteration } -#endif } diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h index d298c7f0..bf2a0036 100755 --- a/src/occ_405/amec/amec_sys.h +++ b/src/occ_405/amec/amec_sys.h @@ -337,8 +337,6 @@ typedef struct uint16_t f_request; // Reason for the frequency request generated by the voting box uint32_t f_reason; - // Current state of this core frequency state machine - uint8_t f_sms; } amec_core_t; diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c index d3e9a3f8..30e2ea98 100755 --- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c +++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c @@ -42,6 +42,7 @@ #include #include "dimm.h" #include +#include "p9_pstates_occ.h" #define FREQ_FORMAT_PWR_MODE_NUM 6 #define FREQ_FORMAT_BASE_DATA_SZ (sizeof(cmdh_store_mode_freqs_t) - sizeof(cmdh_fsp_cmd_header_t)) @@ -67,12 +68,8 @@ extern uint8_t G_occ_interrupt_type; -extern uint32_t G_proc_fmin; -extern uint32_t G_proc_fmax; -extern uint32_t G_khz_per_pstate; - -extern uint8_t G_proc_pmin; -extern uint8_t G_proc_pmax; +extern uint16_t G_proc_fmax_mhz; // Maximum frequency (uturbo if WOF enabled, otherwise turbo) +extern OCCPstateParmBlock G_oppb; // OCC Pstate Parameters Block Structure typedef struct data_req_table { @@ -284,39 +281,64 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr, // Bytes 3-4 Nominal Frequency Point l_freq = (l_buf[0] << 8 | l_buf[1]); l_table[OCC_MODE_NOMINAL] = l_freq; - CMDH_TRAC_INFO("Nominal frequency = %d", l_freq); + CMDH_TRAC_INFO("Nominal frequency = %d MHz", l_freq); // Bytes 5-6 Turbo Frequency Point: // also store for DPS modes l_freq = (l_buf[2] << 8 | l_buf[3]); + // Verify that turbo frequency is <= G_proc_fmax_mhz + if(l_freq > G_proc_fmax_mhz) + { + CMDH_TRAC_ERR("Turbo Frequency[%d] (MHz)) is higher than " + "G_proc_fmax_mhz[%d], clip Turbo Frequency", + l_freq, G_proc_fmax_mhz); + l_freq = G_proc_fmax_mhz; + } l_table[OCC_MODE_TURBO] = l_freq; l_table[OCC_MODE_DYN_POWER_SAVE] = l_freq; l_table[OCC_MODE_DYN_POWER_SAVE_FP] = l_freq; - CMDH_TRAC_INFO("Turbo frequency = %d", l_freq); + CMDH_TRAC_INFO("Turbo frequency = %d MHz", l_freq); // Bytes 7-8 Minimum Frequency Point l_freq = (l_buf[4] << 8 | l_buf[5]); + // Verify that minimum frequency is >= G_oppb.frequency_min_khz + if(l_freq * 1000 < G_oppb.frequency_min_khz) + { + CMDH_TRAC_ERR("Minimum Frequency[%d] (Mhz) is lower than PGPE's " + "G_oppb.frequency_min_khz[%d], clip Minimum Frequency", + l_freq, G_oppb.frequency_min_khz); + l_freq = G_oppb.frequency_min_khz / 1000; + } l_table[OCC_MODE_MIN_FREQUENCY] = l_freq; - G_proc_fmin = l_freq; - CMDH_TRAC_INFO("Minimum frequency = %d", l_freq); + CMDH_TRAC_INFO("Minimum frequency = %d MHz", l_freq); // Bytes 9-10 Ultr Turbo Frequency Point l_freq = (l_buf[6] << 8 | l_buf[7]); - if(l_freq) + // Verify that ultra turbo frequency is <= G_proc_fmax_mhz + if(l_freq > G_proc_fmax_mhz) + { + CMDH_TRAC_ERR("Ultra Turbo Frequency[%d] (MHz) is higher than PGPE's " + "Max freq (G_proc_fmax_mhz[%d]) clip Ultra Turbo Frequency", + l_freq, G_proc_fmax_mhz); + l_freq = G_proc_fmax_mhz; + } + l_table[OCC_MODE_UTURBO] = l_freq; + CMDH_TRAC_INFO("UT frequency = %d MHz", l_freq); + + // clip G_proc_fmax_mhz to TMGT's MAX(turbo, ultra turbo) frequency point + if(l_table[OCC_MODE_UTURBO] > l_table[OCC_MODE_TURBO]) { - G_proc_fmax = l_freq; + G_proc_fmax_mhz = l_table[OCC_MODE_UTURBO]; } - else // If Ultra Turbo Frequency Point = 0, Fmax = Turbo Frequency + else { - G_proc_fmax = l_table[OCC_MODE_TURBO]; + G_proc_fmax_mhz = l_table[OCC_MODE_TURBO]; } - l_table[OCC_MODE_UTURBO] = l_freq; - CMDH_TRAC_INFO("UT frequency = %d", l_freq); // Bytes 11-12 Static Power Save Frequency Point l_freq = (l_buf[8] << 8 | l_buf[9]); l_table[OCC_MODE_PWRSAVE] = l_freq; - CMDH_TRAC_INFO("Static Power Save frequency = %d", l_freq); + CMDH_TRAC_INFO("Static Power Save frequency = %d MHz", l_freq); // Bytes 13-14 FFO Frequency Point l_freq = (l_buf[10] << 8 | l_buf[11]); @@ -324,19 +346,19 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr, { // Check and make sure that FFO freq is within valid range const uint16_t l_req_freq = l_freq; - if (l_freq < G_proc_fmin) + if (l_freq < l_table[OCC_MODE_MIN_FREQUENCY]) { - l_freq = G_proc_fmin; + l_freq = l_table[OCC_MODE_MIN_FREQUENCY]; } - else if (l_freq > G_proc_fmax) + else if (l_freq > G_proc_fmax_mhz) { - l_freq = G_proc_fmax; + l_freq = G_proc_fmax_mhz; } // Log an error if we could not honor the requested FFO frequency, but keep going. if (l_req_freq != l_freq) { - TRAC_ERR("FFO Frequency out of range. requested %d, but using %d", + TRAC_ERR("FFO Frequency out of range. requested %d MHz, but using %d MHz", l_req_freq, l_freq); /* @ * @errortype @@ -360,10 +382,7 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr, } } l_table[OCC_MODE_FFO] = l_freq; - CMDH_TRAC_INFO("FFO Frequency = %d", l_freq); - - // Calculate minimum Pstate: - G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate); + CMDH_TRAC_INFO("FFO Frequency = %d Mhz", l_freq); // inconsistent Frequency Points? if((l_table[OCC_MODE_UTURBO] < l_table[OCC_MODE_TURBO] && l_table[OCC_MODE_UTURBO]) || @@ -2091,6 +2110,8 @@ errlHndl_t DATA_store_cnfgdata (const cmdh_fsp_cmd_t * i_cmd_ptr, l_errlHndl = data_store_freq_data(i_cmd_ptr , o_rsp_ptr); if(NULL == l_errlHndl) { + // New Frequency config data packet received with no error logs: set the + // DATA_MASK_FREQ_PRESENT to flag that we received the frequency from TMGT l_new_data = DATA_MASK_FREQ_PRESENT; } break; diff --git a/src/occ_405/homer.h b/src/occ_405/homer.h index f276c678..b6347018 100755 --- a/src/occ_405/homer.h +++ b/src/occ_405/homer.h @@ -54,6 +54,10 @@ #define OCC_HTMGT_RSP_OFFSET_HOMER 0x000E1000 #define OCC_HTMGT_RSP_ADDRESS_HOMER (HOMER_BASE_ADDRESS+OCC_HTMGT_RSP_OFFSET_HOMER) +// PPMR Header space +#define PPMR_OFFSET_HOMER 0x00300000 // PPMR image HOMER offset +#define PPMR_ADDRESS_HOMER (HOMER_BASE_ADDRESS+PPMR_OFFSET_HOMER) // PPMR image memory address + // Version(s) of HOMER host data currently supported typedef enum homer_version diff --git a/src/occ_405/img_defs.mk b/src/occ_405/img_defs.mk index abdef459..9dea1ebe 100644 --- a/src/occ_405/img_defs.mk +++ b/src/occ_405/img_defs.mk @@ -240,6 +240,7 @@ APP_INCLUDES = -I$(IMAGE_SRCDIR)/rtls \ -I$(IMAGE_SRCDIR)/lock \ -I$(IMAGE_SRCDIR)/wof \ -I$(IMAGE_SRCDIR)/../common \ + -I$(IMAGE_SRCDIR)/pgpe \ INCLUDES += $(IMG_INCLUDES) $(GLOBAL_INCLUDES) $(APP_INCLUDES) \ -I$(SSX_SRCDIR)/ssx -I$(SSX_SRCDIR)/ppc32 -I$(SSX_SRCDIR)/ppc405 \ diff --git a/src/occ_405/incl/comp_ids.h b/src/occ_405/incl/comp_ids.h index 893b9f9c..e6270d6b 100755 --- a/src/occ_405/incl/comp_ids.h +++ b/src/occ_405/incl/comp_ids.h @@ -91,5 +91,10 @@ // Workload Optimize Frequency #define WOF_COMP_ID 0x1100 #define WOF_COMP_NAME "WOF" + +// PGPE Interface +#define PGPE_COMP_ID 0x1200 +#define PGPE_COMP_NAME "PGPE" + #endif diff --git a/src/occ_405/incl/occ_common.h b/src/occ_405/incl/occ_common.h index 2dc0c9fe..eadcd95b 100755 --- a/src/occ_405/incl/occ_common.h +++ b/src/occ_405/incl/occ_common.h @@ -261,7 +261,8 @@ enum NEST_DTS_INITIALIZED = 0x0700, CENTAUR_INITIALIZED = 0x07ff, SLAVE_OCC_INITIALIZED = 0x08ff, - PGPE_IMAGE_HEADER_READ = 0x098f, + PGPE_IMAGE_HEADER_READ = 0x094f, + PPMR_IMAGE_HEADER_READ = 0x098f, WATCHDOG_INITIALIZED = 0x09ff, RTL_TIMER_INITIALIZED = 0x0aff, SEMS_AND_TIMERS_INITIALIZED = 0x0bff, diff --git a/src/occ_405/main.c b/src/occ_405/main.c index fdbe9f36..e4eaf6e8 100755 --- a/src/occ_405/main.c +++ b/src/occ_405/main.c @@ -59,6 +59,7 @@ #include "occhw_shared_data.h" #include #include +#include extern uint32_t __ssx_boot; // Function address is 32 bits extern uint32_t G_occ_phantom_critical_count; @@ -78,8 +79,13 @@ extern uint32_t G_pgpe_beacon_address; IMAGE_HEADER (G_mainAppImageHdr,__ssx_boot,MAIN_APP_ID,ID_NUM_INVALID); // PGPE Image Header Parameters -uint32_t G_pgpe_sram_address; -uint32_t G_pgpe_sram_sz; +uint32_t G_pgpe_shared_sram_address = 0; +uint32_t G_pgpe_shared_sram_sz = 0; + +ppmr_header_t G_ppmr_header; // PPMR Header layout format +OCCPstateParmBlock G_oppb; // OCC Pstate Parameters Block Structure +extern uint16_t G_proc_fmax_mhz; // max(turbo,uturbo) frequencies + //Set main thread timer for one second #define MAIN_THRD_TIMER_SLICE ((SsxInterval) SSX_SECONDS(1)) @@ -119,6 +125,7 @@ extern uint8_t g_trac_err_buffer[]; void pmc_hw_error_isr(void *private, SsxIrqId irq, int priority); void create_tlb_entry(uint32_t address, uint32_t size); +void read_oppb_params(const OCCPstateParmBlock* occ_ppb); //Macro creates a 'bridge' handler that converts the initial fast-mode to full //mode interrupt handler @@ -404,8 +411,9 @@ void create_tlb_entry(uint32_t address, uint32_t size) tlb_entry_size = PAGE_ALIGNED_SIZE(size); } + #if PPC405_MMU_SUPPORT - // define DTLB for PGPE image header + // define DTLB for page aligned address and size l_rc = ppc405_mmu_map( tlb_entry_address, tlb_entry_address, @@ -465,33 +473,308 @@ void create_tlb_entry(uint32_t address, uint32_t size) void read_pgpe_header(void) { + uint64_t magic_number; + errlHndl_t l_err; // define DTLB for the PGPE image header create_tlb_entry(PGPE_HEADER_ADDR, PGPE_HEADER_SZ); - // Read PGPE Beacon address from PGPE image header - G_pgpe_beacon_address = in32(PGPE_BEACON_ADDR_PTR); + // verify the validity of the magic number + magic_number = in64(PGPE_HEADER_ADDR); + if(PGPE_MAGIC_NUMBER != magic_number) + { + // The Magic number is invalid .. Invalid or corrupt PGPE image header + MAIN_TRAC_ERR("Invalid PGPGE Magic number. Address[0x%08X], Magic Number[0x%08X%08X]", + PGPE_HEADER_ADDR, (uint32_t)(magic_number>>32), (uint32_t)magic_number); + /* @ + * @errortype + * @moduleid READ_PGPE_HEADER + * @reasoncode INVALID_MAGIC_NUMBER + * @userdata1 Low order 32 bits of retrieved PGPE magic number + * @userdata2 Hight order 32 bits of retrieved PGPE magic number + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc SSX semaphore related failure + */ - MAIN_TRAC_IMP("Read PGPE Beacon Address[0x%08x]", - G_pgpe_beacon_address); + l_err = createErrl(READ_PGPE_HEADER, //modId + INVALID_MAGIC_NUMBER, //reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_UNRECOVERABLE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + (uint32_t)magic_number, //userdata1 + (uint32_t)(magic_number>>32)); //userdata2 - // Read OCC/PGPE Shared SRAM address and size - G_pgpe_sram_address = in32(PGPE_SHARED_SRAM_ADDR_PTR); - G_pgpe_sram_sz = in32(PGPE_SHARED_SRAM_SZ_PTR); + REQUEST_RESET(l_err); - MAIN_TRAC_IMP("Read PGPE Shared SRAM Start Address[0x%08x], Size[0x%08x]", - G_pgpe_sram_address, G_pgpe_sram_sz); + } - // PGPE Beacon is not implemented in simics yet - // the G_pgpe_sram_address and G_pgpe_sram_sz pointers don't - // have the proper values yet. - // @TODO: remove this condition when PGPE code is integrated. RTC: 163934 - if(!G_simics_environment) + if(l_err == NULL) { - // define DTLB for OCC/PGPE shared SRAM, which enables access - // to OCC-PGPE Shared SRAM space, including pgpe_beacon - create_tlb_entry(G_pgpe_sram_address, G_pgpe_sram_sz); + // Read PGPE Beacon address from PGPE image header + G_pgpe_beacon_address = in32(PGPE_BEACON_ADDR_PTR); + + MAIN_TRAC_IMP("Read PGPE Beacon Address[0x%08x]", + G_pgpe_beacon_address); + + // Read OCC/PGPE Shared SRAM address and size + G_pgpe_shared_sram_address = in32(PGPE_SHARED_SRAM_ADDR_PTR); + G_pgpe_shared_sram_sz = in32(PGPE_SHARED_SRAM_SZ_PTR); + + MAIN_TRAC_IMP("Read PGPE Shared SRAM Start Address[0x%08x], Size[0x%08x]", + G_pgpe_shared_sram_address, G_pgpe_shared_sram_sz); + + // PGPE Beacon is not implemented in simics yet + // the G_pgpe_shared_sram_address and G_pgpe_shared_sram_sz pointers don't + // have the proper values yet. + // @TODO: remove this condition when PGPE code is integrated. RTC: 163934 + if(!G_simics_environment) + { + // define DTLB for OCC/PGPE shared SRAM, which enables access + // to OCC-PGPE Shared SRAM space, including pgpe_beacon + create_tlb_entry(G_pgpe_shared_sram_address, G_pgpe_shared_sram_sz); + } } + return; +} + + +/* + * Function Specification + * + * Name: read_ppmr_header + * + * Description: read PPMR image header, and extract the + * OPPB HOMER offset and sturcture size.. + * + * End Function Specification + */ +void read_ppmr_header(void) +{ + int l_ssxrc = SSX_OK; + uint32_t l_reasonCode = 0; + uint32_t l_extReasonCode = 0; + + // error log parameters, if any + uint32_t userdata1 = 0; + uint32_t userdata2 = 0; + + // create a DTLB entry for the PPMR image header + create_tlb_entry(PPMR_ADDRESS_HOMER, sizeof(ppmr_header_t)); + + do{ + // use block copy engine to read the PPMR header + BceRequest pba_copy; + + // Set up a copy request + l_ssxrc = bce_request_create(&pba_copy, // block copy object + &G_pba_bcde_queue, // mainstore to sram copy engine + PPMR_ADDRESS_HOMER, // mainstore address + (uint32_t) &G_ppmr_header, // sram starting address + (size_t) sizeof(G_ppmr_header), // size of copy + SSX_WAIT_FOREVER, // no timeout + NULL, // no call back + NULL, // no call back arguments + ASYNC_REQUEST_BLOCKING); // blocking request + + if(l_ssxrc != SSX_OK) + { + MAIN_TRAC_ERR("read_ppmr_header: BCDE request create failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid READ_PPMR_HEADER + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata2 Internal function checkpoint + * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE + * @devdesc Failed to create BCDE request + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE; + + userdata1 = (uint32_t)(-l_ssxrc); + break; + } + + // Do actual copying + l_ssxrc = bce_request_schedule(&pba_copy); + + if(l_ssxrc != SSX_OK) + { + MAIN_TRAC_ERR("read_ppmr_header: BCE request schedule failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid READ_PPMR_HEADER + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE + * @devdesc Failed to read PPMR data by using BCDE + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; + + userdata1 = (uint32_t)(-l_ssxrc); + break; + } + + if(G_ppmr_header.oppb_length != sizeof(OCCPstateParmBlock)) + { + MAIN_TRAC_ERR("read_ppmr_header: OCCPstateParmBlock size mismatch:" + "PPMR header sz[0x%08x] PPMR struct sz[0x%08x]", + G_ppmr_header.oppb_length, sizeof(OCCPstateParmBlock)); + + /* + * @errortype + * @moduleid READ_PPMR_HEADER + * @reasoncode PGPE_FAILURE + * @userdata1 G_ppmr_header.oppb_length + * @userdata2 sizeof(OCCPstateParmBlock) + * @userdata4 ERC_PGPE_PPMR_OPPB_SIZE_MISMATCH + * @devdesc PPMR's OPPB size mismatches data structure's + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; + + userdata1 = G_ppmr_header.oppb_length; + userdata2 = sizeof(OCCPstateParmBlock); + break; + } + + + + } while (0); + + if ( l_reasonCode ) + { + errlHndl_t l_errl = createErrl(READ_PPMR_HEADER, //modId + l_reasonCode, //reasoncode + l_extReasonCode, //Extended reason code + ERRL_SEV_UNRECOVERABLE, //Severity + NULL, //Trace Buf + 0, //Trace Size + userdata1, //userdata1 + userdata2); //userdata2 + + // Callout firmware + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + + REQUEST_RESET(l_errl); + + return; + } + + // Read OCC pstates parameter block + read_oppb_params((OCCPstateParmBlock*)G_ppmr_header.oppb_offset); +} + +/* + * Function Specification + * + * Name: read_oppb_params + * + * Description: Read the OCC Pstates Parameter Block, + * and initializa Pstates Global Variables. + * + * End Function Specification + */ +void read_oppb_params(const OCCPstateParmBlock* oppb_offset) +{ + int l_ssxrc = SSX_OK; + uint32_t l_reasonCode = 0; + uint32_t l_extReasonCode = 0; + + create_tlb_entry( ((uint32_t)oppb_offset + (uint32_t)PPMR_ADDRESS_HOMER), + sizeof(OCCPstateParmBlock)); + + do{ + // use block copy engine to read the PPMR header + BceRequest pba_copy; + + // Set up a copy request + l_ssxrc = bce_request_create(&pba_copy, // block copy object + &G_pba_bcde_queue, // mainstore to sram copy engine + (uint32_t)PPMR_ADDRESS_HOMER + + (uint32_t)oppb_offset, // mainstore address + (uint32_t) &G_oppb, // sram starting address + (size_t) sizeof(OCCPstateParmBlock), // size of copy + SSX_WAIT_FOREVER, // no timeout + NULL, // no call back + NULL, // no call back arguments + ASYNC_REQUEST_BLOCKING); // blocking request + + if(l_ssxrc != SSX_OK) + { + CMDH_TRAC_ERR("read_oppb_params: BCDE request create failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid READ_OPPB_PARAMS + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata2 Internal function checkpoint + * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE + * @devdesc Failed to create BCDE request + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE; + break; + } + + // Do actual copying + l_ssxrc = bce_request_schedule(&pba_copy); + + if(l_ssxrc != SSX_OK) + { + CMDH_TRAC_ERR("read_oppb_params: BCE request schedule failure rc=[%08X]", -l_ssxrc); + /* + * @errortype + * @moduleid READ_OPPB_PARAMS + * @reasoncode SSX_GENERIC_FAILURE + * @userdata1 RC for BCE block-copy engine + * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE + * @devdesc Failed to read PPMR data by using BCDE + */ + l_reasonCode = SSX_GENERIC_FAILURE; + l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; + break; + } + } while (0); + + if ( l_ssxrc != SSX_OK ) + { + errlHndl_t l_errl = createErrl(READ_OPPB_PARAMS, //modId + l_reasonCode, //reasoncode + l_extReasonCode, //Extended reason code + ERRL_SEV_UNRECOVERABLE, //Severity + NULL, //Trace Buf + 0, //Trace Size + -l_ssxrc, //userdata1 + 0); //userdata2 + + // Callout firmware + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_COMPONENT_ID, + ERRL_COMPONENT_ID_FIRMWARE, + ERRL_CALLOUT_PRIORITY_HIGH); + + REQUEST_RESET(l_errl); + + return; + } + + // Copy over max frequency into G_proc_fmax_mhz + G_proc_fmax_mhz = G_oppb.frequency_max_khz / 1000; + + + // Used by amec for pcap calculation could use G_oppb.frequency_step_khz + // in PCAP calculationsinstead, but using a separate varaible speeds + // up PCAP relatedcalculations significantly, by eliminating slow + // division operations. + G_mhz_per_pstate = G_oppb.frequency_step_khz/1000; + + TRAC_INFO("read_oppb_params: OCC Pstates Parameter Block read successfully"); } /* @@ -971,11 +1254,44 @@ void Main_thread_routine(void *private) slave_occ_init(); CHECKPOINT(SLAVE_OCC_INITIALIZED); + // @TODO: remove this precompile directive check when PGPE code is integrated. + /// RTC: 163934 +#ifndef PGPE_SUPPORT + extern pstateStatus G_proc_pstate_status; + // TEMP Hack to enable Active State, until PGPE is ready + G_proc_pstate_status = PSTATES_ENABLED; + + + // Temp hack to Set up Key Globals for use by proc_freq2pstate functions + G_oppb.frequency_max_khz = 4322500; + G_oppb.frequency_min_khz = 2028250; + G_oppb.frequency_step_khz = 16667; + G_oppb.pstate_min = PMAX + + ((G_oppb.frequency_max_khz - G_oppb.frequency_min_khz)/G_oppb.frequency_step_khz); + + G_proc_fmax_mhz = G_oppb.frequency_max_khz / 1000; + + + // Set globals used by amec for pcap calculation + // could have used G_oppb.frequency_step_khz in PCAP calculations + // instead, but using a separate varaible speeds up PCAP related + // calculations significantly, by eliminating division operations. + G_mhz_per_pstate = G_oppb.frequency_step_khz/1000; + + TRAC_INFO("Main_thread_routine: Pstate Key globals initialized to default values"); + +#else // Read PGPE header file, extract OCC/PGPE Shared SRAM address and size, // Read other global parameters, e.g. G_pgpe_beacon_address, etc. read_pgpe_header(); CHECKPOINT(PGPE_IMAGE_HEADER_READ); + // Read PPMR header, extract OCC pstates parameter block address and size, + // Read OCCC pstate parameter block. + read_ppmr_header(); + CHECKPOINT(PPMR_IMAGE_HEADER_READ); +#endif + // Initialize watchdog timers. This needs to be right before // start rtl to make sure timer doesn't timeout. This timer is being // reset from the rtl task. diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile index 16dbd5fa..21b5a3fc 100644 --- a/src/occ_405/occLinkInputFile +++ b/src/occ_405/occLinkInputFile @@ -60,6 +60,7 @@ INPUT ( amec_amester.o occhw_irq_init.o occhw_ocb.o occhw_pba.o + pgpe_interface.o ppc405_boot.o ppc405_breakpoint.o ppc405_cache_core.o @@ -73,6 +74,7 @@ INPUT ( amec_amester.o ppc405_mmu_asm.o ppc405_thread_init.o proc_data.o + proc_data_control.o proc_pstate.o reset.o rtls_tables.o diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h index b96ff0d0..6633ba5b 100644 --- a/src/occ_405/occ_service_codes.h +++ b/src/occ_405/occ_service_codes.h @@ -113,11 +113,17 @@ enum occReasonCode DIMM_GPE_FAILURE = 0xD0, MEMORY_INIT_FAILED = 0xD1, DIMM_INVALID_STATE = 0xD2, - PGPE_BEACON_TIMEOUT = 0xD3, + + // PGPE Generic RC + PGPE_FAILURE = 0xD3, + /// GPE IPC TASK RCs GPE_REQUEST_CREATE_FAILURE = 0xD4, GPE_REQUEST_SCHEDULE_FAILURE = 0xD5, GPE_REQUEST_TASK_TIMEOUT = 0xD6, + GPR_REQUEST_RC_FAILURE = 0xD7, + + INVALID_MAGIC_NUMBER = 0xDA, /// Success! OCC_SUCCESS_REASON_CODE = 0xFF, @@ -227,6 +233,13 @@ enum occExtReasonCode ERC_AVSBUS_VDN_VOLTAGE_FAILURE = 0x00AC, ERC_AVSBUS_VDN_CURRENT_FAILURE = 0x00AD, + ERC_PGPE_BEACON_TIMEOUT = 0x00B0, + ERC_PGPE_NOT_IDLE = 0x00B1, + ERC_PGPE_UNSUCCESSFULL = 0x00B2, + ERC_PGPE_START_FAILURE = 0x00B3, + ERC_PGPE_SUSPEND_FAILURE = 0x00B4, + ERC_PGPE_CLIP_FAILURE = 0x00B5, + ERC_PGPE_PPMR_OPPB_SIZE_MISMATCH = 0x00B6, }; // Error log Module Ids @@ -249,6 +262,10 @@ enum occModuleId CMDH_DBUG_MID = MAIN_COMP_ID | 0x0f, I2C_LOCK_UPDATE = MAIN_COMP_ID | 0x10, CREATE_TLB_ENTRY = MAIN_COMP_ID | 0x11, + READ_PGPE_HEADER = MAIN_COMP_ID | 0x12, + READ_PPMR_HEADER = MAIN_COMP_ID | 0x13, + READ_OPPB_PARAMS = MAIN_COMP_ID | 0x14, + MAIN_SMGR_MID = MAIN_COMP_ID | 0x15, }; enum occUserDataType diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h index 9380cfb6..6b85d7c6 100755 --- a/src/occ_405/occ_sys_config.h +++ b/src/occ_405/occ_sys_config.h @@ -40,6 +40,7 @@ #define MAX_NUM_NODES 4 #define MAX_NUM_CORES 24 #define MAX_NUM_QUADS 6 +#define NUM_CORES_PER_QUAD 4 #define MAX_THREADS_PER_CORE 4 #define MAX_NUM_CHIP_MODULES 4 #define MAX_NUM_POWER_SUPPLIES 4 diff --git a/src/occ_405/pgpe/pgpe_interface.c b/src/occ_405/pgpe/pgpe_interface.c new file mode 100644 index 00000000..bbdf8018 --- /dev/null +++ b/src/occ_405/pgpe/pgpe_interface.c @@ -0,0 +1,812 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/pgpe/pgpe_interface.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + + +#include "occ_common.h" +#include "occhw_async.h" +#include "pgpe_interface.h" +#include "pstate_pgpe_occ_api.h" +#include "occ_service_codes.h" +#include "pgpe_service_codes.h" +#include "trac.h" +#include "state.h" +#include "proc_pstate.h" +#include "proc_data_control.h" +#include "occ_sys_config.h" + +extern opal_static_table_t G_opal_static_table; + +extern pstateStatus G_proc_pstate_status; +extern PMCR_OWNER G_proc_pmcr_owner; + +extern uint16_t G_proc_fmax_mhz; + +extern GPE_BUFFER(PstatesClips* G_core_data_control_gpewrite_ptr); +extern GPE_BUFFER(PstatesClips* G_core_data_control_occwrite_ptr); + +// IPC GPE Requests +GpeRequest G_clip_update_req; +GpeRequest G_pmcr_set_req; +GpeRequest G_start_suspend_req; +GpeRequest G_wof_control_req; +GpeRequest G_wof_vfrt_req; + +// The the GPE parameter fields for PGPE IPC calls. +GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr); +GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr); +GPE_BUFFER(ipcmsg_start_suspend_t G_start_suspend_parms); +GPE_BUFFER(ipcmsg_wof_control_t G_wof_control_parms); +GPE_BUFFER(ipcmsg_wof_vfrt_t G_wof_vfrt_parms); + + +// Function Specification +// +// Name: init_pgpe_ipcs +// +// Description: Create all PGPE IPC messages. +// +// End Function Specification + +errlHndl_t init_pgpe_ipcs(void) +{ + errlHndl_t err = NULL; // Error handler + + //Set PMCR IPC task parameters to gpewrite's quad pstates data structure + G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates; + + //Set Clip IPC task parameters to gpewrite's quad pstates data structure + G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips; + + do + { + err = pgpe_init_clips(); + if(err) + { + break; + } + err = pgpe_init_pmcr(); + if(err) + { + break; + } + err = pgpe_init_start_suspend(); + if(err) + { + break; + } + err = pgpe_init_wof_control(); + if(err) + { + break; + } + err = pgpe_init_wof_vfrt(); + }while(0); + + if(err) + { + REQUEST_RESET(err); + } + + // Initialization used in the task_core_data_control for PGPE success + // checks made before the first clip/pstate IPC message to be ever sent + // from either of the two double buffers. + G_core_data_control_occwrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS; + G_core_data_control_occwrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS; + + G_core_data_control_gpewrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS; + G_core_data_control_gpewrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS; + + + return(err); +} + + +// Function Specification +// +// Name: pgpe_init_clips +// +// Description: Create PGPE clip update IPC messages (non-blocking). +// +// End Function Specification + +errlHndl_t pgpe_init_clips(void) +{ + int rc; // return code + errlHndl_t err = NULL; // Error handler + + do + { + //Initializes the GpeRequest object for pgpe clips setting IPC + rc = gpe_request_create(&G_clip_update_req, // GpeRequest for the task + &G_async_gpe_queue2, // Queue + IPC_MSGID_405_CLIPS, // Function ID + G_clip_update_parms_ptr, // Task parameters + SSX_WAIT_FOREVER, // Timeout (none) + NULL, // Callback + NULL, // Callback arguments + ASYNC_CALLBACK_IMMEDIATE ); // Options + + if( rc ) + { + // If we failed to create the GpeRequest then there is a serious problem. + MAIN_TRAC_ERR("pgpe_init_clips: Failure creating the " + "IPC_MSGID_405_CLIPS GpeRequest. [RC=0x%08x]", rc ); + + /* + * @errortype + * @moduleid PGPE_INIT_CLIPS_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 gpe_request_create return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failure to create clips GpeRequest object + */ + err = createErrl( + PGPE_INIT_CLIPS_MOD, //ModId + GPE_REQUEST_CREATE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //Userdata1 + 0 //Userdata2 + ); + } + + } while (0); + + return(err); +} + +// Function Specification +// +// Name: pgpe_init_pmcr +// +// Description: Create PGPE PMCR set IPC messages (non-blocking). +// +// End Function Specification + +errlHndl_t pgpe_init_pmcr(void) +{ + int rc; // return code + errlHndl_t err = NULL; // Error handler + + do + { + //Initializes the GpeRequest object for pgpe PMCR setting IPC + rc = gpe_request_create(&G_pmcr_set_req, // GpeRequest for the task + &G_async_gpe_queue2, // Queue + IPC_MSGID_405_SET_PMCR, // Function ID + G_pmcr_set_parms_ptr, // Task parameters + SSX_WAIT_FOREVER, // Timeout (none) + NULL, // Callback + NULL, // Callback arguments + ASYNC_CALLBACK_IMMEDIATE); // Options + + if( rc ) + { + // If we failed to create the GpeRequest then there is a serious problem. + MAIN_TRAC_ERR("pgpe_init_pmcr: Failure creating the " + "IPC_MSGID_405_SET_PMCR GpeRequest. [RC=0x%08x]", + rc ); + + /* + * @errortype + * @moduleid PGPE_INIT_PMCR_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 gpe_request_create return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failure to create pmcr GpeRequest object + */ + err = createErrl( + PGPE_INIT_PMCR_MOD, //ModId + GPE_REQUEST_CREATE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //Userdata1 + 0 //Userdata2 + ); + } + + } while (0); + + return(err); +} + +// Function Specification +// +// Name: pgpe_init_start_suspend +// +// Description: Create PGPE start/suspend IPC messages (blocking). +// +// End Function Specification + +errlHndl_t pgpe_init_start_suspend(void) +{ + int rc; // return code + errlHndl_t err = NULL; // Error handler + + do + { + //Initializes the GpeRequest object for pgpe start/suspend IPC + rc = gpe_request_create(&G_start_suspend_req, // GpeRequest for the task + &G_async_gpe_queue2, // Queue + IPC_MSGID_405_START_SUSPEND, // Function ID + &G_start_suspend_parms, // Task parameters + SSX_WAIT_FOREVER, // Timeout (none) + (AsyncRequestCallback)pgpe_start_suspend_callback, // Callback + NULL, // Callback arguments + ASYNC_CALLBACK_IMMEDIATE ); // Options + + if( rc ) + { + // If we failed to create the GpeRequest then there is a serious problem. + MAIN_TRAC_ERR("pgpe_init_start_suspend: Failure creating the " + "IPC_MSGID_405_START_SUSPEND GpeRequest. [RC=0x%08x]", + rc ); + + /* + * @errortype + * @moduleid PGPE_INIT_START_SUSPEND_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 gpe_request_create return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failure to create start_suspend GpeRequest object + */ + err = createErrl( + PGPE_INIT_START_SUSPEND_MOD, //ModId + GPE_REQUEST_CREATE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //Userdata1 + 0 //Userdata2 + ); + } + + } while (0); + + return(err); +} + + +// Function Specification +// +// Name: pgpe_init_wof_control +// +// Description: Create PGPE WOF control IPC messages (non-blocking). +// +// End Function Specification + +errlHndl_t pgpe_init_wof_control(void) +{ + int rc; // return code + errlHndl_t err = NULL; // Error handler + + do + { + //Initializes the GpeRequest object for pgpe wof control IPC + rc = gpe_request_create(&G_wof_control_req, // GpeRequest for the task + &G_async_gpe_queue2, // Queue + IPC_MSGID_405_WOF_CONTROL, // Function ID + &G_wof_control_parms, // Task parameters + SSX_WAIT_FOREVER, // Timeout (none) + NULL, // Callback + NULL, // Callback arguments + ASYNC_CALLBACK_IMMEDIATE); // Options + + if( rc ) + { + // If we failed to create the GpeRequest then there is a serious problem. + MAIN_TRAC_ERR("pgpe_init_wof_control: Failure creating the " + "IPC_MSGID_405_WOF_CONTROL GpeRequest. [RC=0x%08x]", + rc ); + + /* + * @errortype + * @moduleid PGPE_INIT_WOF_CONTROL_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 gpe_request_create return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failure to create wof control GpeRequest object + */ + err = createErrl( + PGPE_INIT_WOF_CONTROL_MOD, //ModId + GPE_REQUEST_CREATE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //Userdata1 + 0 //Userdata2 + ); + } + + } while (0); + + return(err); +} + +// Function Specification +// +// Name: pgpe_init_wof_vfrt +// +// Description: Create PGPE WOF vfrt IPC messages (non-blocking). +// +// End Function Specification + +errlHndl_t pgpe_init_wof_vfrt(void) +{ + int rc; // return code + errlHndl_t err = NULL; // Error handler + + do + { + //Initializes the GpeRequest object for pgpe wof vfrt IPC + rc = gpe_request_create(&G_wof_vfrt_req, // GpeRequest for the task + &G_async_gpe_queue2, // Queue + IPC_MSGID_405_WOF_VFRT, // Function ID + &G_wof_vfrt_parms, // Task parameters + SSX_WAIT_FOREVER, // Timeout (none) + NULL, // Callback + NULL, // Callback arguments + ASYNC_CALLBACK_IMMEDIATE); // Options + + if( rc ) + { + // If we failed to create the GpeRequest then there is a serious problem. + MAIN_TRAC_ERR("pgpe_init_wof_vfrt: Failure creating the " + "IPC_MSGID_405_WOF_VFRT GpeRequest. [RC=0x%08x]", + rc ); + + /* + * @errortype + * @moduleid PGPE_INIT_WOF_VFRT_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 gpe_request_create return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failure to create wof control GpeRequest object + */ + err = createErrl( + PGPE_INIT_WOF_VFRT_MOD, //ModId + GPE_REQUEST_CREATE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + rc, //Userdata1 + 0 //Userdata2 + ); + } + + } while (0); + + return(err); +} + + +// Function Specification +// +// Name: pgpe_widen_clip_ranges +// +// Description: Wide open PGPE clip ranges. Since this IPC call +// is non-blocking, this routine has to assure call +// completion before checking the pgpe return value. +// +// End Function Specification + +errlHndl_t pgpe_widen_clip_ranges(void) +{ + + errlHndl_t err = NULL; // Error handler + uint8_t i; // Loop variable + + // Set clip bounds wide open + for(i=0; ips_val_clip_min[i] = pmin_rail(); + + // maximum pstate: + G_clip_update_parms_ptr->ps_val_clip_max[i] = proc_freq2pstate(G_proc_fmax_mhz); + } + + // Check that no previous clip update calls are still in progress + if(async_request_is_idle(&G_clip_update_req.request)) + { + // will check for this IPC completion at transition to active state + err = pgpe_clip_update(); + } + else + { + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC task is not Idle"); + + // log an error + MAIN_TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC is not Idle"); + + /* + * @errortype + * @moduleid PGPE_WIDEN_CLIP_RANGES_MOD + * @reasoncode PGPE_FAILURE + * @userdata1 0 + * @userdata4 ERC_PGPE_NOT_IDLE + * @devdesc pgpe clip update not idle + */ + err = createErrl( + PGPE_WIDEN_CLIP_RANGES_MOD, //ModId + PGPE_FAILURE, //Reasoncode + OCC_NO_EXTENDED_RC, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + 0, //Userdata1 + 0 //Userdata2 + ); + } + + return(err); +} + +// Function Specification +// +// Name: pgpe_clip_update +// +// Description: call PGPE IPC to update clip ranges. Since this IPC call is +// non-blocking, the calling function needs to assure previous +// call completion before calling this call. +// +// End Function Specification + +errlHndl_t pgpe_clip_update(void) +{ + int rc; // gpe schedule return code + errlHndl_t err = NULL; // Error handler + + do + { + // Caller must check the completion of previous invocation of clip updates. + // This check is a safety feature in case caller didn't check IPC is idle. + if(!async_request_is_idle(&G_clip_update_req.request)) + { + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("pgpe_clip_update: clip update IPC task is not Idle"); + + /* + * @errortype + * @moduleid PGPE_CLIP_UPDATE_MOD + * @reasoncode PGPE_FAILURE + * @userdata1 0 + * @userdata4 ERC_PGPE_NOT_IDLE + * @devdesc pgpe clip update not idle + */ + err = createErrl( + PGPE_CLIP_UPDATE_MOD, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_NOT_IDLE, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + 0, //Userdata1 + 0 //Userdata2 + ); + + break; + } + + // @TODO: remove this precompile directive check when PGPE code is integrated. + // RTC: 163934 +#ifdef PGPE_SUPPORT + // Schedule PGPE clip update IPC task + rc = gpe_request_schedule(&G_clip_update_req); +#else + G_start_suspend_parms.msg_cb.rc = PGPE_RC_SUCCESS; + rc = 0; +#endif + // Confirm Successfull completion of PGPE clip update task + if(rc != 0) + { + //Error in scheduling pgpe clip update task + TRAC_ERR("pgpe_clip_update: Failed to schedule clip update pgpe task rc=%x", + rc); + + /* @ + * @errortype + * @moduleid PGPE_CLIP_UPDATE_MOD + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 rc - gpe_request_schedule return code + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc OCC Failed to schedule a GPE job for clip update + */ + err = createErrl( + PGPE_CLIP_UPDATE_MOD, // modId + GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode + OCC_NO_EXTENDED_RC, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + rc, // userdata1 + 0 // userdata2 + ); + + REQUEST_RESET(err); //This will add a firmware callout for us + } + }while(0); + + return err; +} + + +// Function Specification +// +// Name: start_suspend_callback +// +// Description: callback function for the pgpe_start_suspend IPC function +// gets called after the PGPE IPC enables/disables pstates. +// Upon successful completion, it sets/clears the G_proc_pstate_status +// flag to indicat whether it is enabled/disabled/in-transition. +// +// End Function Specification + +void pgpe_start_suspend_callback(void) +{ + int pgpe_rc; // pgpe return codes + errlHndl_t err = NULL; // Error handler + + pgpe_rc = G_start_suspend_parms.msg_cb.rc; + + do + { + // Confirm Successfull completion of PGPE clup update task + if(pgpe_rc != PGPE_RC_SUCCESS) + { + //Error in scheduling pgpe clip update task + + /* @ + * @errortype + * @moduleid PGPE_START_SUSPEND_CALLBACK_MOD + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 pgpe_rc - PGPE return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc OCC Failed to schedule a GPE job for start_suspend + */ + err = createErrl( + PGPE_START_SUSPEND_CALLBACK_MOD, // modId + PGPE_FAILURE, // reasoncode + ERC_PGPE_UNSUCCESSFULL, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + pgpe_rc, // userdata1 + 0 // userdata2 + ); + + REQUEST_RESET(err); //This will add a firmware callout for us + break; + } + // task completed successfully + else + { + // this was a command to enable pstates + if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_START) + { + // Pstates are now enabled (enable Active State transition). + G_proc_pstate_status = PSTATES_ENABLED; + } + // this was a command to disable pstates + else if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_SUSPEND) + { + // Pstates are now disabled (disaable Active State transition). + G_proc_pstate_status = PSTATES_DISABLED; + } + + G_proc_pmcr_owner = G_start_suspend_parms.pmcr_owner; + } + + } while(0); + +} + +// Function Specification +// +// Name: pgpe_start_suspend +// +// Description: Schedule a PGPE IPC to enable/disable pstates. This will also tell +// PGPE how to set PMCR mode register (OCC/OPAL control pstates). +// when this IPC is successfully scheduled, it sets the G_proc_pstate_status +// global variable to in-transition, a call back function +// (pgpe_start_suspend_callback) will set it to the appropriate value upon +// successfull completion. +// +// End Function Specification + +errlHndl_t pgpe_start_suspend(uint8_t action) +{ + PMCR_OWNER owner; // PMCR owner + int rc; // gpe schedule return codes + errlHndl_t err = NULL; // Error handler + + // For now, we set PMCR ownership based on whether the system + // is OPAL system or not. + if(G_sysConfigData.system_type.kvm) + { + owner = PMCR_OWNER_HOST; + } + else + { + owner = PMCR_OWNER_OCC; + } + + // set the IPC parameters + G_start_suspend_parms.action = action; + G_start_suspend_parms.pmcr_owner = owner; + + // @TODO: remove this precompile directive check when PGPE code is integrated. + // RTC: 163934 +#ifdef PGPE_SUPPORT + // Schedule PGPE start_suspend task + rc = gpe_request_schedule(&G_start_suspend_req); +#else + rc = 0; +#endif + + // couldn't schedule the IPC task? + if(rc != 0) + { + //Error in scheduling pgpe clip update task + TRAC_ERR("pgpe_start_suspend: Failed to schedule pgpe start_suspend task rc=%x", + rc); + /* @ + * @errortype + * @moduleid PGPE_START_SUSPEND_MOD + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 rc - gpe_request_schedule return code + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc OCC Failed to schedule a GPE job for start_suspend + */ + err = createErrl( + PGPE_START_SUSPEND_MOD, // modId + GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode + OCC_NO_EXTENDED_RC, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + rc, // userdata1 + 0 // userdata2 + ); + + REQUEST_RESET(err); //This will add a firmware callout for us + } + // successfully scheduled, set the G_proc_pstate_status to indicate transition + else + { + G_proc_pstate_status = PSTATES_IN_TRANSITION; + } + +#ifndef PGPE_SUPPORT + pgpe_start_suspend_callback(); +#endif + + return err; +} + + +// Function Specification +// +// Name: pgpe_pmcr_set +// +// Description: call PGPE IPC to set the PMCR with the pstate values. +// Since this IPC call is non-blocking, the calling +// function needs to assure previous call completion +// before calling this call. +// +// End Function Specification + +errlHndl_t pgpe_pmcr_set(void) +{ + int rc; // gpe schedule return codes + errlHndl_t err = NULL; // Error handler + + do + { + // Caller must check the completion of previous invocation of pmcr set IPC call. + // This check is a safety feature in case caller didn't check IPC is idle. + if(!async_request_is_idle(&G_pmcr_set_req.request)) + { + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("pgpe_pmcr_set: clip update IPC task is not Idle"); + + /* + * @errortype + * @moduleid PGPE_PMCR_SET_MOD + * @reasoncode PGPE_FAILURE + * @userdata1 0 + * @userdata4 ERC_PGPE_NOT_IDLE + * @devdesc pgpe pmcr set not idle + */ + err = createErrl( + PGPE_PMCR_SET_MOD, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_NOT_IDLE, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + 0, //Userdata1 + 0 //Userdata2 + ); + + break; + } + + // @TODO: remove this precompile directive check when PGPE code is integrated. + // RTC: 163934 +#ifdef PGPE_SUPPORT + // Schedule PGPE clip update IPC task + rc = gpe_request_schedule(&G_pmcr_set_req); +#else + rc = 0; +#endif + + // Confirm Successfull completion of PGPE clup update task + if(rc != 0) + { + //Error in scheduling pgpe clip update task + TRAC_ERR("pgpe_pmcr_set: Failed to schedule PMCR setup pgpe task rc=%x", + rc); + } + + if(rc != 0) + { + /* @ + * @errortype + * @moduleid PGPE_PMCR_SET_MOD + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 rc - gpe_request_schedule return code + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc OCC Failed to schedule a GPE job for clip update + */ + err = createErrl( + PGPE_PMCR_SET_MOD, // modId + GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode + OCC_NO_EXTENDED_RC, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buf + DEFAULT_TRACE_SIZE, // Trace Size + rc, // userdata1 + 0 // userdata2 + ); + + REQUEST_RESET(err); //This will add a firmware callout for us + } + } + while(0); + + return err; +} + diff --git a/src/occ_405/pgpe/pgpe_interface.h b/src/occ_405/pgpe/pgpe_interface.h new file mode 100644 index 00000000..a777f28d --- /dev/null +++ b/src/occ_405/pgpe/pgpe_interface.h @@ -0,0 +1,45 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/pgpe/pgpe_interface.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _PGPE_INTERFACE_H_ +#define _PGPE_INTERFACE_H_ + +#include "errl.h" + +errlHndl_t init_pgpe_ipcs(void); + +errlHndl_t pgpe_init_clips(void); +errlHndl_t pgpe_init_pmcr(void); +errlHndl_t pgpe_init_start_suspend(void); +errlHndl_t pgpe_init_wof_control(void); +errlHndl_t pgpe_init_wof_vfrt(void); + +errlHndl_t pgpe_widen_clip_ranges(void); +errlHndl_t pgpe_clip_update(void); +errlHndl_t pgpe_pmcr_set(void); +errlHndl_t pgpe_start_suspend(uint8_t action); +void pgpe_start_suspend_callback(void); + +#endif /* #ifndef _PGPE_INTERFACE_H_ */ diff --git a/src/occ_405/pgpe/pgpe_service_codes.h b/src/occ_405/pgpe/pgpe_service_codes.h new file mode 100644 index 00000000..2e669523 --- /dev/null +++ b/src/occ_405/pgpe/pgpe_service_codes.h @@ -0,0 +1,46 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/pgpe/pgpe_service_codes.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _PGPE_SERVICE_CODES_H_ +#define _PGPE_SERVICE_CODES_H_ + +#include + +enum pgpeModuleId +{ + PGPE_INIT_CLIPS_MOD = PGPE_COMP_ID | 0x00, + PGPE_INIT_PMCR_MOD = PGPE_COMP_ID | 0x01, + PGPE_INIT_START_SUSPEND_MOD = PGPE_COMP_ID | 0x02, + PGPE_INIT_WOF_CONTROL_MOD = PGPE_COMP_ID | 0x03, + PGPE_INIT_WOF_VFRT_MOD = PGPE_COMP_ID | 0x04, + PGPE_CLIP_UPDATE_MOD = PGPE_COMP_ID | 0x05, + PGPE_START_SUSPEND_MOD = PGPE_COMP_ID | 0x06, + PGPE_PMCR_SET_MOD = PGPE_COMP_ID | 0x07, + PGPE_WIDEN_CLIP_RANGES_MOD = PGPE_COMP_ID | 0x08, + PGPE_START_SUSPEND_CALLBACK_MOD = PGPE_COMP_ID | 0x09, +}; + + +#endif /* #ifndef _PGPE_SERVICE_CODES_H_ */ diff --git a/src/occ_405/pgpe_shared.h b/src/occ_405/pgpe/pgpe_shared.h similarity index 70% rename from src/occ_405/pgpe_shared.h rename to src/occ_405/pgpe/pgpe_shared.h index 0dac88fb..eb4b27a5 100644 --- a/src/occ_405/pgpe_shared.h +++ b/src/occ_405/pgpe/pgpe_shared.h @@ -1,7 +1,7 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ_405/pgpe_shared.h $ */ +/* $Source: src/occ_405/pgpe/pgpe_shared.h $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ @@ -26,6 +26,8 @@ #define PGPE_HEADER_ADDR 0xFFF20180 // 0xfff20000 + 0x180 #define PGPE_HEADER_SZ 96 // Size of PGPE Image header +#define PGPE_MAGIC_NUMBER 0x5849502050475045ull // "XIP PGPE" + // Offset addresses of PGPE Header parameters (relative to start address) #define PGPE_SHARED_SRAM_ADDR_OFFSET 0x0c #define PGPE_SHARED_SRAM_SZ_OFFSET 0x14 @@ -40,3 +42,32 @@ // A pointer to PGPE Beacon Address #define PGPE_BEACON_ADDR_PTR (PGPE_HEADER_ADDR + PGPE_BEACON_ADDR_OFFSET) + +// PMMR (Pstates PM region) in HOMMR +#define PPMR_OPPM_ADDR_OFFSET 0x40 //offset of the OCC Pstates Parameter Block address in the PPMR header +#define PPMR_OPPM_SZ_OFFSET 0x44 //offset of the OCC Pstates Parameter Block size in the PPMR header + + +// This size must be a multiple of 128 +typedef struct __attribute__ ((packed)) +{ + uint64_t magic_number; + uint32_t bc_offset; + uint32_t resserved; + uint32_t bl_offset; + uint32_t bl_length; + uint32_t build_date;; + uint32_t version; + uint8_t resvd_flag[8]; + uint32_t pgpe_hcode_offset; + uint32_t pgpe_hcode_length; + uint32_t gppb_offset; + uint32_t gppb_length; + uint32_t lppb_offset; + uint32_t lppb_length; + uint32_t oppb_offset; + uint32_t oppb_length; + uint32_t pstables_offset; + uint32_t pstables_length; + uint8_t pad[48]; +} ppmr_header_t __attribute__ ((aligned (128))); diff --git a/src/occ_405/proc/proc_data.c b/src/occ_405/proc/proc_data.c index 0a0b5284..4de69256 100755 --- a/src/occ_405/proc/proc_data.c +++ b/src/occ_405/proc/proc_data.c @@ -35,6 +35,7 @@ #include "apss.h" #include "state.h" #include "proc_data_control.h" +#include "pgpe_interface.h" #include "cmdh_fsp.h" #include "sensor.h" @@ -319,7 +320,8 @@ void proc_core_init( void ) // cores are present and configured. The Core Configuration Status Register // has this information, so we will need to read it over OCI. uint64_t l_ccsr_val = in64(OCB_CCSR); - MAIN_TRAC_INFO("proc_core_init: CCSR read 0x%08X%08X", (uint32_t) (l_ccsr_val>>32), (uint32_t) l_ccsr_val); + MAIN_TRAC_INFO("proc_core_init: CCSR read 0x%08X%08X", + (uint32_t) (l_ccsr_val>>32), (uint32_t) l_ccsr_val); G_present_hw_cores = ((uint32_t) (l_ccsr_val >> 32)) & HW_CORES_MASK; G_present_cores = G_present_hw_cores; @@ -405,9 +407,8 @@ void proc_core_init( void ) } while(0); - // Initialize the core data control structures at the same time -// TEMP/TODO: Needs to be re-enabled when the data control task is enabled -// proc_core_data_control_init(); + // Initialize the core data control at the same time + init_pgpe_ipcs(); return; } diff --git a/src/occ_405/proc/proc_data_control.c b/src/occ_405/proc/proc_data_control.c index c68b4223..38165ac2 100755 --- a/src/occ_405/proc/proc_data_control.c +++ b/src/occ_405/proc/proc_data_control.c @@ -24,6 +24,7 @@ /* IBM_PROLOG_END_TAG */ #include "proc_data.h" +#include "proc_data_control.h" #include "occhw_async.h" #include "threadSch.h" #include "pmc_register_addresses.h" @@ -35,231 +36,147 @@ #include "apss.h" #include "state.h" #include "occ_sys_config.h" +#include "p9_pstates_common.h" +#include "pgpe_interface.h" +#include "rtls_service_codes.h" -// Pore flex request for GPE job. The initialization will be done one time -// during pore flex create. -PoreFlex G_core_data_control_req; +// The the GPE parameter fields for PGPE IPC calls. +extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr); +extern GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr); -// Global double buffering for core data control -GPE_BUFFER(PcbsPstateRegs G_core_data_control_a[MAX_NUM_HW_CORES]) = {{{0}}}; -GPE_BUFFER(PcbsPstateRegs G_core_data_control_b[MAX_NUM_HW_CORES]) = {{{0}}}; - -// Pointer to the core data control that will be used by GPE engine. -GPE_BUFFER(PcbsPstateRegs * G_core_data_control_gpewrite_ptr) = { &G_core_data_control_a[0] }; - -// Pointer to the core data control that will be written to by the OCC FW. -GPE_BUFFER(PcbsPstateRegs * G_core_data_control_occwrite_ptr) = { &G_core_data_control_b[0] }; +extern GpeRequest G_clip_update_req; +extern GpeRequest G_pmcr_set_req; -// The Gpe parameter fields are set up each time before the GPE starts. -GPE_BUFFER(GpeSetPstatesParms G_core_data_control_parms); +// create gpe request for GPE job. The initialization will be done one time +// during gpe request create. +GpeRequest G_core_data_control_req; -// Function Specification -// -// Name: proc_set_pstate -// -// Description: Function to demonstrate setting Pstates to all cores -// Should only be run from RTL -// -// End Function Specification -void proc_set_pstate_all(Pstate i_pstate) -{ - uint8_t l_chiplet = 0; +// Global double buffering for core data control +GPE_BUFFER(PstatesClips G_quads_data_control[2]) = {{{{0}}}}; - for(; l_chipletmsg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors + { - set_chiplet_pmax(G_core_data_control_occwrite_ptr, - l_hw_core, - l_pmax); - set_chiplet_pmin(G_core_data_control_occwrite_ptr, - l_hw_core, - i_pmin); -} + //The previous OPAL PGPE request succeeded: + //1) swap gpewrite ptr with the occwrite ptr (double buffering). + l_temp = G_core_data_control_occwrite_ptr; + G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr; + G_core_data_control_gpewrite_ptr = l_temp; -// Function Specification -// -// Name: proc_core_data_control_init -// -// Description: Initializations needed for core data control task -// -// End Function Specification -void proc_core_data_control_init( void ) -{ - errlHndl_t l_err = NULL; //Error handler - tracDesc_t l_trace = NULL; //Temporary trace descriptor - int rc = 0; //Return code + //2) Set clip values from gpewrite's quad clips data-structure + G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips; - do - { - //FIXME: Need to change this to use PGPE queue - //Initializes PoreFlex object for pstate control - rc = pore_flex_create( &G_core_data_control_req, //gpe_req for the task - &G_pore_gpe0_queue, //queue - gpe_set_pstates, //entry point - (uint32_t) &G_core_data_control_parms, //parm for the task - SSX_WAIT_FOREVER, //no timeout - NULL, //callback - NULL, //callback argument - 0 ); //options - if( rc ) + //call PGPE IPC function to update the clips + pgpe_clip_update(); + } + else if(G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS) { - //If fail to create pore flex object then there is a problem. - TRAC_ERR("Fail to create core control poreFlex object[0x%x]", rc ); + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("task_core_data_control: clip update IPC task returned an error, %d", + G_clip_update_parms_ptr->msg_cb.rc); /* * @errortype - * @moduleid PROC_CORE_INIT_MOD - * @reasoncode SSX_GENERIC_FAILURE - * @userdata1 pore_flex_create return code - * @userdata4 ERC_PROC_CONTROL_INIT_FAILURE - * @devdesc Failure to create poreflex object + * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD + * @reasoncode PGPE_FAILURE + * @userdata1 rc + * @userdata2 idle? + * @userdata4 ERC_PGPE_UNSUCCESSFULL + * @devdesc pgpe clip update returned an error */ - l_err = createErrl( - PROC_CORE_INIT_MOD, //modId - SSX_GENERIC_FAILURE, //reasoncode - ERC_PROC_CONTROL_INIT_FAILURE, //Extended reason code - ERRL_SEV_PREDICTIVE, //Severity - l_trace, //TODO: create l_trace //Trace Buf - DEFAULT_TRACE_SIZE, //Trace Size - rc, //userdata1 - 0 //userdata2 - ); - - // commit error log - REQUEST_RESET(l_err); //$gm006 - break; + err = createErrl( + RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_UNSUCCESSFULL, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + G_clip_update_parms_ptr->msg_cb.rc, //Userdata1 + async_request_is_idle(&G_clip_update_req.request) //Userdata2 + ); } - - } while(0); -} - -// Function Specification -// -// Name: task_core_data_control -// -// Description: Control core actuation for all configured cores on every tick. -// -// End Function Specification -void task_core_data_control( task_t * i_task ) -{ -//TEMP/TODO: proc_core_data_control_init needs to be called from proc_core_init() -// when this task is enabled for it to function properly. - errlHndl_t l_err = NULL; //Error handler - tracDesc_t l_trace = NULL; //Temporary trace descriptor - int rc = 0; //Return code - PcbsPstateRegs * l_temp = NULL; - - do + } + else { - - //Check to see if the previous GPE request still running - if( !(async_request_is_idle(&G_core_data_control_req.request)) ) + // NON OPAL System, OCC owns PMCR: + if( async_request_is_idle(&G_pmcr_set_req.request) && // PMCR IPC from last TICK completed + (G_pmcr_set_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors { - break; - } + //The previous Non-OPAL PGPE request succeeded: - //Check to see if the previosuly GPE request has been succeeded - if( async_request_completed(&G_core_data_control_req.request) ) - { - //If the previous GPE request succeeded then swap the - //gpewrite ptr with the occwrite ptr. + //1) swap gpewrite ptr with the occwrite ptr (double buffering). l_temp = G_core_data_control_occwrite_ptr; + G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr; G_core_data_control_gpewrite_ptr = l_temp; - } - //Setup the core data control parms - G_core_data_control_parms.config = (uint64_t) (((uint64_t) G_present_hw_cores) << 32); - if(G_sysConfigData.system_type.kvm) - { - //Set the chiplet bounds (pmax/pmin) only on opal - G_core_data_control_parms.select = GPE_SET_PSTATES_PMBR; - } - else - { - //Set the chiplet pstate request on non-opal systems - G_core_data_control_parms.select = GPE_SET_PSTATES_PMCR; - } - - G_core_data_control_parms.regs = (uint32_t) G_core_data_control_gpewrite_ptr; + //2) Set Pstate values from gpewrite's quad pstates data-structure + G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates; - rc = pore_flex_schedule( &G_core_data_control_req ); - if( rc != 0 ) + //call PGPE IPC function to update Pstates + pgpe_pmcr_set(); + } + else if(G_pmcr_set_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS) { - TRAC_ERR("Failed PoreFlex schedule core data control [%x] \n", rc); + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("task_core_data_control: pstate update IPC task returned an error, %d", + G_pmcr_set_parms_ptr->msg_cb.rc); /* * @errortype - * @moduleid PROC_TASK_CORE_DATA_MOD - * @reasoncode SSX_GENERIC_FAILURE - * @userdata1 pore_flex_schedule return code - * @userdata4 ERC_PROC_CONTROL_TASK_FAILURE - * @devdesc Failure to schedule poreflex object + * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD + * @reasoncode PGPE_FAILURE + * @userdata1 rc + * @userdata4 ERC_PGPE_UNSUCCESSFULL + * @devdesc pgpe PMCR set returned an error */ - l_err = createErrl( - PROC_TASK_CORE_DATA_MOD, //modId - SSX_GENERIC_FAILURE, //reasoncode - ERC_PROC_CONTROL_TASK_FAILURE, //Extended reason code - ERRL_SEV_PREDICTIVE, //Severity - l_trace, //TODO: create l_trace //Trace Buf - DEFAULT_TRACE_SIZE, //Trace Size - rc, //userdata1 - 0 //userdata2 - ); - - // commit error log - REQUEST_RESET(l_err); - break; + err = createErrl( + RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_UNSUCCESSFULL, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + G_pmcr_set_parms_ptr->msg_cb.rc, //Userdata1 + 0 //Userdata2 + ); } - } while(0); + } + + if(err) + { + // commit error log + REQUEST_RESET(err); + } return; } diff --git a/src/occ_405/proc/proc_data_control.h b/src/occ_405/proc/proc_data_control.h index ec65c2f7..4188c08b 100755 --- a/src/occ_405/proc/proc_data_control.h +++ b/src/occ_405/proc/proc_data_control.h @@ -30,21 +30,26 @@ #include #include "rtls.h" #include "p9_pstates_common.h" +#include "pstate_pgpe_occ_api.h" -//#include "gpe_control.h" +/// Per-quad Pstate/Clip control data-structure +/// +/// Firmware maintains a copy of PstateClipStruct structures - with an entry +/// for each quad on the chip - and updates the pstate/clip fields in place. +/// The PGPE IPC procedures (MSGID_405_SET_PMCR and MSGID_405_CLIPS) +/// are run periodically to update the core psates or clips control values +/// from this data structure. The array can (should) be cleared initially. +typedef struct { -// Initialze the structures used by the GPE -void proc_core_data_control_init( void ); + /// The Pstate control values + ipcmsg_set_pmcr_t pstates; -// Task that sets the PMCR, PMBR, PMICR -void task_core_data_control( task_t * i_task ); + /// The clipping values + ipcmsg_clip_update_t clips; -// Function to demonstrate setting Pstates to all cores -void proc_set_pstate_all(Pstate i_pstate); +} PstatesClips; -// Function to demonstrate setting Pstates one core -void proc_set_core_pstate(Pstate i_pstate, uint8_t i_core); +// Task that sets the PMCR, PMBR, PMICR +void task_core_data_control( task_t * i_task ); -// Sets the Pmin/Pmax clip values for one core -void proc_set_core_bounds(Pstate i_pmin, Pstate i_pmax, uint8_t i_core); #endif diff --git a/src/occ_405/proc/proc_pstate.c b/src/occ_405/proc/proc_pstate.c index d63c96fa..15b66d8b 100755 --- a/src/occ_405/proc/proc_pstate.c +++ b/src/occ_405/proc/proc_pstate.c @@ -40,30 +40,28 @@ #include #include #include +#include +#include //OPAL processor and memory throttle reason coming from the frequency voting boxes. extern opal_proc_voting_reason_t G_amec_opal_proc_throt_reason; extern opal_mem_voting_reason_t G_amec_opal_mem_throt_reason; -// Holds Fmax for ease of proc_freq2pstate calculation -uint32_t G_proc_fmax = 0; +//Global OCC Pstate Parameters Block Structure +extern OCCPstateParmBlock G_oppb; -// Holds Fmin for ease of proc_freq2pstate calculation -uint32_t G_proc_fmin = 0; +//Holds Fmax for ease of proc_freq2pstate calculation = max(fturbo,futurbo) +uint16_t G_proc_fmax_mhz; -// Holds frequency steps between consequtive Pstates -uint32_t G_khz_per_pstate = 0; +// A global variable indicating whether the pstates have been enabled. +// initialized to PSTATES_DISABLED, turns to PSTATES_ENABLED only after +// the PGPE IPC that enable pstates completes successfully. While the IPC +// task is still running, this variable be set to PSTATES_IN_TRANSITION +pstateStatus G_proc_pstate_status = PSTATES_DISABLED; -// Holds Pmax for ease of proc_freq2pstate calculation -uint8_t G_proc_pmax = 0; -// Holds Pmin for ease of proc_freq2pstate calculation -uint8_t G_proc_pmin = 0; - -// Holds a flag indicating whether the pstates have been enabled. -// initialized to FALSE, turns TRUE only after the PGPE IPC that -// enable pstates completes successfully. -bool G_proc_pstate_enabled = FALSE; +// A Global parameter indicating the owner of the PMCR. +PMCR_OWNER G_proc_pmcr_owner = G_sysConfigData.system_type.kvm? PMCR_OWNER_HOST: PMCR_OWNER_HOST; // OPAL Dynamic data, updated whenever any OCC G_opal_table.dynamic parameter change DMA_BUFFER( opal_dynamic_table_t G_opal_dynamic_table ) = {{0}}; @@ -81,7 +79,7 @@ DMA_BUFFER( opal_static_table_t G_opal_static_table ) = {{0}}; // End Function Specification bool proc_is_hwpstate_enabled(void) { - return ( G_proc_pstate_enabled ? TRUE : FALSE); + return ( G_proc_pstate_status == PSTATES_ENABLED ? TRUE : FALSE); } // Function Specification @@ -93,20 +91,16 @@ bool proc_is_hwpstate_enabled(void) // End Function Specification uint32_t proc_pstate2freq(Pstate i_pstate) { - // If passed in Pstate is lower than Pmin, just use Pmin - if(i_pstate < G_proc_pmin) - { - i_pstate = G_proc_pmin; - } - - // If passed in Pstate is greater than Pmax, just use Pmax - else if (i_pstate > G_proc_pmax) + // The higher the pstate number, the lower the frequency: + // If passed in Pstate is lower than Pmin (higher pstate value), + // just use Pmin. + if(i_pstate > G_oppb.pstate_min) { - i_pstate = G_proc_pmax; + i_pstate = G_oppb.pstate_min; } // Calculate Frequency in kHz based on Pstate - return (G_proc_fmin + (G_proc_pmin - i_pstate) * G_khz_per_pstate); + return ( G_oppb.frequency_max_khz - (i_pstate * G_oppb.frequency_step_khz)); } // Function Specification @@ -135,29 +129,21 @@ Pstate proc_freq2pstate(uint32_t i_freq_mhz) l_freq_khz = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY] * 1000; } - if(l_freq_khz < G_proc_fmax) + if(l_freq_khz < G_proc_fmax_mhz * 1000) { // First, calculate the delta between passed in freq, and Pmin - l_temp_freq = l_freq_khz - G_proc_fmin; - - // Check if the passed in frequency is lower than Minimum Frequency - if(l_freq_khz <= G_proc_fmin) - { - // We need to substract a full step (minus 1) to make sure we - // are keeping things safe - l_temp_freq -= (G_khz_per_pstate - 1); - } + l_temp_freq = l_freq_khz - G_oppb.frequency_min_khz; // Next, calculate how many Pstate steps there are in that delta - l_temp_pstate = l_temp_freq / (int32_t) G_khz_per_pstate; + l_temp_pstate = l_temp_freq / (int32_t) G_oppb.frequency_step_khz; // Lastly, calculate Pstate, by adding delta Pstate steps to Pmin - l_pstate = G_proc_pmin - l_temp_pstate; + l_pstate = G_oppb.pstate_min - l_temp_pstate; } else { // Freq is higher than maximum frequency -- return Pmax - l_pstate = G_proc_pmax; + l_pstate = PMAX + (G_oppb.frequency_max_khz - G_proc_fmax_mhz*1000)/G_oppb.frequency_step_khz; } } while(0); @@ -183,11 +169,13 @@ void proc_pstate_kvm_setup() break; } + TRAC_INFO("proc_pstate_kvm_setup: populate static OPAL data"); + // Initialize the opal table in SRAM (sets valid bit) - populate_static_opal_data(); + populate_opal_static_data(); // copy sram image into mainstore HOMER - populate_opal_tbl_to_mem(); + populate_opal_tbl_to_mem(OPAL_STATIC); TRAC_IMP("proc_pstate_kvm_setup: RUNNING IN KVM MODE"); }while(0); @@ -195,12 +183,12 @@ void proc_pstate_kvm_setup() // Function Specification // -// Name: populate_dynamic_opal_data +// Name: populate_opal_dynamic_data // // Description: populate the dynamic data entries in the OPAL table // // End Function Specification -void populate_dynamic_opal_data() +void populate_opal_dynamic_data() { memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table)); @@ -228,18 +216,33 @@ void populate_dynamic_opal_data() // Function Specification // -// Name: populate_static_opal_data +// Name: populate_opal_static_data // // Description: populate the static configuration entries, // the generated pstates table, and maximum pstates // for all possible number of active cores. // // End Function Specification -void populate_static_opal_data() +void populate_opal_static_data() { - memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table)); + // clear all entries of the OPAL static table + memset(&G_opal_static_table, 0, sizeof(G_opal_static_table)); + + populate_opal_static_config_data(); + populate_opal_static_pstates_data(); +} + +// Function Specification +// +// Name: populate_opal_static_config_data +// +// Description: populate the static configuration entries, +// +// End Function Specification +void populate_opal_static_config_data(void) +{ // Static OPAL configuration data G_opal_static_table.config.valid = 1; G_opal_static_table.config.version = 0x90; @@ -247,43 +250,90 @@ void populate_static_opal_data() G_opal_static_table.config.pmin = pmin_rail(); G_opal_static_table.config.pnominal = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]); G_opal_static_table.config.pturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]); - G_opal_static_table.config.puturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_UTURBO]); + G_opal_static_table.config.puturbo = proc_freq2pstate(G_proc_fmax_mhz); +} + +// Function Specification +// +// Name: populate_opal_static_data +// +// Description: populate the generated pstates table, and maximum +// pstates for all possible number of active cores. +// +// End Function Specification +void populate_opal_static_pstates_data(void) +{ + uint16_t i; // loop variable + for (i=0; i <= G_oppb.pstate_min; i++) + { + G_opal_static_table.pstates[i].pstate = i; // pstate number + G_opal_static_table.pstates[i].flag = 0; // flag is reserved for future use + G_opal_static_table.pstates[i].freq_khz = proc_pstate2freq(i); // pstate's frequency + } - // TODO - RTC:130201 generate pstates table & Max pstates for var #cores + for (i=0; i move to initialization code, reading from parameter block - G_proc_fmax = 4322500; - G_proc_fmin = 2028250; - G_khz_per_pstate = 33250; - G_proc_pmax = 0; - G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate); - - // Set globals used by amec for pcap calculation - // could have used G_khz_per_pstate in PCAP calculations - // instead, but using a separate varaible speeds up PCAP related - // calculations significantly, by eliminating division operations. - G_mhz_per_pstate = G_khz_per_pstate/1000; - - TRAC_INFO("proc_pstate_initialize: Pstate Key globals initialized to default values"); - -} // Function Specification // @@ -429,14 +441,14 @@ void check_for_opal_updates(void) // End Function Specification void update_dynamic_opal_data (void) { + TRAC_INFO("update_dynamic_opal_data: populate dynamic OPAL data"); + // Initialize the opal table in SRAM (sets valid bit) - populate_dynamic_opal_data(); + populate_opal_dynamic_data(); // copy sram image into mainstore HOMER - populate_opal_tbl_to_mem(); - TRAC_IMP("update_dynamic_opal_data: update dynamic OPAL data"); - - + populate_opal_tbl_to_mem(OPAL_DYNAMIC); + TRAC_IMP("update_dynamic_opal_data: updated dynamic OPAL data"); } @@ -451,14 +463,15 @@ void update_dynamic_opal_data (void) // End Function Specification uint8_t pmin_rail(void) { - uint8_t configMinPstate = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]); + uint8_t configMinPstate = + proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]); - if(configMinPstate < G_proc_pmin) + if(configMinPstate < G_oppb.pstate_min) { return configMinPstate; } else { - return G_proc_pmin; + return G_oppb.pstate_min; } } diff --git a/src/occ_405/proc/proc_pstate.h b/src/occ_405/proc/proc_pstate.h index 962c71a1..b552237a 100755 --- a/src/occ_405/proc/proc_pstate.h +++ b/src/occ_405/proc/proc_pstate.h @@ -39,6 +39,25 @@ //#include "gpsm.h" //#include "pstates.h" +// The pstate associated with highest possible frequency +// is always 0 in POWER9. +#define PMAX 0 + +typedef enum +{ + PSTATES_IN_TRANSITION = -1, + PSTATES_DISABLED = 0, + PSTATES_ENABLED = 1, +} pstateStatus; + + +typedef enum +{ + OPAL_STATIC = 0, + OPAL_DYNAMIC = 1, +} opalDataType; + + typedef struct __attribute__ ((packed)) { uint8_t valid; @@ -100,9 +119,7 @@ typedef struct __attribute__ ((packed)) extern uint32_t G_mhz_per_pstate; extern opal_dynamic_table_t G_opal_dynamic_table; - -// Initialize PState Key parameters -void proc_pstate_initialize(void); +extern opal_static_table_t G_opal_static_table; // Helper function to translate from Frequency to nearest Pstate Pstate proc_freq2pstate(uint32_t i_freq_mhz); @@ -115,13 +132,19 @@ Pstate proc_freq2pstate(uint32_t i_freq_mhz); inline bool proc_is_hwpstate_enabled(void); // Copy pstate data to opal table -void populate_dynamic_opal_data(void); +void populate_opal_dynamic_data(void); // Copy all opal static data to opal table -void populate_static_opal_data(void); +void populate_opal_static_data(void); + +// Copy pstates sections of opal static data to opal table +void populate_opal_static_pstates_data(void); + +// Copy config section of opal static data to opal table +void populate_opal_static_config_data(void); -// Copy opal table to mainstore memory at OPAL_OFFSET_HOMER -void populate_opal_tbl_to_mem(void); +// Copy opal static/dynamic table to mainstore memory at OPAL_OFFSET_HOMER +void populate_opal_tbl_to_mem(opalDataType opal_data_type); // Check if opal table needs update void check_for_opal_updates(void); diff --git a/src/occ_405/pss/apss.c b/src/occ_405/pss/apss.c index e93b156a..ae4d100d 100755 --- a/src/occ_405/pss/apss.c +++ b/src/occ_405/pss/apss.c @@ -1097,7 +1097,7 @@ errlHndl_t initialize_apss(void) //Create the request for measure start. Scheduling will happen in apss.c gpe_request_create(&G_meas_start_request, &G_async_gpe_queue0, // queue - IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point + IPC_ST_APSS_START_PWR_MEAS_READ_FUNCID, // entry_point &G_gpe_start_pwr_meas_read_args, // entry_point arg SSX_WAIT_FOREVER, // no timeout NULL, // callback diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h index 6da68254..8babaab2 100755 --- a/src/occ_405/rtls/rtls.h +++ b/src/occ_405/rtls/rtls.h @@ -53,11 +53,11 @@ typedef enum { TASK_ID_DCOM_TX_OUTBX, TASK_ID_MISC_405_CHECKS, // Miscellaneous checks to be done by 405 TASK_ID_DCOM_PARSE_FW_MSG, - TASK_ID_AMEC_SLAVE, // AMEC SMH tasks - TASK_ID_AMEC_MASTER, // AMEC SMH tasks -// TASK_ID_CORE_DATA_CONTROL, // TODO RTC: 163365 + TASK_ID_AMEC_SLAVE, // AMEC SMH tasks + TASK_ID_AMEC_MASTER, // AMEC SMH tasks + TASK_ID_CORE_DATA_CONTROL, // TASK_ID_GPU_SM, // GPU State Machine TODO RTC: 133824 - TASK_ID_DIMM_SM, // DIMM State Machine + TASK_ID_DIMM_SM, // DIMM State Machine TASK_ID_MEMORY_CONTROL, // Memory (centaur/dimm) control task TASK_ID_NEST_DTS, TASK_END // This must always be the last enum in this list, diff --git a/src/occ_405/rtls/rtls_service_codes.h b/src/occ_405/rtls/rtls_service_codes.h index 5aab7280..44f20d84 100755 --- a/src/occ_405/rtls/rtls_service_codes.h +++ b/src/occ_405/rtls/rtls_service_codes.h @@ -30,12 +30,13 @@ enum rtlsModuleId { - RTLS_OCB_INIT_MOD = RTLS_COMP_ID | 0x00, - RTLS_DO_TICK_MOD = RTLS_COMP_ID | 0x01, - RTLS_START_TASK_MOD = RTLS_COMP_ID | 0x02, - RTLS_STOP_TASK_MOD = RTLS_COMP_ID | 0x03, - RTLS_TASK_RUNABLE_MOD = RTLS_COMP_ID | 0x04, - RTLS_SET_TASK_DATA_MOD = RTLS_COMP_ID | 0x05, + RTLS_OCB_INIT_MOD = RTLS_COMP_ID | 0x00, + RTLS_DO_TICK_MOD = RTLS_COMP_ID | 0x01, + RTLS_START_TASK_MOD = RTLS_COMP_ID | 0x02, + RTLS_STOP_TASK_MOD = RTLS_COMP_ID | 0x03, + RTLS_TASK_RUNABLE_MOD = RTLS_COMP_ID | 0x04, + RTLS_SET_TASK_DATA_MOD = RTLS_COMP_ID | 0x05, + RTLS_TASK_CORE_DATA_CONTROL_MOD = RTLS_COMP_ID | 0x06, }; #endif /* #ifndef _RTLS_SERVICE_CODES_H_ */ diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c index b7b1a4cb..fdcce40a 100755 --- a/src/occ_405/rtls/rtls_tables.c +++ b/src/occ_405/rtls/rtls_tables.c @@ -113,8 +113,7 @@ task_t G_task_table[TASK_END] = { { FLAGS_DCOM_PARSE_OCC_FW_MSG, task_dcom_parse_occfwmsg, NULL }, // TASK_ID_DCOM_PARSE_FW_MSG { FLAGS_AMEC_SLAVE, task_amec_slave, NULL }, // TASK_ID_AMEC_SLAVE { FLAGS_AMEC_MASTER, task_amec_master, NULL }, // TASK_ID_AMEC_MASTER -// TODO RTC: 163365 - /proc/ and /pss/ "TODO" cleanup -// { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL + { FLAGS_CORE_DATA_CONTROL, task_core_data_control, NULL }, // TASK_ID_CORE_DATA_CONTROL // TODO RTC: 133824 - New GPU interface via main memory and SMBUS // { FLAGS_GPU_SM, task_gpu_sm, NULL }, // TASK_ID_GPU_SM { FLAGS_MEMORY_DATA, task_dimm_sm, NULL }, // TASK_ID_DIMM_SM @@ -130,7 +129,7 @@ const uint8_t G_tick0_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -149,7 +148,7 @@ const uint8_t G_tick1_seq[] = { TASK_ID_APSS_CONT, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -170,7 +169,7 @@ const uint8_t G_tick2_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -190,7 +189,7 @@ const uint8_t G_tick3_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -210,7 +209,7 @@ const uint8_t G_tick4_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -229,7 +228,7 @@ const uint8_t G_tick5_seq[] = { TASK_ID_APSS_CONT, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -249,7 +248,7 @@ const uint8_t G_tick6_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -268,7 +267,7 @@ const uint8_t G_tick7_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -288,7 +287,7 @@ const uint8_t G_tick8_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -307,7 +306,7 @@ const uint8_t G_tick9_seq[] = { TASK_ID_APSS_CONT, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -328,7 +327,7 @@ const uint8_t G_tick10_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -347,7 +346,7 @@ const uint8_t G_tick11_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -367,7 +366,7 @@ const uint8_t G_tick12_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -386,7 +385,7 @@ const uint8_t G_tick13_seq[] = { TASK_ID_APSS_CONT, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -406,7 +405,7 @@ const uint8_t G_tick14_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, @@ -425,7 +424,7 @@ const uint8_t G_tick15_seq[] = { TASK_ID_CORE_DATA_HIGH, TASK_ID_APSS_DONE, TASK_ID_MEMORY_CONTROL, - //TASK_ID_CORE_DATA_CONTROL, + TASK_ID_CORE_DATA_CONTROL, TASK_ID_DCOM_WAIT_4_MSTR, TASK_ID_DCOM_RX_INBX, TASK_ID_DCOM_RX_OUTBX, diff --git a/src/occ_405/state.c b/src/occ_405/state.c index 956d06e3..bac2de89 100755 --- a/src/occ_405/state.c +++ b/src/occ_405/state.c @@ -32,18 +32,23 @@ #include "state.h" #include "dcom.h" #include "occ_service_codes.h" -#include "proc_pstate.h" #include "cmdh_fsp_cmds_datacnfg.h" #include "cmdh_fsp.h" #include "proc_data.h" #include "scom.h" #include #include +#include "pgpe_interface.h" +#include "pstate_pgpe_occ_api.h" extern bool G_mem_monitoring_allowed; extern task_t G_task_table[TASK_END]; // Global task table extern bool G_simics_environment; +extern GpeRequest G_clip_update_req; +extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr); + + // Maximum allowed value approx. 16.3 ms #define PCBS_HEARBEAT_TIME_US 16320 @@ -141,9 +146,6 @@ errlHndl_t SMGR_standby_to_observation() rtl_clr_run_mask_deferred(RTL_FLAG_STANDBY); rtl_set_run_mask_deferred(RTL_FLAG_OBS); - // Initialize key freq2pstate Global parameters - proc_pstate_initialize(); - // Set the actual STATE now that we have finished everything else CURRENT_STATE() = OCC_STATE_OBSERVATION; @@ -211,9 +213,9 @@ errlHndl_t SMGR_observation_to_standby() // Function Specification // -// Name: +// Name: SMGR_observation_to_active // -// Description: +// Description: Transition from Observation state to Active state // // End Function Specification errlHndl_t SMGR_observation_to_active() @@ -223,19 +225,89 @@ errlHndl_t SMGR_observation_to_active() int l_extRc = OCC_NO_EXTENDED_RC; int l_rc = 0; - // Pstates are enabled via an IPC call to PGPE once the OCC reaches the - // observation state. We still have to check that the enable_pstates() IPC job - // on the PGPE has completed before transitioning to active state. Otherwise, - // we wait TBD seconds in case we are going directly from Standby to Active - // (pstate init only happens in observation state, so it might not be - // done yet...must call it in this while loop since it is done in this - // same thread...) - // + // confirm that the clip update IPC call to widen clip ranges + // has successfully completed on PGPE (with no errors) + if( !async_request_is_idle(&G_clip_update_req.request) ) //widen_clip_ranges didn't complete + { + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("SMGR: clip update IPC task is not Idle"); + + /* + * @errortype + * @moduleid MAIN_SMGR_MID + * @reasoncode PGPE_FAILURE + * @userdata4 ERC_PGPE_NOT_IDLE + * @devdesc pgpe clip update not idle + */ + l_errlHndl = createErrl( + MAIN_SMGR_MID, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_NOT_IDLE, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + 0, //Userdata1 + 0 //Userdata2 + ); + // TODO now: REQUEST_RESET? + } + else if ( G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS ) // IPC task completed with errors + { + // an earlier clip update IPC call has not completed, trace and log an error + TRAC_ERR("SMGR: clip update IPC task returned an error [0x%08X]", + G_clip_update_parms_ptr->msg_cb.rc); + + /* + * @errortype + * @moduleid MAIN_SMGR_MID + * @reasoncode PGPE_FAILURE + * @userdata1 PGPE clip update's rc + * @userdata4 ERC_PGPE_CLIP_FAILURE + * @devdesc pgpe clip update not idle + */ + l_errlHndl = createErrl( + MAIN_SMGR_MID, //ModId + PGPE_FAILURE, //Reasoncode + ERC_PGPE_CLIP_FAILURE, //Extended reason code + ERRL_SEV_PREDICTIVE, //Severity + NULL, //Trace Buf + DEFAULT_TRACE_SIZE, //Trace Size + G_clip_update_parms_ptr->msg_cb.rc, //Userdata1 + 0 //Userdata2 + ); + // TODO now: REQUEST_RESET? + } + + else // Clips wide opened with no errors, enable Pstates on PGPE + { + + // Pstates are enabled via an IPC call to PGPE, which will + // set the G_proc_pstate_status flag + + l_errlHndl = pgpe_start_suspend(PGPE_ACTION_PSTATE_START); + + if(l_errlHndl) + { + TRAC_ERR("SMGR: Failed to switch to Active state because of a " + "failure to start the pstate protocol on PGPE."); + } + else + { + // Pstates enabled, update OPAL static table in main memory + if(G_sysConfigData.system_type.kvm) + { + // upon succesful enablement of Pstate protocol on + // PGPE update OPAL table with pstate information. + proc_pstate_kvm_setup(); + } + } + } + // NOTE that this is really unnecessary if you follow the TMGT OCC // Interface Spec, which tells you that you need to check for the "Active // Ready" bit in the poll response before you go to active state. // But since we have scenerios where TMGT isn't the one putting us in - // active state (we are going there automatically) we needed to add this + // active state (we are going there automatically) we needed to add this. // If we have all data we need to go to active state, but don't have pstates // enabled yet...then we will do the aforementioned wait @@ -253,8 +325,8 @@ errlHndl_t SMGR_observation_to_active() { TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, " "pmc_mode[%08x], chips_present[%02x], Cores Present [%08x]", - in32(PMC_MODE_REG), - G_sysConfigData.is_occ_present, + in32(PMC_MODE_REG), + G_sysConfigData.is_occ_present, (uint32_t) ((in64(OCB_CCSR)) >> 32)); } l_extRc = ERC_GENERIC_TIMEOUT; diff --git a/src/occ_405/timer/timer.c b/src/occ_405/timer/timer.c index ef42c5c0..78934972 100755 --- a/src/occ_405/timer/timer.c +++ b/src/occ_405/timer/timer.c @@ -507,15 +507,15 @@ void check_pgpe_beacon(void) /* * @errortype * @moduleid POKE_WD_TIMERS - * @reasoncode INTERNAL_HW_FAILURE + * @reasoncode PGPE_FAILURE * @userdata1 PGPE Beacon Value * @userdata2 PGPE Beacon Address - * @userdata4 PGPE_BEACON_TIMEOUT + * @userdata4 ERC_PGPE_BEACON_TIMEOUT * @devdesc PGPE Beacon timeout */ l_err = createErrl(POKE_WD_TIMERS, // mod id - PGPE_BEACON_TIMEOUT, // reason code - OCC_NO_EXTENDED_RC, // Extended reason code + PGPE_FAILURE, // reason code + ERC_PGPE_BEACON_TIMEOUT, // Extended reason code ERRL_SEV_UNRECOVERABLE, // severity NULL, // trace buffer 0, // trace size diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk index c5c16a07..ed33ebf9 100644 --- a/src/occ_405/topfiles.mk +++ b/src/occ_405/topfiles.mk @@ -72,7 +72,9 @@ TOP-C-SOURCES = amec/amec_analytics.c \ mode.c \ occ_sys_config.c \ occbuildname.c \ + pgpe/pgpe_interface.c \ proc/proc_data.c \ + proc/proc_data_control.c \ proc/proc_pstate.c \ pss/apss.c \ pss/avsbus.c \