由上图可知:
CLKINP = 24MHz
REFCLK = CLKINP/(N+1)
fDPLL = CLKDCOLDO = 2 * [M / (N+1)] * CLKINP
CLKDCOLDO: Oscillator (DCO) output clock with no bypass
CLKOUT = [M / (N+1)] * CLKINP * [1/M2] = CLKDCOLDO/2 * [1/M2]
core配置
clocks_am335x.h(arch/arm/include/asm/ti81xx)
/* Core PLL Fdll = 1 GHZ, */
#define COREPLL_M 1000 /* 125 * n */
#define COREPLL_N 23 /* (n -1 ) *///adu modify 24 -> 23
#define COREPLL_M4 10 /* CORE_CLKOUTM4 = 200 MHZ */
#define COREPLL_M5 8 /* CORE_CLKOUTM5 = 250 MHZ */
#define COREPLL_M6 4 /* CORE_CLKOUTM6 = 500 MHZ */
pll.c(board/forlinx/ok335x)
static void core_pll_config(void)
{
u32 clkmode, clksel, div_m4, div_m5, div_m6;
clkmode = __raw_readl(CM_CLKMODE_DPLL_CORE);
clksel = __raw_readl(CM_CLKSEL_DPLL_CORE);
div_m4 = __raw_readl(CM_DIV_M4_DPLL_CORE);
div_m5 = __raw_readl(CM_DIV_M5_DPLL_CORE);
div_m6 = __raw_readl(CM_DIV_M6_DPLL_CORE);
/* Set the PLL to bypass Mode */
__raw_writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_CORE);
while(__raw_readl(CM_IDLEST_DPLL_CORE) != 0x00000100);
/*设置M= 1000,N=23*/
clksel = clksel & (~0x7ffff);
clksel = clksel | ((COREPLL_M << 0x8) | COREPLL_N);
__raw_writel(clksel, CM_CLKSEL_DPLL_CORE);
div_m4 = div_m4 & ~0x1f;
div_m4 = div_m4 | COREPLL_M4;
__raw_writel(div_m4, CM_DIV_M4_DPLL_CORE);
div_m5 = div_m5 & ~0x1f;
div_m5 = div_m5 | COREPLL_M5;
__raw_writel(div_m5, CM_DIV_M5_DPLL_CORE);
div_m6 = div_m6 & ~0x1f;
div_m6 = div_m6 | COREPLL_M6;
__raw_writel(div_m6, CM_DIV_M6_DPLL_CORE);
clkmode = clkmode | 0x7;
__raw_writel(clkmode, CM_CLKMODE_DPLL_CORE);
while(__raw_readl(CM_IDLEST_DPLL_CORE) != 0x1);
}
CLKDCOLDO = 2 * [M / (N+1)] * CLKINP = 2 * [1000/24] * 24 = 2000
MPU配置:
8.1.6.9.1 Configuring the MPU PLL
The following steps detail how to configure the MPU PLL.
1. Switch PLL to bypass mode by setting CM_CLKMODE_DPLL_MPU.DPLL_EN to 0x4.
2. Wait for CM_IDLEST_DPLL_MPU.ST_MN_BYPASS = 1 to ensure PLL is in bypass
(CM_IDLEST_DPLL_MPU.ST_DPLL_CLK should also change to 0 to denote the PLL is unlocked).
3. Configure Multiply and Divide values by setting CM_CLKSEL_DPLL_MPU.DPLL_MULT and
DPLL_DIV to the desired values.
4. Configure M2 divider by setting CM_DIV_M2_DPLL_MPU.DPLL_CLKOUT_DIV to the desired value.
5. Switch over to lock mode by setting CM_CLKMODE_DPLL_MPU.DPLL_EN to 0x7.
6. Wait for CM_IDLEST_DPLL_MPU.ST_DPLL_CLK = 1 to ensure PLL is locked
(CM_IDLEST_DPLL_MPU.ST_MN_BYPASS should also change to 0 to denote the PLL is out of
bypass mode).
#define MPUPLL_M_500 500 /* 125 * n */
#define MPUPLL_M_550 550 /* 125 * n */
#define MPUPLL_M_600 600 /* 125 * n */
#define MPUPLL_M_720 720 /* 125 * n */
#define MPUPLL_N 23 /* (n -1 ) *///adu modify 24 -> 23
#define MPUPLL_M2 1
void mpu_pll_config(void)
{
u32 clkmode, clksel, div_m2;
clkmode = __raw_readl(CM_CLKMODE_DPLL_MPU);
clksel = __raw_readl(CM_CLKSEL_DPLL_MPU);
div_m2 = __raw_readl(CM_DIV_M2_DPLL_MPU);
/* Set the PLL to bypass Mode */
__raw_writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_MPU);
while(__raw_readl(CM_IDLEST_DPLL_MPU) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((MPUPLL_M_720 << 0x8) | MPUPLL_N);
__raw_writel(clksel, CM_CLKSEL_DPLL_MPU);
div_m2 = div_m2 & ~0x1f;
div_m2 = div_m2 | MPUPLL_M2;
__raw_writel(div_m2, CM_DIV_M2_DPLL_MPU);
clkmode = clkmode | 0x7;
__raw_writel(clkmode, CM_CLKMODE_DPLL_MPU);
while(__raw_readl(CM_IDLEST_DPLL_MPU) != 0x1);
}
CLKOUT = [M / (N+1)] * CLKINP * [1/M2] = [720/24]*24*1= 720;
DDR配置:
/* DDR Freq is 166 MHZ for now*/
/* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */
#if (CONFIG_AM335X_EVM_IS_13x13 == 1)
#define DDRPLL_M 166 /* M/N + 1 = 25/3 */
#else
#define DDRPLL_M /*266*/303
#endif
#define DDRPLL_N 23 //adu modify 24 -> 23
#define DDRPLL_M2 1
static void ddr_pll_config(void)
{
u32 clkmode, clksel, div_m2;
clkmode = __raw_readl(CM_CLKMODE_DPLL_DDR);
clksel = __raw_readl(CM_CLKSEL_DPLL_DDR);
div_m2 = __raw_readl(CM_DIV_M2_DPLL_DDR);
/* Set the PLL to bypass Mode */
clkmode = (clkmode & 0xfffffff8) | 0x00000004;
__raw_writel(clkmode, CM_CLKMODE_DPLL_DDR);
while ((__raw_readl(CM_IDLEST_DPLL_DDR) & 0x00000100) != 0x00000100);
clksel = clksel & (~0x7ffff);
clksel = clksel | ((DDRPLL_M << 0x8) | DDRPLL_N);
__raw_writel(clksel, CM_CLKSEL_DPLL_DDR);
div_m2 = div_m2 & 0xFFFFFFE0;
div_m2 = div_m2 | DDRPLL_M2;
__raw_writel(div_m2, CM_DIV_M2_DPLL_DDR);
clkmode = (clkmode & 0xfffffff8) | 0x7;
__raw_writel(clkmode, CM_CLKMODE_DPLL_DDR);
while ((__raw_readl(CM_IDLEST_DPLL_DDR) & 0x00000001) != 0x1);
}
CLKOUT = [M / (N+1)] * CLKINP * [1/M2] = [303/24]*24*1= 303;