📄 dvfc.c
字号:
//-----------------------------------------------------------------------------
//
// 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 + -