先前使用3559开发板时,一直没觉得emmc会是个问题,但是最近一个国产化的项目中3559配合的是一款国产128G的emmc,因为板上面积限制,走线有点限制,导致uboot启动emmc有时候会失败。
1、报错的打印如下:
MMC read: dev # 0, block # 2048, count 18432 ... sdhci_transfer_data: Error detected in status(0x208000)!
=========== REGISTER DUMP (mmc0)===========
Sys addr: 0x00002544 | Version: 0x00000005
Blk size: 0x00007200 | Blk cnt: 0x00000000
Argument: 0x00000800 | Trn mode: 0x00000033
Present: 0x03f702f2 | Host ctl: 0x0000003c
Power: 0x0000000f | Blk gap: 0x00000000
Wake-up: 0x00000000 | Clock: 0x0000000f
Timeout: 0x0000000e | Int stat: 0x00208000
Int enab: 0x027f003b | Sig enab: 0x00000000
ACMD err: 0x00000000 | Slot int: 0x00000000
Caps: 0x3f6ec881 | Caps_1: 0x08000077
Cmd: 0x0000123a | Max curr: 0x00000000
Host ctl2: 0x00000087 | ADMA Err: 0x00000060
ADMA Ptr: 0x00000000_5fe6d588
===========================================
0 blocks read: ERROR
Load fip from 0x0000000042000000 ...
Firmware Image Package ToC:
---------------------------
- EL3 Runtime Firmware BL3-1: offset=0x88, size=0x7090
- Non-Trusted Firmware BL3-3: offset=0x7118, size=0x84E32A
---------------------------
Create Entry Point info ...
Get - EL3 Runtime Firmware BL3-1
Get - Non-Trusted Firmware BL3-3
kernel_size[0x84e32a] fdt_size[0x82ea] fdt_addr[0x00000000448c6000]
Invalid FDT at 0x0000000046000000, hdr at 0x000000004407ffc0
2、查看emmc的信息如下:
hisilicon # mmc info
Device: hisi-sdhci
Manufacturer ID: 88
OEM: 103
Name: 88A19
Tran Speed: 200000000
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 123731968000
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 115.2 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
hisilicon #
3、开发板上的emmc信息如下:
hisilicon # mmc info
Device: hisi-sdhci
Manufacturer ID: 11
OEM: 100
Name: 008G3
Tran Speed: 200000000
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 7818182656
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 4 MiB
User Capacity: 7.3 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
4、解决办法
查看emmc的信息看不出什么问题,因此我的第一反应就是去降低emmc的总线速率。因为先前在玩zynq和emmc是遇到过问题,降低emmc的时钟可以解决。zynq下降低速率最简单的办法就是在最小系统勾选时把emmc的时钟降低,编译就可以了。但是在海思的sdk中,我没有找到相应的配置方法,所以就只能去修改源码了!!!
5、uboot修改
分析代码的调用关系后,发现在uboot中drivers/mmc/mmc.c中函数static int mmc_startup(struct mmc *mmc)中屏蔽对hs400和hs200的代码,参考如下,则不会进入高速模式。
mmc_set_clock(mmc, mmc->tran_speed);
#if 0
if (mmc->card_caps & MMC_MODE_HS400ES) {
err = mmc_select_hs400es(mmc);
if (err)
return err;
mmc->ddr_mode = 1;
} else if (mmc->card_caps & MMC_MODE_HS200) {
err = mmc_select_hs200(mmc);
if (err)
return err;
}
#endif
6、设备树修改
设备树也要修改,linux-4.9.y_multi-core/arch/arm64/boot/dts/hisilicon/hi3559av100.dtsi中,屏蔽hs400的描述,参考如下:
mmc0: eMMC@0x100f0000 {
compatible = "hisi-sdhci";
reg = <0x100f0000 0x1000>, <0x10290000 0x1000>;
interrupts = <0 26 4>;
clocks = <&clock HI3559AV100_MMC0_CLK>;
clock-names = "mmc_clk";
resets = <&clock 0x1a8 27>, <&clock 0x1a8 29>, <&clock 0x1a8 30>;
reset-names = "crg_reset", "dll_reset", "sampl_reset";
max-frequency = <198000000>;
crg_regmap = <&clock>;
non-removable;
bus-width = <8>;
cap-mmc-highspeed;
/*
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
*/
cap-mmc-hw-reset;
devid = <0>;
status = "disabled";
};
7、测试确认
修改以后确实测试没有问题。
同时也测试了调速前后对emmc的访问速度,对比如下:
写测试命令:dd if=/dev/zero of=/mnt/1.dat bs=1M count=1k
读测试命令:dd of=/dev/null if=/mnt/1.dat bs=1M count=1k
未降速时,写速度在160MB左右,读速度在210MB左右;
降速后,写速度在45MB左右,读速度在40MB左右。