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

📄 ddk_clk.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 2 页
字号:

    // Allow OEM to configure EMI clock gating
    BSPClockSetEmiGatingMode(index, mode);
    
    return TRUE;
    
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockGetGatingMode
//
// Retrieves the clock gating mode of the peripheral.
//
// Parameters:
//      index
//           [in] Index for referencing the peripheral clock gating control 
//           bits.
//
//      pMode
//           [out] Current clock gating mode for the peripheral.
//
// Returns:
//      Returns TRUE if the clock gating mode was set successfully, otherwise 
//      returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockGetGatingMode(DDK_CLOCK_GATE_INDEX index, DDK_CLOCK_GATE_MODE *pMode)
{
    UINT32 mcgrIndex, mcgrShift;
    
    // Divide clock gating index by 16 to determine MCGR register index
    mcgrIndex = index >> 4;

    // Calculate shift for MCG bits by using the index within the
    // MCGR register (0-15) and multiply by 2
    mcgrShift = (index % 16) << 1;

    *pMode = ((INREG32(&g_pCCM->CGR[mcgrIndex])) >> mcgrShift)
             & CCM_CGR_CG_MASK;

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockGetFreq
//
// Retrieves the clock frequency in Hz for the specified clock signal.
//
// Parameters:
//      sig
//           [in] Clock signal.
//
//      freq
//           [out] Current frequency in Hz.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockGetFreq(DDK_CLOCK_SIGNAL sig, UINT32 *freq)
{
    return BSPClockGetFreq(sig, freq);
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockConfigBaud
//
// Configures the input source clock and dividers for the specified 
// CCM peripheral baud clock output.
//
// Parameters:
//      sig
//          [in] Clock signal to configure.
//
//      src
//          [in] Selects the input clock source.
//
//      preDiv
//          [in] Specifies the value programmed into the baud clock predivider.
//
//      postDiv
//          [in] Specifies the value programmed into the baud clock postdivider.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockConfigBaud(DDK_CLOCK_SIGNAL sig, DDK_CLOCK_BAUD_SOURCE src, 
    UINT32 preDiv, UINT32 postDiv)
{
    BOOL rc = TRUE;

    UINT32 oldReg, newReg, *pPDR;
    UINT32 ccmrShift, ccmrMask;
    UINT32 preDivShift, preDivMask, postDivShift, postDivMask;
    
    switch (sig)
    {
        
    case DDK_CLOCK_SIGNAL_SSI1:
        ccmrShift = CCM_CCMR_SSI1S_LSH;
        ccmrMask = CSP_BITFMASK(CCM_CCMR_SSI1S);
        preDivShift = CCM_PDR1_SSI1_PRE_PODF_LSH;
        preDivMask = CSP_BITFMASK(CCM_PDR1_SSI1_PRE_PODF);
        postDivShift = CCM_PDR1_SSI1_PODF_LSH;
        postDivMask = CSP_BITFMASK(CCM_PDR1_SSI1_PODF);
        pPDR = &g_pCCM->PDR1;
        break;

    case DDK_CLOCK_SIGNAL_SSI2:
        ccmrShift = CCM_CCMR_SSI2S_LSH;
        ccmrMask = CSP_BITFMASK(CCM_CCMR_SSI2S);
        preDivShift = CCM_PDR1_SSI2_PRE_PODF_LSH;
        preDivMask = CSP_BITFMASK(CCM_PDR1_SSI2_PRE_PODF);
        postDivShift = CCM_PDR1_SSI2_PODF_LSH;
        postDivMask = CSP_BITFMASK(CCM_PDR1_SSI2_PODF);
        pPDR = &g_pCCM->PDR1;
        break;

    case DDK_CLOCK_SIGNAL_FIRI:
        ccmrShift = CCM_CCMR_FIRS_LSH;
        ccmrMask = CSP_BITFMASK(CCM_CCMR_FIRS);
        preDivShift = CCM_PDR1_FIRI_PRE_PODF_LSH;
        preDivMask = CSP_BITFMASK(CCM_PDR1_FIRI_PRE_PODF);
        postDivShift = CCM_PDR1_FIRI_PODF_LSH;
        postDivMask = CSP_BITFMASK(CCM_PDR1_FIRI_PODF);
        pPDR = &g_pCCM->PDR1;
        break;

    case DDK_CLOCK_SIGNAL_CSI:
        // CSI has different clock source selections
        if (src == DDK_CLOCK_BAUD_SOURCE_SERPLL)
        {
            src = CCM_CCMR_CSCS_SERIAL_CLK;
        }
        else if (src == DDK_CLOCK_BAUD_SOURCE_USBPLL)
        {
            src = CCM_CCMR_CSCS_USB_CLK;
        }
        else
        {
            rc = FALSE;
            break;
        }
        
        ccmrShift = CCM_CCMR_CSCS_LSH;
        ccmrMask = CSP_BITFMASK(CCM_CCMR_CSCS);
        preDivShift = 0;
        preDivMask = 0;
        preDiv = 0;
        postDivShift = CCM_PDR0_CSI_PODF_LSH;
        postDivMask = CSP_BITFMASK(CCM_PDR0_CSI_PODF);
        pPDR = &g_pCCM->PDR0;
        break;

    case DDK_CLOCK_SIGNAL_USB:
        // USBPLL is only USB clock source
        if (src != DDK_CLOCK_BAUD_SOURCE_USBPLL)
        {
            rc = FALSE;
            break;
        }
        ccmrMask = 0;

        preDivShift = CCM_PDR1_USB_PRDF_LSH;
        preDivMask = CSP_BITFMASK(CCM_PDR1_USB_PRDF);
        postDivShift = CCM_PDR1_USB_PODF_LSH;
        postDivMask = CSP_BITFMASK(CCM_PDR1_USB_PODF);
        pPDR = &g_pCCM->PDR1;
        break;

    default:
        rc = FALSE;
        break;

    }

    // If baud configuration is available
    if (rc)
    {
        // Update the global clock signal table
        BSPClockUpdateFreq(sig, src, preDiv, postDiv);
        
        // Update the source selection
        if (ccmrMask)
        {
            // Grab mutex before updating CCMR
            WaitForSingleObject(g_hDdkClkMutex, INFINITE);

            INSREG32(&g_pCCM->CCMR, ccmrMask, (src << ccmrShift));

            ReleaseMutex(g_hDdkClkMutex);

        }

        // Update the dividers
        preDiv <<= preDivShift;
        preDiv &= preDivMask;
        postDiv <<= postDivShift;
        postDiv &= postDivMask;
        do
        {
            oldReg = INREG32(pPDR);
            newReg = (oldReg & (~(preDivMask | postDivMask))) 
                | (preDiv) | (postDiv);
        } while (InterlockedTestExchange(pPDR, 
                           oldReg, newReg) != oldReg);        
    }

    return rc;

}


//-----------------------------------------------------------------------------
//
// Function: DDKClockSetCKO
//
// Configures the clock output source (CKO) signal.
//
// Parameters:
//      bEnable
//          [in] Set to TRUE to enable CKO output.  Set to FALSE to disable
//          CKO output.
//
//      src
//          [in] Selects the CKO source signal.
//
//      div
//          [in] Specifies the CKO divide factor.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockSetCKO(BOOL bEnable, DDK_CLOCK_CKO_SRC src, DDK_CLOCK_CKO_DIV div)
{
    // Configure the CKO signal using the CCM COSR
    OUTREG32(&g_pCCM->COSR, CSP_BITFVAL(CCM_COSR_CLKOEN, bEnable) |
                            CSP_BITFVAL(CCM_COSR_CLKOSEL, src) |
                            CSP_BITFVAL(CCM_COSR_CLKODIV, div));

    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockEnablePanicMode
//
// Forces the DVFS logic to report a panic condition so that the system
// will immediately transition to the highest DVFS setpoint and prevent 
// future requests to a lower setpoint.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockEnablePanicMode(void)
{
    WaitForSingleObject(g_hDvfcMutex, INFINITE);
        
    // If this is first panic request
    if (BSPClockIncrPanicRequests() == 1)
    {    
        // Issue request to enter panic mode
        SETREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_PANIC);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            
    }
    
    ReleaseMutex(g_hDvfcMutex);
    
    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockDisablePanicMode
//
// Restores normal DVFS operation from a prior request for panic mode
// and allows the DVFS logic to request higher/lower setpoints as needed.
//
// Parameters:
//      None.  
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockDisablePanicMode(void)
{
    WaitForSingleObject(g_hDvfcMutex, INFINITE);
    
    // If there are no active panic requests
    if (BSPClockDecrPanicRequests() == 0)
    {
        // Issue request to return to normal mode
        CLRREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_PANIC);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            
    }
    
    ReleaseMutex(g_hDvfcMutex);
    
    return TRUE;
}


//-----------------------------------------------------------------------------
//
// Function: DDKClockBusScale
//
// Scales the AHB bus clock by an integer factor.
//
// Parameters:
//      ratio
//          [in] Specifies the integer ratio used to scale the
//          AHB bus clock.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockBusScale(UINT32 ratio)
{
    BOOL rc = TRUE;
    DDK_CLOCK_GATE_MODE cgm;
        
    DDKClockGetGatingMode(DDK_CLOCK_GATE_INDEX_IPU, &cgm);

    if (cgm != DDK_CLOCK_GATE_MODE_DISABLED)
    {
        DEBUGMSG(TRUE, (_T("DDKClockBusScale:  IPU clock is enabled, ignoring request...\r\n")));
        rc = FALSE;
        goto cleanUp;
    }
    
    WaitForSingleObject(g_hDvfcMutex, INFINITE);
    
    switch(ratio)
    {
    // No scaling
    case 1:
        CLRREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_BUS_LOW);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            
        break;
        
    // Scale down 1:2
    case 2:
        SETREG32(&g_pCCM->PMCR1, DDK_CLOCK_DVFC_MODE_BUS_LOW);
        INSREG32BF(&g_pCCM->PMCR0, CCM_PMCR0_DVFEV, CCM_PMCR0_DVFEV_REQ_ALWAYS);            
        break;

    // Invalid ratio
    default:
        ERRORMSG(TRUE, (_T("Invalid bus scale ratio 0x%x"), ratio));
        rc = FALSE;
        break;
    }
        
    ReleaseMutex(g_hDvfcMutex);

cleanUp:

    return rc;
}

⌨️ 快捷键说明

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