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

📄 ddk_clk.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
//
//  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:  ddk_clk.c
//
//  This file contains the CCM DDK interface that is used by applications and
//  other drivers to access the capabilities of the CCM driver.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include "csp.h"

//-----------------------------------------------------------------------------
// External Functions
extern BOOL BSPClockAlloc(void);
extern BOOL BSPClockDealloc(void);
extern BOOL BSPClockGetFreq(DDK_CLOCK_SIGNAL sig, UINT32 *freq);
extern BOOL BSPClockUpdateFreq(DDK_CLOCK_SIGNAL sig, DDK_CLOCK_BAUD_SOURCE src, 
    UINT32 preDiv, UINT32 postDiv);
extern UINT32 BSPClockIncrPanicRequests(void);
extern UINT32 BSPClockDecrPanicRequests(void);
extern BOOL BSPClockSetEmiGatingMode(DDK_CLOCK_GATE_INDEX index, DDK_CLOCK_GATE_MODE mode);


//-----------------------------------------------------------------------------
// External Variables


//-----------------------------------------------------------------------------
// Defines


//-----------------------------------------------------------------------------
// Types


//-----------------------------------------------------------------------------
// Global Variables
HANDLE g_hDdkClkMutex;
PCSP_CCM_REGS g_pCCM = NULL;


//-----------------------------------------------------------------------------
// Local Variables
static HANDLE g_hDvfcMutex;

//-----------------------------------------------------------------------------
// Local Functions
BOOL ClockAlloc(void);
BOOL ClockDealloc(void);

//-----------------------------------------------------------------------------
//
// Function:  ClockAlloc
//
// This function allocates the data structures required for interaction
// with the clock configuration hardware.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL ClockAlloc(void)
{
    BOOL rc = FALSE;
    PHYSICAL_ADDRESS phyAddr;
         
    if (g_pCCM == NULL)
    {
        phyAddr.QuadPart = CSP_BASE_REG_PA_CCM;

        // Map peripheral physical address to virtual address
        g_pCCM = (PCSP_CCM_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_CCM_REGS),
            FALSE);

        // Check if virtual mapping failed
        if (g_pCCM == NULL)
        {
            DBGCHK((_T("CSPDDK")),  FALSE);
            ERRORMSG(1, (_T("ClockAlloc:  MmMapIoSpace failed!\r\n")));
            goto cleanUp;
        }

    }

    // Create mutex for safe access to CCM register shared with DVFC driver
    if (g_hDvfcMutex == NULL)
    {
        g_hDvfcMutex = CreateMutex(NULL, FALSE, L"MUTEX_DVFC");

        if (g_hDvfcMutex == NULL)
        {
            ERRORMSG(1, (_T("CreateMutex failed!\r\n")));
            goto cleanUp;
        }
    }

    // Create mutex for safe access to PLL control register
    if (g_hDdkClkMutex == NULL)
    {
        g_hDdkClkMutex = CreateMutex(NULL, FALSE, L"MUTEX_DDKCLK");

        if (g_hDdkClkMutex == NULL)
        {
            ERRORMSG(1, (_T("CreateMutex failed!\r\n")));
            goto cleanUp;
        }
    }

    rc = BSPClockAlloc();
     
cleanUp:

    if (!rc) ClockDealloc();

    return rc;
    
}


//-----------------------------------------------------------------------------
//
// Function:  ClockDealloc
//
// This function deallocates the data structures required for interaction
// with the clock configuration hardware.
//
// Parameters:
//      None.
//
// Returns:
//      Returns TRUE.
//
//-----------------------------------------------------------------------------
BOOL ClockDealloc(void)
{
    // Unmap peripheral address space
    if (g_pCCM == NULL)
    {
        MmUnmapIoSpace(g_pCCM, sizeof(CSP_CCM_REGS));
        g_pCCM = NULL;
    }

    if (g_hDvfcMutex)
    {
        CloseHandle(g_hDvfcMutex);
        g_hDvfcMutex = NULL;
    }

    if (g_hDdkClkMutex)
    {
        CloseHandle(g_hDdkClkMutex);
        g_hDdkClkMutex = NULL;
    }

    return BSPClockDealloc();
    
}

//-----------------------------------------------------------------------------
//
// Function: DDKClockSetGatingMode
//
// Sets the clock gating mode of the peripheral.
//
// Parameters:
//      index
//           [in] Index for referencing the peripheral clock gating control 
//           bits.
//
//      mode
//           [in] Requested clock gating mode for the peripheral.
//
// Returns:
//      Returns TRUE if the clock gating mode was set successfully, otherwise 
//      returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL DDKClockSetGatingMode(DDK_CLOCK_GATE_INDEX index, DDK_CLOCK_GATE_MODE mode)
{
    UINT32 mcgrValOld, mcgrValNew, mcgrIndex, mcgrShift, mcgrMask;
    UINT32 cgr0, cgr1, cgr2, ccmr, clkSel;
    BOOL bUsbPllEn, bSerPllEn;
    
    // 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;
    
    // Calculate bitmask for MCG bits
    mcgrMask = CCM_CGR_CG_MASK <<  mcgrShift;

    // Keep trying until the shared register access to the CCM MCGR succeeds
    do
    {
        mcgrValOld = INREG32(&g_pCCM->CGR[mcgrIndex]);
        mcgrValNew = (mcgrValOld & (~mcgrMask)) | (mode << mcgrShift);
    } while (InterlockedTestExchange(&g_pCCM->CGR[mcgrIndex], 
                       mcgrValOld, mcgrValNew) != mcgrValOld);        

    // If this is a clock signal that can be sourced by 
    // the SERPLL or USBPLL
    switch (index)
    {
    case DDK_CLOCK_GATE_INDEX_USBOTG:
    case DDK_CLOCK_GATE_INDEX_FIRI:
    case DDK_CLOCK_GATE_INDEX_SSI1:
    case DDK_CLOCK_GATE_INDEX_SSI2:
    case DDK_CLOCK_GATE_INDEX_CSI:

        // Grab mutex before attempting to enable/disable SERPLL or USBPLL
        WaitForSingleObject(g_hDdkClkMutex, INFINITE);
        
        // Scan through the clock tree and determine if we 
        // can turn off the SERPLL or USBPLL
        bUsbPllEn = FALSE;
        bSerPllEn = FALSE;
            
        ccmr = INREG32(&g_pCCM->CCMR);
        cgr0 = INREG32(&g_pCCM->CGR[0]);
        cgr1 = INREG32(&g_pCCM->CGR[1]);
        cgr2 = INREG32(&g_pCCM->CGR[2]);

        // If USBPLL is peripheral clock source
        if (CSP_BITFEXT(ccmr, CCM_CCMR_PERCS) == CCM_CCMR_PERCS_USB_CLK)
        {
            bUsbPllEn = TRUE;
        }
        
        // If SSI1 clock is enabled
        if (cgr0 & CCM_CGR0_SSI1_MASK)
        {
            clkSel = CSP_BITFEXT(ccmr, CCM_CCMR_SSI1S);

            // If SSI1 clock source is USBPLL
            if (clkSel == CCM_CCMR_SSI1S_USB_CLK)
            {
                bUsbPllEn = TRUE;
            }

            // If SSI1 clock source is SERPLL
            else if (clkSel == CCM_CCMR_SSI1S_SERIAL_CLK)
            {
                bSerPllEn = TRUE;
            }                    
        }
        
        // If CSI clock is enabled
        if (cgr1 & CCM_CGR1_CSI_MASK)
        {
            clkSel = CSP_BITFEXT(ccmr, CCM_CCMR_CSCS);

            // If CSI clock source is USBPLL
            if (clkSel == CCM_CCMR_CSCS_USB_CLK)
            {
                bUsbPllEn = TRUE;
            }

            // If CSI clock source is SERPLL
            else if (clkSel == CCM_CCMR_CSCS_SERIAL_CLK)
            {
                bSerPllEn = TRUE;
            }                    
        }  

        // If USB clock is enabled
        if (cgr1 & CCM_CGR1_USBOTG_MASK)
        {
            bUsbPllEn = TRUE;
        }  

        // If SSI2 clock is enabled
        if (cgr2 & CCM_CGR2_SSI2_MASK)
        {
            clkSel = CSP_BITFEXT(ccmr, CCM_CCMR_SSI2S);

            // If SSI2 clock source is USBPLL
            if (clkSel == CCM_CCMR_SSI2S_USB_CLK)
            {
                bUsbPllEn = TRUE;
            }

            // If SSI2 clock source is SERPLL
            else if (clkSel == CCM_CCMR_SSI2S_SERIAL_CLK)
            {
                bSerPllEn = TRUE;
            }                    
        }  
        
        // If FIR clock is enabled
        if (cgr2 & CCM_CGR2_FIRI_MASK)
        {
            clkSel = CSP_BITFEXT(ccmr, CCM_CCMR_FIRS);

            // If FIR clock source is USBPLL
            if (clkSel == CCM_CCMR_FIRS_USB_CLK)
            {
                bUsbPllEn = TRUE;
            }

            // If FIR clock source is SERPLL
            else if (clkSel == CCM_CCMR_FIRS_SERIAL_CLK)
            {
                bSerPllEn = TRUE;
            }                    
        }  
    
        // If clock tree scan found a module that needs USBPLL
        if (bUsbPllEn)
        {
            // If USBPLL is not already enabled
            if (CSP_BITFEXT(ccmr, CCM_CCMR_UPE) == CCM_CCMR_UPE_DISABLED)
            {
                // Turn on USBPLL
                CSP_BITFINS(ccmr, CCM_CCMR_UPE, CCM_CCMR_UPE_ENABLED);
                OUTREG32(&g_pCCM->CCMR, ccmr);

                // Lock time is 100us
                StallExecution(100);
            }
        }

        // Else clock tree scan did not find any module that needs
        // USBPLL
        else
        {
            // If USBPLL is not already disabled
            if (CSP_BITFEXT(ccmr, CCM_CCMR_UPE) != CCM_CCMR_UPE_DISABLED)
            {
                // Turn off USBPLL
                CSP_BITFINS(ccmr, CCM_CCMR_UPE, CCM_CCMR_UPE_DISABLED);
                OUTREG32(&g_pCCM->CCMR, ccmr);
            }
        }

        // If clock tree scan found a module that needs SERPLL
        if (bSerPllEn)
        {
            // If SERPLL is not already enabled
            if (CSP_BITFEXT(ccmr, CCM_CCMR_SPE) == CCM_CCMR_SPE_DISABLED)
            {
                // Turn on SERPLL
                CSP_BITFINS(ccmr, CCM_CCMR_SPE, CCM_CCMR_SPE_ENABLED);
                OUTREG32(&g_pCCM->CCMR, ccmr);

                // Lock time is 100us
                StallExecution(100);
            }
        }

        // Else clock tree scan did not find any module that needs
        // SERPLL
        else
        {
            // If SERPLL is not already disabled
            if (CSP_BITFEXT(ccmr, CCM_CCMR_SPE) != CCM_CCMR_SPE_DISABLED)
            {
                // Turn off SERPLL
                CSP_BITFINS(ccmr, CCM_CCMR_SPE, CCM_CCMR_SPE_DISABLED);
                OUTREG32(&g_pCCM->CCMR, ccmr);
            }
        }

        ReleaseMutex(g_hDdkClkMutex);
    }

⌨️ 快捷键说明

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