eMMC(Embedded Multi Media Card)
是MMC
协会订立的内嵌式存储器标准规格。
eMMC
在封装中集成了一个控制器,并提供标准接口管理闪存。
从开发者角度看,只要遵循eMMC
协议,既可以对eMMC
芯片进行读写操作。
下面介绍RK3568 eMMC
控制器驱动和调试方法。
一、eMMC驱动
1、eMMC控制器
RK3568 eMMC
主机控制器框图如下:
RK3568 eMMC
主机控制器特性如下:
1)、支持eMMC 5.1
协议
2)、支持自动tuning
3)、支持4/8-bit
接口
4)、支持 legacy、High Speed SDR、High Speed DDR、HS200/HS400
速度模式
5)、AHB
从接口:支持32bit
数据和地址宽度
6)、AXI
主接口:支持32bit
地址宽度和64bit
数据宽度
7)、时钟调整:支持transmit clock、sample clok和data strobe
相位自动调整
2、eMMC原理图
预调驱动,先看原理图。
RK3568
和eMMC
之间的连接方式见下图:
注:
1)eMMC D0~D8/CMD
电压需一致,为3.3V
或1.8V
2)Data Strobe
时钟信号由eMMC
发给RK3568
,频率与CLK
信号相同。用于RK3568
侧数据接收的同步。Data Strobe
信号只能在HS400
模式下配置启用,启用后可以提高数据传输的稳定性,省去总线 tuning
过程。
3、eMMC配置
RK3568 eMMC
配置文件:
1)arch/arm64/boot/dts/rockchip/rk3568.dtsi
sdhci: sdhci@fe310000 {
compatible = "rockchip,dwcmshc-sdhci", "snps,dwcmshc-sdhci";
reg = <0x0 0xfe310000 0x0 0x10000>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
assigned-clocks = <&cru BCLK_EMMC>, <&cru TCLK_EMMC>,
<&cru CCLK_EMMC>;
assigned-clock-rates = <200000000>, <24000000>, <200000000>;
clocks = <&cru CCLK_EMMC>, <&cru HCLK_EMMC>,
<&cru ACLK_EMMC>, <&cru BCLK_EMMC>,
<&cru TCLK_EMMC>;
clock-names = "core", "bus", "axi", "block", "timer";
status = "disabled";
};
2)arch/arm64/boot/dts/rockchip/rk3568-firefly-core.dtsi
&sdhci {
bus-width = <8>;
supports-emmc;
non-removable;
max-frequency = <200000000>;
status = "okay";
};
其中:
max-frequency
:eMMC
在该模式下支持的最大运行频率,单位HZ
。
**注:根据不同的模式进行调整该值,注意和数据传输速率(`Max Data Transfer rate,MB/s`)区别。**
supports-emmc
:表示为emmc
功能,必须添加。否则无法初始化eMMC
卡。
bus-width
:eMMC
使用8线模式。
non-removable
:表示该卡槽为不可移动设备,必须添加。
4、eMMC驱动
RK3568 eMMC
控制器使用Synopsys IP
。
RK3568
驱动文件:drivers/mmc/host/sdhci-of-dwcmshc.c
,主要关注:
static const struct sdhci_ops sdhci_dwcmshc_ops = {
.set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.reset = sdhci_reset,
.adma_write_desc = dwcmshc_adma_write_desc,
};
static const struct sdhci_ops sdhci_dwcmshc_rk_ops = {
.set_clock = dwcmshc_rk_set_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.reset = sdhci_reset,
.adma_write_desc = dwcmshc_adma_write_desc,
};
二、eMMC调试
1、U-Boot阶段
1.1、查看U-Boot
支持的mmc
命令
=> mmc
mmc - MMC sub system
Usage:
mmc info - display info of the current MMC device
mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
mmc rescan
mmc part - lists available partition on current mmc device
mmc dev [dev] [part] - show or set current mmc device [partition]
mmc list - lists available devices
...
1.2、显示mmc
设备信息
=> mmc info
Device: sdhci@fe310000
Manufacturer ID: 9b
OEM: 100
Name: Y2P03
Timing Interface: HS200 ## EMMC支持的速度模式
Tran Speed: 200000000 ## EMMC速度
Rd Block Len: 512 ## block大小512字节
MMC version 5.1
High Capacity: Yes
Capacity: 29.1 GiB ## EMMC容量
Bus Width: 8-bit ## EMMC总线宽度8bit
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 29.1 GiB
Boot Capacity: 4 MiB ENH
RPMB Capacity: 16 MiB ENH
1.3、查看mmc
设备列表
=> mmc list
dwmmc@fe2b0000: 1 ## SDCard
dwmmc@fe2c0000: 2 ## SDIO
sdhci@fe310000: 0 (eMMC) ## eMMC设备,当前设备
1.4、查看mmc
设备分区
当前是eMMC
设备,查看的eMMC
分区如下:
=> mmc part
Partition Map for MMC device 0 -- Partition Type: EFI
Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
1 0x00004000 0x00005fff "uboot"
attrs: 0x0000000000000000
type: 3e240000-0000-4719-8000-1de100003030
guid: cb6b0000-0000-4224-8000-356000002c8d
...
3 0x00008000 0x00027fff "boot"
attrs: 0x0000000000000000
type: 32410000-0000-487f-8000-685e0000531d
guid: a2570000-0000-4e68-8000-720100007df8
...
7 0x00098000 0x00497fff "rootfs"
attrs: 0x0000000000000000
type: be090000-0000-487c-8000-551300005560
guid: 614e0000-0000-4b53-8000-1d28000054a9
8 0x00498000 0x03a3dfde "userdata"
attrs: 0x0000000000000000
type: 323c0000-0000-4345-8000-065600004955
guid: 7d060000-0000-4411-8000-53ba000044af
1.5、eMMC
读/写和擦除命令
mmc read addr blk# cnt
mmc write addr blk# cnt
mmc erase blk# cnt
注:
addr
:内存地址,内存中保存的内容可以通过md
命令查看
blk#
:eMMC sector
地址,sector
大小一般为512,eMMC
的实际地址为512 * blk#
cnt
:eMMC sector
个数
注:配合eMMC
读/写和擦除命令,可以实现映像更新等调试功能。
2、内核阶段
在加载Linux
内核时,eMMC
驱动加载信息如下:
[ 1.187234] mmc0: new HS200 MMC card at address 0001
[ 1.188078] mmcblk0: mmc0:0001 Y2P032 29.1 GiB
[ 1.188559] mmcblk0boot0: mmc0:0001 Y2P032 partition 1 4.00 MiB
[ 1.189039] mmcblk0boot1: mmc0:0001 Y2P032 partition 2 4.00 MiB
[ 1.189273] mmcblk0rpmb: mmc0:0001 Y2P032 partition 3 16.0 MiB, chardev (240:0)
[ 1.192329] mmcblk0: p1 p2 p3 p4 p5 p6 p7 p8
2.1、查看eMMC
属性
[root@xiaotianbsp:/sys/kernel/debug/mmc0]# cat ios
clock: 198000000 Hz ## eMMC时钟频率
vdd: 18 (3.0 ~ 3.1 V)
bus mode: 2 (push-pull)
chip select: 0 (don't care)
power mode: 2 (on)
bus width: 3 (8 bits) ## eMMC数据位宽
timing spec: 9 (mmc HS200) ## eMMC速度模式
signal voltage: 1 (1.80 V) ## eMMC引脚电平
driver type: 0 (driver type B)
2.2、查看eMMC
分区名
[root@xiaotianbsp:/dev/block/by-name]# ls -l
total 0
lrwxrwxrwx 1 root root 15 Jan 1 19:32 backup -> ../../mmcblk0p5
lrwxrwxrwx 1 root root 15 Jan 1 19:32 boot -> ../../mmcblk0p3
lrwxrwxrwx 1 root root 15 Jan 1 19:32 misc -> ../../mmcblk0p2
lrwxrwxrwx 1 root root 15 Jan 1 19:32 oem -> ../../mmcblk0p6
lrwxrwxrwx 1 root root 15 Jan 1 19:32 recovery -> ../../mmcblk0p4
lrwxrwxrwx 1 root root 15 Jan 1 19:32 rootfs -> ../../mmcblk0p7
lrwxrwxrwx 1 root root 15 Jan 1 19:32 uboot -> ../../mmcblk0p1
lrwxrwxrwx 1 root root 15 Jan 1 19:32 userdata -> ../../mmcblk0p8
2.3、查看eMMC
分区
[root@xiaotianbsp:/]# cat /proc/partitions
major minor #blocks name
1 0 4096 ram0
179 0 30535680 mmcblk0
179 1 4096 mmcblk0p1
179 2 4096 mmcblk0p2
179 3 65536 mmcblk0p3
179 4 65536 mmcblk0p4
179 5 32768 mmcblk0p5
179 6 131072 mmcblk0p6
179 7 2097152 mmcblk0p7
179 8 28127215 mmcblk0p8
179 96 31166976 mmcblk1
179 97 31166968 mmcblk1p1
2.4、查看eMMC
已挂载分区
[root@xiaotianbsp:/]# mount
/dev/mmcblk0p7 on / type ext4 (rw,relatime)
...
/dev/mmcblk0p6 on /oem type ext2 (rw,relatime)
/dev/mmcblk0p8 on /userdata type ext4 (rw,relatime)
...
2.5、查看挂载的eMMC
分区大小
[root@xiaotianbsp:/]# df -h
Filesystem Size Used Avail Use% Mounted on
...
/dev/mmcblk0p6 126M 13M 107M 11% /oem
/dev/mmcblk0p8 27G 45M 27G 1% /userdata
2.6、按不同方式查看eMMC
分区
# 可以按照id/label等方式查看EMMC各分区
[root@xiaotianbsp:/dev/disk]# ls
by-id by-label by-partlabel by-partuuid by-path by-uuid
[root@xiaotianbsp:/dev/disk/by-id]# ls
mmc-SD32G_0x54c496d5 mmc-Y2P032_0x745a16bb-part4
mmc-SD32G_0x54c496d5-part1 mmc-Y2P032_0x745a16bb-part5
mmc-Y2P032_0x745a16bb mmc-Y2P032_0x745a16bb-part6
mmc-Y2P032_0x745a16bb-part1 mmc-Y2P032_0x745a16bb-part7
mmc-Y2P032_0x745a16bb-part2 mmc-Y2P032_0x745a16bb-part8
mmc-Y2P032_0x745a16bb-part3
[root@xiaotianbsp:/dev/disk/by-path]# ls
platform-fe2b0000.dwmmc platform-fe310000.sdhci-part3
platform-fe2b0000.dwmmc-part1 platform-fe310000.sdhci-part4
platform-fe310000.sdhci platform-fe310000.sdhci-part5
platform-fe310000.sdhci-boot0 platform-fe310000.sdhci-part6
platform-fe310000.sdhci-boot1 platform-fe310000.sdhci-part7
platform-fe310000.sdhci-part1 platform-fe310000.sdhci-part8
platform-fe310000.sdhci-part2
2.7、查看eMMC
时钟关系
1)逐级查找父时钟
# 1.sdmmc0_drv的父时钟是clk_sdmmc0
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_drv]# cat clk_phase
180
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_drv]# cat clk_rate
148500000
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_drv]# cat clk_parent
clk_sdmmc0
# 2.sdmmc0_sample的父时钟是clk_sdmmc0
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_sample]# cat clk_phase
264
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_sample]# cat clk_rate
148500000
[root@xiaotianbsp:/sys/kernel/debug/clk/sdmmc0_sample]# cat clk_parent
clk_sdmmc0
# 3.clk_sdmmc0的父时钟是gpll_300m
[root@xiaotianbsp:/sys/kernel/debug/clk/clk_sdmmc0]# cat clk_rate
297000000
[root@xiaotianbsp:/sys/kernel/debug/clk/clk_sdmmc0]# cat clk_parent
gpll_300m
# 4.gpll_300m的父时钟是gpll
[root@xiaotianbsp:/sys/kernel/debug/clk/gpll_300m]# cat clk_rate
297000000
[root@xiaotianbsp:/sys/kernel/debug/clk/gpll_300m]# cat clk_parent
gpll
# 5.gpll的父时钟是pll_gpll
[root@xiaotianbsp:/sys/kernel/debug/clk/gpll]# cat clk_rate
1188000000
[root@xiaotianbsp:/sys/kernel/debug/clk/gpll]# cat clk_parent
pll_gpll
# 5.pll_gpll的父时钟是xin24m
[root@xiaotianbsp:/sys/kernel/debug/clk/pll_gpll]# cat clk_parent
xin24m
[root@xiaotianbsp:/sys/kernel/debug/clk/pll_gpll]# cat clk_rate
1188000000
2)直接查找时钟树
[root@xiaotianbsp:/sys/kernel/debug/clk]# cat clk_summary
enable prepare protect duty
clock count count count rate accuracy phase cycle
---------------------------------------------------------------------------------------------
...
xin24m 22 24 0 24000000 0 0 50000
...
pll_gpll 1 1 0 1188000000 0 0 50000
gpll 6 14 0 1188000000 0 0 50000
...
gpll_300m 5 9 0 297000000 0 0 50000
clk_sdmmc0 1 1 0 297000000 0 0 50000
sdmmc0_sample 0 0 0 148500000 0 263 50000
sdmmc0_drv 0 0 0 148500000 0 180 50000
...
2.8、eMMC
读写测试
## eMMC读
echo 3 > /proc/sys/vm/drop_caches
time dd if=/dev/mmcblk0p8 of=/dev/null bs=1M count=300
## eMMC写,test是eMMC某个分区内的文件夹
time dd if=/dev/zero of=test bs=1M count=300 conv=fsync
注:转载请注明出处。