imx53 时钟设置过程和详细说明

/* The function prog_pll sets up all four PLLs as follows:

    PLL1 800MHz

    PLL2 400MHz

    PLL3 216MHz

    PLL4 595MHz

 */

void prog_pll(void)

{

    // Clear ESDCTL configuration bit to allow handshake

    reg32clrbit(ESDCTL_REGISTERS_BASE_ADDR + ESDCTL_ESDSCR_OFFSET, 15);

    // disabling automatic restart on PLLs

    reg32clrbit(PLL1_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32clrbit(PLL2_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32clrbit(PLL3_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32clrbit(PLL4_BASE_ADDR + PLL_DP_CONFIG, 1);

    // Program PLL1 to 800Mhz - assuming 24MHz OSC as reference

    reg32_write(PLL1_BASE_ADDR + PLL_DP_CTL, 0x00001222);

    reg32_write(PLL1_BASE_ADDR + PLL_DP_OP, 0x00000080);    //MFI=8; PDF=0

    reg32_write(PLL1_BASE_ADDR + PLL_DP_MFD, 8);    //MFD=9

    reg32_write(PLL1_BASE_ADDR + PLL_DP_MFN, 3);    //MFN=3

    // Program PLL2 to 400Mhz - assuming 24MHz OSC as reference

    reg32_write(PLL2_BASE_ADDR + PLL_DP_CTL, 0x00001222);

    reg32_write(PLL2_BASE_ADDR + PLL_DP_OP, 0x00000081);    //MFI=8; PDF=1

    reg32_write(PLL2_BASE_ADDR + PLL_DP_MFD, 8);    //MFD=9

    reg32_write(PLL2_BASE_ADDR + PLL_DP_MFN, 3);    //MFN=3

    // Program PLL3 freq to 300MHz - assuming 24MHz OSC as reference

    // Note, PLL3 will later be changed to 216MHz

    reg32_write(PLL3_BASE_ADDR + PLL_DP_CTL, 0x00001222);

    reg32_write(PLL3_BASE_ADDR + PLL_DP_OP, 0x00000061);    //MFI=6; PDF=1

    reg32_write(PLL3_BASE_ADDR + PLL_DP_MFD, 999);  //MFD=999

    reg32_write(PLL3_BASE_ADDR + PLL_DP_MFN, 250);  //MFN=250

    // Program PLL4 to 595Mhz - assuming 24MHz OSC as reference

    reg32_write(PLL4_BASE_ADDR + PLL_DP_CTL, 0x00001222);

    reg32_write(PLL4_BASE_ADDR + PLL_DP_OP, 0x00000060);    //MFI=6; PDF=0

    reg32_write(PLL4_BASE_ADDR + PLL_DP_MFD, 999);  //MFD=999

    reg32_write(PLL4_BASE_ADDR + PLL_DP_MFN, 198);  //MFN=198

    /* Sequence for re-programming PLL1

     * Since ARM runs off of PLL1, a particular sequence should be followed

     * such that the ARM clock can be moved safely from PLL1 to PLL3 to allow

     * re-programing of PLL1.

     * The sequence is as follows:

     * Choose PLL3 to source step clk (periph_apm_clk)

     * Set pll1_periph_clk_sel to "1" - DDR/axi_a is now sourced from PLL3

     */

    // switch ARM to PLL3 (still at original/default slow frequency)

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CCSR, 0x00000180, 0x00000180);  // step clk to PLL3

    reg32setbit(CCM_BASE_ADDR + CLKCTL_CCSR, 2);    // set ARM to step clk (periph_apm_clk)

    // added handshake MK

    while (reg32_read(CCM_BASE_ADDR + CLKCTL_CDHIPR)) ; // verify handshake is over

 

    // restart PLL1

    reg32setbit(PLL1_BASE_ADDR + PLL_DP_CTL, 4);

 

    // Wait for PLL 1 to lock

    while (!((reg32_read(PLL1_BASE_ADDR + PLL_DP_CTL) & 1))) ;

 

    // switch ARM back to PLL1 (now full speed)

    reg32clrbit(CCM_BASE_ADDR + CLKCTL_CCSR, 2);    // set ARM to PLL1

    /* Sequence for re-programming PLL2

     * Since DDR runs off of PLL2, a particular sequence should be followed

     * such that the DDR clock can be moved safely from PLL2 to PLL3 to allow

     * re-programing of PLL2.

     * The sequence is as follows:

     * Program PLL3 to 300MHz, DDR clock will be at 300MHz

     * Set periph_apm_sel to PLL3, choosing PLL3 to source periph_apm_clk

     * Set periph_clk_sel to "1" - DDR/axi_a is now sourced from PLL3

     * Program PLL2 to 400MHz

     * Set PLL2 periph_clk_sel to "0" - pll2_sw_clk = PLL2

     * Set step clk back to lp_apm

     */

    // re-start PLL3 (above it was programmed to 300MHz)

    reg32setbit(PLL3_BASE_ADDR + PLL_DP_CTL, 4);

 

    // Wait for PLL 3 to lock

    while (!((reg32_read(PLL3_BASE_ADDR + PLL_DP_CTL) & 1))) ;

 

    /* In CBCMR, select PLL3 to source periph_apm_clk */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCMR, 0x00001000, 0x00003000);

 

    /* The following moves DDR clock to PLL3 and sets to 300MHz */

    /* Note: periph_apm_clk was selected to be sourced from PLL3 per above, and PLL3 should now be 300MHz */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCDR, 0x02000000, 0x02000000); // set pll2_sw_clk to periph_apm_clk (periph_clk_sel=1)

 

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCDR, 0x00000000, 0x00070000); // axi_a_podf = div-by-1

    /* Now re-start PLL2 at new freq of 400MHz */

    reg32setbit(PLL2_BASE_ADDR + PLL_DP_CTL, 4);

 

    // Wait for PLL 2 to lock

    while (!((reg32_read(PLL2_BASE_ADDR + PLL_DP_CTL) & 1))) ;

 

    /* Before setting pll2_sw_clk (and DDR clock) back to PLL2, first check to see if the axi_a_podf is greater

     * than div-by-1. If it is div-by-1, set to div-by-2, this will ensure the DDR clock is at a safe frequency

     * prior to switching over to PLL2 */

    /*    if((reg32_read(CCM_BASE_ADDR + CLKCTL_CBCDR)&(0x00070000))==0)

       {

       reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCDR, 0x00010000, 0x00070000);    // axi_a_podf = div-by-2

       }

     */

    /* Set pll2_sw_clk back to PLL2 now at 400MHz */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCDR, 0x00000000, 0x02000000); // set pll2_sw_clk to periph_apm_clk (periph_clk_sel=0)

    /* Make sure DDR clock is set to axi_a and that axi_a_podf is set to div-by-1 */

    /* Set axi_podf to div-by-1, DDR will be 400MHz */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCDR, 0x00000000, 0x00070000); // axi_a_podf = div-by-1

    /* Set DDR clock to be sourced from axi_a */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CBCMR, 0x00000000, 0x00000C00); // ddr_clk_sel = axi_a

    /* set step_clk back to default (lp_apm)     */

    reg32_write_mask(CCM_BASE_ADDR + CLKCTL_CCSR, 0x00000000, 0x00000180);

    /* Set PLL3 to 216MHz

     * was set to 300MHz as an intermediate step above

     */

    // Program PLL3 to 216Mhz - assuming 24MHz OSC as reference

    reg32_write(PLL3_BASE_ADDR + PLL_DP_CTL, 0x00000222);

    reg32_write(PLL3_BASE_ADDR + PLL_DP_OP, 0x00000081);    //MFI=8; PDF=2

    reg32_write(PLL3_BASE_ADDR + PLL_DP_MFD, 0);    //MFD=0

    reg32_write(PLL3_BASE_ADDR + PLL_DP_MFN, 1);    //MFN=1

    // re-start PLL3

    reg32setbit(PLL3_BASE_ADDR + PLL_DP_CTL, 4);

 

    // Wait for PLL 3 to lock

    while (!((reg32_read(PLL3_BASE_ADDR + PLL_DP_CTL) & 1))) ;

 

    /*

     * Re-start PLL4 for 595MHz

     */

    reg32setbit(PLL4_BASE_ADDR + PLL_DP_CTL, 4);

 

    // Wait for PLL 4 to lock

    while (!((reg32_read(PLL4_BASE_ADDR + PLL_DP_CTL) & 1))) ;

 

    // re-enable automatic restart on PLLs

    reg32setbit(PLL1_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32setbit(PLL2_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32setbit(PLL3_BASE_ADDR + PLL_DP_CONFIG, 1);

    reg32setbit(PLL4_BASE_ADDR + PLL_DP_CONFIG, 1);

}

 

 

/*!

 * Retrieve the clocks based on the hardware configuration and fill in the freq

 * info in each module's structure.

 */

void freq_populate(void)

{

    int i;

    volatile unsigned int temp;

    struct hw_module *tmp;

    /* Ungate clocks to all modules */

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR0_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR1_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR2_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR3_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR4_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR5_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR6_OFFSET) = 0xFFFFFFFF;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CCM_CCGR7_OFFSET) = 0xFFFFFFFF;

    /* For MX53, set UART clock source to PLL3 (216MHz) and set dividers to div-by-4 to get 54MHz */

    /* CSCMR1 - to select PLL3 source. uart_clk_sel[1:0] = 10 (bits 25 and 24)

       CSCDR1 - to select divide values */

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CSCMR1);

    temp &= ~(0x03000000);      // clear bits 25 and 24

    temp |= 0x02000000;         // set bits 25 and 24 to 10

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CSCMR1) = temp;

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CSCDR1);

    temp &= ~(0x0000003F);      // clear bits 5 to 0

    temp |= 0x00000018;         // set bits 5 to 3 to 011 (div-by-4); bits 3 to 0 set to 000 (div-by-1)

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CSCDR1) = temp;

    /* To align with operating systems such as WinCE and Linux, configure PERCLK to be sourced

     * from lp_apm with a divider set to DIV-BY-3 to achieve 8MHz on PERCLK*/

    /* first choose lp_apm as the clock source to PERCLK */

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCMR);

    temp |= 0x00000002;         // set bit 1, perclk_lp_apm_sel

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCMR) = temp;

    /* now set perclk_pred1 to div-by-3 */

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCDR);

    temp &= ~(0x000000FF);

    temp |= 0x00000080;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCDR) = temp;

 

    for (i = 0; (tmp = mx53_module[i]) != NULL; i++) {

        tmp->freq = get_freq(tmp->base);

    }

 

    /* config IPU hsp clock, derived from AXI B */

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCMR);

    temp &= ~(0x000000C0);

    temp |= 0x00000040;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCMR) = temp;

    /* now set perclk_pred1 to div-by-2 */

    temp = *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCDR);

    temp &= ~(0x00380000);

    temp |= 0x00080000;

    *(volatile unsigned int *)(CCM_BASE_ADDR + CLKCTL_CBCDR) = temp;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值