📄 clock.c
字号:
/*
* File: clock.c
* Purpose: Driver for the on-chip Clock module
*
* Notes:
*/
#include "common.h"
#include "clock.h"
/********************************************************************/
/* Initialize the PLL
*
* Parameters:
* fref PLL reference clock frequency in KHz
* fsys Desired PLL output frequency in KHz
* flags Operating parameters
*
* Return Value:
* The resulting output system frequency
*/
int
clock_pll (int fsys, int flags)
{
int fref, temp, fout, mfd;
uint32 i;
fref = FREF;
if (fsys == 0)
{
/* Return current PLL output */
mfd = MCF_PLL_PFDR;
return ( fref * mfd / (BUSDIV * 4));
}
/* Check bounds of requested system clock */
if (fsys > MAX_FSYS)
fsys = MAX_FSYS;
if (fsys < MIN_FSYS)
fsys = MIN_FSYS;
/* Multiplying by 100 when calculating the temp value,
and then dividing by 100 to calculate the mfd allows
for exact values without needing to include floating
point libraries. */
temp = 100 * fsys / fref;
mfd = 4 * BUSDIV * temp / 100;
/* Determine the output frequency for selected values */
fout = ( fref * mfd / (BUSDIV * 4));
/*
* Check to see if the SDRAM has already been initialized.
* If it has then the SDRAM needs to be put into self refresh
* mode before reprogramming the PLL.
*/
if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
/* Put SDRAM into self refresh mode */
MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
/*
* Initialize the PLL to generate the new system clock frequency.
* The device must be put into LIMP mode to reprogram the PLL.
*/
/* Enter LIMP mode */
clock_limp( DEFAULT_LPD );
/* Reprogram PLL for desired fsys */
MCF_PLL_PODR = ( 0
| MCF_PLL_PODR_CPUDIV(BUSDIV/3)
| MCF_PLL_PODR_BUSDIV(BUSDIV) );
MCF_PLL_PFDR = mfd;
/* Exit LIMP mode */
clock_exit_limp();
/*
* Return the SDRAM to normal operation if it is in use.
*/
if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
/* Exit self refresh mode */
MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
/* software workaround for SDRAM operation after exiting LIMP mode errata */
*((uint32 *)(0xFC0B8080)) = 0x40000000;
/* wait for DQS logic to relock */
for(i=0; i<0x200; i++);
return fout;
}
/********************************************************************/
/*
* Initialize the Low Power Divider circuit
*
* Parameters:
* div Desired system frequency divider
*
* Return Value:
* The resulting output system frequency
*/
int
clock_limp (int div)
{
uint32 temp;
/* Check bounds of divider */
if (div < MIN_LPD)
div = MIN_LPD;
if (div > MAX_LPD)
div = MAX_LPD;
/* Save of the current value of the SSIDIV so we don't
overwrite the value*/
temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF) );
/* Apply the divider to the system clock */
MCF_CCM_CDR = ( 0
| MCF_CCM_CDR_LPDIV(div)
| MCF_CCM_CDR_SSIDIV(temp) );
MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
return (FREF/(3*(1 << div)));
}
/********************************************************************/
/*
* Exit low power LIMP mode
*
* Parameters:
* div Desired system frequency divider
*
* Return Value:
* The resulting output system frequency
*/
int
clock_exit_limp (void)
{
int fout;
/* Exit LIMP mode */
MCF_CCM_MISCCR = ( MCF_CCM_MISCCR
& ~ MCF_CCM_MISCCR_LIMP);
/* Wait for PLL to lock */
while ( !(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK ));
fout = get_sys_clock();
return fout;
}
/********************************************************************/
/*
* Get the value of the current system clock
*
* Parameters:
* none
*
* Return Value:
* The current output system frequency
*/
int
get_sys_clock (void)
{
int divider;
/* Test to see if device is in LIMP mode */
if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP)
{
divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
return (FREF/(2 << divider));
}
else
{
return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
}
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -