SDMMC使用参考


1. 概述

Kernel下SDMMC采用标准的LINUX MMC框架,能够使用标准接口驱动mmc device(sd card或sdio device)。

MMC子系统由card层,core层和host层构成。Card层将整个mmc device注册成mmc block device,可支持上层的数据请求工作;Core层实现mmc协议中初始化流程和读写等工作。Host层可以调动硬件,把core层传下来的cmd或data request通过sdio engine与sd card device进行数据通信。

2. LINUX配置使用MMC device

2.1. 编译MMC相关driver

Card层(mmc_block.ko)与Core层(mmc_host.ko)使用linux标准code,Host层(kdrv_sdmmc.ko)由我们自己维护,在menuconfig可将它们选择编译进kernel或编译为模块,一般做storage时选择编译成模块,而作为启动介质时选择built-in。

Device Drivers --->
    <M> MMC/SD/SDIO card support --->
        <M> MMC block device driver
    [*] SStar SoC platform drivers --->
        <M> SStar SD/MMC Card Interface Support
            [*] Support SD3.0

make menuconfig中的设置与生成的ko对应关系如表2-1:

表2-1

menuconfig option module name
MMC/SD/SDIO card support mmc_core.ko
MMC block device driver mmc_block.ko
SStar SD/MMC Card Interface Support kdrv_sdmmc.ko

2.2. 设备树配置

可以通过配置dts中sdmmc项设定host层driver的基本参数,参数展示如下:

1.  sdmmc {
2.      compatible = "sstar, sdmmc";
3.  
4.      slotnum = <1>;
5.      revcdz = <0>;
6.  
7.      slot-ip-orders = <0>,<1>,<2>;
8.      slot-pad-orders = <0>,<1>,<2>;
9.      slot-max-clks = <48000000>,<48000000>,<36000000>;
10.     slot-intcdzs = <1>,<1>,<0>;
11.     slot-support-sd30 = <1>,<0>,<0>;
12.     slot-cdzs-pad = <PAD_SD0_CDZ>,<PAD_SD1_CDZ>,<PAD_GPIO2>;
13.     slot-pwr-pad = <PAD_SD0_GPIO0>,<PAD_SD1_GPIO1>,<PAD_UNKNOW>;
14.     slot-pwr-off-delay = <30>,<30>,<30>;
15.     slot-pwr-on-delay = <1>,<1>,<1>;
16.     slot-sdio-use-1bit = <0>,<0>,<0>;
17.     slot-sdio-dis-intr = <0>,<0>,<0>;
18.     slot-fakecdzs = <0>,<0>,<0>;
19.     slot-sdio-use = <0>,<0>,<0>;
20.     slot-removable = <1>,<1>,<1>;
21.     slot-en-clk-phase = <0>,<0>,<0>;  // 0/1
22.     slot-tx-clk-phase = <0>,<0>,<0>;  // 0-3
23.     slot-rx-clk-phase = <0>,<0>,<0>;  // 0-3
24.     slot-clk-driving = <7>,<2>,<0>;
25.     slot-cmd-driving = <7>,<2>,<0>;
26.     slot-data-driving = <7>,<2>,<0>;
27. 
28.     clocks = <&CLK_sd>,<&CLK_sd>,<&CLK_sd>,
29.              <&CLK_sd>,<&CLK_sd>,<&CLK_sd>;
30. 
31.     interrupts-extended = <&ms_main_intc GIC_SPI INT_IRQ_SD IRQ_TYPE_LEVEL_HIGH>,
32.                           <&ms_main_intc GIC_SPI INT_IRQ_SD IRQ_TYPE_LEVEL_HIGH>,
33.                           <&ms_main_intc GIC_SPI INT_FIQ_SD_CDZ_0 IRQ_TYPE_LEVEL_HIGH>,
34.                           <&ms_main_intc GIC_SPI INT_FIQ_SD_CDZ_1 IRQ_TYPE_LEVEL_HIGH>,
35.                           <&ms_main_intc GIC_SPI INT_FIQ_SD_CDZ_0 IRQ_TYPE_LEVEL_HIGH>;
36.     interrupt-names = "mie0_irq", "mie1_irq", 
37.                         "cdz_slot0_irq", "cdz_slot1_irq", "cdz_slot2_irq";
38. 
39.     status = "ok";
40. };

由此可见,sdmmc节点下几乎所有的属性都有三组value,分别代表最多三个SD slot口的属性参数。释义如表2-2:

表2-2

属性 描述 备注
slotnum 当前board正在使用的SD/SDIO IP个数,driver根据该值读取相应列的参数。 根据实际使用情况配置该项。
revcdz 颠倒卡检测逻辑。 0->cdz pad为0卡存在,1 -> cdz pad为1卡存在。
slot-ip-orders 配置对应卡槽的IP编号
slot-pad-orders 配置对应卡槽的padmux mode编号 与slot-ip-order项共同决定要用哪组pad脚
slot-max-clks 配置对应卡槽支持的最大时钟频率
slot-intcdzs 配置对应卡槽支持通过cdz中断来探测卡拔插,置0表示使用polling mode 针对固定在板上的设备和没有cdz的pcb设计
slot-support-sd30 配置对应卡槽是否支持sd3.0功能
slot-cdzs-pad 配置对应卡槽的CDZ pin脚
slot-pwr-pad 配置对应卡槽的Power pin脚
slot-pwr-off-delay 设置对应卡槽的下电延迟时间
slot-pwr-on-delay 设置对应卡槽的上电延迟时间 SDIO设备一般需要配置delay时间以便SDIO设备加载固件及状态ready,具体时间以SDIO设备厂家的建议为准
slot-sdio-use-1bit 配置对应卡槽buswidth为1bit mode 虽然名字中带SDIO标志,但SD card也可通过此参数配置为1bit mode
slot-sdio-dis-intr 配置对应卡槽是否disable detect SDIO中断
slot-fakecdzs 配置对应卡槽是否忽视Card detect,置1表示默认认为有卡接入 正对固定在板上的设备,如部分SDIO设备
slot-sdio-use 配置对应卡槽是否接入SDIO设备
slot-removable 配置对应卡槽是否固定在板上,置1表示可移动设备 若为固定在板上的设备,程式开机后仅会detect一次
slot-en-clk-phase 配置对应卡槽是否使能clock phase tuning
slot-tx-clk-phase 配置对应卡槽的clock tx phase 需要slot-en-clk-phase置1此参数才有效
slot-rx-clk-phase 配置对应卡槽的clock rx phase 需要slot-en-clk-phase置1此参数才有效
slot-clk-driving 配置对应卡槽的clk pin的driving能力
slot-cmd-driving 配置对应卡槽的cmd pin的driving能力
slot-data-driving 配置对应卡槽的data[3:0] pin的driving能力
clocks 配置对应卡槽的clock source
interrupts-extended 配置中断信息
interrupt-names 配置中断名称 与interrupts-extended配合使用,code中可以根据ip自动匹配中断号

另外,为了方便padmux同一管理,sdmmc driver还支持使用padmux.dtsi配置要使用的pad组,当padmux.dtsi中有关于SDMMC的PUSE时,driver将优先使用该种方式配置padmux。该方式相较于上一种方式的好处是,它能很直观得发现自己是否与其他使用该方式配置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. };

2.3. Linux下使用mmc device

开发板启动进入到kernel命令行后,会生成sd card的设备分区节点/dev/mmcblk*。使用fdisk、mkfs、mount、dd等工具操作该节点即可实现访问mmc block device,这与其他linux是没有差异的。

另外我们也提供sysfs进行debug,进入kernel命令行后,在/sys/device/platform/soc/soc:sdmmc目录下可以查看到所有支持的sysfs。

1.  cd /sys/device/platform/soc/soc:sdmmc
2.  
3.  # 查看所有slot当前的clock挡位
4.  cat get_sdmmc_clock
5.  
6.  # 查看所有slot最近发送的command以及运行状态
7.  cat get_sdmmc_status
8.  
9.  # 复位,重识别[slotNo] mmc device
10. echo [slotNo] > sdmmc_reset
11. 
12. # 对[slotNo]的engine进行power save mode测试验证
13. echo [slotNo] > test_sdmmc_power_save_mode
14. 
15. # 对[slotNo]的engine进行sdio data1 interrupt测试验证
16. echo [slotNo] > test_sdmmc_sdio_interrupt
17. 
18. # 对[slotNo]的engine进行ipverify测试验证
19. # 包括1/4 bit、dma/adma/cifd、low/default/highspeed测试
20. echo [slotNo] > sdmmc_ipverify
21. 
22. # 设置[slotNo]的<signal>信号线的驱动能力为[level]。
23. # [slotNo] -选择操作的slot。
24. # <signal> -可以选择设置clk、cmd、data、all或空值(等同all)。
25. # [level]  -driving能力挡位,取值范围0~15。
26. echo [slotNo] <signal> [level] > set_sdmmc_driving_control
27.