MTK DDR调试
1. 获取 flash id:
硬件信息:通过这个节点可以知道当前flash的id,上层根据id找到对应的flash名字。
cat /sys/block/mmcblk0/device/cid
\kernel-4.4\drivers\mmc\core\Mmc.c
MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1]
MT8163_MT8127
GDT42A32ED7_T2E 0x700100543532373332010585581e937d
MT8321 只支持如下方式兼容:
1. EMCP类: 只要emmc id不同,就可以兼容。
2. discrete lp2 类: dram vendor ID不同,就可以兼容(也就是说不同晶圆厂家兼容,具体对应的是datasheet中的MR5值,对应到code中MemoryDeviceList_xxxx.xlsx 表格的MODE_REG5 列)
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不能兼容