MTK DDR调试
阅读原文时间:2023年07月12日阅读:2

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

if ($scan_idx eq $PartNum) # scan column for Part Number

     {  
         my $boardid ;  
         $boardid = &xls\_cell\_value($Sheet, $row, $COLUMN\_BOARD\_ID) ;  
         if ($CustBoard\_ID eq $boardid)  
         {  
             $rows\_part\_found\[$num\_part\_found\] = $row;

             print "\\nPartNum($PartNum==$scan\_idx) found in row $row\\n" ;  
             $Total\_PART\_NUMBER\[$TotalCustemChips\] = $PartNum;  
             $num\_part\_found +=  ;  
             $TotalCustemChips += ;  
         }  
     }

if ($num_part_found == )
{
print "\n[Error]unsupported part number $PartNum\n" ;
die "\n[Error]unsupported part number $PartNum\n" ;
}

①: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。

EMI_SETTINGS emi_settings[] =
{

 //K4E6E304EE\_EGCF  
 {  
     0x0,        /\* sub\_version \*/  
     0x0003,        /\* TYPE \*/  
     ,        /\* EMMC ID/FW ID checking length \*/  
     ,        /\* FW length \*/  
     {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},        /\* NAND\_EMMC\_ID \*/  
     {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0},        /\* FW\_ID \*/  
     0x000250A2,        /\* EMI\_CONA\_VAL \*/  
     0xAA00AA00,        /\* DRAMC\_DRVCTL0\_VAL \*/  
     0xAA00AA00,        /\* DRAMC\_DRVCTL1\_VAL \*/  
     0x66CB4619,        /\* DRAMC\_ACTIM\_VAL \*/  
     0x01000000,        /\* DRAMC\_GDDR3CTL1\_VAL \*/  
     0xF00487C3,        /\* DRAMC\_CONF1\_VAL \*/  
     0xC00652D1,        /\* DRAMC\_DDR2CTL\_VAL \*/  
     0xBF090401,        /\* DRAMC\_TEST2\_3\_VAL \*/  
     0x01806C60,        /\* DRAMC\_CONF2\_VAL \*/  
     0xD1643542,        /\* DRAMC\_PD\_CTRL\_VAL \*/  
     0x00008888,        /\* DRAMC\_PADCTL3\_VAL \*/  
     0x88888888,        /\* DRAMC\_DQODLY\_VAL \*/  
     0x00000000,        /\* DRAMC\_ADDR\_OUTPUT\_DLY \*/  
     0x00000000,        /\* DRAMC\_CLK\_OUTPUT\_DLY \*/  
     0x11000D21,        /\* DRAMC\_ACTIM1\_VAL\*/  
     0x17800000,        /\* DRAMC\_MISCTL0\_VAL\*/  
     0x040004C1,        /\* DRAMC\_ACTIM05T\_VAL\*/  
     {0x40000000,0x40000000,,},        /\* DRAM RANK SIZE \*/  
     {,,,,,,,,,},        /\* reserved 10 \*/  
     0x00C30001,        /\* LPDDR3\_MODE\_REG1 \*/  
     0x000A0002,        /\* LPDDR3\_MODE\_REG2 \*/  
     0x00020003,        /\* LPDDR3\_MODE\_REG3 \*/  
     0x00000001,        /\* LPDDR3\_MODE\_REG5 \*/  
     0x00FF000A,        /\* LPDDR3\_MODE\_REG10 \*/  
     0x0000003F,        /\* LPDDR3\_MODE\_REG63 \*/  
 } ,  

};

vendor/mediatek/proprietary/bootable/bootloader/preloader/platform/mt8127/src/drivers/inc/emi.h

这个结构体在emi.h中定义

typedef struct
{
int sub_version; // sub_version: 0x1 for new version
int type; /* 0x0000 : Invalid
0x0001 : Discrete DDR1
0x0002 : Discrete LPDDR2
0x0003 : Discrete LPDDR3
0x0004 : Discrete PCDDR3
0x0101 : MCP(NAND+DDR1)
0x0102 : MCP(NAND+LPDDR2)
0x0103 : MCP(NAND+LPDDR3)
0x0104 : MCP(NAND+PCDDR3)
0x0201 : MCP(eMMC+DDR1)
0x0202 : MCP(eMMC+LPDDR2)
0x0203 : MCP(eMMC+LPDDR3)
0x0204 : MCP(eMMC+PCDDR3)
*/
int id_length; // EMMC and NAND ID checking length
int fw_id_length; // FW ID checking length
char ID[];
char fw_id[]; // To save fw id
int EMI_CONA_VAL; //@0x3000
int DRAMC_DRVCTL0_VAL; //@0x40B8 -> customized TX I/O driving
int DRAMC_DRVCTL1_VAL; //@0x40BC -> customized TX I/O driving
int DRAMC_ACTIM_VAL; //@0x4000
int DRAMC_GDDR3CTL1_VAL; //@0x40F4
int DRAMC_CONF1_VAL; //@0x4004
int DRAMC_DDR2CTL_VAL; //@0x407C
int DRAMC_TEST2_3_VAL; //@0x4044
int DRAMC_CONF2_VAL; //@0x4008
int DRAMC_PD_CTRL_VAL; //@0x41DC
int DRAMC_PADCTL3_VAL; //@0x4014 -> customized TX DQS delay
int DRAMC_DQODLY_VAL; //@0x4200~0x420C -> customized TX DQ delay
int DRAMC_ADDR_OUTPUT_DLY; // for E1 DDR2 only
int DRAMC_CLK_OUTPUT_DLY; // for E1 DDR2 only
int DRAMC_ACTIM1_VAL; //@0x41E8
int DRAMC_MISCTL0_VAL; //@0x40FC
int DRAMC_ACTIM05T_VAL; //@0x41F8
int DRAM_RANK_SIZE[];
int reserved[];

 union  
 {  
     struct  
     {  
         int   LPDDR2\_MODE\_REG\_1;  
         int   LPDDR2\_MODE\_REG\_2;  
         int   LPDDR2\_MODE\_REG\_3;  
         int   LPDDR2\_MODE\_REG\_5;  
         int   LPDDR2\_MODE\_REG\_10;  
         int   LPDDR2\_MODE\_REG\_63;  
     };  
     struct  
     {  
         int   DDR1\_MODE\_REG;  
         int   DDR1\_EXT\_MODE\_REG;  
     };  
     struct  
     {  
         int   PCDDR3\_MODE\_REG0;  
         int   PCDDR3\_MODE\_REG1;  
         int   PCDDR3\_MODE\_REG2;  
         int   PCDDR3\_MODE\_REG3;  
         int   PCDDR3\_MODE\_REG4;  
         int   PCDDR3\_MODE\_REG5;  
     };  
     struct  
     {  
         int   LPDDR3\_MODE\_REG\_1;  
         int   LPDDR3\_MODE\_REG\_2;  
         int   LPDDR3\_MODE\_REG\_3;  
         int   LPDDR3\_MODE\_REG\_5;  
         int   LPDDR3\_MODE\_REG\_10;  
         int   LPDDR3\_MODE\_REG\_63;  
     };  
 };  

} 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)

//try to find discrete dram by DDR2_MODE_REG5(vendor ID)
for (i = ; i < num_of_emi_records; i++)
{
if (TYPE_LPDDR2 == dram_type)
mode_reg_5 = emi_settings[i].LPDDR2_MODE_REG_5;
else if (TYPE_LPDDR3 == dram_type)
mode_reg_5 = emi_settings[i].LPDDR3_MODE_REG_5;
printf("emi_settings[i].MODE_REG_5:%x,emi_settings[i].type:%x\n",mode_reg_5,emi_settings[i].type);
//only check discrete dram type
if (((emi_settings[i].type & 0x0F00) == 0x0000) || ((emi_settings[i].type & 0x0F00) == 0x0F00))
{
//support for compol discrete dram
if ((mode_reg_5 == manu_id) )
{
mdl_number = i;
found = ;
break;
}
}
}

对应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.
* if there is MCP dram in the list, we try to find emi setting by emmc ID
* */
if (mcp_dram_num > )
{
result = platform_get_mcp_id (id, emmc_nand_id_len,&fw_id_len);

         for (i = ; i < num\_of\_emi\_records; i++)  
         {  
             if (emi\_settings\[i\].type != )  
             {  
                 if ((emi\_settings\[i\].type & 0x0F00) != 0x0000)  
                 {  
                     if (result == )  
                     {   /\* valid ID \*/

                         if ((emi\_settings\[i\].type & 0x0F00) == 0x100)  
                         {  
                             /\* NAND \*/  
                             if (memcmp(id, emi\_settings\[i\].ID, emi\_settings\[i\].id\_length) == ){  
                                 memset(id + emi\_settings\[i\].id\_length, , sizeof(id) - emi\_settings\[i\].id\_length);  
                                 mdl\_number = i;  
                                 found = ;  
                                 break; /\* found \*/  
                             }  
                         }  
                         else  
                         {

                             /\* eMMC \*/  
                             if (memcmp(id, emi\_settings\[i\].ID, emi\_settings\[i\].id\_length) == )  
                             {  

#if 0
printf("fw id len:%d\n",emi_settings[i].fw_id_length);
if (emi_settings[i].fw_id_length > )
{
char fw_id[];
memset(fw_id, , sizeof(fw_id));
memcpy(fw_id,id+emmc_nand_id_len,fw_id_len);
for (j = ; j < fw_id_len;j ++){
printf("0x%x, 0x%x ",fw_id[j],emi_settings[i].fw_id[j]);
}
if(memcmp(fw_id,emi_settings[i].fw_id,fw_id_len) == )
{
mdl_number = i;
found = ;
break; /* found */
}
else
{
printf("[EMI] fw id match failed\n");
}
}
else
{
mdl_number = i;
found = ;
break; /* found */
}
#else
mdl_number = i;
found = ;
break; /* found */
#endif
}
else{
printf("[EMI] index(%d) emmc id match failed\n",i);
}

                         }  
                     }  
                 }  
             }  
         }  
 }

所以:

可以兼容的情况:

1:兼容列表的ddr类型都是Discrete LPDDR2  (MODE_REG5不能有相同的)

2:兼容列表的ddr类型都是Discrete LPDDR3 (MODE_REG5不能有相同的)

不能兼容的情况:

1:兼容列表中不能同时包含LPDDR2,LPDDR3或PCDDR3类型

2:多个PCDDR3类型的ddr不能兼容