⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvfc.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
            g_MC13783SwitcherVoltTable[0]);

        pSP->voltIndex = 0;
            
        // Update the DPTC threshold registers
        OUTREG32(&g_pCCM->DCVR[0], g_DptcDcvrTable[pSP->freqIndex][pSP->voltIndex][0]);
        OUTREG32(&g_pCCM->DCVR[1], g_DptcDcvrTable[pSP->freqIndex][pSP->voltIndex][1]);
        OUTREG32(&g_pCCM->DCVR[2], g_DptcDcvrTable[pSP->freqIndex][pSP->voltIndex][2]);
        OUTREG32(&g_pCCM->DCVR[3], g_DptcDcvrTable[pSP->freqIndex][pSP->voltIndex][3]);

        // Complete the DPTC threshold update
        CSP_BITFINS(pmcr0, CCM_PMCR0_DPVCR, CCM_PMCR0_DPVCR_CHANGE_REQ);
        OUTREG32(&g_pCCM->PMCR0, pmcr0);
        CSP_BITFINS(pmcr0, CCM_PMCR0_DPVV, CCM_PMCR0_DPVV_VOLT_VALID);
        OUTREG32(&g_pCCM->PMCR0, pmcr0);

        // Flag the DVFC IST that we are entering suspend mode
        SETREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_SUSPEND);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            


    }

    // We are powering on
    else
    {
        // Restore state of DVFC module enables
        if (dvfen == CCM_PMCR0_DVFEN_DVFS_ENABLE)
        {
            CSP_BITFINS(pmcr0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_ENABLE);
        }

        if (dpten == CCM_PMCR0_DPTEN_DPTC_ENABLE)
        {
            CSP_BITFINS(pmcr0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_ENABLE);
        }
        
        // Update the power management control register
        OUTREG32(&g_pCCM->PMCR0, pmcr0);

        // Flag the DVFC IST that we are leaving suspend mode
        CLRREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_SUSPEND);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            
    }
        
    
    DVFC_UNLOCK();

    return TRUE;
}


//-----------------------------------------------------------------------------
//
//  Function:  BSPDvfcIntrServ
//
//  This function is invoked from the DVFC interrupt service thread to
//  perform the frequency/voltage switch.    
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void BSPDvfcIntrServ(void)
{
    UINT32 pmcr0, pmcr1, pdr0, ptvai, fsvai, dvsup, acr;
    PDVFC_SETPOINT pSP = &g_SetPoint[g_CurSpeed];
    BOOL bFreqUpdate = FALSE, bVoltUpdate = FALSE, bBusUpdate = FALSE;
    UINT32 stop_stat;
    UINT32 ahbPodf = g_AhbPodf;
    
    DVFC_LOCK();
    
    // Grab the CCM registers for DVFC control
    pmcr0 = INREG32(&g_pCCM->PMCR0);
    pdr0 = INREG32(&g_pCCM->PDR0);

    // Make sure previous DVFS request is complete
    if (CSP_BITFEXT(pmcr0, CCM_PMCR0_UPDTEN) == CCM_PMCR0_UPDTEN_DISABLE_UPDATE)
    {
        goto cleanUp;
    }

    if (CSP_BITFEXT(pmcr0, CCM_PMCR0_PTVAIM) == CCM_PMCR0_PTVAIM_UNMASK)
    {
        ptvai = CSP_BITFEXT(pmcr0, CCM_PMCR0_PTVAI);
    }
    else
    {
        ptvai = CCM_PMCR0_PTVAI_VOLT_NO_CHANGE;
    }
    
    if (CSP_BITFEXT(pmcr0, CCM_PMCR0_FSVAIM) == CCM_PMCR0_FSVAIM_UNMASK)
    {
        fsvai = CSP_BITFEXT(pmcr0, CCM_PMCR0_FSVAI);
    }
    else
    {
        fsvai = CCM_PMCR0_FSVAI_FREQ_NO_CHANGE;
    }
    
    // If this is a forced DVFC mode request
    if (CSP_BITFEXT(pmcr0, CCM_PMCR0_DVFEV) == CCM_PMCR0_DVFEV_REQ_ALWAYS)
    {
        // Clear the request
        CSP_BITFINS(pmcr0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_NOT_ALWAYS);
        
        // DVFC mode flags are stored in PMCR1 DVGP bits
        pmcr1 = INREG32(&g_pCCM->PMCR1);

        // If panic mode is being forced
        if (pmcr1 & DDK_CLOCK_DVFC_MODE_PANIC)
        {
            // If we are not already in forced panic mode
            if (g_DvfcForcedMode != DDK_CLOCK_DVFC_MODE_PANIC)
            {
                // Create DVFS panic request and mask DVFS interrupts
                CSP_BITFINS(pmcr0, CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_MASK);
                fsvai = CCM_PMCR0_FSVAI_FREQ_UP_PANIC;
                g_DvfcForcedMode = DDK_CLOCK_DVFC_MODE_PANIC;
            }
        }
        else
        {
            // If we are trying to suspend
            if (pmcr1 & DDK_CLOCK_DVFC_MODE_SUSPEND)
            {
                // If we are not already in forced suspend mode
                if (g_DvfcForcedMode != DDK_CLOCK_DVFC_MODE_SUSPEND)
                {
                    // Create DVFS request to lower speed and mask DVFS interrupts
                    fsvai = CCM_PMCR0_FSVAI_FREQ_DOWN;                
                    CSP_BITFINS(pmcr0, CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_MASK);
                    g_DvfcForcedMode = DDK_CLOCK_DVFC_MODE_SUSPEND;
                }
            }

            // Else if we are tring to lower the bus speed
            else if (pmcr1 & DDK_CLOCK_DVFC_MODE_BUS_LOW)
            {
                // If we are not already in forced low-speed bus mode
                if (g_DvfcForcedMode != DDK_CLOCK_DVFC_MODE_BUS_LOW)
                {
                    // Create DVFS request to lower speed, mask DVFS interrupts,
                    // and scale the AHB
                    fsvai = CCM_PMCR0_FSVAI_FREQ_DOWN;
                    ahbPodf = DVFC_SCALED_AHB_PODF;
                    CSP_BITFINS(pmcr0, CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_MASK);
                    g_DvfcForcedMode = DDK_CLOCK_DVFC_MODE_BUS_LOW;
                }
            }

            // No panic, no suspend, no lower bus, return to normal DVFS
            // operation
            else
            {
                CSP_BITFINS(pmcr0, CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_UNMASK);
                g_DvfcForcedMode = DDK_CLOCK_DVFC_MODE_NORMAL;
            }
        }            
    }

    dvsup = CSP_BITFEXT(pmcr0, CCM_PMCR0_DVSUP);

    // Handle adjustment cases and give priority to
    // rising voltage/frequency requests

    // DPTC voltage increase request.  Make sure DPTC is
    // enabled for this speed and we are not already at the
    // highest voltage.
    if (((ptvai == CCM_PMCR0_PTVAI_VOLT_UP) ||
        (ptvai == CCM_PMCR0_PTVAI_VOLT_UP_PANIC)) &&
        (pSP->dpten) && (pSP->voltIndex != 0))
    {
        --pSP->voltIndex;
        bVoltUpdate = TRUE;
        RETAILMSG(g_bVerbose, (_T("DPTC UP\r\n")));
    }

    // DVFS frequency panic increase request.
    else if (fsvai == CCM_PMCR0_FSVAI_FREQ_UP_PANIC)
    {
        g_CurSpeed = DVFC_SPEED_HIGH;
        pSP = &g_SetPoint[DVFC_SPEED_HIGH];
        CSP_BITFINS(pmcr0, CCM_PMCR0_UDSC, CCM_PMCR0_UDSC_FREQ_UP);
        CSP_BITFINS(pmcr0, CCM_PMCR0_VSCNT, g_Vscnt);
        bFreqUpdate = TRUE;
        RETAILMSG(g_bVerbose, (_T("DVFS PANIC UP\r\n")));
    }
            
    // DVFS frequency increase request.  Make sure we are
    // not already at the highest DVS configuration or speed.
    else if ((fsvai == CCM_PMCR0_FSVAI_FREQ_UP) && (dvsup != 0) 
        && (g_CurSpeed != 0))
    {
        --g_CurSpeed;
        pSP = &g_SetPoint[g_CurSpeed];
        CSP_BITFINS(pmcr0, CCM_PMCR0_UDSC, CCM_PMCR0_UDSC_FREQ_UP);
        CSP_BITFINS(pmcr0, CCM_PMCR0_VSCNT, g_Vscnt);
        bFreqUpdate = TRUE;
        RETAILMSG(g_bVerbose, (_T("DVFS UP\r\n")));
    }
            
    // DVFS frequency decrease request.  Make sure we are
    // not already at the lowest DVS configuration or speed.
    else if ((fsvai == CCM_PMCR0_FSVAI_FREQ_DOWN) &&
        (dvsup != 0x3) && (g_CurSpeed < (DVFC_NUM_SPEEDS-1)))
    {
        ++g_CurSpeed;
        pSP = &g_SetPoint[g_CurSpeed];
        CSP_BITFINS(pmcr0, CCM_PMCR0_UDSC, CCM_PMCR0_UDSC_FREQ_DOWN);
        bFreqUpdate = TRUE;
        RETAILMSG(g_bVerbose, (_T("DVFS DOWN\r\n")));
    }

    // DPTC voltage decrease request.   Make sure DPTC is
    // enabled for this speed and we are not already at the
    // lowest voltage.
    else if ((ptvai == CCM_PMCR0_PTVAI_VOLT_DOWN) &&
        (pSP->dpten) && (pSP->voltIndex < (DVFC_VOLT_LEVELS-1)))
    {
        ++pSP->voltIndex;        
        bVoltUpdate = TRUE;
        RETAILMSG(g_bVerbose, (_T("DPTC DOWN\r\n")));
    }

    // Check for scaling bus to high-speed
    if (CSP_BITFEXT(pdr0, CCM_PDR0_MAX_PODF) > ahbPodf)
    {
        // Use unscaled AHB/IPG dividers
        CSP_BITFINS(pdr0, CCM_PDR0_MAX_PODF, g_AhbPodf);
        CSP_BITFINS(pdr0, CCM_PDR0_IPG_PODF, g_IpgPodf);

        // Use unscaled SDMA ACR bit
        acr = g_SdmaAcr;

        // Set flags for bus/frequency scaling
        bBusUpdate = TRUE;
        bFreqUpdate = TRUE;

        // If we are transitioning to high-speed and high-speed bus
        if (g_CurSpeed == DVFC_SPEED_HIGH)
        {            
            // Set VSCNT to minumum, voltage will by scaled by
            // software to prevent peripheral overrun/underrun
            // due to SDMA being disabled during DVS
            CSP_BITFINS(pmcr0, CCM_PMCR0_VSCNT, 0);

            // Scale the DVS voltage to the high-speed setpoint
            // voltage.
            DvfcScaleVoltage(g_SetPoint[DVFC_SPEED_LOW].sw,
                g_SetPoint[DVFC_SPEED_LOW].swVolt,
                g_LowBusVolt,
                g_MC13783SwitcherVoltTable[0]);

            RETAILMSG(g_bVerbose, (_T("DVFS BUS SCALE CPU/BUS = HIGH/HIGH\r\n")));
        }

        // Else we are staying at low CPU speed, but
        // transitioning to high-speed bus
    else
    {
            // Scale the DVS voltage higher before increasing
            // the bus speed.
            DvfcScaleVoltage(g_SetPoint[DVFC_SPEED_LOW].sw,
                g_SetPoint[DVFC_SPEED_LOW].swVolt,
                g_LowBusVolt,
                g_LowSpeedVolt);

            RETAILMSG(g_bVerbose, (_T("DVFS BUS SCALE CPU/BUS = LOW/HIGH\r\n")));
        }
            
        // Force DPTC logic to return to highest setpoint when we
        // switch to high speed.  This will provide a safe setpoint 
        // since we may have been in the scaled bus mode for a while.
        g_SetPoint[DVFC_SPEED_HIGH].voltIndex = 0;
        PmicSwitchModeRegulatorSetVoltageLevel(
            g_SetPoint[DVFC_SPEED_HIGH].voltIndex, 
            g_SetPoint[DVFC_SPEED_HIGH].swVolt,
            g_MC13783SwitcherVoltTable[0]);

    }

    // Check for scaling bus to low-speed
    if (CSP_BITFEXT(pdr0, CCM_PDR0_MAX_PODF) < ahbPodf)
    {
        // Scale the AHB/IPG dividers
        CSP_BITFINS(pdr0, CCM_PDR0_MAX_PODF, DVFC_SCALED_AHB_PODF);
        CSP_BITFINS(pdr0, CCM_PDR0_IPG_PODF, DVFC_SCALED_IPG_PODF);

        // Configure SDMA ACR setting for 1:1 ratio
        acr = SDMA_CONFIG_ACR_AHB1X;

        // Set flags for bus/frequency scaling
        bBusUpdate = TRUE;
        bFreqUpdate = TRUE;

        RETAILMSG(g_bVerbose, (_T("DVFS BUS SCALE CPU/BUS = LOW/LOW\r\n")));

    }

    // If bus will be scaled
    if (bBusUpdate)
    {
        // Acquire bus scaling lock
        DVFC_ACRLOCK();

        // Save active DMA channels
        stop_stat = INREG32(&g_pSDMA->STOP_STAT);

        // Halt active DMA channels
        OUTREG32(&g_pSDMA->STOP_STAT, stop_stat);

        // Wait for SDMA to go idle
        while ((INREG32(&g_pSDMA->ONCE_STAT) & 0xF000) != 0x6000)
        {
            // RETAILMSG(TRUE, (_T("Waiting for DMA idle\r\n")));
        }
    }

    // Disable DPTC voltage change requests
    CSP_BITFINS(pmcr0, CCM_PMCR0_DPVCR, CCM_PMCR0_DPVCR_NO_CHANGE_REQ);

    // Configure DVS signals
    CSP_BITFINS(pmcr0, CCM_PMCR0_DVSUP, pSP->dvs);

    // Update the power management control register
    OUTREG32(&g_pCCM->PMCR0, pmcr0);

    // If we are scaling the frequency
    if (bFreqUpdate)
    {        
        // Update the MCU dividers
        CSP_BITFINS(pdr0, CCM_PDR0_MCU_PODF, pSP->mcuPodf);

        // Initiate scaling by writing to PDR0
        OUTREG32(&g_pCCM->PDR0, pdr0);
    }

    // If bus was scaled
    if (bBusUpdate)
    {
        // Need to synchronize bus scaling by polling UPDTEN
        while (EXTREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_UPDTEN) ==
            CCM_PMCR0_UPDTEN_DISABLE_UPDATE);

        // Configure SDMA ACR setting
        INSREG32BF(&g_pSDMA->CONFIG, SDMA_CONFIG_ACR, acr);

        // Restore SDMA channels active before scaling AHB/IPG
        OUTREG32(&g_pSDMA->HSTART, stop_stat);

        // Release bus scaling lock
        DVFC_ACRUNLOCK();

        // If we are scaling bus down, use software scaling
        // to drop the voltage for the slower bus
        if (acr == SDMA_CONFIG_ACR_AHB1X)
        {
            DvfcScaleVoltage(g_SetPoint[DVFC_SPEED_LOW].sw,
                g_SetPoint[DVFC_SPEED_LOW].swVolt,
                g_LowSpeedVolt,
                g_LowBusVolt);
        }

        // Else bus was scaled up.  If we switched to high speed,
        // we need to reconfigure the low-speed voltage since we
        // used software voltage scaling on this voltage setting.
        else if (pSP->dvs == 0x0)
        {
            // Configure DVS voltage
            PmicSwitchModeRegulatorSetVoltageLevel(
                g_SetPoint[DVFC_SPEED_LOW].sw, 
                g_SetPoint[DVFC_SPEED_LOW].swVolt, 
                g_LowSpeedVolt);
    
        }
        
        RETAILMSG(g_bVerbose, (_T("ACR = %d\r\n"), acr));

    }

    // If DPTC is enabled for the current setpoint
    if (pSP->dpten)
    {

        // If DPTC wants us to update the voltage
        if (bVoltUpdate)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -