Esempio n. 1
0
// Function Specification
//
// Name: amec_slv_freq_smh
//
// Description: Slave OCC's frequency state machine.
//              This function will run every tick.
//
// Thread: RealTime Loop
//
// Task Flags:
//
// End Function Specification
void amec_slv_freq_smh(void)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    uint16_t                        k = 0;
    int8_t                          l_pstate = 0;

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/

    for (k=0; k<MAX_NUM_CORES; k++)
    {
        switch (g_amec->proc[0].core[k].f_sms)
        {
            case AMEC_CORE_FREQ_IDLE_STATE:
                // Translate frequency request into a Pstate
                l_pstate = proc_freq2pstate(g_amec->proc[0].core[k].f_request);

                // Fall through
            case AMEC_CORE_FREQ_PROCESS_STATE:
                if(G_sysConfigData.system_type.kvm)
                {
                    // update core bounds on kvm systems
                    proc_set_core_bounds(gpst_pmin(&G_global_pstate_table) + 1, (Pstate) l_pstate, k);
                }
                else
                {
                    // update core pstate request on non-kvm systems
                    proc_set_core_pstate((Pstate) l_pstate, k);
                }
                break;
        }
    }
}
Esempio n. 2
0
// Function Specification
//
// Name:  cmdh_mnfg_request_quad_pstate
//
// Description: This function handles the manufacturing command to request
// a Pstate per Quad.
//
// End Function Specification
uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr,
                                            cmdh_fsp_rsp_t * o_rsp_ptr)
{
    uint8_t                     l_rc = ERRL_RC_SUCCESS;
    uint16_t                    l_datalength = 0;
    uint16_t                    l_resp_data_length = 0;
    uint8_t                     l_pmin = 0xFF;
    uint8_t                     l_pmax = 0xFF;
    uint8_t                     l_pstate_request = 0xFF;
    uint8_t                     l_quad = 0;
    mnfg_quad_pstate_cmd_t     *l_cmd_ptr = (mnfg_quad_pstate_cmd_t*) i_cmd_ptr;
    mnfg_quad_pstate_rsp_t     *l_rsp_ptr = (mnfg_quad_pstate_rsp_t*) o_rsp_ptr;

    do
    {
        if(!IS_OCC_STATE_ACTIVE())
        {
            TRAC_ERR("cmdh_mnfg_request_quad_pstate: OCC must be active to request pstate");
            l_rc = ERRL_RC_INVALID_STATE;
            break;
        }

        if(G_sysConfigData.system_type.kvm)
        {
            TRAC_ERR("cmdh_mnfg_request_quad_pstate: Must be PowerVM to request pstate");
            l_rc = ERRL_RC_INVALID_CMD;
            break;
        }

        // Check command packet data length
        l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
        if(l_datalength != (sizeof(mnfg_quad_pstate_cmd_t) -
                            sizeof(cmdh_fsp_cmd_header_t)))
        {
            TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect data length. exp[%d] act[%d]",
                     (sizeof(mnfg_quad_pstate_cmd_t) -
                      sizeof(cmdh_fsp_cmd_header_t)),
                      l_datalength);
            l_rc = ERRL_RC_INVALID_CMD_LEN;
            break;
        }

        // Check version
        if(l_cmd_ptr->version != MFG_QUAD_PSTATE_VERSION)
        {
            TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect version. exp[%d] act[%d]",
                     MFG_QUAD_PSTATE_VERSION,
                     l_cmd_ptr->version);
            l_rc = ERRL_RC_INVALID_DATA;
            break;
        }

        // only allow a Pstate within the current range based on mode
        l_pmin = proc_freq2pstate(g_amec->sys.fmin);
        l_pmax = proc_freq2pstate(g_amec->sys.fmax);

        // Process each quad Pstate request, clip any request to min/max
        // 0xFF has special meaning that OCC is in control
        for(l_quad = 0; l_quad < MAXIMUM_QUADS; l_quad++)
        {
            l_pstate_request = l_cmd_ptr->quad_pstate_in[l_quad];
            if(l_pstate_request != 0xFF)
            {
                // pmin is lowest frequency corresponding to highest pState value
                if(l_pstate_request > l_pmin)
                   l_pstate_request = l_pmin;

                // pmax is highest frequency corresponding to lowest pState value
                else if(l_pstate_request < l_pmax)
                   l_pstate_request = l_pmax;
            }
            // save the quad pState request for amec and return in rsp data
            g_amec->mnfg_parms.quad_pstate[l_quad] = l_pstate_request;
            l_rsp_ptr->quad_pstate_out[l_quad] = l_pstate_request;
            TRAC_INFO("cmdh_mnfg_request_quad_pstate: Quad %d Pstate in = 0x%02x Pstate out = 0x%02x",
                      l_quad,
                      l_cmd_ptr->quad_pstate_in[l_quad],
                      l_rsp_ptr->quad_pstate_out[l_quad]);
        }

    }while(0);

    // Populate the response data header
    G_rsp_status = l_rc;
    l_resp_data_length = sizeof(mnfg_quad_pstate_rsp_t) - sizeof(cmdh_fsp_rsp_header_t);
    l_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
    l_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];

    return l_rc;
}
Esempio n. 3
0
// Verifies that each core is at the correct frequency after they have had
// time to stabilize
void amec_verify_pstate()
{
    uint8_t                             l_core = 0;
    int8_t                              l_pstate_from_fmax = 0;
    gpe_bulk_core_data_t *              l_core_data_ptr;
    pmc_pmsr_ffcdc_data_t               l_pmc_pmsr_ffdc;
    errlHndl_t                          l_err = NULL;

    if ( (G_time_until_freq_check == 0) &&
            ( CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE ) &&
            ( CURRENT_MODE() != OCC_MODE_DYN_POWER_SAVE_FP ) &&
            (!G_sysConfigData.system_type.kvm))
    {
        // Reset the counter
        G_time_until_freq_check = FREQ_CHG_CHECK_TIME;

        // Convert fmax to the corresponding pstate
        l_pstate_from_fmax = proc_freq2pstate(g_amec->sys.fmax);

        for( l_core = 0; l_core < MAX_NUM_CORES; l_core++ )
        {
            // If the core isn't present, skip it
            if(!CORE_PRESENT(l_core))
            {
                l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].value = 0;
                continue;
            }

            // Get pointer to core data
            l_core_data_ptr = proc_get_bulk_core_data_ptr(l_core);

            // Get the core's pmsr data
            l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core] = l_core_data_ptr->pcb_slave.pmsr;

            // Verify that the core is running at the correct frequency
            // If not, log an error
            if( (l_pstate_from_fmax != l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.local_pstate_actual) &&
                (l_pstate_from_fmax > l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.pv_min) &&
                (l_err == NULL) )
            {
                TRAC_ERR("Frequency mismatch in core %d: actual_ps[%d] req_ps[%d] fmax[%d] mode[%d].",
                    l_core,
                    l_pmc_pmsr_ffdc.pmsr_ffdc_data.data[l_core].fields.local_pstate_actual,
                    l_pstate_from_fmax,
                    g_amec->sys.fmax,
                    CURRENT_MODE());

                fill_pmc_ffdc_buffer(&l_pmc_pmsr_ffdc.pmc_ffcdc_data);

                /* @
                 * @moduleid   AMEC_VERIFY_FREQ_MID
                 * @reasonCode TARGET_FREQ_FAILURE
                 * @severity   ERRL_SEV_PREDICTIVE
                 * @userdata1  0
                 * @userdata2  0
                 * @userdata4  OCC_NO_EXTENDED_RC
                 * @devdesc    A core is not running at the expected frequency
                 */
                l_err = createErrl( AMEC_VERIFY_FREQ_MID,      // i_modId,
                                    TARGET_FREQ_FAILURE,       // i_reasonCode,
                                    OCC_NO_EXTENDED_RC,
                                    ERRL_SEV_UNRECOVERABLE,
                                    NULL,                      // i_trace,
                                    DEFAULT_TRACE_SIZE,        // i_traceSz,
                                    0,                         // i_userData1,
                                    0);                        // i_userData2

                //Add firmware callout
                addCalloutToErrl(l_err,
                        ERRL_CALLOUT_TYPE_COMPONENT_ID,
                        ERRL_COMPONENT_ID_FIRMWARE,
                        ERRL_CALLOUT_PRIORITY_HIGH);

                //Add processor callout
                addCalloutToErrl(l_err,
                        ERRL_CALLOUT_TYPE_HUID,
                        G_sysConfigData.proc_huid,
                        ERRL_CALLOUT_PRIORITY_MED);
            }
        }

        if( l_err != NULL)
        {
            //Add our register dump to the error log
            addUsrDtlsToErrl(l_err,
                    (uint8_t*) &l_pmc_pmsr_ffdc,
                    sizeof(l_pmc_pmsr_ffdc),
                    ERRL_USR_DTL_STRUCT_VERSION_1,
                    ERRL_USR_DTL_BINARY_DATA);

            REQUEST_RESET(l_err);
        }
    }
}
Esempio n. 4
0
// Function Specification
//
// Name:  populate_pstate_to_sapphire_tbl
//
// Description:
//
// End Function Specification
void populate_pstate_to_sapphire_tbl()
{
    uint8_t                 i = 0;
    GlobalPstateTable      *l_gpst_ptr = NULL;
    uint16_t                l_turboFreq = 0;
    uint16_t                l_ultraturboFreq = 0;

    if(G_sysConfigData.sys_mode_freq.table[OCC_MODE_STURBO] == 0)
    {
        // In this case, there is no UltraTurbo frequency defined. For OPAL-OCC
        // interface, make UltraTurbo = Turbo frequency
        l_turboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
        l_ultraturboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
    }
    else
    {
        l_turboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_STURBO];
        l_ultraturboFreq = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
    }

    memset(&G_sapphire_table, 0, sizeof(sapphire_table_t));

    l_gpst_ptr = gpsm_gpst();
    const int8_t l_pmax = (int8_t) l_gpst_ptr->pmin + l_gpst_ptr->entries - 1;
    G_sapphire_table.config.valid = 0x01; // default 0x01
    G_sapphire_table.config.version = 0x02; // default 0x02
    G_sapphire_table.config.throttle = NO_THROTTLE; // default 0x00
    G_sapphire_table.config.pmin = gpst_pmin(&G_global_pstate_table)+1; //Per David Du, we must use pmin+1 to avoid gpsa hang
    G_sapphire_table.config.pnominal = (int8_t)proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]);
    G_sapphire_table.config.turbo = (int8_t) proc_freq2pstate(l_turboFreq);
    G_sapphire_table.config.ultraTurbo = (int8_t) proc_freq2pstate(l_ultraturboFreq);

    int8_t l_tempPmax = gpst_pmax(&G_global_pstate_table);
    const uint16_t l_entries = l_tempPmax - G_sapphire_table.config.pmin + 1;
    const uint8_t l_idx = l_gpst_ptr->entries-1;

    for (i = 0; i < l_entries; i++)
    {
        G_sapphire_table.data[i].pstate = (int8_t) l_pmax - i;
        G_sapphire_table.data[i].flag = 0; // default 0x00
        if (i < l_gpst_ptr->entries)
        {
            G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[i].fields.evid_vdd;
            G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[i].fields.evid_vcs;
        }
        else
        {
            // leave the VDD & VCS Vids the same as the "Pstate Table Pmin"
            G_sapphire_table.data[i].evid_vdd = l_gpst_ptr->pstate[l_idx].fields.evid_vdd;
            G_sapphire_table.data[i].evid_vcs = l_gpst_ptr->pstate[l_idx].fields.evid_vcs;
        }
        // extrapolate the frequency
        G_sapphire_table.data[i].freq_khz = l_gpst_ptr->pstate0_frequency_khz + (G_sapphire_table.data[i].pstate * l_gpst_ptr->frequency_step_khz);
    }

    uint8_t l_core = 0;
    uint16_t l_maxFreq = l_turboFreq;

    //Write the max pstate for each possible number of active cores.
    for (l_core = 1; l_core <= MAX_CORES; l_core++)
    {
        //If wof is enabled, then use the wof uplift table to find the max freq for given # of active cores.
        if (g_amec->wof.enable_parm != 0)
        {
            l_maxFreq = amec_wof_get_max_freq(l_core);
        }

        //If the l_core (# of Active cores) is greater than G_wof_max_cores_per_chip
        //then return 0x01 for Pstate.
        if (l_core > G_wof_max_cores_per_chip)
        {
            G_sapphire_table.activeCore_max_pstate[l_core - 1] = 0x01;
        }
        else
        {
            G_sapphire_table.activeCore_max_pstate[l_core - 1] = (int8_t)proc_freq2pstate((uint32_t)l_maxFreq);
        }
    }

    //For Version 0x02 of the interface, we need to make the first four reserved bytes
    //equal to 0x01 to prevent confusion
    for(i=0; i<4; i++)
    {
        G_sapphire_table.pad[i] = 0x01;
    }
}
Esempio n. 5
0
// Function Specification
//
// Name: amec_slv_freq_smh
//
// Description: Slave OCC's frequency state machine.
//              This function will run every tick.
//
// Thread: RealTime Loop
//
// Task Flags:
//
// End Function Specification
void amec_slv_freq_smh(void)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    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[MAXIMUM_QUADS] = {0}; // max pstate (min frequency) within each quad
    Pstate      pmax_chip = 0;  // highest Pstate (lowest frequency) across all quads
    bool        l_atLeast1Core[MAXIMUM_QUADS] = {FALSE};  // at least 1 core present and online in quad
    bool        l_atLeast1Quad = FALSE;    // at least 1 quad online
    static bool L_mfg_set_trace[MAXIMUM_QUADS] = {FALSE};
    static bool L_mfg_clear_trace[MAXIMUM_QUADS] = {FALSE};

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/

    // loop through all quads, get f_requests, translate to pstates and determine pmax across chip
    for (quad = 0; quad < MAXIMUM_QUADS; quad++)
    {
        for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++)  // loop thru all cores in quad
        {
            core_num = (quad*NUM_CORES_PER_QUAD) + core_idx;

            // ignore core if freq request is 0 (core not present when amec_slv_proc_voting_box ran)
            if(g_amec->proc[0].core[core_num].f_request != 0)
            {
               l_atLeast1Core[quad] = TRUE;
               l_atLeast1Quad = TRUE;
               // The higher the pstate number, the lower the frequency
               if(pmax[quad] <  proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
               {
                   pmax[quad] = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
                   if(pmax_chip < pmax[quad])  // check if this is a new lowest freq for the chip
                      pmax_chip = pmax[quad];
               }
            }
        }
    }

    // Skip determining new frequency if all cores in all quads are offline
    if(l_atLeast1Quad)
    {
        // check for mfg quad Pstate request and set Pstate for each quad
        for (quad = 0; quad < MAXIMUM_QUADS; quad++)
        {
            // set quad with no cores present to lowest frequency for the chip
            if(l_atLeast1Core[quad] == FALSE)
               pmax[quad] = pmax_chip;

            // check if there is a mnfg Pstate request for this quad
            if(g_amec->mnfg_parms.quad_pstate[quad] != 0xFF)
            {
               // use mnfg request if it is a lower frequency (higher pState)
               if(g_amec->mnfg_parms.quad_pstate[quad] > pmax[quad])
                  pmax[quad] = g_amec->mnfg_parms.quad_pstate[quad];

               if(L_mfg_clear_trace[quad] == FALSE)
                  L_mfg_set_trace[quad] = TRUE;
            }
            else if(L_mfg_clear_trace[quad] == TRUE)
            {
                TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request cleared. New Pstate = 0x%02x", quad, pmax[quad]);
                L_mfg_clear_trace[quad] = FALSE;
            }

#ifdef PROC_DEBUG
            if (G_desired_pstate[quad] != pmax[quad])
            {
                TRAC_IMP("Updating Quad %d's Pstate to %d", quad, pmax[quad]);
            }
#endif
            // update quad pstate request
            G_desired_pstate[quad] = pmax[quad];

            if(L_mfg_set_trace[quad] == TRUE)
            {
                TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request set = 0x%02x", quad, pmax[quad]);
                L_mfg_set_trace[quad] = FALSE;
                L_mfg_clear_trace[quad] = TRUE;
            }
        }
    }  // if at least 1 core online
}
Esempio n. 6
0
// Function Specification
//
// Name: amec_set_freq_range
//
// Description: Set the frequency range for AMEC based on mode only
//              NOTE:  Any other clipping of frequency should be done in
//                     amec_slv_proc_voting_box() (called every tick)
//                     so the CLIP history in poll response will accurately
//                     show all clipping for the given mode the system is in
//              This function will run on mode changes and cnfg_data changes
//
// Thread: RealTime Loop
//
// Task Flags:
//
// End Function Specification
errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
{
    /*------------------------------------------------------------------------*/
    /*  Local Variables                                                       */
    /*------------------------------------------------------------------------*/
    errlHndl_t                  l_err = NULL;
    uint16_t                    l_freq_min  = 0;
    uint16_t                    l_freq_max  = 0;
    uint32_t                    l_temp = 0;
    amec_mode_freq_t            l_ppm_freq[OCC_INTERNAL_MODE_MAX_NUM] = {{0}};

    /*------------------------------------------------------------------------*/
    /*  Code                                                                  */
    /*------------------------------------------------------------------------*/

    // First set to Max Freq Range for this 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 (turbo if wof off, otherwise max possible (ultra turbo)
        if( g_amec->wof.wof_disabled || (g_amec->wof.wof_init_state != WOF_ENABLED))
        {
            l_freq_max = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
        }
        else
        {
            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];

      // Use max frequency for performance modes and FMF
      if( (i_mode == OCC_MODE_NOM_PERFORMANCE) || (i_mode == OCC_MODE_MAX_PERFORMANCE) ||
          (i_mode == OCC_MODE_FMF) || (i_mode == OCC_MODE_DYN_POWER_SAVE) ||
          (i_mode == OCC_MODE_DYN_POWER_SAVE_FP) )
      {
          // clip to turbo if WOF is disabled
          if( g_amec->wof.wof_disabled || (g_amec->wof.wof_init_state != WOF_ENABLED))
          {
              l_freq_max = G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO];
          }
          else
          {
              l_freq_max = G_proc_fmax_mhz;
          }
      }
      else
      {
          l_freq_max = G_sysConfigData.sys_mode_freq.table[i_mode];
      }
    }

    if( (l_freq_min == 0) || (l_freq_max == 0) )
    {
      // Do not update amec vars with a 0 frequency.
      // The frequency limit for each mode should have been set prior
      // to calling or the mode passed was invalid
      TRAC_ERR("amec_set_freq_range: Freq of 0 found! mode[0x%02x] Fmin[%u] Fmax[%u]",
                  i_mode,
                  l_freq_min,
                  l_freq_max);

      // Log an error if this is PowerVM as this should never happen when OCC
      // supports modes
      if(!G_sysConfigData.system_type.kvm)
      {
        /* @
         * @errortype
         * @moduleid    AMEC_SET_FREQ_RANGE
         * @reasoncode  INTERNAL_FW_FAILURE
         * @userdata1   Mode
         * @userdata2   0
         * @userdata4   ERC_FW_ZERO_FREQ_LIMIT
         * @devdesc     Fmin or Fmax of 0 found for mode
         */
         errlHndl_t l_err = createErrl(AMEC_SET_FREQ_RANGE,           //modId
                                       INTERNAL_FW_FAILURE,           //reasoncode
                                       ERC_FW_ZERO_FREQ_LIMIT,        //Extended reason code
                                       ERRL_SEV_PREDICTIVE,           //Severity
                                       NULL,                          //Trace Buf
                                       DEFAULT_TRACE_SIZE,            //Trace Size
                                       i_mode,                        //userdata1
                                       0);                            //userdata2

         // Callout Firmware
         addCalloutToErrl(l_err,
                          ERRL_CALLOUT_TYPE_COMPONENT_ID,
                          ERRL_COMPONENT_ID_FIRMWARE,
                          ERRL_CALLOUT_PRIORITY_LOW
                          );
      }
    }
    else
    {
      g_amec->sys.fmin = l_freq_min;
      g_amec->sys.fmax = l_freq_max;

      TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] (Pmin 0x%02x) Fmax[%u] (Pmax 0x%02x)",
                i_mode,
                l_freq_min,
                proc_freq2pstate(g_amec->sys.fmin),
                l_freq_max,
                proc_freq2pstate(g_amec->sys.fmax));

      // Now determine the max frequency for the PPM structure
      l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax    = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL];
      l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax    = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE];
      l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_DYN_POWER_SAVE_FP];

      // Determine the min frequency for the PPM structure. This Fmin should
      // always be set to the system Fmin
      l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmin    = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
      l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin    = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
      l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];

      // Determine the min speed allowed for DPS power policies (this is needed
      // by the DPS algorithms)
      l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS].fmax;
      l_ppm_freq[OCC_INTERNAL_MODE_DPS].min_speed = l_temp;

      l_temp = (l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmin * 1000)/l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].fmax;
      l_ppm_freq[OCC_INTERNAL_MODE_DPS_MP].min_speed = l_temp;

      // Copy the PPM frequency information into g_amec
      memcpy(g_amec->part_mode_freq, l_ppm_freq, sizeof(l_ppm_freq));

    }
    return l_err;
}