【轉】PowerPC DPAA平臺啟動方式
在Freescale DPAA QorIQ平臺上的啟動和non-DPAA QorIQ平臺的啟動有一些區別:
1.non-DPAA QorIQ平臺在上電時通過取樣配置管腳來決定對CPU的配置(P2020 ( e500核 ) 上電啟動及uboot流程|http://bbs.ednchina.com/BLOG_ARTICLE_1988662.HTM),而DPAA QorIQ平臺採用RCW (Reset ConfigurationWord)來決定對CPU的各種配置。
2. 在從SD Card/SPI flash啟動的時候,non-DPAA平臺是通過on-Chip ROM邏輯將U-Boot image拷貝到L2 SRAM中啟動,而從NAND flash啟動時,是將4K的啟動程式碼拷貝到eLBC FCM的RAM buffer中,該段程式碼負責將U-Boot image搬移到L2 SRAM中啟動;DPAA平臺是通過PBL(Pre-Boot Loader)邏輯將U-Boot image搬移的CPC SRAM中啟動。
大體啟動流程是這樣的:上電PBL會取樣cfg_rcw_src管腳來判斷RCW存放在那種儲存介質中,然後從相應的儲存裝置讀取RCW對CPU進行配置。如果是從NOR flash啟動,則不需要執行PBI command和拷貝U-Boot image到alternate配置空間,直接跳轉到0xFFFFFFFC處執行。如果不是從NOR flash啟動,在配置完畢CPU後會讀取PBI command完成部分初始化工作,然後根據PBI command中對alternate配置空間地址的配置將U-Boot image拷貝到alternate配置空間中開始執行。
1. RCW
RCW是存放在外部儲存裝置中的512bit的配置資訊,用來對CPU進行配置。和non-DPAA平臺中的配置管腳完成的功能是一樣的。當然RCW是存放在哪裡的?這個還是通過配置管腳來完成的。
在上電的時候,PBL首先會取樣cfg_rcw_src管腳來判斷RCW存放在那種儲存介質中,然後從相應的儲存介質讀取RCW來對CPU進行配置。那麼PBL是從哪裡開始讀取呢?下表列出了對不同介質PBL開始讀取的地址:
Interface
Starting Address
eLBC
0x00000000
I2C
0x00000000
eSPI
0x00000000
eSDHC
0x00001000
其中比較特殊的是Hard-coded RCW options. 如果選擇RCW為Hard-coded,那麼PBL不會去外部儲存裝置去讀取RCW而是使用預先定義好的RCW配置來對CPU進行配置。有以下兩個好處:
1. 如果儲存裝置介面有問題從而沒法儲存RCW,可以選擇使用Hard-coded啟動。
2. 如果使用者自己設定的RCW有問題導致系統沒法啟動,可以使用hard-coded RCW來啟動,啟動完成後可以恢復使用者自己設定的RCW。
RCW主要完成對CPU一些資源的配置,比如Core的頻率,serdes lane的使用,管腳複用的配置等等。對啟動來說應該關注以下幾個bit位的配置:
1. 選擇PBI資料來源的存放處,關於PBI的含義可以參考下面的PBL部分
2.Boot location的選擇
3. 從PCIe啟動時配置哪個PCIe controller為Agent模式
4.Secure boot模式
2. PBL
PBL(Pre-Boot Loader)用來輔助從I2C,SD,NAND flash,SPI flash啟動的一個硬體單元。主要功能是在上電之初首先配置以上介面的暫存器來對介面初始化,根據cfg_rcw_src管腳的配置從相應的介面讀取RCW和PBI命令,然後根據RCW來配置CPU,並執行PBI命令完成初始化操作,最後釋放CPU core跳轉到0xFFFFFFFC處執行第一條指令。
在釋放CPU core後,CPU core去哪兒執行第一條指令?這個是很關鍵的一點,會影響到U-Boot image的TEXT_BASE的設定,而且在non-DPAA平臺和DPAA平臺上的實現是不同的。在non-DPAA平臺上,若是從SD/SPI flash啟動,on-chip ROM將U-Boot image拷貝到L2 SRAM後,會跳轉到下面的控制字指定的地址去執行,我們知道CPU執行的第一條指令是存放到512K U-Boot image最後4個位元組的一條跳轉指令(bl start_e500),所以跳轉指令的地址(下面的”Execution Starting Address”)應該指向U-Boot的TEXT_BASE的最後4個位元組的地址。
如果是從NAND flash啟動,on-chip ROM會將4K的啟動程式碼拷貝到eLBC內部的RAM buffer,並將CPU釋放到0xFFFFFFFC出執行指令,所以從NAND啟動時的4K啟動到程式碼的TEXT_BASE是0xfffff000。
而在DPAA平臺上CPU core,只要不是從NOR flash啟動,PBL都會從相應的啟動裝置中拷貝RCW,執行PBI command,拷貝U-Boot image到CPC SRAM中(當然這個是PBI command指定的,下面會有詳細的介紹),並將CPU core釋放到到0xFFFFFFFC處執行第一條指令。
和non-DPAA平臺的on-chip
ROM一樣,PBL也只能識別固定的資料格式,所以我們需要將RCW,PBI
command(可選)封裝為PBL能夠識別的格式。Freescale提供了一套工具QCS來完成封裝的工作。
2.1 RCW的封裝
如果只是從NOR flash啟動,我們只需要RCW即可,下面是RCW的封裝格式:
SYS_ADDR地址是將n位元組的資料寫入的地址。SYS_ADDR是指向CCSRBAR空間或者alternate配置空間(ACS值決定)的地址。CCSRBAR空間比較好理解,那麼alternate配置空間指的是哪裡?該空間的高8位地址是多少?是由暫存器ALTCBARH/ALTCBARL/ALTCAR來決定的。
對於RCW DATA的SYS_ADDR來說就是CCSRBAR空間的device control and pincontrol block中的RCW狀態暫存器(RCWSR[1-16]=64B),即:
fe_000000+ 0x0E_0000 + 0x100
2.2 RCW+PBI的封裝
如果需要PBI command,比如配置CPC cache為SRAM,建立相應的LAW,配置alternate配置空間或者將U-Boot image拷貝到CPC SRAM等,都是通過
PBI command的設定完成的。
3. Boot from SD/NAND flash/SPI flash
3.1 程式碼解析
首先PBI command會做下面的初始化工作:
1. Invalidateand flush CPC cache
2. 將CPC SRAM配置為SRAM,地址為0xfff00000
3. 給CPC SRAM配置一個LAW entry(LAW16)
4. 配置alternate 配置空間,用來指示PBL將U-Boot image拷貝到CPC SRAM的0xfff80000開始的512K
5. 重新配置SPI controller的暫存器提高傳輸速率。PBL本身會配置各個介面的暫存器的,但SPI介面配置的速率比較低,傳輸U-Boot image花費的時間比較長,所有重新配置從而提高傳輸速率
下面是P4080DS的PBI command,從下面的command可以看出,CPC cache配置為SRAM,地址為0xfff0000,大小為1M,PBL將U-Boot iamge拷貝到0xfff80000開始
的地方。
下面是U-Boot image封裝為PBI data的結構。
0x81f8000000的解析:
0x81 = 1000 0001 => ACS=1,CNT=1
F80000 => 指定alternate配置空間的低24位
然後在boards.cfg檔案中新增對Boot from NAND的支援,並設定CONFIG_SYS_TEXT_BASE 為0xfff80000
-
"boards.cfg"
-
P5020DS_NAND powerpc mpc85xx corenet_ds freescale - P5020DS:RAMBOOT_PBL,NAND,SYS_TEXT_BASE=0xFFF80000
-
"include/configs/corenet_ds.h"
-
#ifdef CONFIG_RAMBOOT_PBL
-
#define CONFIG_RAMBOOT_TEXT_BASE CONFIG_SYS_TEXT_BASE
-
#define CONFIG_RESET_VECTOR_ADDRESS 0xfffffffc
-
#endif
-
#define CONFIG_SYS_INIT_L3_ADDR 0xfff80000
-
#define CONFIG_SYS_INIT_L3_ADDR_PHYS CONFIG_SYS_INIT_L3_ADDR
-
#define CONFIG_SYS_L3_SIZE (1024 << 10)
-
#define CONFIG_SYS_INIT_L3_END (CONFIG_SYS_INIT_L3_ADDR + CONFIG_SYS_L3_SIZE)
配置CPC SRAM需要的TLB表項
-
"board/freescale/common/p_corenet/tlb.c"
-
struct fsl_e_tlb_entry tlb_table[] = {
-
#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L3_ADDR)
-
SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L3_ADDR, CONFIG_SYS_INIT_L3_ADDR,
-
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-
0, 0, BOOKE_PAGESZ_1M, 1),
-
#else
-
SET_TLB_ENTRY(1, 0xfffff000, 0xfffff000,
-
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
-
0, 0, BOOKE_PAGESZ_4K, 1),
-
#endif
-
<p>會對齊到1M,即0xfff80000 -> 0xfff00000,目的是在跳轉到AS0時, 還有TLB entry覆蓋對L3 SRAM,因為此時程式碼是在L3中存放的,還沒有relocate到DDR。</p><p></p><p>init_tlbs會執行上面的TLB entry</p><p>_start-> cpu_init_early_f –> init_tlbs run in AS=1</p>
在invalidate CPC cache的時候,判斷是否作為SRAM,若為SRAM則不invalidate, 因為程式碼還是在L3 SRAM中,若此時invalidateCPC SRAM,則執行的U-Boot程式碼也會被清掉。
-
"arch/powerpc/cpu/mpc85xx/cpu_init.c"
-
_start_cont -> cpu_init_f -> invalidate_cpc
-
void invalidate_cpc(void)
-
{
-
int i;
-
cpc_corenet_t *cpc = (cpc_corenet_t *)CONFIG_SYS_FSL_CPC_ADDR;
-
for (i = 0; i < CONFIG_SYS_NUM_CPC; i++, cpc++) {
-
if (in_be32(&cpc->cpcsrcr0) & CPC_SRCR0_SRAMEN)
-
continue;
-
out_be32(&cpc->cpccsr0, CPC_CSR0_FI | CPC_CSR0_LFC);
-
while (in_be32(&cpc->cpccsr0) & (CPC_CSR0_FI | CPC_CSR0_LFC))
-
;
-
}
-
}
在使能CPC cache時,disable PBI command為CPC SRAM配置的LAW16
-
"arch/powerpc/cpu/mpc85xx/cpu_init.c"
-
Relocate to RAM -> board_init_r -> cpu_init_r -> enable_cpc
-
static void enable_cpc(void)
-
{
-
cpc_corenet_t *cpc = (cpc_corenet_t *)CONFIG_SYS_FSL_CPC_ADDR;
-
for (i = 0; i < CONFIG_SYS_NUM_CPC; i++, cpc++) {
-
u32 cpccfg0 = in_be32(&cpc->cpccfg0);
-
size += CPC_CFG0_SZ_K(cpccfg0);
-
#ifdef CONFIG_RAMBOOT_PBL
-
if (in_be32(&cpc->cpcsrcr0) & CPC_SRCR0_SRAMEN) {
-
struct law_entry law = find_law(CONFIG_SYS_INIT_L3_ADDR);
-
if (law.index == -1) {
-
printf("\nFatal error happened\n");
-
return;
-
}
-
disable_law(law.index);
-
clrbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_CDQ_SPEC_DIS);
-
out_be32(&cpc->cpccsr0, 0);
-
out_be32(&cpc->cpcsrcr0, 0);
-
}
-
#endif
-
out_be32(&cpc->cpccsr0, CPC_CSR0_CE | CPC_CSR0_PE);
-
in_be32(&cpc->cpccsr0);
-
}
-
}
3.2 啟動image的製作
Freescale的SDK release中用相應的步驟,請參見下面的連結,這裡不贅述。
4. Open source上的patch