1.总览
Primary Clock Generation
Clock Tree
Switcher clock generation
2.内核时钟
1. 切换 pll1_sw_clk 使用 step_clk
CCM_CACRR
2. 设置 pll1_main_clk 为 792MHz
CCM_ANALOG_PLL_ARMn
3. 切回 pll1_sw_clk 使用 pll1_main_clk
4. 设置分频 为 1
2.PFD
1.PLL2 PFD
CCM_ANALOG_PFD_528n
2.PLL3 PFD
CCM_ANALOG_PFD_480n
3.AHB
BUS clock generation
1.CCM_CBCMR.pre_periph_clk_sel 给 1
derive clock from PLL2 PFD2
CCM_CBCMR
2.CCM_CBCDR.periph_clk_sel 给 0
CCM_CBCDR
3.CCM_CBCDR.ahb_podf
暂时不懂
CDHIPR
4.IPG
1.CCM_CBCDR.ipg_podf 给 1
5.PERCLK
PERCLK_CLK_ROOT
1.CSCMR1[PERCLK_PODF]
CSCMR1.PERCLK_CLK_SEL 给 1
CSCMR1.PERCLK_PODF 给 000000
void imx6u_clkinit(void) {
// 内核时钟
// 1. 切换 pll1_sw_clk 使用 step_clk
if ((((CCM->CCSR) >> 2) & 0x1) == 0) {
CCM->CCSR &= ~(1 << 8);
CCM->CCSR |= (1 << 2);
}
// 2. 设置 pll1_main_clk 为 792MHz
CCM_ANALOG->PLL_ARM = (1 << 13) | ((66 << 0) & 0X7F);
// 3. 切回 pll1_sw_clk 使用 pll1_main_clk
CCM->CCSR &= ~(1 << 2);
// 4. 设置分频 为 1
CCM->CACRR = 0;
// PFD
unsigned int reg = 0;
// 1. PLL2 PFD
reg = CCM_ANALOG->PFD_528;
reg &= ~(0X3F3F3F3F); // 清除原来的设置
reg |= 32 << 24; // PLL2_PFD3=528*18/32=297Mhz
reg |= 24 << 16; // PLL2_PFD2=528*18/24=396Mhz(DDR使用的时钟,最大400Mhz)
reg |= 16 << 8; // PLL2_PFD1=528*18/16=594Mhz
reg |= 27 << 0; // PLL2_PFD0=528*18/27=352Mhz
CCM_ANALOG->PFD_528 = reg;
// 2. PLL3 PFD
reg = CCM_ANALOG->PFD_480;
reg &= ~(0X3F3F3F3F); // 清除原来的设置
reg |= 19 << 24; // PLL3_PFD3=480*18/19=454.74Mhz
reg |= 17 << 16; // PLL3_PFD2=480*18/17=508.24Mhz
reg |= 16 << 8; // PLL3_PFD1=480*18/16=540Mhz
reg |= 12 << 0; // PLL3_PFD0=480*18/12=720Mhz
CCM_ANALOG->PFD_480 = reg;
// AHB
// 1.pre_periph_clk_sel 给到 PLL2_PFD2=396MHz
CCM->CBCMR &= ~(3 << 18);
CCM->CBCMR |= (1 << 18);
// 2.periph_clk_sel 给0
CCM->CBCDR &= ~(1 << 25);
// 3.等待握手完成
while (CCM->CDHIPR & (1 << 5))
;
// IPG
// 1.CCM_CBCDR.ipg_podf 给 1
CCM->CBCDR &= ~(3 << 8);
CCM->CBCDR |= 1 << 8;
// PERCLK
// 1.CSCMR1.PERCLK_CLK_SEL 给 1 时钟源为IPG
CCM->CSCMR1 &= ~(1 << 6);
// 2.CSCMR1.PERCLK_PODF 给 000000 1分频
CCM->CSCMR1 &= ~(7 << 0);
}