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.