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

📄 dvfc.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  FREESCALE SEMICONDUCTOR, INC.
//
//-----------------------------------------------------------------------------
//
//  File:  dvfc.cpp
//
//  Provides BSP-specific configuration routines for the DVFS/DPTC driver.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include "bsp.h"

#include "regs.h"
#include "regs_regulator.h"
#include "pmic_lla.h"
#include "pmic_regulator.h"

//-----------------------------------------------------------------------------
// External Functions


//-----------------------------------------------------------------------------
// External Variables
extern PCSP_CCM_REGS g_pCCM;
extern UINT32 g_DvfcIntrMask;


//-----------------------------------------------------------------------------
// Defines
#define DVFC_REG_PATH           (_T("\\Drivers\\Builtin\\DVFC"))
#define DVFC_IST_PRIORITY       250

#define DVFC_VOLT_LEVELS        16
#define DPTC_REF_CIRCUITS       4

// Only using DPTC reference circuit #1 (DCVR1)
#define DPTC_REF_CIRCUIT_MASK   CSP_BITFMASK(CCM_PMCR0_DRCE1) | \
                                CSP_BITFMASK(CCM_PMCR0_DRCE3)

#define DVFC_INTR_MASK          CSP_BITFMASK(CCM_PMCR0_PTVAIM) | \
                                CSP_BITFMASK(CCM_PMCR0_FSVAIM)

#define DVFC_INTR_VAL           CSP_BITFVAL(CCM_PMCR0_PTVAIM, CCM_PMCR0_PTVAIM_UNMASK) | \
                                CSP_BITFVAL(CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_UNMASK)
                                
#define DVFC_DVS_MASK           CSP_BITFMASK(CCM_PMCR0_DVS0) | \
                                CSP_BITFMASK(CCM_PMCR0_DVS1)

#define DVFC_DVFEN              CCM_PMCR0_DVFEN_DVFS_ENABLE

#define DVFC_DIV3CK             3
#define DVFC_MAX_THRESHOLD      31

#define DVFC_TRACKING_LOAD(load) \
        (((load)*DVFC_MAX_THRESHOLD)/100)

#define DVFC_TRACKING_WINDOW(width, cpufreq)  \
        (((width)*((cpufreq)/1000))/(1024*128))

#define DVFC_FREQ_UP            532000000
#define DVFC_FREQ_DOWN          266000000
#define DVFC_DNTHR              DVFC_TRACKING_LOAD(50)     // 50% load
#define DVFC_UPTHR              DVFC_TRACKING_LOAD(90)     // 90% load
#define DVFC_PNCTHR             CCM_LTR_THRESHOLD_DISABLE
#define DVFC_EMAC               0x10 // 31-sample EMA
#define DVFC_DNCNT              DVFC_TRACKING_WINDOW(5, DVFC_FREQ_UP)  // 5 ms
#define DVFC_UPCNT              DVFC_TRACKING_WINDOW(5, DVFC_FREQ_DOWN)  // 5 ms

#define DCVR(elv, llv, ulv)     ((elv << CCM_DCVR_ELV_LSH) | \
                                 (llv << CCM_DCVR_LLV_LSH) | \
                                 (ulv << CCM_DCVR_ULV_LSH))

#define DVFC_LOCK()             WaitForSingleObject(g_hDvfcMutex, INFINITE)
#define DVFC_UNLOCK()           ReleaseMutex(g_hDvfcMutex)

#define DVFC_ACRLOCK()          WaitForSingleObject(g_hAcrMutex, INFINITE)
#define DVFC_ACRUNLOCK()        ReleaseMutex(g_hAcrMutex)

#define DVFC_DVSSPEED           3   // 16 us per step

// DVFC_DVS_STEP_DELAY determines the delay in us of a voltage step based on the 
// specified DVSSPEED
#define DVFC_DVS_STEP_DELAY(speed)  \
        ((speed == 0) ? 4 : (1 << (speed + 1)))
                                
// DVFC_DVS_RAMP_DELAY determines the delay in us of a ramp between two voltages
#define DVFC_DVS_RAMP_DELAY(upV, lowV, speed)  \
        ((upV - lowV) * DVFC_DVS_STEP_DELAY(speed))
                                
// DVFC_DVS_CNT determines the number of CKIL (32768 kHz) clocks required to
// delay before switching to a higher CPU frequency.
#define DVFC_DVS_CNT(upV, lowV, speed)  \
        ((DVFC_DVS_RAMP_DELAY(upV, lowV, speed) * 32768) / 1000000)
                                
// DVFC_VSCNT clamps the VSCNT calculation
#define DVFC_VSCNT(upV, lowV, speed)  \
        ((DVFC_DVS_CNT(upV, lowV, speed) > 7)  ?  7 : DVFC_DVS_CNT(upV, lowV, speed))
                                
#define DVFC_SCALED_AHB_PODF    (8 - 1) // AHB scaled to MCUPLL / 8
#define DVFC_SCALED_IPG_PODF    (1 - 1) // IPG scaled to AHB / 1

#define DVFC_LOWSPEED_VOLT      0x12    // MC13783 code for 1.350V      
#define DVFC_LOWBUS_VOLT        0x0F    // MC13783 code for 1.275V

//-----------------------------------------------------------------------------
// Types
typedef enum
{
    DVFC_SPEED_HIGH         = 0,
    DVFC_SPEED_LOW          = 1,
    DVFC_NUM_SPEEDS         = 2
} DVFC_SPEED;

typedef enum
{
    DVFC_FREQ_532MHz        = 0,
    DVFC_FREQ_266MHz        = 1,
    DVFC_NUM_FREQ           = 2
} DVFC_FREQ;

typedef enum
{
    DVFC_VOLT_CODE_1_675V   = 0x1F,
    DVFC_VOLT_CODE_1_650V   = 0x1E,
    DVFC_VOLT_CODE_1_625V   = 0x1D,
    DVFC_VOLT_CODE_1_600V   = 0x1C,
    DVFC_VOLT_CODE_1_575V   = 0x1B,
    DVFC_VOLT_CODE_1_550V   = 0x1A,
    DVFC_VOLT_CODE_1_525V   = 0x19,
    DVFC_VOLT_CODE_1_500V   = 0x18,
    DVFC_VOLT_CODE_1_475V   = 0x17,
    DVFC_VOLT_CODE_1_450V   = 0x16,
    DVFC_VOLT_CODE_1_425V   = 0x15,
    DVFC_VOLT_CODE_1_400V   = 0x14,
    DVFC_VOLT_CODE_1_375V   = 0x13,
    DVFC_VOLT_CODE_1_350V   = 0x12,
    DVFC_VOLT_CODE_1_325V   = 0x11,
    DVFC_VOLT_CODE_1_300V   = 0x10,
    DVFC_VOLT_CODE_1_275V   = 0xF,
    DVFC_VOLT_CODE_1_250V   = 0xE,
    DVFC_VOLT_CODE_1_225V   = 0xD,
    DVFC_VOLT_CODE_1_200V   = 0xC,
    DVFC_VOLT_CODE_1_175V   = 0xB,
    DVFC_VOLT_CODE_1_150V   = 0xA,
    DVFC_VOLT_CODE_1_125V   = 0x9,
    DVFC_VOLT_CODE_1_100V   = 0x8,
    DVFC_VOLT_CODE_1_075V   = 0x7,
    DVFC_VOLT_CODE_1_050V   = 0x6,
    DVFC_VOLT_CODE_1_025V   = 0x5,
    DVFC_VOLT_CODE_1_000V   = 0x4,
    DVFC_VOLT_CODE_0_975V   = 0x3,
    DVFC_VOLT_CODE_0_950V   = 0x2,
    DVFC_VOLT_CODE_0_925V   = 0x1,
    DVFC_VOLT_CODE_0_900V   = 0x0
} DVFC_VOLT_CODE;

typedef struct
{
    DVFC_FREQ freqIndex;
    UINT32 voltIndex;
    UINT32 mcuPodf;
    PMIC_REGULATOR_SREG sw;
    PMIC_REGULATOR_SREG_VOLTAGE_TYPE swVolt;
    UINT32 dvs;
    BOOL dpten;
} DVFC_SETPOINT, *PDVFC_SETPOINT;


//-----------------------------------------------------------------------------
// Global Variables



//-----------------------------------------------------------------------------
// Local Variables
static HANDLE g_hDvfcMutex;
static HANDLE g_hAcrMutex;
static DVFC_SPEED g_CurSpeed;
static UINT32 g_AhbPodf;
static UINT32 g_IpgPodf;
static UINT32 g_SdmaAcr;
static UINT32 g_Vscnt;
static UINT32 g_DvsSpeed;
static DVFC_VOLT_CODE g_LowSpeedVolt;
static DVFC_VOLT_CODE g_LowBusVolt;
static int g_IstPriority;
static BOOL g_bVerbose;

static volatile DDK_CLOCK_DVFC_MODE g_DvfcForcedMode;

static DVFC_SETPOINT g_SetPoint[DVFC_NUM_SPEEDS] = 
{ 
 // freqIndex, voltIndex, mcuPodf, sw, swVolt, dvs, dpten
    DVFC_FREQ_532MHz, 0, 0, BSP_PMIC_CPU_REGULATOR, SW_VOLTAGE_NORMAL, 0x0, TRUE,
    DVFC_FREQ_266MHz, 0, 1, BSP_PMIC_CPU_REGULATOR, SW_VOLTAGE_DVS, 0x3, FALSE
};
static PCSP_SDMA_REGS g_pSDMA;

static PMIC_REGULATOR_SREG_VOLTAGE g_MC13783SwitcherVoltTable[DVFC_VOLT_LEVELS] = 
{
    DVFC_VOLT_CODE_1_600V,
    DVFC_VOLT_CODE_1_575V,
    DVFC_VOLT_CODE_1_550V,
    DVFC_VOLT_CODE_1_525V,
    DVFC_VOLT_CODE_1_500V,
    DVFC_VOLT_CODE_1_475V,
    DVFC_VOLT_CODE_1_450V,
    DVFC_VOLT_CODE_1_425V,
    DVFC_VOLT_CODE_1_400V,
    DVFC_VOLT_CODE_1_375V,
    DVFC_VOLT_CODE_1_350V,
    DVFC_VOLT_CODE_1_325V,
    DVFC_VOLT_CODE_1_300V,
    DVFC_VOLT_CODE_1_275V,
    DVFC_VOLT_CODE_1_250V,
    DVFC_VOLT_CODE_1_225V,
};
    
static UINT32 g_DptcDcvrTable[DVFC_NUM_FREQ][DVFC_VOLT_LEVELS][DPTC_REF_CIRCUITS] =
{
//---------------------------- 532 MHz -----------------------------
//       DCVR0          DCVR1            DCVR2          DCVR3
//------------------------------------------------------------------
    DCVR(0,0,1023), DCVR(0,0,599), DCVR(0,0,1023), DCVR(0,0,918),
    DCVR(0,0,1023), DCVR(569,574,599), DCVR(0,0,1023), DCVR(872,879,918),
    DCVR(0,0,1023), DCVR(570,574,599), DCVR(0,0,1023), DCVR(873,880,919),
    DCVR(0,0,1023), DCVR(570,575,600), DCVR(0,0,1023), DCVR(874,881,920),
    DCVR(0,0,1023), DCVR(572,576,601), DCVR(0,0,1023), DCVR(876,883,922),
    DCVR(0,0,1023), DCVR(573,578,603), DCVR(0,0,1023), DCVR(879,886,925),
    DCVR(0,0,1023), DCVR(575,580,605), DCVR(0,0,1023), DCVR(882,889,928),
    DCVR(0,0,1023), DCVR(577,582,607), DCVR(0,0,1023), DCVR(886,893,933),
    DCVR(0,0,1023), DCVR(580,584,610), DCVR(0,0,1023), DCVR(890,897,938),
    DCVR(0,0,1023), DCVR(582,587,613), DCVR(0,0,1023), DCVR(894,902,943),
    DCVR(0,0,1023), DCVR(585,590,1023), DCVR(0,0,1023), DCVR(898,906,1023),
    DCVR(0,0,1023), DCVR(587,593,1023), DCVR(0,0,1023), DCVR(903,911,1023),
    DCVR(0,0,1023), DCVR(590,596,1023), DCVR(0,0,1023), DCVR(907,917,1023),
    DCVR(0,0,1023), DCVR(593,599,1023), DCVR(0,0,1023), DCVR(913,922,1023),
    DCVR(0,0,1023), DCVR(597,603,1023), DCVR(0,0,1023), DCVR(918,928,1023),
    DCVR(0,0,1023), DCVR(600,606,1023), DCVR(0,0,1023), DCVR(924,934,1023),

//---------------------------- 266 MHz -----------------------------
//       DCVR0          DCVR1          DCVR2          DCVR3
//------------------------------------------------------------------
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),
    DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023), DCVR(0,0,1023),

};


//-----------------------------------------------------------------------------
//
//  Function:  DvfcScaleVoltage
//
//  This function scales the voltage using software-controlled steps.
//
//  Parameters:
//      None.
//
//  Returns:
//      DVFC thread priority.
//
//-----------------------------------------------------------------------------
BOOL DvfcScaleVoltage(PMIC_REGULATOR_SREG regulator,
    PMIC_REGULATOR_SREG_VOLTAGE_TYPE voltageType,
    DVFC_VOLT_CODE curVolt,
    DVFC_VOLT_CODE newVolt)
{
    // If we are raising the voltage
    if (curVolt < newVolt)
    {
        do
        {
            ++curVolt;

            // Request for transition to new voltage
            PmicSwitchModeRegulatorSetVoltageLevel(regulator, voltageType,
                curVolt);

            // Delay for voltage step
            StallExecution(DVFC_DVS_STEP_DELAY(g_DvsSpeed));

        } while (curVolt < newVolt);
    }

    // Else we are lowering the voltage (current setpoint will increase)
    else if (curVolt > newVolt)
    {
        do
        {
            --curVolt;

            // Request for transition to new voltage
            PmicSwitchModeRegulatorSetVoltageLevel(regulator, voltageType,
                curVolt);

            // Delay for voltage step
            StallExecution(DVFC_DVS_STEP_DELAY(g_DvsSpeed));

        } while (curVolt > newVolt);
    }

    return TRUE;

}


//-----------------------------------------------------------------------------
//
//  Function:  BSPDvfcGetThreadPriority
//
//  This function provides the thread priority for the DVFC IST.
//
//  Parameters:
//      None.
//
//  Returns:
//      DVFC thread priority.
//
//-----------------------------------------------------------------------------
int BSPDvfcGetThreadPriority(void)
{
    return g_IstPriority;
}


//-----------------------------------------------------------------------------
//
//  Function:  BSPDvfcPowerSet
//
//  This function responds to a IOCTL_POWER_SET request to prepare the
//  DVFC driver for suspend/resume.
//
//  Parameters:
//      dx
//          [in] Requested device state.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL BSPDvfcPowerSet(CEDEVICE_POWER_STATE dx)
{    
    static UINT32 dvfen, dpten;
    UINT32 pmcr0;
    PDVFC_SETPOINT pSP = &g_SetPoint[DVFC_SPEED_HIGH];
    
    DVFC_LOCK();

    pmcr0 = INREG32(&g_pCCM->PMCR0);

    // If we are turning off
    if (dx == D4)
    {
        // Save off current state of DVFC module enables
        dvfen = CSP_BITFEXT(pmcr0, CCM_PMCR0_DVFEN);
        dpten = CSP_BITFEXT(pmcr0, CCM_PMCR0_DPTEN);

        // Turn off DVFC module enables
        CSP_BITFINS(pmcr0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_DISABLE);
        CSP_BITFINS(pmcr0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
        
        // Disable DPTC voltage change requests
        CSP_BITFINS(pmcr0, CCM_PMCR0_DPVCR, CCM_PMCR0_DPVCR_NO_CHANGE_REQ);

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

        // Force DPTC logic to return to highest setpoint.  This will
        // provide a safe setpoint for resuming the system
        DvfcScaleVoltage(pSP->sw, pSP->swVolt,
            g_MC13783SwitcherVoltTable[pSP->voltIndex],

⌨️ 快捷键说明

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