1. 獲取 flash id:數組
硬件信息:經過這個節點能夠知道當前flash的id,上層根據id找到對應的flash名字。spa
cat /sys/block/mmcblk0/device/cidcode
\kernel-4.4\drivers\mmc\core\Mmc.corm
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1]blog
MT8163_MT8127ip
GDT42A32ED7_T2E 0x700100543532373332010585581e937dci
MT8321 只支持以下方式兼容:get
1. EMCP類: 只要emmc id不一樣,就能夠兼容。flash
2. discrete lp2 類: dram vendor ID不一樣,就能夠兼容(也就是說不一樣晶圓廠家兼容,具體對應的是datasheet中的MR5值,對應到code中MemoryDeviceList_xxxx.xlsx 表格的MODE_REG5 列)it
3. discrete lp3 類: dram vendor ID不一樣,就能夠兼容(也就是說不一樣晶圓廠家兼容,具體對應的是datasheet中的MR5值,對應到code中MemoryDeviceList_xxxx.xlsx 表格的MODE_REG5 列)
4. PCDDR3類:不支持。
編譯腳本
判斷哪些ddr能夠兼容,編譯時會容許這個腳本
vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/emigen/MT8127/emigen.pl
1 if ($scan_idx eq $PartNum) # scan column 2 for Part Number 2 3 { 4 my $boardid ; 5 $boardid = &xls_cell_value($Sheet, $row, $COLUMN_BOARD_ID) ; 6 if ($CustBoard_ID eq $boardid) 7 { 8 $rows_part_found[$num_part_found] = $row; 9 10 print "\nPartNum($PartNum==$scan_idx) found in row $row\n" ; 11 $Total_PART_NUMBER[$TotalCustemChips] = $PartNum; 12 $num_part_found += 1 ; 13 $TotalCustemChips += 1; 14 } 15 }
1 if ($num_part_found == 0) 2 { 3 print "\n[Error]unsupported part number $PartNum\n" ; 4 die "\n[Error]unsupported part number $PartNum\n" ; 5 }
①:Board ID不匹配,不支持
[Error]unsupported part number H9TKNNN8KDMP
因此xls表格裏面配置的board id跟當前平臺不一致的話,會報不支持。
②:兼容不了LPDDR2和LPDDR3同時選配
TotalCustemChips:2
[Error] LPDDR2 and LPDDR3 are not allowed to be mixed in the Combo Discrete DRAM list.
③:兼容不了多個PCDDR3同時選配
[Error] At most one discrete PCDDR3 DRAM is allowed in the Combo MCP list
④:兼容不了LPDDR3和PCDDR3同時選配
[Error] At most one discrete PCDDR3 DRAM is allowed in the Combo MCP list
編譯事後會生成
out/target/product/hiteq8127_ce/obj/PRELOADER_OBJ/inc/custom_emi.h
此文件包含兼容的全部ddr時序,就是將xls表格裏的時序信息構建成數組。開機時會利用這個數組emi_settings[]找到指定的ddr。
1 EMI_SETTINGS emi_settings[] = 2 { 3 4 //K4E6E304EE_EGCF 5 { 6 0x0, /* sub_version */ 7 0x0003, /* TYPE */ 8 0, /* EMMC ID/FW ID checking length */ 9 0, /* FW length */ 10 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, /* NAND_EMMC_ID */ 11 {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, /* FW_ID */ 12 0x000250A2, /* EMI_CONA_VAL */ 13 0xAA00AA00, /* DRAMC_DRVCTL0_VAL */ 14 0xAA00AA00, /* DRAMC_DRVCTL1_VAL */ 15 0x66CB4619, /* DRAMC_ACTIM_VAL */ 16 0x01000000, /* DRAMC_GDDR3CTL1_VAL */ 17 0xF00487C3, /* DRAMC_CONF1_VAL */ 18 0xC00652D1, /* DRAMC_DDR2CTL_VAL */ 19 0xBF090401, /* DRAMC_TEST2_3_VAL */ 20 0x01806C60, /* DRAMC_CONF2_VAL */ 21 0xD1643542, /* DRAMC_PD_CTRL_VAL */ 22 0x00008888, /* DRAMC_PADCTL3_VAL */ 23 0x88888888, /* DRAMC_DQODLY_VAL */ 24 0x00000000, /* DRAMC_ADDR_OUTPUT_DLY */ 25 0x00000000, /* DRAMC_CLK_OUTPUT_DLY */ 26 0x11000D21, /* DRAMC_ACTIM1_VAL*/ 27 0x17800000, /* DRAMC_MISCTL0_VAL*/ 28 0x040004C1, /* DRAMC_ACTIM05T_VAL*/ 29 {0x40000000,0x40000000,0,0}, /* DRAM RANK SIZE */ 30 {0,0,0,0,0,0,0,0,0,0}, /* reserved 10 */ 31 0x00C30001, /* LPDDR3_MODE_REG1 */ 32 0x000A0002, /* LPDDR3_MODE_REG2 */ 33 0x00020003, /* LPDDR3_MODE_REG3 */ 34 0x00000001, /* LPDDR3_MODE_REG5 */ 35 0x00FF000A, /* LPDDR3_MODE_REG10 */ 36 0x0000003F, /* LPDDR3_MODE_REG63 */ 37 } , 38 };
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt8127/src/drivers/inc/emi.h
這個結構體在emi.h中定義
1 typedef struct 2 { 3 int sub_version; // sub_version: 0x1 for new version 4 int type; /* 0x0000 : Invalid 5 0x0001 : Discrete DDR1 6 0x0002 : Discrete LPDDR2 7 0x0003 : Discrete LPDDR3 8 0x0004 : Discrete PCDDR3 9 0x0101 : MCP(NAND+DDR1) 10 0x0102 : MCP(NAND+LPDDR2) 11 0x0103 : MCP(NAND+LPDDR3) 12 0x0104 : MCP(NAND+PCDDR3) 13 0x0201 : MCP(eMMC+DDR1) 14 0x0202 : MCP(eMMC+LPDDR2) 15 0x0203 : MCP(eMMC+LPDDR3) 16 0x0204 : MCP(eMMC+PCDDR3) 17 */ 18 int id_length; // EMMC and NAND ID checking length 19 int fw_id_length; // FW ID checking length 20 char ID[16]; 21 char fw_id[8]; // To save fw id 22 int EMI_CONA_VAL; //@0x3000 23 int DRAMC_DRVCTL0_VAL; //@0x40B8 -> customized TX I/O driving 24 int DRAMC_DRVCTL1_VAL; //@0x40BC -> customized TX I/O driving 25 int DRAMC_ACTIM_VAL; //@0x4000 26 int DRAMC_GDDR3CTL1_VAL; //@0x40F4 27 int DRAMC_CONF1_VAL; //@0x4004 28 int DRAMC_DDR2CTL_VAL; //@0x407C 29 int DRAMC_TEST2_3_VAL; //@0x4044 30 int DRAMC_CONF2_VAL; //@0x4008 31 int DRAMC_PD_CTRL_VAL; //@0x41DC 32 int DRAMC_PADCTL3_VAL; //@0x4014 -> customized TX DQS delay 33 int DRAMC_DQODLY_VAL; //@0x4200~0x420C -> customized TX DQ delay 34 int DRAMC_ADDR_OUTPUT_DLY; // for E1 DDR2 only 35 int DRAMC_CLK_OUTPUT_DLY; // for E1 DDR2 only 36 int DRAMC_ACTIM1_VAL; //@0x41E8 37 int DRAMC_MISCTL0_VAL; //@0x40FC 38 int DRAMC_ACTIM05T_VAL; //@0x41F8 39 int DRAM_RANK_SIZE[4]; 40 int reserved[10]; 41 42 union 43 { 44 struct 45 { 46 int LPDDR2_MODE_REG_1; 47 int LPDDR2_MODE_REG_2; 48 int LPDDR2_MODE_REG_3; 49 int LPDDR2_MODE_REG_5; 50 int LPDDR2_MODE_REG_10; 51 int LPDDR2_MODE_REG_63; 52 }; 53 struct 54 { 55 int DDR1_MODE_REG; 56 int DDR1_EXT_MODE_REG; 57 }; 58 struct 59 { 60 int PCDDR3_MODE_REG0; 61 int PCDDR3_MODE_REG1; 62 int PCDDR3_MODE_REG2; 63 int PCDDR3_MODE_REG3; 64 int PCDDR3_MODE_REG4; 65 int PCDDR3_MODE_REG5; 66 }; 67 struct 68 { 69 int LPDDR3_MODE_REG_1; 70 int LPDDR3_MODE_REG_2; 71 int LPDDR3_MODE_REG_3; 72 int LPDDR3_MODE_REG_5; 73 int LPDDR3_MODE_REG_10; 74 int LPDDR3_MODE_REG_63; 75 }; 76 }; 77 } EMI_SETTINGS;
三:開機檢測ddr
Discrete lp3 (LPDDR3類) 或Discrete lp2 (LPDDR2類)
vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt8163/src/drivers/emi.c
static int mt_get_mdl_number (void)
1 //try to find discrete dram by DDR2_MODE_REG5(vendor ID) 2 for (i = 0; i < num_of_emi_records; i++) 3 { 4 if (TYPE_LPDDR2 == dram_type) 5 mode_reg_5 = emi_settings[i].LPDDR2_MODE_REG_5; 6 else if (TYPE_LPDDR3 == dram_type) 7 mode_reg_5 = emi_settings[i].LPDDR3_MODE_REG_5; 8 printf("emi_settings[i].MODE_REG_5:%x,emi_settings[i].type:%x\n",mode_reg_5,emi_settings[i].type); 9 //only check discrete dram type 10 if (((emi_settings[i].type & 0x0F00) == 0x0000) || ((emi_settings[i].type & 0x0F00) == 0x0F00)) 11 { 12 //support for compol discrete dram 13 if ((mode_reg_5 == manu_id) ) 14 { 15 mdl_number = i; 16 found = 1; 17 break; 18 } 19 } 20 }
對應log:
[EMI]MR5:3 ----------->讀出來的值
emi_settings[i].MODE_REG_5:3,emi_settings[i].type:3
MODE_REG_5---------->時序表中MODE_REG5列配置的值
eMCP類
eMCP類的DDR是經過讀emmc_id來實現兼容的。
1 /* 1. 2 * if there is MCP dram in the list, we try to find emi setting by emmc ID 3 * */ 4 if (mcp_dram_num > 0) 5 { 6 result = platform_get_mcp_id (id, emmc_nand_id_len,&fw_id_len); 7 8 for (i = 0; i < num_of_emi_records; i++) 9 { 10 if (emi_settings[i].type != 0) 11 { 12 if ((emi_settings[i].type & 0x0F00) != 0x0000) 13 { 14 if (result == 0) 15 { /* valid ID */ 16 17 if ((emi_settings[i].type & 0x0F00) == 0x100) 18 { 19 /* NAND */ 20 if (memcmp(id, emi_settings[i].ID, emi_settings[i].id_length) == 0){ 21 memset(id + emi_settings[i].id_length, 0, sizeof(id) - emi_settings[i].id_length); 22 mdl_number = i; 23 found = 1; 24 break; /* found */ 25 } 26 } 27 else 28 { 29 30 /* eMMC */ 31 if (memcmp(id, emi_settings[i].ID, emi_settings[i].id_length) == 0) 32 { 33 #if 0 34 printf("fw id len:%d\n",emi_settings[i].fw_id_length); 35 if (emi_settings[i].fw_id_length > 0) 36 { 37 char fw_id[6]; 38 memset(fw_id, 0, sizeof(fw_id)); 39 memcpy(fw_id,id+emmc_nand_id_len,fw_id_len); 40 for (j = 0; j < fw_id_len;j ++){ 41 printf("0x%x, 0x%x ",fw_id[j],emi_settings[i].fw_id[j]); 42 } 43 if(memcmp(fw_id,emi_settings[i].fw_id,fw_id_len) == 0) 44 { 45 mdl_number = i; 46 found = 1; 47 break; /* found */ 48 } 49 else 50 { 51 printf("[EMI] fw id match failed\n"); 52 } 53 } 54 else 55 { 56 mdl_number = i; 57 found = 1; 58 break; /* found */ 59 } 60 #else 61 mdl_number = i; 62 found = 1; 63 break; /* found */ 64 #endif 65 } 66 else{ 67 printf("[EMI] index(%d) emmc id match failed\n",i); 68 } 69 70 } 71 } 72 } 73 } 74 } 75 }
因此:
能夠兼容的狀況:
1:兼容列表的ddr類型都是Discrete LPDDR2 (MODE_REG5不能有相同的)
2:兼容列表的ddr類型都是Discrete LPDDR3 (MODE_REG5不能有相同的)
不能兼容的狀況:
1:兼容列表中不能同時包含LPDDR2,LPDDR3或PCDDR3類型
2:多個PCDDR3類型的ddr不能兼容