DDR(六)DDR2初始化原始碼分析
1.u-boot關於DDR的原始碼分析在mem_setup.S中,一點一點來,先看第一段
/* DMC0 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP1_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP1_8DRV_SR_OFFSET]
首先在初始化DDR之前,引入一個關於DRAM Drive Strength的概念----DRAM Drive Strength(也被稱為:driving strength),表示“DRAM驅動強度”。這個引數用來控制記憶體資料匯流排的訊號強度,數值越高代表訊號強度越高,增加訊號強度可以提高超頻的穩定性。但是並非訊號強度高就一定好。
所以,這裡我們需要配置這個Drive Striegth,DDR2記憶體的所有線都需要配置,這裡我們從地址線開始看,我們的記憶體是掛載在Memory Port1(以下簡稱MP1)上,所以,先在S5PV210的晶片手冊搜尋Xm1ADDR。
在P63頁,找到MP1的各個pin腳的描述,繼續向下搜尋。
在P107頁,Pin腳複用的描述表裡找到他的GPIO口定義
Xm1ADDR[0]~[7]的GPIO的MP1_0[0]~7是複用的,OK,搜尋MP1_0。
在P122頁最終找到MP1_0DRV,在這個暫存器的描述中,顯示這個暫存器就是用來配置我們的記憶體的Drive Strength的暫存器,搜尋MP1_0DRV。
找到MP1_0DRV的暫存器的配置表,這裡給出的初始值是AAAA,我總共是0-7,8根線,每根線我配的值都是10,也就是2x,符合我們上面介紹DRAM Driver Strength的描述,OK,到這裡我們的MP1_0暫存器----Xm1ADDR[0]~[7]的Driver Strength配置完畢。剩下的就按照上面的方法,再把剩下的線全部配好,初始均按晶片手冊的參考值配為2x,也就是10。現在再回過頭來看上面的初始化程式碼,清楚多了,整個這麼一長串程式碼,其實只做了一件事,就是給MP1上接的記憶體的每一根線都配置Driver Strength的值為2x,這裡有一個地方,需要注意一下,最後一個MP1_8他的參考配置為0x2AAA。照樣的,再配置DM1,把Memory Port2也配置完畢,這裡我們沒有用到MP2,不配置,應該也沒有關係。繼續看下一段程式碼:
/* DMC0 initialization at single Type*/
ldr r0, =APB_DMC_0_BASE
ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
str r1, [r0, #DMC_PHYCONTROL1]
ldr r1, =0x00101002 @PhyControl0 DLL on
str r1, [r0, #DMC_PHYCONTROL0]
ldr r1, =0x00101003 @PhyControl0 DLL start
str r1, [r0, #DMC_PHYCONTROL0]
根據晶片手冊給出的參考步驟,第2步如下:
2.依照時鐘頻率正確配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc bit-fields的值。配置的PhyControl0.ctrl_dll_on值為'1'以開啟PHY DLL。
那開始配置PhyControl0的相關位,P614頁找到DRAM的暫存器配置表,找到有關PhyControl0的暫存器為PHYCONTROL0
OK,我們需要正確配置PhyControl0暫存器的ctrl_start_point和ctrl_inc這兩個位的值,OK,檢視暫存器的描述
ctrl_start_point和ctrl_inc這兩位晶片手冊上給的參考值為0x10,先配這兩位,則為:
ctrl_start_point: 0x10 ---- 10000(二進位制)
ctrl_inc: 0x10 ---- 10000(二進位制)
其餘的位全部配成0,最終為10000 00010000 00000000 ---- 0x00101000,程式碼如下:
ldr r0, =APB_DMC_0_BASE
ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000
str r1, [r0, #DMC_PHYCONTROL0]
第2步配置完成,接著往下看第3步--3.DQS Cleaning:依照時鐘頻率和記憶體的tAC引數正確設定PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetc bit-fields位的值。
檢視PhyControl1的ctrl_shiftc和ctrl_offsetc這兩位的描述
我們的記憶體是DDR2-800,所以ctrl_shiftc配置為0x6 ---- 110,ctrl_offsetc的配置暫時參考三星的裸板引數配置為0,ctrl_ref配置為1000,整理程式碼如下:
ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
str r1, [r0, #DMC_PHYCONTROL1]
按照第2步的要求,開啟PLL,將PhyControl0.ctrl_dll_on配置為1
ldr r1, =0x00101002 @PhyControl0 DLL on
str r1, [r0, #DMC_PHYCONTROL0]
繼續第4步--4.配置PhyControl0.ctrl_start位的值為'1'
ldr r1, =0x00101003 @PhyControl0 DLL start
str r1, [r0, #DMC_PHYCONTROL0]
後面的步驟,全部是按照三星的晶片手冊上的那28步來一步一步的在操作暫存器,沒有一步有漏掉,所以,對比著晶片手冊上的那28步一行一行的檢視程式碼就OK了。有一點,在配置完16-25步後,到第26步時--配置第26步--26.如果有兩組DDR晶片,重複14-25步配置chip1的記憶體,剛剛配置的是chip0,也就是第一組記憶體晶片。這裡就把第16-25步重新再做一次,初始化chip1就OK了。程式碼太多,這裡就不詳細重複了,我這裡參考的是三星的裸板的DDR原始碼。至此,DDR的原始碼也分析完成,下面,應該可以開始將這些移植進一個新的u-boot中去了。