📄 ddk_clk.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: 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 + -