本文 以MSM8976平台为例,其他8K的平台都差不多类似。

MSM8976支持两个DDR3接口(EBI0,EBI1)。每个EBI提供两个CS片选(CS0,CS1)。

在SBL1的的代码实现中,一个EBI就是一个channel也就是一个INTERFACE。

EBI0对应 SDRAM_INTERFACE_0;

EBI1对应 SDRAM_INTERFACE_1;

下面我们看一下SBL1中对ddr初始化的具体实现:

入口函数是 sbl1_ddr_init:

void sbl1_ddr_init()
{ddr_info sbl1_ddr_info;/* Initialize DDR */boot_ddr_initialize_device(boot_clock_get_ddr_speed());--------------------(1)
}

(1)boot_clock_get_ddr_speed()获取ddr时钟,8976上是384MHZ

下面接着看ddr_initialize_device函数:

void ddr_initialize_device(uint32 clk_speed)
{struct ddr_device_params_common *ddr_param_interface_0, *ddr_param_interface_1;if(!ddr_init_done){    /* Pass the ddr parameters to HAL */ddr_init();  ---------------------------------------(1)          /* Update the ddr clock speed variable to the initialization clock */ddr_status.clk_speed = clk_speed;if(ddr_status.sdram0_cs0 != DDR_UNAVAILABLE) -----------------------(2)         {if(ddr_status.sdram0_cs1 != DDR_UNAVAILABLE) ----------------------(3){HAL_SDRAM_Init(SDRAM_INTERFACE_0, SDRAM_BOTH, clk_speed); ------------------(4)}else{HAL_SDRAM_Init(SDRAM_INTERFACE_0, SDRAM_CS0, clk_speed); ---------------------(5)}}if(ddr_status.sdram1_cs0 != DDR_UNAVAILABLE){if(ddr_status.sdram1_cs1 != DDR_UNAVAILABLE){HAL_SDRAM_Init(SDRAM_INTERFACE_1, SDRAM_BOTH, clk_speed);}else{HAL_SDRAM_Init(SDRAM_INTERFACE_1, SDRAM_CS0, clk_speed);}}/* Get DDR device parameters after detection during initialization */ddr_param_interface_0 = &(ddr_get_params(SDRAM_INTERFACE_0)->common);ddr_param_interface_1 = &(ddr_get_params(SDRAM_INTERFACE_1)->common);/* Update DDR status */ddr_status.sdram0_cs0 = (ddr_param_interface_0->num_rows_cs0 != 0) ?DDR_ACTIVE : DDR_UNAVAILABLE;ddr_status.sdram0_cs1 = (ddr_param_interface_0->num_rows_cs1 != 0) ?DDR_ACTIVE : DDR_UNAVAILABLE;ddr_status.sdram1_cs0 = (ddr_param_interface_1->num_rows_cs0 != 0) ?DDR_ACTIVE : DDR_UNAVAILABLE;ddr_status.sdram1_cs1 = (ddr_param_interface_1->num_rows_cs1 != 0) ?DDR_ACTIVE : DDR_UNAVAILABLE;/* Copy DDR device parameters to shared memory */ddr_params_set_shared_memory();ddr_init_done = TRUE;}/* Else, already initialized ddr, do nothing */
} /* ddr_initialize_device */

(1)ddr_init用已有的ddr参数初始化HAL层的一些数据结构,主要是ddr_status。

(2)(3)(4)(5)根据ddr_status状态判断SDRAM0的接口上的两个CS是否连了DDR,然后调用HAL_SDRAM_Init进行初始化。

后面几句是判断SDRAM1上是否连了DDR,并且相应的调用HAL_SDRAM_Init进行初始化。

ddr_init():

void ddr_init(void)
{struct ddr_device_params_common *ddr_param_interface_0, *ddr_param_interface_1;/* Initialize the ddr driver Mutex */DDR_SYNC_INIT();/* Get DDR parameters */ddr_param_interface_0 = &(ddr_get_params(SDRAM_INTERFACE_0)->common);ddr_param_interface_1 = &(ddr_get_params(SDRAM_INTERFACE_1)->common);/* First initialize all the ddr devices to be unavailable */ddr_status.sdram0_cs0 = DDR_UNAVAILABLE;ddr_status.sdram0_cs1 = DDR_UNAVAILABLE;ddr_status.sdram1_cs0 = DDR_UNAVAILABLE;ddr_status.sdram1_cs1 = DDR_UNAVAILABLE;/* based on ddr parameter selected, set the ddr status for active ddr */if(ddr_param_interface_0->num_rows_cs0 != 0){ddr_status.sdram0_cs0 = DDR_ACTIVE;}if(ddr_param_interface_0->num_rows_cs1 != 0){ddr_status.sdram0_cs1 = DDR_ACTIVE;}if(ddr_param_interface_1->num_rows_cs0 != 0){ddr_status.sdram1_cs0 = DDR_ACTIVE;}if(ddr_param_interface_1->num_rows_cs1 != 0){ddr_status.sdram1_cs1 = DDR_ACTIVE;}} /* ddr_init */

ddr_init()函数通过 ddr_get_params从IMEM中获取DDR参数,根据参数对ddr_status的两个SDRAM接口的CS进行设置。

我们下面来看

HAL_SDRAM_Init(SDRAM_INTERFACE interface, SDRAM_CHIPSELECT chip_select, uint32 clk_speed)函数:
这个函数完成DDR控制器,DDR 设备的初始化,DDR大小的检测等等基本的配置。
void HAL_SDRAM_Init(SDRAM_INTERFACE interface, SDRAM_CHIPSELECT chip_select, uint32 clk_speed)
{uint32 offset;struct ddr_device_params_common *ddr_params;/* Channel offset */offset = (interface == SDRAM_INTERFACE_0) ? SDRAM_0_OFFSET : SDRAM_1_OFFSET;/* Get DDR device parameters */ddr_params = &(ddr_get_params(interface)->common);ddr_set_config(offset, ddr_bimc_config_base, ddr_bimc_config_delta); --------------(1)/* Configure BIMC clock period */HAL_SDRAM_BIMC_Update_Clock_Period(clk_speed);/* Configure DPE timing */HAL_SDRAM_DPE_Update_AC_Parameters(interface, clk_speed);#ifndef BOOT_PRE_SILICON/* Initialize DDR PHY */HAL_SDRAM_PHY_Init(interface, clk_speed);
#endif/* Initialize DDR device */HAL_SDRAM_SHKE_Device_Init(interface, chip_select, clk_speed);#ifndef BOOT_PRE_SILICON/* Rank detection */chip_select = HAL_SDRAM_BIMC_Rank_Detection(interface); -----------------(2)/* Size detection */HAL_SDRAM_Ram_Size_Detection(interface); --------------------------------(3)/* Parameter detection */if (ddr_params_detection(interface)){/* Re-configure DPE timing */HAL_SDRAM_DPE_Update_AC_Parameters(interface, clk_speed);}
#endif/* Initialize BIMC DPE */HAL_SDRAM_DPE_Init(interface);/* Initialize BIMC SHKE */HAL_SDRAM_SHKE_Init(interface);/* Initialize BIMC SCMO */HAL_SDRAM_SCMO_Init(interface);}} /* HAL_SDRAM_Init */

只列出了主要的函数流程。

(1)ddr_set_config根据不同的平台对BMIC接口进行基本的配置。

(2)HAL_SDRAM_BIMC_Rank_Detection(interface)检测该interface上有几个rank,也就是说连了几个CS,返回值为SDRAM_CS0或者SDRAM_CS0|SDRAM_CS1即SDRAM_BOTH。

(3)HAL_SDRAM_Ram_Size_Detection(interface)计算该interface上连的DDR的容量,也就是计算有多少行,多少列,多少个bank,位宽是多少((num_rows_csx,num_cols_csx,num_banks_csx,interface_width)。有了这几个参数可以算出DDR的总的容量,对于DDR3来说,bank的数是8,因为有BA0-BA2。

大家可以注意一下高通平台上DDR的几个概念:CHANNEL(INTERFACE),RANK,BANK,ROW,COL,INTERFACE_WIDTH。弄清楚了这几个概念对高通平台的DDR初始化也就弄清楚了一大半,剩下的就是时序等硬件参数的初始化。

看到这里可能有些糊涂,因为我们都知道高通平台有一个CDT机制专门用来设置DDR参数的,为什么这里还需要重新检测设置,本文上面提到的获取IMEM中获取的DDR参数其实就是通过CDT机制得到的参数,因为在sbl1_ddr_init之前首先会调用boot_config_data_table_init函数,这个函数会会从CDT分区读取DDR相关参数,如果没有CDT分区则从编译生成的boot_cdt_array.c中提取DDR参数并保存中全局的bl_shared_data中,然后再用函数sbl1_ddr_set_params把DDR数据保存到SMEM中。

高通平台的DDR的autodetection机制并不是所有平台都有,老的平台并不支持。

高通平台DDR3初始化相关推荐

  1. 高通平台device tree生成platform device的过程(MSM8909)

    点击打开链接 在arch/arm/kernel/setup.c中,通过customize_machine函数中的machine_desc->init_machine();来调用高通平台的mach ...

  2. 高通android开源代码下载,高通平台Android源码bootloader分析之sbl1(三)

    前两篇博文分析了启动流程.代码流程.cdt,接下来就分析另外几个需要格外关注的部分. ##log系统 sbl1中的log系统也是sbl1部分调试会经常接触得部分高通平台在sbl中做的log系统并不是很 ...

  3. 高通平台sensor学习

    刚入行驱动时最先接触调试的外设模块便是sensor,一直都是零零散散的记录,这次终于下定决心对自己所学做一个系统的总结. sensor作为一款常用的外设,虽不起眼但是很多功能确实离不开它.比如我们手机 ...

  4. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

  5. 高通平台msm8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)

    本系列导航: 高通平台8953  Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...

  6. 高通平台android开发总结

    http://www.cnblogs.com/yuzaipiaofei/archive/2012/07/24/4124179.html 1.高通平台android开发总结 1.1 搭建高通平台环境开发 ...

  7. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  8. 高通平台android 环境配置编译及开发经验总结

    完全转自:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  9. 高通平台android开发总结 .

    http://blog.csdn.net/mirkerson/article/details/7691029 http://blog.csdn.net/mirkerson/article/detail ...

  10. 高通平台android 环境配置编译及开发经验总结【转】

    1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通开发板上烧录文件系统 建立高通平台开发环境 高通平台,android和 modem 编译流程分析 高通平台 7620 启动流 ...

最新文章

  1. 图解TCP/UDP原理!秒懂!
  2. 《麻省理工科技评论》发布2019年全球十大突破性技术!
  3. ios 接收 c# socket udp 组播
  4. C++内存管理学习堆和栈
  5. 一刻钟精通正则表达式
  6. 郑州军办计算机学校,郑州市国防科技学校2019级新生开启军训模式
  7. 【Makefile由浅入深完全学习记录7】Makefile中变量的高级主题下
  8. Mendix宣布推出低代码人工智能与机器学习功能
  9. 只包含因子 2 3 5 的数(51Nod-1010)
  10. wampserver的phpmyadmin(默认3306)端口如何更改为3307?
  11. varnish构建高速缓存
  12. spring boot——MockMvc的用法 (SpringBoot 1.5.18)下测试通过
  13. 本部裁员、分部招人,科技公司的岗位都奔向了外地?
  14. mysql的server_id怎么设置_MySQL Server-id踩到的坑
  15. SQL语法很难?其实只需要记住这部分行了
  16. MySQL 安装 [mysql-5.6.37]
  17. linux学习笔记【转】
  18. 汉王考勤 连接mysql_汉王考勤管理软件打开时出现:连接数据错误, 请确认数据库服务器信息是否有误.这样该怎样解决?, 大师请进来...
  19. linux系统压缩zip,linux系统压缩zip命令详解
  20. Regular DLL

热门文章

  1. 从一个app里面 跳转到另一个 app
  2. java上传视频并播放_javaweb中上传视频,并且播放,用上传视频信息为例
  3. Vmware 和宿主机之间的网络互通
  4. Docker容器实现跨宿主机通信
  5. 【181018】纯C 编写的太空大战打字游戏
  6. 游戏排行榜实现mysql_游戏中百万用户排行设计与实现
  7. Riverbed未来要往哪里去?收购Ocedo让你一目了然
  8. 文件无法删除 你需要计算机管理员 提供的权限才能对此文件进行更改解决办法
  9. Python动态网页爬取
  10. HDU 2246 神题?一千多行