Example #1
0
// Function Specification
//
// Name:  cmdh_mnfg_run_stop_slew
//
// Description: This function handles the manufacturing command to start
// or stop frequency autoslewing.
//
// End Function Specification
uint8_t cmdh_mnfg_run_stop_slew(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_fmin = 0;
    uint16_t                    l_fmax = 0;
    uint16_t                    l_step_size = 0;
    uint16_t                    l_step_delay = 0;
    uint32_t                    l_temp = 0;
    mnfg_run_stop_slew_cmd_t    *l_cmd_ptr = (mnfg_run_stop_slew_cmd_t*) i_cmd_ptr;
    mnfg_run_stop_slew_rsp_t    *l_rsp_ptr = (mnfg_run_stop_slew_rsp_t*) o_rsp_ptr;

    do
    {
        // This command is only supported on Master OCC
        if (G_occ_role == OCC_SLAVE)
        {
            TRAC_ERR("cmdh_mnfg_run_stop_slew: Mnfg command not supported on Slave OCCs!");
            break;
        }

        // Do some basic input verification
        if ((l_cmd_ptr->action > MNFG_INTF_SLEW_STOP) ||
            (l_cmd_ptr->step_mode > MNFG_INTF_FULL_SLEW))
        {
            // Invalid values were passed by the user!
            TRAC_ERR("cmdh_mnfg_run_stop_slew: Invalid values were detected! action[0x%02x] step_mode[0x%02x]",
                     l_cmd_ptr->action,
                     l_cmd_ptr->step_mode);
            l_rc = ERRL_RC_INVALID_DATA;
            break;
        }

        // Are we stopping the auto-slew function?
        if (l_cmd_ptr->action == MNFG_INTF_SLEW_STOP)
        {
            // Collect the slew count
            l_rsp_ptr->slew_count = AMEC_MST_CUR_SLEW_COUNT();

            // Collect the frequency range used for the auto-slew
            l_rsp_ptr->fstart = AMEC_MST_CUR_MNFG_FMIN();
            l_rsp_ptr->fstop = AMEC_MST_CUR_MNFG_FMAX();

            TRAC_INFO("cmdh_mnfg_run_stop_slew: Auto-slewing has been stopped. Count[%u] fstart[%u] fstop[%u]",
                      AMEC_MST_CUR_SLEW_COUNT(),
                      AMEC_MST_CUR_MNFG_FMIN(),
                      AMEC_MST_CUR_MNFG_FMAX());

            // Send a signal to RTL to stop auto-slewing
            AMEC_MST_STOP_AUTO_SLEW();

            // We are done
            break;
        }

        // If we made it here, that means we are starting up a slew run
        // First, determine the Fmax and Fmin for the slew run
        if (l_cmd_ptr->bottom_mode == OCC_MODE_PWRSAVE)
        {
            // If bottom mode is Static Power Save, use the min frequency
            // available
            l_fmin = G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY];
        }
        else
        {
            l_fmin = G_sysConfigData.sys_mode_freq.table[l_cmd_ptr->bottom_mode];
        }
        l_fmax = G_sysConfigData.sys_mode_freq.table[l_cmd_ptr->high_mode];

        // Add the percentages to compute the min/max frequencies
        l_fmin = l_fmin + (l_fmin * l_cmd_ptr->bottom_percent)/100;
        l_fmax = l_fmax + (l_fmax * l_cmd_ptr->high_percent)/100;

        TRAC_INFO("cmdh_mnfg_run_stop_slew: We are about to start auto-slewing function");
        TRAC_INFO("cmdh_mnfg_run_stop_slew: bottom_mode[0x%.2X] freq[%u] high_mode[0x%.2X] freq[%u]",
                  l_cmd_ptr->bottom_mode,
                  l_fmin,
                  l_cmd_ptr->high_mode,
                  l_fmax);

        // Determine the frequency step size and the step delay
        if (l_cmd_ptr->step_mode == MNFG_INTF_FULL_SLEW)
        {
            l_step_size = l_fmax - l_fmin;

            // Disable step delays if full slew mode has been selected
            l_step_delay = 0;

            TRAC_INFO("cmdh_mnfg_run_stop_slew: Enabling full-slew mode with step_size[%u] step_delay[%u]",
                      l_step_size,
                      l_step_delay);
        }
        else
        {
            l_step_size = (uint16_t)G_mhz_per_pstate;

            // Translate the step delay to internal OCC ticks
            l_temp = (l_cmd_ptr->step_delay * 1000) / AMEC_US_PER_TICK;
            l_step_delay = (uint16_t) l_temp;

            TRAC_INFO("cmdh_mnfg_run_stop_slew: Enabling single-step mode with step_size[%u] step_delay[%u]",
                      l_step_size,
                      l_step_delay);
        }

        // Now, load the values for RTL consumption
        AMEC_MST_SET_MNFG_FMIN(l_fmin);
        AMEC_MST_SET_MNFG_FMAX(l_fmax);
        AMEC_MST_SET_MNFG_FSTEP(l_step_size);
        AMEC_MST_SET_MNFG_DELAY(l_step_delay);

        // Reset the slew-counter before we start auto-slewing
        AMEC_MST_CUR_SLEW_COUNT() = 0;

        // Wait a little bit for RTL to process above parameters
        ssx_sleep(SSX_MILLISECONDS(5));

        // Send a signal to RTL to start auto-slewing
        AMEC_MST_START_AUTO_SLEW();

        // We are auto-slewing now, populate the response packet
        l_rsp_ptr->slew_count = 0;
        l_rsp_ptr->fstart = l_fmin;
        l_rsp_ptr->fstop = l_fmax;

    }while(0);

    // Populate the response data packet
    G_rsp_status = l_rc;
    l_rsp_ptr->data_length[0] = 0;
    l_rsp_ptr->data_length[1] = MNFG_INTF_RUN_STOP_SLEW_RSP_SIZE;

    return l_rc;
}
Example #2
0
// Function Specification
//
// Name:  Dcom_thread_routine
//
// Description: Purpose of this task is to handle messages passed from
//              Master to Slave and vice versa.
//
//              Nothing in this thread should be time-critical, but should
//              happen more often than the 1-second that other threads run
//              at.
//
//              This thread currently runs ~1ms, based on the RTL loop of
//              250us.
//
//              FWIW -- It is pointless to set this thread to run any more
//              often than the length of the RTL loop, since it is acting
//              on data passed back and forth via that loop.
//
// End Function Specification
void Dcom_thread_routine(void *arg)
{
    OCC_STATE l_newOccState  = 0;
    OCC_MODE  l_newOccMode   = 0;
    SsxTimer  l_timeout_timer;
    errlHndl_t l_errlHndl = NULL;
    // --------------------------------------------------
    // Create a timer that pops every 10 seconds to wake up
    // this thread, in case a semaphore never gets posted.
    // TODO: Is this really needed?
    // --------------------------------------------------
    ssx_timer_create(&l_timeout_timer,
                     (SsxTimerCallback) ssx_semaphore_post,
                     (void *) &G_dcomThreadWakeupSem);
    ssx_timer_schedule(&l_timeout_timer,
                       SSX_SECONDS(10),
                       SSX_SECONDS(10));

    for(;;)
    {
        // --------------------------------------------------
        // Wait on Semaphore until we get new data over DCOM
        // (signalled by sem_post() or timeout occurs.
        // Sem timeout is designed to be the slowest
        // interval we will attempt to run this thread at.
        // --------------------------------------------------

        // Wait for sem_post before we run through this thread.
        ssx_semaphore_pend(&G_dcomThreadWakeupSem, SSX_WAIT_FOREVER);

        // --------------------------------------------------
        // Counter to ensure thread is running (can wrap)
        // --------------------------------------------------
        G_dcom_thread_counter++;

        // --------------------------------------------------
        // Check if we need to update the sapphire table
        // --------------------------------------------------
        if(G_sysConfigData.system_type.kvm)
        {
            proc_check_for_sapphire_updates();
        }

        // --------------------------------------------------
        // Set Mode and State Based on Master
        // --------------------------------------------------
        l_newOccState = (G_occ_master_state == CURRENT_STATE()) ? OCC_STATE_NOCHANGE : G_occ_master_state;

        if(G_sysConfigData.system_type.kvm)
        {
            l_newOccMode  = (G_occ_master_mode  == G_occ_external_req_mode_kvm ) ? OCC_MODE_NOCHANGE : G_occ_master_mode;
        }
        else
        {
            l_newOccMode  = (G_occ_master_mode  == CURRENT_MODE() ) ? OCC_MODE_NOCHANGE : G_occ_master_mode;
        }

        // Override State if SAFE state is requested
        l_newOccState = ( isSafeStateRequested() ) ? OCC_STATE_SAFE : l_newOccState;

        // Override State if we are in SAFE state already
        l_newOccState = ( OCC_STATE_SAFE == CURRENT_STATE() ) ? OCC_STATE_NOCHANGE : l_newOccState;

        if( (OCC_STATE_NOCHANGE != l_newOccState)
            || (OCC_MODE_NOCHANGE != l_newOccMode) )
        {
            // If we're active, then we should always process the mode change first
            // If we're not active, then we should always process the state change first
            if(OCC_STATE_ACTIVE == CURRENT_STATE())
            {
                // Set the new mode
                l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ );
                if(l_errlHndl)
                {
                    commitErrl(&l_errlHndl);
                }
                // Set the new state
                l_errlHndl = SMGR_set_state(l_newOccState);
                if(l_errlHndl)
                {
                    commitErrl(&l_errlHndl);
                }
            }
            else
            {
                // Set the new state
                l_errlHndl = SMGR_set_state(l_newOccState);
                                if(l_errlHndl)
                {
                    commitErrl(&l_errlHndl);
                }
                // Set the new mode
                l_errlHndl = SMGR_set_mode(l_newOccMode, 0 /* TODO V/F */ );
                if(l_errlHndl)
                {
                    commitErrl(&l_errlHndl);
                }
            }
        }

        // --------------------------------------------------
        // DCM PStates
        // \_ can do sem_post to increment through state machine
        // --------------------------------------------------
        if(OCC_STATE_SAFE != CURRENT_STATE())
        {
            proc_gpsm_dcm_sync_enable_pstates_smh();
        }

        // --------------------------------------------------
        // SSX Sleep
        // --------------------------------------------------
        // Even if semaphores are continually posted, there is no reason
        // for us to run this thread any more often than once every 250us
        // so we don't starve any other thread
        ssx_sleep(SSX_MICROSECONDS(250));
    }
}