SDMMC使用参考

REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 06/27/2023
    2.0
  • Update sdmmc driver framework/device tree source/api information
  • 12/13/2023
    3.0
  • Update some content
  • 04/18/2024

    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通过SD/SDIO Engine与eMMC/SD/SDIO card进行数据通信。

    图1-1 SDMMC Host层框架

    SD host层的整体框架共有三层,分别是Drv层,Hal层和Support层,以及接在Support层上的MMC设备,各个层次的作用如下:

    Drv层:

    Drv层主要完成host的注册,完善mmc_host和mmc_host_ops结构体的描述,向core层增加Host的信息,还会额外提供一些封装接口来给用户层设置或获得Engine和卡的状态,比如:debug_get_sdmmc_clock,set_sdmmc_driving_control等。此外,Drv层还会完成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 产品
    QFN SD0 Card 1,4 300k-48M - Default Speed,High Speed 0x1413 ifado
    QFN SD1 Card 1,4 300k-48M - Default Speed,High Speed 0x1410 ifado

    总线带宽设置:

    SD支持配置1 -1bit mode/4 – 4bit mode 两种总线带宽,默认使用4bit mode。SDIO卡需要设置带宽为1 bit mode可以设置设备树中的sdio-use-1bit参数。

    时钟设置:

    ifado: SD0 Card/SD1 Card支持配置300KHz-48MHz范围内的时钟频率,可以通过修改设备树中的max-frequency参数来设置最大时钟大小,最终设置的clock频率是当前bus speed支持的最大频率。

    图3-1 SDMMC 总线速率模式

    配置不同的总线带宽及时钟频率会影响数据传输速率,SDR104,SDR50和DDR50速率模式属于SD3.0范畴,ifado不支持,ifado支持High Speed和Default Speed两种速率模式

    速率模式:

    (1)查看SD卡速率模式

    cat /sys/kernel/debug/mmc0/ios

    (2)设置SD卡速率模式

    SD卡速率模式可直接在dtsi文件配置,默认支持Default Speed,若想要跑High Speed,则配置cap-sd-highspeed即可:


    4. 硬件连接介绍

    4.1. ifado

    图4-1 SD0 硬件原理图

    图4-2 SD1 硬件原理图


    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_FUART_RTS>;
                cdz-pad = <PAD_PM_SD_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-1
    cmd-driving 配置对应卡槽的command pad pin的driving能力 档位:0-1
    data-driving 配置对应卡槽的data[3:0] pad pin的driving能力 档位:0-1
    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. #            Sstar SDMMC DDR Mode (sdr/ddr Mode)  --->
    8. #            Sstar SDMMC RECEIVE RESPONSE Mode (interrupt Mode)  --->
    9. #        [ ]     Support SD30
    10.#        [ ]     Support EMMC50
    11.#        [ ]     Support SDMMC Command
    12.#        [ ]       Support SDMMC UT verify
    

    6.2. Dts配置参数说明

    可以通过配置dtsi中sstar_sdmmc1项设定Host层driver的基本参数。dtsi的参数展示如下:

    sstar_sdmmc0: sstar_sdmmc0 {
                compatible = "sstar,sdmmc";
    
                bus-width = <4>;
                max-frequency = <48000000>;
                //non-removable;
                //broken-cd;
                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 = <0x1F283200 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 =  /bits/ 8 <0>;
                rev-cdz = /bits/ 8 <0>;
                cdz-pad = <PAD_PM_SD_CDZ>;
                pwr-pad = <PAD_FUART_RTS>;
                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 配置对应卡槽支持的最大时钟频率 ifado最大时钟频率支持到48MHz
    non-removable 配置是否不可移除设备,置1表示默认该设备不可移除 eMMC/SDIO设备一般设置为不可移除属性
    broken-cd 配置是否使用cdz中断
    cap-sd-highspeed 配置设备是否支持sd highspeed总线速率模式 for sd/sdio
    sd-uhs-sdr50 配置是否启用sdr50总线速率模式 ifado未使用
    sd-uhs-sdr104 配置是否启用sdr104总线速率模式 ifado未使用
    sd-uhs-ddr50 配置是否启用ddr总线速率模式 ifado未使用
    cap-sdio-irq 配置是否启用sdio中断模式 SDIO设备使用
    no-sdio 配置设备不支持sdio协议 接的设备不是sdio WiFi,若接sdio,需要注释掉
    no-sd 配置设备不支持sd协议 接的设备不是SD卡,若接SD卡,需要注释掉
    no-mmc 配置设备不支持eMMC协议 接的设备不是eMMC
    reg 配置SD/SDIO Host Engine Bank地址 根据'功能描述'使用
    pll-reg 配置SD/SDIO Host Engine PLL Bank地址 ifado未使用
    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编号 ifado当前支持0, 1两个槽位
    pad-order 配置对应卡槽的padmux mode编号 根据实际硬件配置对应padmux mode
    trans-mode 配置对应的卡槽的数据传输模式 默认使用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-1
    cmd-driving 配置对应卡槽的cmd line的driving 档位:0-1
    data-driving 配置对应卡槽的data line的driving 档位:0-1
    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-1,en-eight-phase置1此参数有效
    tx-eight-phase 配置对应卡槽的clock tx phase 档位:0-1,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冲突。实例如下,当接的设备是SD卡时,cdz pin需要被配置为SD_CDZ mode

    1.    padmux {
    2.        compatible = "sstar-padmux";
    3.        schematic =
    4.            //SDMMC0
    5.            <PAD_SD_D1        PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_D1>,
    6.            <PAD_SD_D0        PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_D0>,
    7.            <PAD_SD_CLK       PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_CLK>,
    8.            <PAD_SD_CMD       PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_CMD>,
    9.            <PAD_SD_D3        PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_D3>,
    10.           <PAD_SD_D2        PINMUX_FOR_SD_MODE_1        MDRV_PUSE_SDIO0_D2>,
    11.           <PAD_FUART_RTS    PINMUX_FOR_GPIO_MODE        MDRV_PUSE_SDIO0_PWR>,
    12.           #if 1 //sd power & cdz
    13.           <PAD_PM_SD_CDZ    PINMUX_FOR_SD0_CDZ_MODE_1   MDRV_PUSE_SDIO0_CDZ>;
    14.           #else //emmc rst
    15.           <PAD_PM_SD_CDZ    PINMUX_FOR_EMMC_RST_MODE_1  MDRV_PUSE_SDIO0_CDZ>;
    16.           #endif // sd or emmc end
    17.    };
    

    依据客户实际情况,替换第一栏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_sdmmc0目录下可进行操作:

    1.  cd /sys/devices/soc0/soc/{reg}.sstar_sdmmc0
    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/EMMC设备
    10. echo [slotIndex] > sdmmc_reset
    21. #[slotIndex]: 0-1
    22.
    23. # 设置SD/SDIO pin的驱动能力
    24. echo [slotIndex] [signalLine] [drvLevel] > set_sdmmc_driving_control
    25. echo [slotIndex]  [drvLevel] > set_sdmmc_driving_control
    26. echo [signalLine] [drvLevel] > set_sdmmc_driving_control
    27. echo [drvLevel] > set_sdmmc_driving_control
    28. #[slotIndex]: 0-1
    29. #[signalLine]: "clk"/"cmd"/"data"/"all"
    30. #[drvLevel]: 0-1
    

    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_sdmmc_v5.h文件中设定:

    • 读写CRC问题

      现象:驱动log报(E: 0x0001)或(E: 0x0002)信息

      debug方法:debug方法见前文,另外读写过程中的CRC问题,若对速率要求不是很高,可以考虑降频或者降bus width。

      相关日志:

    卡读写速度慢

    首先检查卡时钟频率和bus width是否正常,另外可以测试对比下不同型号卡的读写速度。

    注:SD卡读写受命令及其响应的传输时间,卡busy时间,停止命令时间等多重因素影响,实际读写速率是低于其理论速率的; 读写速度测试应该测试应用层的读写带宽,即传输一个大文件进行测试。