📄 dvfc.c
字号:
// 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,
BSP_PMIC_LOWSPEED_VOLT,
BSP_PMIC_LOWBUS_VOLT);
}
// 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,
BSP_PMIC_LOWSPEED_VOLT);
}
RETAILMSG(DVFC_VERBOSE, (_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)
{
// Request for transition to new voltage
PmicSwitchModeRegulatorSetVoltageLevel(pSP->sw, pSP->swVolt,
g_MC13783SwitcherVoltTable[pSP->voltIndex]);
RETAILMSG(DVFC_VERBOSE, (_T("DPTC volt update (swVolt = 0x%x)\r\n"),
g_MC13783SwitcherVoltTable[pSP->voltIndex]));
}
// 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]);
// Enable the DPTC hardware
CSP_BITFINS(pmcr0, CCM_PMCR0_DPVCR, CCM_PMCR0_DPVCR_CHANGE_REQ);
OUTREG32(&g_pCCM->PMCR0, pmcr0);
// Avoid immediately overriding DPVV (voltage valid) when DVFS is
// transitioning to a higher voltage. The MC13783 PWRREADY signal
// can be used to set the DPVV after the new voltage setpoint
// has been reached, or we can just insert a fixed delay.
if (bFreqUpdate &&
(CSP_BITFEXT(pmcr0, CCM_PMCR0_UDSC) == CCM_PMCR0_UDSC_FREQ_UP))
{
Sleep(1);
}
CSP_BITFINS(pmcr0, CCM_PMCR0_DPVV, CCM_PMCR0_DPVV_VOLT_VALID);
OUTREG32(&g_pCCM->PMCR0, pmcr0);
}
cleanUp:
DVFC_UNLOCK();
}
//-----------------------------------------------------------------------------
//
// Function: BSPDvfcInit
//
// This function provides platform-specific initialization for supporting
// DVFS/DPTC.
//
// Parameters:
// None.
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL BSPDvfcInit(void)
{
BOOL rc = FALSE;
PHYSICAL_ADDRESS phyAddr;
UINT32 freq = 0;
// DDKClockSetCKO(TRUE, DDK_CLOCK_CKO_SRC_AHB, DDK_CLOCK_CKO_DIV_4);
// Map SDMA registers for access to ACR bit
if (g_pSDMA == NULL)
{
phyAddr.QuadPart = CSP_BASE_REG_PA_SDMA;
// Map peripheral physical address to virtual address
g_pSDMA = (PCSP_SDMA_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_SDMA_REGS),
FALSE);
// Check if virtual mapping failed
if (g_pSDMA == NULL)
{
ERRORMSG(TRUE, (_T("MmMapIoSpace failed!\r\n")));
goto cleanUp;
}
}
// Map PBC registers for access to power ready signal from MC13783
if (g_pPBC == NULL)
{
phyAddr.QuadPart = BSP_BASE_REG_PA_PBC_BASE;
// Map peripheral physical address to virtual address
g_pPBC = (PCSP_PBC_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_PBC_REGS),
FALSE);
// Check if virtual mapping failed
if (g_pPBC == NULL)
{
ERRORMSG(TRUE, (_T("MmMapIoSpace failed!\r\n")));
goto cleanUp;
}
}
g_PBC_DSW = EXTREG16BF(&g_pPBC->BSTAT2, PBC_BSTAT2_DSW);
// Mask DVFC interrupts
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_FSVAIM, CCM_PMCR0_FSVAIM_MASK);
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_PTVAIM, CCM_PMCR0_PTVAIM_MASK);
// Claim the DVS pins
DDKIomuxSetPinMux(DDK_IOMUX_PIN_DVFS0, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_NONE);
DDKIomuxSetPinMux(DDK_IOMUX_PIN_DVFS1, DDK_IOMUX_OUT_FUNC, DDK_IOMUX_IN_NONE);
// Determine current working point frequency
if (!DDKClockGetFreq(DDK_CLOCK_SIGNAL_ARM, &freq))
{
ERRORMSG(TRUE, (_T("DDKClockGetFreq failed for DDK_CLOCK_SIGNAL_ARM.\r\n")));
goto cleanUp;
}
// Configure DVFC setpoint parameters tied to CPU frequency
switch (freq)
{
case BSP_CLK_MCUPLL_FREQ:
case BSP_CLK_MCUPLL_FREQ_ALT:
// Start in high speed
g_CurSpeed = DVFC_SPEED_HIGH;
break;
default:
ERRORMSG(TRUE, (_T("Unsupported MCUPLL frequency.\r\n")));
goto cleanUp;
}
// Save off default bus configuration to restore from bus scaling
g_AhbPodf = EXTREG32BF(&g_pCCM->PDR0, CCM_PDR0_MAX_PODF);
g_IpgPodf = EXTREG32BF(&g_pCCM->PDR0, CCM_PDR0_IPG_PODF);
g_SdmaAcr = EXTREG32BF(&g_pSDMA->CONFIG, SDMA_CONFIG_ACR);
// Initialize the forced mode globals
g_DvfcForcedMode = DDK_CLOCK_DVFC_MODE_NORMAL;
#if 0
// Configure MC13783 for dual-DVS mode
if (PmicRegisterWrite(MC13783_ARB_SW_ADDR, CSP_BITFVAL(MC13783_ARB_SW_SW1ABDVS, 1),
CSP_BITFMASK(MC13783_ARB_SW_SW1ABDVS)) != PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("PmicRegisterWrite failed\r\n")));
goto cleanUp;
}
#endif
// Configure the default high-speed voltage
if (PmicSwitchModeRegulatorSetVoltageLevel(g_SetPoint[DVFC_SPEED_HIGH].sw,
g_SetPoint[DVFC_SPEED_HIGH].swVolt,
g_MC13783SwitcherVoltTable[g_SetPoint[DVFC_SPEED_HIGH].voltIndex])
!= PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("PmicSwitchModeRegulatorSetVoltageLevel failed!\r\n")));
goto cleanUp;
}
// Configure the default high-speed DPTC thresholds
OUTREG32(&g_pCCM->DCVR[0], g_DptcDcvrTable[g_SetPoint[DVFC_SPEED_HIGH].freqIndex][g_SetPoint[DVFC_SPEED_HIGH].voltIndex][0]);
OUTREG32(&g_pCCM->DCVR[1], g_DptcDcvrTable[g_SetPoint[DVFC_SPEED_HIGH].freqIndex][g_SetPoint[DVFC_SPEED_HIGH].voltIndex][1]);
OUTREG32(&g_pCCM->DCVR[2], g_DptcDcvrTable[g_SetPoint[DVFC_SPEED_HIGH].freqIndex][g_SetPoint[DVFC_SPEED_HIGH].voltIndex][2]);
OUTREG32(&g_pCCM->DCVR[3], g_DptcDcvrTable[g_SetPoint[DVFC_SPEED_HIGH].freqIndex][g_SetPoint[DVFC_SPEED_HIGH].voltIndex][3]);
// Configure the default low-speed voltage
if (PmicSwitchModeRegulatorSetVoltageLevel(g_SetPoint[DVFC_SPEED_LOW].sw,
g_SetPoint[DVFC_SPEED_LOW].swVolt, BSP_PMIC_LOWSPEED_VOLT)
!= PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("PmicSwitchModeRegulatorSetVoltageLevel failed!\r\n")));
goto cleanUp;
}
// Configure the DVS transition speed
if (PmicSwitchModeRegulatorSetDVSSpeed(g_SetPoint[DVFC_SPEED_HIGH].sw,
DVFC_DVSSPEED) != PMIC_SUCCESS)
{
ERRORMSG(TRUE, (_T("PmicSwitchModeRegulatorSetDVSSpeed failed!\r\n")));
goto cleanUp;
}
// Configure counting range for 256 system clocks
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DCR, CCM_PMCR0_DCR_256_CLOCKS);
// Configure DVFS logic for integer frequency scaling of MCUPLL
// using MCU post-divider
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DFSUP1,
CCM_PMCR0_DFSUP1_MCUPLL_UPDATE);
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DFSUP0,
CCM_PMCR0_DFSUP0_POSTDIV_UPDATE);
// Configure WFI sampling granularity
INSREG32BF(&g_pCCM->LTR0, CCM_LTR0_DIV3CK, DVFC_DIV3CK);
// Configure frequency transition thresholds compared against EMA
// for WFI signal
INSREG32BF(&g_pCCM->LTR0, CCM_LTR0_DNTHR, DVFC_DNTHR);
INSREG32BF(&g_pCCM->LTR0, CCM_LTR0_UPTHR, DVFC_UPTHR);
INSREG32BF(&g_pCCM->LTR1, CCM_LTR1_PNCTHR, DVFC_PNCTHR);
// Configure number of consecutive times a threshold is exceeded
// before a frequency transition is requested
INSREG32BF(&g_pCCM->LTR1, CCM_LTR1_DNCNT, DVFC_DNCNT);
INSREG32BF(&g_pCCM->LTR1, CCM_LTR1_UPCNT, DVFC_UPCNT);
INSREG32BF(&g_pCCM->LTR1, CCM_LTR1_LTBRSR, 1);
// Disable weighted load tracking signals
OUTREG32(&g_pCCM->LTR2, 0);
OUTREG32(&g_pCCM->LTR3, 0);
// Configure EMA calculation
INSREG32BF(&g_pCCM->LTR2, CCM_LTR2_EMAC, DVFC_EMAC);
// Unmask selected DVFC interrupts
INSREG32(&g_pCCM->PMCR0, DVFC_INTR_MASK, DVFC_INTR_VAL);
// Initialize mutex for safe access to CCM registers
// used by the DVFC driver
g_hDvfcMutex = CreateMutex(NULL, FALSE, L"MUTEX_DVFC");
if (g_hDvfcMutex == NULL)
{
ERRORMSG(1, (_T("CreateMutex failed!\r\n")));
goto cleanUp;
}
// Initialize mutex for protecting bus scaling
g_hAcrMutex = CreateMutex(NULL, FALSE, L"MUTEX_ACR");
if (g_hAcrMutex == NULL)
{
ERRORMSG(1, (_T("CreateMutex failed!\r\n")));
goto cleanUp;
}
// Enable/disable DVFS features
if (g_PBC_DSW & BSP_PBC_DSW_DVFS)
{
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_DISABLE);
RETAILMSG(DVFC_VERBOSE, (_T("DVFS disabled\r\n")));
}
else
{
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_ENABLE);
RETAILMSG(DVFC_VERBOSE, (_T("DVFS enabled (DVSSPEED = %d, VSCNT = %d)\r\n"),
DVFC_DVSSPEED, DVFC_VSCNT));
}
if (g_SetPoint[g_CurSpeed].dpten)
{
if (g_PBC_DSW & BSP_PBC_DSW_DPTC)
{
g_SetPoint[g_CurSpeed].dpten = FALSE;
// Disable the DPTC hardware
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
RETAILMSG(DVFC_VERBOSE, (_T("DPTC disabled\r\n")));
}
else
{
// Enable the DPTC hardware
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_ENABLE);
// Enable DPTC reference circuits
SETREG32(&g_pCCM->PMCR0, DPTC_REF_CIRCUIT_MASK);
RETAILMSG(DVFC_VERBOSE, (_T("DPTC enabled\r\n")));
}
}
else
{
// Disable the DPTC hardware
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
RETAILMSG(DVFC_VERBOSE, (_T("DPTC disabled")));
}
rc = TRUE;
cleanUp:
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: BSPDvfcDeinit
//
// This function deinitializes the platform-specific DVFS/DPTC support
// established by BSPDvfcInit.
//
// Parameters:
// None.
//
// Returns:
// Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL BSPDvfcDeinit(void)
{
// Disable DPTC & DVFS
CLRREG32(&g_pCCM->PMCR0, DPTC_REF_CIRCUIT_MASK);
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_DISABLE);
// Unmap SDMA registers
if (g_pSDMA)
{
MmUnmapIoSpace(g_pSDMA, sizeof(CSP_SDMA_REGS));
g_pSDMA = NULL;
}
// Unmap PBC registers
if (g_pPBC)
{
MmUnmapIoSpace(g_pPBC, sizeof(CSP_PBC_REGS));
g_pPBC = NULL;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -