SDMMC使用参考
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.0 | 06/27/2023 | |
2.0 | 12/13/2023 |
1. 概述¶
Kernel下MMC采用标准的Linux框架,能够使用标准接口驱动MMC Device(eMMC card,SD card或SDIO device)。
MMC子系统由card层,core层和host层构成。Card层将整个MMC Device注册成MMC Block Device,可支持上层的数据请求工作;Core层实现MMC/SD/SDIO协议中初始化流程和读写等工作。Host层可以调动硬件,把core层传下来的cmd或data request通过FCIE/SDIO Engine与eMMC/SD/SDIO card进行数据通信。
SD host层的整体框架共有三层,分别是MDrv层,Hal层和Support层,以及接在Support层上的MMC设备,各个层次的作用如下:
Mdrv层:
Mdrv层主要完成host的注册,完善mmc_host和mmc_host_ops结构体的描述,向core层增加Host的信息,还会额外提供一些封装接口来给用户层设置或获得Engine和卡的状态,比如:debug_get_sdmmc_clock,set_sdmmc_driving_control等。此外,Mdrv层还会完成MIE和热插拔中断注册,以保证后续信号的正常传输和卡的拔插检测。
Hal层:
Hal层直接设置寄存器,与HW Engine密切相关,主要包括操作Host Engine的hal_sdmmc_v5.c文件,命令和数据的发送接收就是在这个文件里实现。决定Host Engine接哪组pad pin,并对其上下拉等操作的是hal_sdmmc_platform_common.c文件。中断处理相关的是hal_sdmmc_intr.c文件,还有时间处理相关的hal_sdmmc_timer.c文件等。
Support层:
该层属于硬件支持层,驱动相关的最终实现都需要硬件的支持。
MMC device:
MMC设备,比如SD/SDIO卡,直接接在驱动的硬件支持上,是驱动的最终操作对象。
2. 关键字说明¶
IP:连接SD/SDIO卡的Host Engine
IP bank:驱动访问SD/SDIO卡所使用的Host Engine的寄存器地址
SDSC:标准容量卡,不超过2GB的卡
SDHC:高容量卡,大于2GB又不超过32GB的卡
SDXC:扩展容量卡,大于32GB的卡
3. 功能描述¶
封装 | SD卡 | 总线带宽 | 时钟范围 | SD3.0支持的速率模式 | SD2.0支持的速率模式 | IP bank | 产品 |
---|---|---|---|---|---|---|---|
BGA | SD0 Card | 1,4 | 300k-200M | SDR50,SDR104,DDR50 | Default Speed,High Speed | 0x1413 | souffle |
BGA | SD1 Card | 1,4 | 300k-100M | SDR50 | Default Speed,High Speed | 0x1416 | souffle |
QFN | SD0 Card | 1,4 | 300k-200M | SDR50,SDR104,DDR50 | Default Speed,High Speed | 0x1413 | souffle |
BGA | SD0 Card | 1,4 | 300k-48M | - | Default Speed,High Speed | 0x1413(non-pm) | iford |
BGA | WIFI Card | 1,4 | 300k-48M | - | Default Speed,High Speed | 0x42(pm) | iford |
注:souffle BGA封装的板子拥有2个SD卡插槽,其中SD0支持最高200M速率,SD1最高只支持100M速率,而QFN封装只有1个SD卡插槽,最高支持200M速率。
总线带宽设置:
SD支持配置1 -1bit mode/4 – 4bit mode 两种总线带宽,默认使用4bit mode。SDIO卡需要设置带宽为1 bit mode可以设置设备树中的sdio-use-1bit参数。
时钟设置:
souffle: SD0 Card支持配置300KHz-200MHz范围内的时钟频率,SD1 Card支持配置300KHz-100MHz范围内的时钟频率,可以通过修改设备树中的max-frequency参数来设置最大时钟大小,最终设置的clock频率是当前bus speed支持的最大频率。
iford: SD0 Card/WIFI Card支持配置300KHz-48MHz范围内的时钟频率,可以通过修改设备树中的max-frequency参数来设置最大时钟大小,最终设置的clock频率是当前bus speed支持的最大频率。
配置不同的总线带宽及时钟频率会影响数据传输速率,SD3.0支持使用SDR50,SDR104和DDR50速率模式,若要使用可以在设备树中对应槽位配置sd-uhs-sdr50/sd-uhs-sdr104/sd-uhs-ddr50。
速率模式:
(1)查看SD卡速率模式
cat /sys/kernel/debug/mmc1/ios
(2)设置SD卡速率模式
SD卡速率模式在souffle及之后产品均可直接在dtsi文件配置
4. 硬件连接介绍¶
4.1. souffle¶
4.2. iford¶
5. Uboot用法介绍¶
5.1. uboot config配置¶
1. make menuconfig 2. # SigmaStar drivers --> 3. # <*> SigmaStar mmc host
boot下SDMMC驱动所在目录为drivers/sstar/mmc_host/,编译需要开启SSTAR_MMC_HOST编译选项,打开方式如上。
5.2. Dts参数配置说明¶
可以通过配置dtsi中sstar_mmc0项设定host层driver的基本参数。dtsi的参数展示如下:
sstar_mmc0: sstar_mmc0 { compatible = "sstar-mmc"; bus-width = <4>; max-frequency = <48000000>; cap-mmc-highspeed = <1>; ip-order = <0>; pad-orders = <0>; pwr-on-delay = <10>; pwr-off-delay = <50>; fack-cdz = <0>; rev-cdz = <0>; pwr-pad = <PAD_SD0_GPIO0>; cdz-pad = <PAD_SD0_CDZ>; clk-driving = <1>; //0~7 cmd-driving = <1>; //0~7 data-driving = <1>; //0~7 en-clk-phase = <0>; //0/1 rx-clk-phase = <0>; //0-3 tx-clk-phase = <0>; //0-3 status = "okay"; };
释义如下:
参数 | 释义 | 备注 |
---|---|---|
bus-width | 配置卡槽的buswidth | 4 – 4bit mode |
max-frequency | 配置对应卡槽支持的最大时钟频率 | |
ip-order | 配置对应卡槽的IP编号 | |
pad-order | 指定卡接哪组pad | |
pwr-on-delay | 配置每个卡槽的power-on delay时间,以ms为单位 | SDIO设备一般需要配置delay时间以便SDIO设备加载固件及状态ready,具体时间以SDIO设备厂家的建议为准 |
pwr-off-delay | 配置每个卡槽的power-off delay时间,以ms为单位 | |
fake-cdz | 配置是否忽视Card detect,置1表示默认认为该槽有卡接入 | 针对固定在板上的设备,如部分SDIO设备,建议将卡槽对应项配置为1 |
rev-cdz | 该参数可配置是否颠倒当前Board的Card detect条件 | |
pwr-pad | 配置对应卡槽的Power pin脚 | |
cdz-pad | 配置对应卡槽的CDZ pin脚 | |
clk-driving | 配置对应卡槽的clock pad pin的driving能力 | 档位:0-7,(iford: 0-3) |
cmd-driving | 配置对应卡槽的command pad pin的driving能力 | 档位:0-7,(iford: 0-3) |
data-driving | 配置对应卡槽的data[3:0] pad pin的driving能力 | 档位:0-7,(iford: 0-3) |
en-clk_phase | 配置对应卡槽是否使能 clock phase tuning | |
rx-clk_phase | 配置对应卡槽的clock tx相位,需en-clk_phase置1此参数才有效 | 档位:0-3 |
tx-clk_phase | 配置对应卡槽的clock rx相位,需en-clk_phase置1此参数才有效 | 档位:0-3 |
5.3. Uboot cmd参数说明¶
(1) fatls
格式:
fatls <interface> [<dev[:part]>] [directory]
说明:读取某接口下第n个设备的第n个分区中的某目录下的所有文件内容。
interface:SD卡和eMMC卡都属于MMC设备
dev: 设备编号,根据ip编号,缺省为0
part:与mmc part
命令下的分区号对应。
directory:目录,使用绝对路径。
示例:打印出SD第一个分区内,根目录的内容
fatls mmc 0:1 /
(2) fatload
格式:
fatload <interface> <dev<:part>> <addr> <filename> <bytes <pos>>
说明:从某接口下第n个设备的第n个分区中的某个文件读取特定大小数据到指定地址的ddr中。
addr:目标内存地址,ddr地址,使用真实物理地址。
filename:需要load的文件名,使用绝对路径文件名。
bytes:load的数据大小,以byte为单位,16进制数,若为0则读取整份文件。
pos:目标文件中的偏移量。如目标文件数据"123456", 若pos为1,则load文件时从‘1’位置开始读取。
示例:将SD第一个分区内根目录下的demo.sh文件读取512个byte到ddr的0x21000000处
fatload mmc 0:1 0x21000000 /demo.sh 0x200
(3) fatwrite
格式:
fatwrite <interface> <dev<:part>> <addr> <filename> <bytes>
说明:从指定地址的ddr中读取特定大小数据<bytes>
写到某接口下第n个设备的第n个分区中的某个文件中
addr:源内存地址,ddr地址,使用真实物理地址。
filename:需要write的文件名,使用绝对路径文件名。
bytes:write的数据大小,以byte为单位,16进制数。
示例:从ddr的0x21000000处读取512个byte写到SD第一个分区内根目录下的demo.sh文件
fatwrite mmc 0:1 0x21000000 /demo.sh 0x200
(4) fatinfo
格式:
fatinfo <interface> <dev<:part>>
说明:显示某接口下第n个设备的第n个分区信息
(5) fatsize
格式:
fatsize <interface> <dev<:part>> <filename>
说明:find某接口下第n个设备的第n个分区的文件并计算文件大小
5.4. Uboot cmd使用实例¶
(1) fdisk
fdisk用来管理linux的磁盘,进行分区和格式化等操作
fdisk -p 显示分区信息
(2) fdisk -d 0: 删除设备0的所有分区
(3) fdisk -c 0 0x32000: 创建分区1并指定分区大小为0x32000个block
(4) fdisk -c 0 0x4800: 创建分区2并指定分区大小为0x4800个block
(5) fdisk -c 0 0x64000: 创建分区3并指定分区大小为0x64000个block
(6) fdisk -c 0 0x96000: 创建分区5并指定分区大小为0x96000个block,此处分区4是扩展分区mbr,需要跳过
(7) fdisk -c 0 0x400000: 创建分区6并指定分区大小为0x400000个block
6. Kernel用法介绍¶
6.1. Kernel Config配置¶
1. 关联到的驱动模块
Card层(mmc_block.ko)与Core层(mmc_host.ko)使用linux标准code,Host层(kdrv_sdmmc.ko)由Sigmastar维护,在menuconfig可将它们选择编译进kernel或编译为ko。
2. enable 对应的驱动模块
1. make menuconfig 2. # Device Drivers --> 3. # <*> MMC/SD/SDIO card support --> (mmc_core.ko) 4. # <*> MMC block device driver (mmc_block.ko) 5. # [*] SStar SoC platform drivers --> 6. # <*> SStar SD/MMC Card Interface Support (kdrv_sdmmc.ko) 7. # [ ] Support SD30 8. # [ ] Support EMMC50 9. # [*] Support SDMMC Command 10.# [*] Support SDMMC UT verify
6.2. Dts配置参数说明¶
可以通过配置dtsi中sstar_sdmmc1项设定Host层driver的基本参数。dtsi的参数展示如下:
sstar_sdmmc1: sstar_sdmmc1 { compatible = "sstar,sdmmc"; bus-width = <4>; max-frequency = <48000000>; //non-removable; //broken-cd; cap-mmc-highspeed; cap-sd-highspeed; //sd-uhs-sdr50; //sd-uhs-sdr104; //sd-uhs-ddr50; cap-sdio-irq; //no-sdio; //no-sd; no-mmc; reg = <0x1F282600 0x200>; pll-reg = <0x1F283400 0x200>; cifd-reg = <0x1F282800 0x200>; pwr-save-reg = <0x1F282A00 0x200>; ip-order = /bits/ 8 <0>; pad-order = /bits/ 8 <0>; trans-mode = /bits/ 8 <1>; support-cmd23 = /bits/ 8 <1>; fake-cdz = <0>; rev-cdz = /bits/ 8 <0>; cdz-pad = <PAD_SD0_CDZ>; pwr-pad = <PAD_PM_GPIO11>; pwr-on-delay = <1>; pwr-off-delay = <30>; sdio-use-1bit = /bits/ 8 <0>; clk-driving = <2>; cmd-driving = <2>; data-driving = <2>; en-clk-phase = /bits/ 8 <0>; //0/1 rx-clk-phase = <0>; //0-3 tx-clk-phase = <0>; //0-3 en-eight-phase = /bits/ 8 <0>; //0/1 rx-eight-phase = /bits/ 8 <0>; //0/1 tx-eight-phase = /bits/ 8 <0>; //0/1 interrupts = <GIC_SPI INT_IRQ_SD IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI INT_FIQ_SD_CDZ_0 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "mie0_irq", "cdz_slot0_irq"; clocks = <&CLK_sd>; clock-names = "clk_sdmmc0"; status = "ok"; };
如上图所示,SD/SDIO设备树配置节点释义分别为:
参数 | 释义 | 备注 |
---|---|---|
bus-width | 配置对应卡槽的buswidth | 4 - 4bit mode |
max-frequency | 配置对应卡槽支持的最大时钟频率 | iford最大时钟频率支持到48MHz |
non-removable | 配置是否不可移除设备,置1表示默认该设备不可移除 | eMMC/SDIO设备一般设置为不可移除属性 |
broken-cd | 配置是否使用cdz中断 | |
cap-mmc-highspeed | 配置设备是否支持mmc highspeed总线速率模式 | 默认开启支持mmc highspeed mode |
cap-sd-highspeed | 配置设备是否支持sd highspeed总线速率模式 | 默认开启支持sd highspeed mode |
sd-uhs-sdr50 | 配置是否启用sdr50总线速率模式 | iford未使用 |
sd-uhs-sdr104 | 配置是否启用sdr104总线速率模式 | iford未使用 |
sd-uhs-ddr50 | 配置是否启用ddr总线速率模式 | 暂未使用 |
cap-sdio-irq | 配置是否启用sdio中断模式 | SDIO设备使用 |
no-mmc | 配置设备不支持eMMC协议 | SD/SDIO设备不支持eMMC协议 |
reg | 配置SD/SDIO Host Engine Bank地址 | 根据'功能描述'使用 |
pll-reg | 配置SD/SDIO Host Engine PLL Bank地址 | iford未使用 |
cifd-reg | 配置SD/SDIO Host Engine CIFD Bank地址 | SD/SDIO Host支持adma/dma/cifd数据传输模式,推荐使用adma |
pwr-save-reg | 配置SD/SDIO Host Engine PSM Bank地址 | SD/SDIO Host支持IP层面的掉电保护功能 |
ip-order | 配置对应卡槽的IP编号 | iford当前支持0, 1 两个槽位 |
pad-order | 配置对应卡槽的padmux mode编号 | 根据实际硬件配置对应padmux mode |
trans-mode | 配置对应的卡槽的数据传输模式 | iford未使用,默认使用adma |
fake-cdz | 配置对应卡槽是否忽视Card Detect | SDIO设备推荐使用 |
rev-cdz | 配置CDZ检测方向 | |
pwr-on-delay | 配置对应卡槽的上电延迟时间 | |
pwr-off-delay | 配置对应卡槽的下电延迟时间 | SDIO设备一般需要配置delay时间以便SDIO设备加载固件及状态ready,具体时间以SDIO设备厂家的建议为准 |
sdio-use-1bit | 配置对应卡槽buswidth为1bit mode | SD/SDIO设备均可设置 |
support-cmd23 | 配置是否支持预设传输Block数功能 | eMMC设备使用 |
clk-driving | 配置对应卡槽的clock line的driving | 档位:0-7,(iford: 0-3) |
cmd-driving | 配置对应卡槽的cmd line的driving | 档位:0-7,(iford: 0-3) |
data-driving | 配置对应卡槽的data line的driving | 档位:0-7,(iford: 0-3) |
en-clk-phase | 配置对应卡槽是否使能clock phase tuning | 0 - 禁用 / 1 - 使能 |
rx-clk-phase | 配置对应卡槽的clock rx phase | 档位:0-3,en-clk-phase 置1此参数有效 |
tx-clk-phase | 配置对应卡槽的clock tx phase | 档位:0-3,en-clk-phase 置1此参数有效 |
en-eight-phase | 配置对应卡槽是否使能clock 8 phase tuning | 0 - 禁用 / 1 - 使能, iford暂未启用 |
rx-eight-phase | 配置对应卡槽的clock rx phase | 档位:0-5,en-eight-phase 置1此参数有效 |
tx-eight-phase | 配置对应卡槽的clock tx phase | 档位:0-5,en-eight-phase 置1此参数有效 |
interrupts | 配置中断信息 | 保持默认值即可 |
interrupt-names | 配置中断名称 | 与interrupts 配对使用 |
clocks | 配置eMMC Host Engine时钟源 | 保持默认值即可 |
clock-names | 配置时钟源名称 | 与clocks 配合使用 |
另外,为了方便padmux同一管理,sdmmc driver还支持使用padmux.dtsi配置要使用的pad组,当padmux.dtsi中有关于SDMMC的PUSE时,driver将优先使用该种方式配置padmux。该方式能直观得与其他模块是否存在pad冲突。实例如下:
1. padmux { 2. compatible = "sstar-padmux"; 3. schematic = 4. //SDMMC0 5. <PAD_SD0_D1 PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_D1>, 6. <PAD_SD0_D0 PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_D0>, 7. <PAD_SD0_CLK PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_CLK>, 8. <PAD_SD0_CMD PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_CMD>, 9. <PAD_SD0_D3 PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_D3>, 10. <PAD_SD0_D2 PINMUX_FOR_SD0_MODE_1 MDRV_PUSE_SDIO0_D2>, 11. <PAD_SD0_GPIO0 PINMUX_FOR_GPIO_MODE MDRV_PUSE_SDIO0_PWR>, 12. <PAD_SD0_CDZ PINMUX_FOR_SD0_CDZ_MODE_1 MDRV_PUSE_SDIO0_CDZ>; 13. };
依据客户实际情况,替换第一栏PAD名以及该pad对应的第二组pad mode即可。
6.3. Sample code¶
无
6.4. 模块使用介绍¶
linux系统启动后,正常加载SD/SDIO驱动,并识别SD/SDIO Card后,会创建对应的块设备节点/dev/mmcblk*。使用fdisk、mkfs、mount、dd工具可对MMC设备申请分区、格式化分区、挂载分区并对挂载分区进行读写等操作。
另外驱动提供sysfs进行debug,进入/sys/devices/soc0/soc/{reg}.sstar_sdmmc1目录下可进行操作:
1. cd /sys/devices/soc0/soc/{reg}.sstar_sdmmc1 2. 3. # 查看SD/SDIO Host时钟频率 4. cat debug_get_sdmmc_clock 5. 6. # 查看SD/SDIO Host与Device上一次通信状态 7. cat debug_get_sdmmc_status 8. 9. # 设置SD/SDIO总线宽度 10. echo [buswidth] > sdmmc_bus_width_set 11. #[buswidth] -2: 4bit buswidth 12. # -0: 1bit buswidth 13. # -others: invalid 14. 15. # 设置SD/SDIO clock和Timing mode 16. echo [clk_freq] > sdmmc_clk_timing_set 17. #[clk_freq] 单位:Hz 18. # -[0,12MHz): set clock only 19. # -[12MHz, 26MHz]: set timing to MMC_TIMING_LEGACY and set clock 20. # -(26MHz, 50MHz): set timing to MMC_TIMING_MMC_HS and set clock 21. 22. # 设置SD/SDIO Host使用中断或polling模式 23. echo [intr_en] > sdmmc_inter_polling_set 24. #[intr_en] -0: polling mode 25. # -1: interrupt mode 26. # Tips: 如果SD/SDIO Host已经工作在polling模式,则无法切换到interrupt模式 27. 28. # 设置SD/SDIO pin的驱动能力 29. echo [slotIndex] [signalLine] [drvLevel] > set_sdmmc_driving_control 30. echo [slotIndex] [drvLevel] > set_sdmmc_driving_control 31. echo [signalLine] [drvLevel] > set_sdmmc_driving_control 32. echo [drvLevel] > set_sdmmc_driving_control 33. #[slotIndex]: 0-1 34. #[signalLine]: "clk"/"cmd"/"data"/"all" 35. #[drvLevel]: 0-7 (iford support 0-3)
7. API参考¶
无
8. Debug & FAQ¶
SD卡状态寄存器说明:
可以根据驱动报错log中的(E: 0xXXXX)信息查找对应的SD卡状态来判断目前卡出现了什么问题。
根据SD卡实际可能遇到的问题,分为以下几个类型:
识别卡失败
若卡识别失败,需要确定是响应获取失败还是传输信号不好有CRC问题,区分问题可以通过驱动打印的日志确定,具体区别以及debug方法如下:
-
SD卡不回复命令响应
现象:驱动log报(E: 0x0008)信息
debug方法:首先确定电压和clock是否正常,其次可以抓波形看host是否有command发出去,若前面两个都没有问题,再确定卡是否有回复响应,若没有响应检查device状态。
相关日志:
-
命令响应存在CRC问题
现象:驱动log报(E: 0x0010)信息
debug方法:若有CRC问题,先需要排除硬件问题,比如:device接触是否良好,是否有外接干扰等。然后再尝试更改dts里的driving档位,若还有问题则需要考虑调整clock phase。
相关日志:
读写失败
若是在正常读写过程中遇到问题,需要确定是读写超时问题,还是信号不好有CRC问题,区分问题可以通过log确定,超时问题有timeout的字眼,debug方法如下:
-
读写超时
现象:驱动报错log里有timeout的字眼
debug方法:首先需要确定当前clock频率以及bus width是否是期望配置的值,其次可以将驱动里的超时时间再加大试试,若还有超时问题,则需要抓波形详细分析。
读写超时时间在驱动对应芯片目录的hal_card_platform_config.h文件中设定:
-
读写CRC问题
现象:驱动log报(E: 0x0001)或(E: 0x0002)信息
debug方法:debug方法见前文,另外读写过程中的CRC问题,若对速率要求不是很高,可以考虑降频或者降bus width。
相关日志:
卡读写速度慢
首先检查卡时钟频率和bus width是否正常,另外可以测试对比下不同型号卡的读写速度。
注:SD卡读写受命令及其响应的传输时间,卡busy时间,停止命令时间等多重因素影响,实际读写速率是低于其理论速率的; 读写速度测试应该测试应用层的读写带宽,即传输一个大文件进行测试。