高通平台DDR3初始化
2016-08-01 23:06
525 查看
本文 以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:
(1)boot_clock_get_ddr_speed()获取ddr时钟,8976上是384MHZ
下面接着看ddr_initialize_device函数:
(2)(3)(4)(5)根据ddr_status状态判断SDRAM0的接口上的两个CS是否连了DDR,然后调用HAL_SDRAM_Init进行初始化。
后面几句是判断SDRAM1上是否连了DDR,并且相应的调用HAL_SDRAM_Init进行初始化。
ddr_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机制并不是所有平台都有,老的平台并不支持。
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机制并不是所有平台都有,老的平台并不支持。
相关文章推荐
- linux-3.2.36内核启动2-setup_arch中的内存初始化1(arm平台 分析高端内存和初始化memblock)【转】
- atheros wifi芯片ics高通平台 wifi睡眠策略分析
- 普元平台初始化数据库
- 高通,mtk,展讯平台的定制集成
- MTK平台上开辟自己的NVRAM段并初始化 http://koudai.360.cn/u/20626231/article_203761437.html?categoryID=200320512&cp=1
- 请把Camera hold住 - Android高通平台调试Camera驱动全纪录
- 【转】Android上HDMI介绍(基于高通平台)
- 高通平台lk是怎样匹配加载DTB的
- 高通平台短信里面含有中文和ftp开头的网址不能解析
- 高通平台如何使用QPST抓DUMP
- 高通平台 开机logo 替换
- Android高通平台处理器间通讯驱动
- 高通平台中简单了解DTB
- 高通平台串口调试 AP与模块串口通讯调试总结
- 高通平台开机logo连续显示调试总结
- androidN_高通平台—计时器结束无铃声问题修改
- 高通平台wifi命令操作
- 高通平台LCD之MDP code解析
- 高通平台上的AMSS(Modeom端)Windows环境搭建
- 高通平台串口调试 AP与模块串口通讯调试总结