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

📄 dvfc.c

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
        {
            // Request for transition to new voltage
            PmicSwitchModeRegulatorSetVoltageLevel(pSP->sw, pSP->swVolt, 
                g_MC13783SwitcherVoltTable[pSP->voltIndex]);

            // Update global tracking VSCNT
            g_Vscnt = DVFC_VSCNT(g_MC13783SwitcherVoltTable[pSP->voltIndex], g_LowSpeedVolt, g_DvsSpeed);

            RETAILMSG(g_bVerbose, (_T("DPTC volt update (swVolt = 0x%x, lowvolt = 0x%x, vscnt = %d)\r\n"), 
                g_MC13783SwitcherVoltTable[pSP->voltIndex], g_LowSpeedVolt, g_Vscnt));
        }
        
        // 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;
    HKEY hKey;
    UINT32 keyVal, dnthr, upthr, dncnt, upcnt, emac;
    UINT32 keySize = sizeof(keyVal);
    BOOL bDvfsForceOff, bDptcForceOff;


    // 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;
        }

    }

    // 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;

    // Supply default DVFC configuration
    g_IstPriority = DVFC_IST_PRIORITY;
    dnthr = DVFC_DNTHR;
    upthr = DVFC_UPTHR;
    dncnt = DVFC_DNCNT;
    upcnt = DVFC_UPCNT;
    emac = DVFC_EMAC;
    bDvfsForceOff = FALSE;
    bDptcForceOff = FALSE;
    g_DvsSpeed = DVFC_DVSSPEED;
    g_LowSpeedVolt = DVFC_LOWSPEED_VOLT;
    g_LowBusVolt = DVFC_LOWBUS_VOLT;
    g_bVerbose = FALSE;

    // Attempt to read DVFS tuning parameters from registry
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, DVFC_REG_PATH, 0, 0, &hKey) == ERROR_SUCCESS)
    {
        if (RegQueryValueEx(hKey, (_T("ThreadPriority")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            g_IstPriority = keyVal;
        }

        if (RegQueryValueEx(hKey, (_T("TrackingLoadDown")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            dnthr = DVFC_TRACKING_LOAD(keyVal) & ((1U << CCM_LTR0_DNTHR_WID) - 1);
        }

        if (RegQueryValueEx(hKey, (_T("TrackingLoadUp")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            upthr = DVFC_TRACKING_LOAD(keyVal) & ((1U << CCM_LTR0_UPTHR_WID) - 1);
        }
        
        if (RegQueryValueEx(hKey, (_T("TrackingWindowDown")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            dncnt = DVFC_TRACKING_WINDOW(keyVal, DVFC_FREQ_UP) & ((1U << CCM_LTR1_DNCNT_WID) - 1);
        }
        
        if (RegQueryValueEx(hKey, (_T("TrackingWindowUp")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            upcnt = DVFC_TRACKING_WINDOW(keyVal, DVFC_FREQ_DOWN) & ((1U << CCM_LTR1_UPCNT_WID) - 1);
        }
        
        if (RegQueryValueEx(hKey, (_T("TrackingEMAC")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            emac = keyVal & ((1U << CCM_LTR2_EMAC_WID) - 1);
        }
        
        if (RegQueryValueEx(hKey, (_T("DvfsForceOff")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            bDvfsForceOff = keyVal;
        }

        if (RegQueryValueEx(hKey, (_T("DptcForceOff")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            bDptcForceOff = keyVal;
        }

        if (RegQueryValueEx(hKey, (_T("DvsSpeed")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            g_DvsSpeed = keyVal & MC13783_SW_DVSSPEED_MAX;
        }

        if (RegQueryValueEx(hKey, (_T("LowSpeedVolt")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            g_LowSpeedVolt = keyVal;
        }

        if (RegQueryValueEx(hKey, (_T("LowBusVolt")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            g_LowBusVolt = keyVal;
        }

        if (RegQueryValueEx(hKey, (_T("Verbose")), NULL, NULL, (LPBYTE) &keyVal, &keySize) == ERROR_SUCCESS)
        {
            g_bVerbose = keyVal;
        }
    }
                                       
    // Use global to track the VSCNT necessary for switching from the low-speed 
    // voltage setpoint to the high-speed voltage setpoint
    g_Vscnt = DVFC_VSCNT(g_MC13783SwitcherVoltTable[g_SetPoint[DVFC_SPEED_HIGH].voltIndex], 
                         g_LowSpeedVolt, g_DvsSpeed);
    
#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, g_LowSpeedVolt) 
        != PMIC_SUCCESS)
    {
        ERRORMSG(TRUE, (_T("PmicSwitchModeRegulatorSetVoltageLevel failed!\r\n")));
        goto cleanUp;
    }

    // Configure the DVS transition speed
    if (PmicSwitchModeRegulatorSetDVSSpeed(g_SetPoint[DVFC_SPEED_HIGH].sw, 
        g_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, dnthr);
    INSREG32BF(&g_pCCM->LTR0, CCM_LTR0_UPTHR, 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, dncnt);
    INSREG32BF(&g_pCCM->LTR1, CCM_LTR1_UPCNT, 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, emac);

    RETAILMSG(g_bVerbose, (_T("LTR0 = 0x%x, LTR1 = 0x%x, LTR2 = 0x%x"), INREG32(&g_pCCM->LTR0), INREG32(&g_pCCM->LTR1), INREG32(&g_pCCM->LTR2)));

    // 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 (bDvfsForceOff)
    {
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_DISABLE);
        RETAILMSG(g_bVerbose, (_T("DVFS disabled\r\n")));
    }
    else
    {
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEN, CCM_PMCR0_DVFEN_DVFS_ENABLE);
        RETAILMSG(g_bVerbose, (_T("DVFS enabled (DVSSPEED = %d, VSCNT = %d)\r\n"), 
            g_DvsSpeed, g_Vscnt));
    }

    if (g_SetPoint[g_CurSpeed].dpten)
    {
        if (bDptcForceOff)
        {
            g_SetPoint[g_CurSpeed].dpten = FALSE;
            // Disable the DPTC hardware
            INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
            RETAILMSG(g_bVerbose, (_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(g_bVerbose, (_T("DPTC enabled\r\n")));
        }
    }
    else
    {
        // Disable the DPTC hardware
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DPTEN, CCM_PMCR0_DPTEN_DPTC_DISABLE);
        RETAILMSG(g_bVerbose, (_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;
    }
    
    return TRUE;
    
}


⌨️ 快捷键说明

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