由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. (剑指Offer)面试题55:字符流中第一个不重复的字符

    题目: 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出前 ...

  2. openstack horizon CSS 离线 改动

    Openstack horizon 的CSS主要保存在几个文件夹中,各自是horizon/static/dashboard/scss;horizon/openstack_dashboard/stati ...

  3. 反射方式,获取出集合ArrayList类的class文件对象

    /* * 定义集合类,泛型String * 要求向集合中添加Integer类型 * * 反射方式,获取出集合ArrayList类的class文件对象 * 通过class文件对象,调用add方法 * * ...

  4. function(window, undefined)的意义

    var num = 10000 for (var i = 0; i++; i < num) { eval("pp" + i + "=" + i); } ( ...

  5. 算法笔记_135:格子取数问题(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 有n*n个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右走,一共走两次(即从左上角往右下角走两趟),把所有经过的格子里的数加起 ...

  6. 18-spring学习-利用Annotation配置AOP

    之前是通过配置完成aop操作,如果自己写的话,太麻烦了,可以使用基于annotation的配置完成. 第一步:打开AOP的annotation支持 加上一句话: <context:annotat ...

  7. Linux平台Boost的编译方法

    本博客(http://blog.csdn.net/livelylittlefish)贴出作 者(三二一@小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Linux平台Boost的编译方法 Bo ...

  8. activeMQ Jms Demo

    概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经 ...

  9. 通讯录结构体方法的实现 和VS中存在的一些问题的分析

    实现一个通讯录: 通讯录能够用来存储1000个人的信息.每一个人的信息包含: 姓名.性别.年龄.电话.住址 功能例如以下: 1.  加入联系人信息 2.  删除指定联系人信息 3.  查找指定联系人信 ...

  10. LaTeX去掉默认显示日期时间

    LaTeX去掉默认显示日期时间: \date{}