由Makefile可知,SPL的入口在u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.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.08\arch\arm\cpu\armv7\omap-common\lowlevel_init.S)

----> s_init   (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.c)

----> 关看门狗

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

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

----> 串口设置

----> init_timer();

----> preloader_console_init();

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

----> DDR设置(DDR2\DDR3)

pll_init();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

----> mpu_pll_config(MPUPLL_M_500);  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

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

----> core_pll_config();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

//设置CORE频率为1GHz

----> per_pll_config();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

//设置外设频率为960MHz

----> interface_clocks_enable();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

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

----> power_domain_transition_enable();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

//使能模块电源

----> per_clocks_enable();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.c)

//使能外设模块的时钟

在u-boot-2011.09-psp04.06.00.08\arch\arm\include\asm\arch-ti81xx\Clocks_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 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:

代码如下:

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:

代码如下:

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.08\board\ti\am335x\Evm.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.08\board\ti\am335x\Evm.c)

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

preloader_console_init();  (u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\omap-common\Spl.c)

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

I2C0初始化,读EEPROM  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.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信息如下:

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\n");

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

DDR设置(DDR2\DDR3)  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Evm.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个部分需要设置,如下:

DDR PLL 结构:

配置DDR PLL:

代码如下:

ddr_pll_config();  (u-boot-2011.09-psp04.06.00.08\board\ti\am335x\Pll.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();

am335x 内核频率 ddr3频率 电压调整的更多相关文章

  1. linux下查看内存频率,内核函数,cpu频率

    查看CPU: cat /proc/cpuinfo # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理 ...

  2. am335x system upgarde ddr3 capacity configuration base on TI DDR3 Software Leveling Tool (二十)

    follow test is  use ti DDR Software Leveling op log. AM335x DDR3 Software Leveling -- Version: Beta ...

  3. am335x内核初始化路径

    /arch/arm/mach-omap2/board_am335xevm.c中 1.myd_am335x_dev_cfg[]{ evm_nand_init() ... myir_gpio_init() ...

  4. Linux(debian7)操作基础(四)之CPU频率调整 Linux系统CPU频率调整工具使用

    在Linux中,内核的开发者定义了一套框架模型来完成CPU频率动态调整这一目的,它就是CPU Freq系统.如下为CPU的几种模式(governor参数): ondemand:系统默认的超频模式,按需 ...

  5. Android FM模块学习之二 FM搜索频率流程

    上一篇大概分析了一下FM启动流程,若不了解Fm启动流程的,能够去打开前面的链接先了解FM启动流程,接下来我们简单分析一下FM的搜索频率流程. 在了解源代码之前.我们先看一下流程图: 事实上从图中能够看 ...

  6. CSS/CSS3长度、时间、频率、角度单位大全

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1494 一.一笔带过的 ...

  7. AI-DRF权限、频率

    权限 权限逻辑 权限逻辑 权限组件可以设置在三个地方:写在每个类下边表示,访问这个类的数据时,没有权限就不能访问:写在全局,表示访问每个字段的数据都需要权限:还有默认已经也写好了. 写在每个类中:写一 ...

  8. DRF Django REST framework 之 频率,响应器与分页器组件(六)

    频率组件 频率组件类似于权限组件,它判断是否给予请求通过.频率指示临时状态,并用于控制客户端可以向API发出的请求的速率. 与权限一样,可以使用多个调节器.API可能会对未经身份验证的请求进行限制,而 ...

  9. day75_10_22频率认证和jwt

    一.频率认证原理. 1.从dispatch中获取配置,找到setting中的配置. 2.从thtoyyling中寻找到各个认证类. 3.所有认证类都继承自basethrottle,basethrott ...

随机推荐

  1. hdu 1007 Quoit Design(分治法求最近点对)

    大致题意:给N个点,求最近点对的距离 d :输出:r = d/2. // Time 2093 ms; Memory 1812 K #include<iostream> #include&l ...

  2. 转:Sublime Text 2 实用快捷键[Mac OS X]

    转: http://lucifr.com/2011/09/10/sublime-text-2-useful-shortcuts/ Sublime Text 2 实用快捷键[Mac OS X] luca ...

  3. token 案例,只是测试,功能并不完善(只是看看token 到底是何方神圣)

    token 简单理解就是 加密 解密的一个过程 JavaWebToken(加密解密工具) public class JavaWebToken { private static Logger log = ...

  4. Android内存泄漏分析实战

    内存泄漏简单介绍 java能够保证当没有引用指向对象的时候,对象会被垃圾回收器回收.与c语言自己申请的内存自己释放相比,java程序猿轻松了非常多.可是并不代表java程序猿不用操心内存泄漏.当jav ...

  5. 纯css实现单行”截取“

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. SuperMap iManager跨网段配置许可

    作者:非法小恋 1.开启Docker容器1947映射 修改docker-compose.yml,在iManager的ports添加- "1947:1947" 2.重启iManage ...

  7. 数据库字符集与排序规则(Character Set And Collation)

    数据库需要适应各种语言和字符就需要支持不同的字符集(Character Set),每种字符集也有各自的排序规则(Collation). (注意:Collation原意为校对,校勘,但是根据实际使用场景 ...

  8. [ASP.NET]使用uploadify上传图片,并在uploadify按钮上生成预览图

    目录 需求 主要代码 总结 需求 项目中有用到uploadify上传插件,给的原型就是上传成功后替换原来的图片.没办法需求在那儿,也不能修改需求吧,只能想办法解决问题了. 主要代码 修改uploadi ...

  9. [C/C++11语法]_[0基础]_[lamba 表达式介绍]

    场景 lambda 表达式在非常多语言里都有一席之地,由于它的原因,能够在函数里高速定义一个便携的函数,或者在函数參数里直接高速构造和传递. 它能够说是匿名函数对象,一般仅仅适用于某个函数内,仅仅做暂 ...

  10. mac 系统使用macaca inspector 获取iphone真机应用元素

    1.安装brew 软件包管理工具:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/inst ...