• am335x 内核频率 ddr3频率 电压调整


    由Makefile可知,SPL的入口在u-boot-2011.09-psp04.06.00.08archarmcpuarmv7start.S中

    SPL的功能无非是设置MPU的Clock、PLL,Power,DDR,Uart,Pin Mux,完成对U-Boot的引导的工作,所以SPL board port主要针对以上几点。

    在start.S中:

    cpu_init_crit

    board_init_f

    board_init_r

    cpu_init_crit

    #ifndef CONFIG_SKIP_LOWLEVEL_INIT 
        bl    cpu_init_crit 
    #endif

    其中,CONFIG_SKIP_LOWLEVEL_INIT 在am335x_evm.h中定义:

    /* Since SPL did all of this for us, we don't need to do it twice. */ 
    #ifndef CONFIG_SPL_BUILD 
    #define CONFIG_SKIP_LOWLEVEL_INIT 
    #endif

    由此可知,cpu_init_crit 只在SPL中才进行编译,U-Boot中不编译,避免了同样的内容重复设置,比如DDR等。

    cpu_init_crit

    ----> lowlevel_init  (u-boot-2011.09-psp04.06.00.08archarmcpuarmv7omap-commonlowlevel_init.S)

            ----> s_init   (u-boot-2011.09-psp04.06.00.08oard iam335xEvm.c)

                      ----> 关看门狗

                      ----> pll_init();  //PLL和时钟设置

                      ----> rtc32k_enable();  //使能RTC

                      ----> 串口设置

                      ----> init_timer();

                      ----> preloader_console_init();

                      ----> I2C0初始化,读EEPROM

                      ----> DDR设置(DDR2DDR3)

     

    pll_init();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c)

    ----> mpu_pll_config(MPUPLL_M_500);  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c)  

          //设置MPU的频率为500MHz,可以修改

    ----> core_pll_config();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c)

          //设置CORE频率为1GHz

    ----> per_pll_config();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c)   

         //设置外设频率为960MHz                     

    ----> interface_clocks_enable();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c) 

         //使能内部连接模块的时钟

    ----> power_domain_transition_enable();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c)  

         //使能模块电源

    ----> per_clocks_enable();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c) 

         //使能外设模块的时钟

     

    在u-boot-2011.09-psp04.06.00.08archarmincludeasmarch-ti81xxClocks_am335x.h中,定义了所有时钟频率:

    /* Put the pll config values over here */

    #define OSC    24              /* 外部晶振为24MHz */

    /* MAIN PLL Fdll = 1 GHZ, */ 
    #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 ) */ 
    #define MPUPLL_M2    1

    /* Core PLL Fdll = 1 GHZ, */ 
    #define COREPLL_M    1000    /* 125 * n */ 
    #define COREPLL_N    23    /* (n -1 ) */

    #define COREPLL_M4    10    /* CORE_CLKOUTM4 = 200 MHZ */ 
    #define COREPLL_M5    8    /* CORE_CLKOUTM5 = 250 MHZ */ 
    #define COREPLL_M6    4    /* CORE_CLKOUTM6 = 500 MHZ */

    /* 
    * USB PHY clock is 960 MHZ. Since, this comes directly from Fdll, Fdll 
    * frequency needs to be set to 960 MHZ. Hence, 
    * For clkout = 192 MHZ, Fdll = 960 MHZ, divider values are given below 
    */ 
    #define PERPLL_M    960 
    #define PERPLL_N    23 
    #define PERPLL_M2    5

    /* DDR Freq is 266 MHZ for now*/ 
    /* Set Fdll = 400 MHZ , Fdll = M * 2 * CLKINP/ N + 1; clkout = Fdll /(2 * M2) */ 
    #define DDRPLL_M    266 
    #define DDRPLL_N    23 
    #define DDRPLL_M2    1

     

     

    MPU PLL结构:

    MPU Subsystem PLL Structure_1

    配置MPU PLL:

    Configuring the MPU PLL

    代码如下:

    void mpu_pll_config(int mpupll_M) 

        u32 clkmode, clksel, div_m2;

        clkmode = readl(CM_CLKMODE_DPLL_MPU); 
        clksel = readl(CM_CLKSEL_DPLL_MPU); 
        div_m2 = readl(CM_DIV_M2_DPLL_MPU);

        /* Set the PLL to bypass Mode */ 
        writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_MPU);

        while(readl(CM_IDLEST_DPLL_MPU) != 0x00000100);

        clksel = clksel & (~0x7ffff); 
        clksel = clksel | ((mpupll_M << 0x8) | MPUPLL_N); 
        writel(clksel, CM_CLKSEL_DPLL_MPU);

        div_m2 = div_m2 & ~0x1f; 
        div_m2 = div_m2 | MPUPLL_M2; 
        writel(div_m2, CM_DIV_M2_DPLL_MPU);

        clkmode = clkmode | 0x7; 
        writel(clkmode, CM_CLKMODE_DPLL_MPU);

        while(readl(CM_IDLEST_DPLL_MPU) != 0x1); 
    }

     

    Core PLL 结构:

    Core PLL

    配置Core PLL:

    Core PLL Configuration

    代码如下:

    static void core_pll_config(void) 

        u32 clkmode, clksel, div_m4, div_m5, div_m6;

        clkmode = readl(CM_CLKMODE_DPLL_CORE); 
        clksel = readl(CM_CLKSEL_DPLL_CORE); 
        div_m4 = readl(CM_DIV_M4_DPLL_CORE); 
        div_m5 = readl(CM_DIV_M5_DPLL_CORE); 
        div_m6 = readl(CM_DIV_M6_DPLL_CORE);

        /* Set the PLL to bypass Mode */ 
        writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_CORE);

        while(readl(CM_IDLEST_DPLL_CORE) != 0x00000100);

        clksel = clksel & (~0x7ffff); 
        clksel = clksel | ((COREPLL_M << 0x8) | COREPLL_N); 
        writel(clksel, CM_CLKSEL_DPLL_CORE);

        div_m4 = div_m4 & ~0x1f; 
        div_m4 = div_m4 | COREPLL_M4; 
        writel(div_m4, CM_DIV_M4_DPLL_CORE);

        div_m5 = div_m5 & ~0x1f; 
        div_m5 = div_m5 | COREPLL_M5; 
        writel(div_m5, CM_DIV_M5_DPLL_CORE);

        div_m6 = div_m6 & ~0x1f; 
        div_m6 = div_m6 | COREPLL_M6; 
        writel(div_m6, CM_DIV_M6_DPLL_CORE);

        clkmode = clkmode | 0x7; 
        writel(clkmode, CM_CLKMODE_DPLL_CORE);

        while(readl(CM_IDLEST_DPLL_CORE) != 0x1); 
    }

     

    Peripheral PLL 结构

    Peripheral PLL Structure

    配置Peripheral PLL:

    Configuring the Peripheral PLL

    代码如下:

    static void per_pll_config(void) 

        u32 clkmode, clksel, div_m2;

        clkmode = readl(CM_CLKMODE_DPLL_PER); 
        clksel = readl(CM_CLKSEL_DPLL_PER); 
        div_m2 = readl(CM_DIV_M2_DPLL_PER);

        /* Set the PLL to bypass Mode */ 
        writel(PLL_BYPASS_MODE, CM_CLKMODE_DPLL_PER);

        while(readl(CM_IDLEST_DPLL_PER) != 0x00000100);

        clksel = clksel & (~0x7ffff); 
        clksel = clksel | ((PERPLL_M << 0x8) | PERPLL_N); 
        writel(clksel, CM_CLKSEL_DPLL_PER);

        div_m2 = div_m2 & ~0x7f; 
        div_m2 = div_m2 | PERPLL_M2; 
        writel(div_m2, CM_DIV_M2_DPLL_PER);

        clkmode = clkmode | 0x7; 
        writel(clkmode, CM_CLKMODE_DPLL_PER);

        while(readl(CM_IDLEST_DPLL_PER) != 0x1); 
    }

     

    串口设置(u-boot-2011.09-psp04.06.00.08oard iam335xEvm.c)

    设置所使用串口的基地址、复位串口、关闭 smart idle。

    u32 uart_base = DEFAULT_UART_BASE;        // 默认使用的串口是UART0,基地址为 0x44E0_9000

    enable_uart0_pin_mux();                   // 配置uart0相关引脚为 UART模式

    同样可以设置为其他串口,比如IA Motor Control Board就是使用的UART3,只要修改上面两步就可以了

     

    init_timer();  (u-boot-2011.09-psp04.06.00.08oard iam335xEvm.c)

    这里初始化的是timer2,在之前 pll_init();----> per_clocks_enable(); 中使能的也是timer2,使用24MHz OSC

     

    preloader_console_init();  (u-boot-2011.09-psp04.06.00.08archarmcpuarmv7omap-commonSpl.c)

    主要是对串口波特率的设置,以及串口终端打印信息。BeagleBone板上使用的是USB转串口芯片,串口驱动driversserialserial.c 、driversserialns16550.c

    I2C0初始化,读EEPROM  (u-boot-2011.09-psp04.06.00.08oard iam335xEvm.c)

    i2c0接了一个eeprom ( CAT24C256W 256K *8 ),i2c读取eeprom的数据到 header 结构体,header 结构体原型为

    struct am335x_baseboard_id { 
        unsigned int  magic; 
        char name[8]; 
        char version[4]; 
        char serial[12]; 
        char config[32]; 
        char mac_addr[NO_OF_MAC_ADDR][ETH_ALEN]; 
    };

    BeagleBone开发板提供的eeprom信息如下:

    image

    enable_i2c0_pin_mux();                  // 配置i2c0相关引脚为 I2C模式                     

    i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);//i2c初始化,速度为标准速度100000,从设备

    if (read_eeprom()) {

    printf("read_eeprom() failure. continuing with ddr3 ");

    }     //读eeprom到 header 结构体,会判断magic是否为上表中提供的0xEE3355AA 

     

        

    DDR设置(DDR2DDR3)  (u-boot-2011.09-psp04.06.00.08oard iam335xEvm.c)

    u32 is_ddr3 = 0; 
    if (!strncmp("A335X_SK", header.name, 8)) { 
        is_ddr3 = 1;

        /* 
         * EVM SK 1.2A and later use gpio0_7 to enable DDR3. 
         * This is safe enough to do on older revs. 
         */ 
        enable_gpio0_7_pin_mux(); 
        gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en"); 
        gpio_direction_output(GPIO_DDR_VTT_EN, 1);       

        //通过gpio0_7输出高电平来触发VTT稳压器,从而产生VTT_DDR电压 
    }

    if(is_ddr3 == 1){ 
        ddr_pll_config(303); 
        config_am335x_ddr3(); 

    else { 
        ddr_pll_config(266); 
        config_am335x_ddr2(); 
    }

    在设置DDR之前,要先判断是DDR2(变量is_ddr3 = 0)还是DDR3(变量is_ddr3 = 1),TI推出的开发板目前只有A335X_StarterKit支持DDR3,其余的均是DDR2,包括BeagleBone

    一开始默认为DDR2(设置is_ddr3 = 0),但是通过比对header.name是否为A335X_SK,来确定DDR3(设置is_ddr3 = 1)

    根据不同的DDR来进行相应的DDR配置,主要有4个部分需要设置,如下:

    image

     

     

    DDR PLL 结构:

    image

    配置DDR PLL:

    image

    image

    代码如下:

    ddr_pll_config();  (u-boot-2011.09-psp04.06.00.08oard iam335xPll.c);

    //配置ddr的时钟频率,DDR2为266MHz,DDR3为303MHz

    void ddr_pll_config(unsigned int ddrpll_M) 

        u32 clkmode, clksel, div_m2;

        clkmode = readl(CM_CLKMODE_DPLL_DDR); 
        clksel = readl(CM_CLKSEL_DPLL_DDR); 
        div_m2 = readl(CM_DIV_M2_DPLL_DDR);

        /* Set the PLL to bypass Mode */ 
        clkmode = (clkmode & 0xfffffff8) | 0x00000004; 
        writel(clkmode, CM_CLKMODE_DPLL_DDR);

        while ((readl(CM_IDLEST_DPLL_DDR) & 0x00000100) != 0x00000100);

        clksel = clksel & (~0x7ffff); 
        clksel = clksel | ((ddrpll_M << 0x8) | DDRPLL_N); 
        writel(clksel, CM_CLKSEL_DPLL_DDR);

        div_m2 = div_m2 & 0xFFFFFFE0; 
        div_m2 = div_m2 | DDRPLL_M2; 
        writel(div_m2, CM_DIV_M2_DPLL_DDR);

        clkmode = (clkmode & 0xfffffff8) | 0x7; 
        writel(clkmode, CM_CLKMODE_DPLL_DDR);

        while ((readl(CM_IDLEST_DPLL_DDR) & 0x00000001) != 0x1); 
    }

    config_am335x_ddr2();

  • 相关阅读:
    百度文库:网站镜像站点解决方案
    百度文库:WEB网站架构分析HTML静态化
    61条面向对象设计的经验原则
    oracle 定时任务例子【项目例子】
    javascript的事件机制(百度文库)
    【转】Oracle回收站(recyclebin)
    java十大低级错误和常见注意点
    JAVA UUID 生成
    Oracle in和exists效率问题分析
    http的长连接和短连接(数据库也一样)
  • 原文地址:https://www.cnblogs.com/zym0805/p/4134466.html
Copyright © 2020-2023  润新知