Exynos4412 移植针对Samsung的Linux-6.1(二)SD卡驱动——解决无法挂载SD卡的根文件系统

系列文章目录


Linux对于SD的支持是很全面的、很完善的。按道理来说,移植SD卡应该很简单。但是,我在移植SD卡驱动的时候,碰到了2个问题:

  1. 加载SDMMC驱动正常,但是无法发现SD卡
  2. 无法挂载SD卡上的根文件系统

解决以上问题仍然花费了很长时间解决问题。问题的解决,关键是对设备树的修改。现记录下来,供大家参考以避坑。

在这里插入图片描述
由电路图可以看出,SD卡用到了CLK、CMD、DATA和CD这4类引脚。WP引脚是写保护,电路上是接地的,根本就不起作用。我这次出问题,就出在CD这个引脚上。CD引脚是用来检测是否插入SD卡的,当SD卡插入时引脚电平会被拉低。
另外,开发板上是接到了SDMMC2控制器上。

1、检查Linux内核的配置

执行了make exynos_defconfig之后,默认是配置加载SDMMC驱动的。但是,还是检查一下为好。有2个地方,一是Device Drivers ;另一个是File systems,要想支持中文还得选上Simplified Chinese charset 。

  • Device Drivers —>
           <*> MMC/SD/SDIO card support —>
                  < > ARM AMBA Multimedia Card Interface support
                  <*> Secure Digital Host Controller Interface support
                         < > SDHCI platform and OF driver helper
                        <*> SDHCI support on Samsung S3C/S5P/Exynos SoC
                  [*] DMA support on S3C SDHCI
                  < > MMC/SD/SDIO over SPI
                  <*> Synopsys DesignWare Memory Card Interface

  • File systems —>
           [ ] Validate filesystem parameter description
           <*> Second extended fs support
           [ ] Ext2 extended attributes
           < > The Extended 3 (ext3) filesystem
           <*> The Extended 4 (ext4) filesystem
           -*- Native language support —>
                  <*> Simplified Chinese charset (CP936, GB2312)
                  <*> NLS UTF-8

2、修改设备树

SDMMC设备树的写法,根据开发板的不同,有不同的写法。

[    2.245838] s3c-sdhci 12530000.sdhci: No vmmc regulator found
[    2.251358] s3c-sdhci 12530000.sdhci: No vqmmc regulator found

原因是设备树中没有为sdhc2设置vmmc或者vqmmc。这两个是关于regulator的。该作者采用的设备树如下:

        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <0>;
 
                mmc_reg: regulator@0 {
                        compatible = "regulator-fixed";
                        reg = <0>;
                        regulator-name = "VMEM_VDD_2.8V";
                        regulator-min-microvolt = <2800000>;
                        regulator-max-microvolt = <2800000>;
                        enable-active-high;
                };
        };
        
&sdhci_2 {
        bus-width = <4>;
        pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
        pinctrl-names = "default";
        vmmc-supply = <&mmc_reg>;			
        status = "okay";
        //status = "disabled";
};

regulator与电源管理有关。但是,我的开发板上没有电源管理芯片,所以这样的写法复制到我的dts文件中,会语法错误,编译不通过。

  • 例2:Documentation/devicetree/bindings/mmc/samsung,s3c6410-sdhci.yaml
    帮助文档的示例如下:
 66     #include <dt-bindings/clock/exynos4.h>
 67     #include <dt-bindings/gpio/gpio.h>
 68     #include <dt-bindings/interrupt-controller/arm-gic.h>
 69 
 70     mmc@12510000 {
 71         compatible = "samsung,exynos4210-sdhci";
 72         reg = <0x12510000 0x100>;
 73         interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 74         clocks = <&clock CLK_SDMMC0>, <&clock CLK_SCLK_MMC0>;
 75         clock-names = "hsmmc", "mmc_busclk.2";
 76         bus-width = <4>;
 77         cd-gpios = <&gpx3 4 GPIO_ACTIVE_LOW>;
 78         pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sdhci2_cd>;
 79         pinctrl-names = "default";
 80         vmmc-supply = <&ldo21_reg>;
 81     };

以上第70 ~ 75行,在arch/arm/boot/dts/exynos4.dtsi中已经有了,只需要引用exynos4.dtsi就可以。可以看出,例子中添加了第77~80行的属性。
我按照上述属性修改我的设备树,如下:

 77 /* SD card deviceTree node
 78  * sdhci_2: sdhci@12530000
 79 */
 80 &sdhci_2 {
 81     pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
 82     pinctrl-names = "default";
 83     samsung,bus-width = <4>;
 84     samsung,timing = <1 2 3>;
 85     cd-gpios = <&gpk2 2 0>;
 86     wp-gpios = <&gpx0 5 0>;
 87     status = "okay";
 88 };

虽然dts编译通过了,但是Linux启动时,显示加载了驱动,但是没有找到SD卡。

[    2.277294][    T9] of_get_named_gpiod_flags: parsed 'cd-gpios' property of node '/soc/mmc@12530000[0]' - status (0)
[    2.294318][    T9] s3c-sdhci 12530000.mmc: clock source 2: mmc_busclk.2 (20000000 Hz)
[    2.308484][    T9] s3c-sdhci 12530000.mmc: GPIO lookup for consumer cd
[    2.319385][    T9] s3c-sdhci 12530000.mmc: using device tree for GPIO lookup
[    2.326584][    T9] of_get_named_gpiod_flags: parsed 'cd-gpios' property of node '/soc/mmc@12530000[0]' - status (0)
[    2.342686][    T9] gpio_stub_drv gpiochip15: Persistence not supported for GPIO 2
[    2.354581][    T9] s3c-sdhci 12530000.mmc: Got CD GPIO
[    2.364380][    T9] s3c-sdhci 12530000.mmc: GPIO lookup for consumer wp
[    2.377609][    T9] s3c-sdhci 12530000.mmc: using device tree for GPIO lookup
[    2.390432][    T9] of_get_named_gpiod_flags: parsed 'wp-gpios' property of node '/soc/mmc@12530000[0]' - status (0)
[    2.400806][    T9] gpio_stub_drv gpiochip32: Persistence not supported for GPIO 5
[    2.416815][    T9] s3c-sdhci 12530000.mmc: Got WP GPIO
[    2.466252][    T9] mmc0: SDHCI controller on samsung-hsmmc [12530000.mmc] using ADMA

其中,有2行错误

[    2.342686][    T9] gpio_stub_drv gpiochip15: Persistence not supported for GPIO 2
[    2.400806][    T9] gpio_stub_drv gpiochip32: Persistence not supported for GPIO 5

第一行针对cd-gpios = <&gpk2 2 0>;,第二行针对wp-gpios = <&gpx0 5 0>;。查找Linux-6.1的源码,Persistence not supported代表的含义是pin的状态是睡眠或者控制器重置。

@PIN_CONFIG_PERSIST_STATE: retain pin state across sleep or controller reset

后来,我受到启发,想到可能是cd-gpios的属性设置不正确,于是把第85行cd-gpios属性注释掉,问题就解决了。CBT4412开发板的可行SDMMC设备树如下:

 77 /* SD card deviceTree node
 78  * sdhci_2: sdhci@12530000
 79 */
 80 &sdhci_2 {
 81     pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
 82     pinctrl-names = "default";
 83     samsung,bus-width = <4>;
 84     samsung,timing = <1 2 3>;
 85     //  cd-gpios = <&gpk2 2 0>;
 86     wp-gpios = <&gpx0 5 0>;
 87     status = "okay";
 88 };

Linux启动结果:

[    2.465081][    T9] mmc0: SDHCI controller on samsung-hsmmc [12530000.mmc] using ADMA

[    2.700852][   T35] mmc0: new high speed SD card at address 0002
[    2.732352][   T35] mmcblk0: mmc0:0002       968 MiB 
[    2.732992][    T1] /dev/root: Can't open blockdev
[    2.739237][    T1] VFS: Cannot open root device "mmcblk0p3" or unknown-block(0,0): error -6
[    2.742335][   T35]  mmcblk0: p1 p2 p3
[    2.880395][    T1]  driver: mmcblk
[    2.888522][    T1]   b301           10240 mmcblk0p1 c5a42637-01
[    2.888534][    T1] 
[    2.896680][    T1]   b302          614400 mmcblk0p2 c5a42637-02
[    2.896691][    T1] 
[    2.904839][    T1]   b303          363008 mmcblk0p3 c5a42637-03
[    2.904850][    T1] 
[    2.913065][    T1] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

3、解决无法挂载SD卡的根文件系统

此时,无法完全启动Linux,显示无法挂载SD卡上的根文件系统

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

原因是挂载根文件系统太早了,此时SD卡还没有挂载完成。
解决方法也很简单,修改BootLoader的启动参数,增加rootwait就可以。如下:

setenv bootargs root=/dev/mmcblk0p3  rw rootfstype=ext4 init=/linuxrc console=ttySAC0,115200n8 rootwait

启动结果如下:

[    2.699872][   T35] mmc0: new high speed SD card at address 0002
[    2.729229][    T1] Waiting for root device /dev/mmcblk0p3...
[    2.730965][   T35] mmcblk0: mmc0:0002       968 MiB 
[    2.746932][   T35]  mmcblk0: p1 p2 p3
[    3.311368][    T1] EXT4-fs (mmcblk0p3): recovery complete
[    3.314494][    T1] EXT4-fs (mmcblk0p3): mounted filesystem with ordered data mode. Quota mode: disabled.
[    3.314748][    T1] VFS: Mounted root (ext4 filesystem) on device 179:3.
[    3.316175][    T1] devtmpfs: mounted
[    3.317624][    T1] Freeing unused kernel image (initmem) memory: 1024K
[    3.321581][    T1] Run /linuxrc as init process
[    3.325766][    T1]   with arguments:
[    3.329340][    T1]     /linuxrc
[    3.332590][    T1]   with environment:
[    3.336371][    T1]     HOME=/
[    3.339408][    T1]     TERM=linux
can't run '/etc/init.d/rcS': No such file or directory

Please press Enter to activate this console. 
/ # ls
bin         etc.old     linuxrc     proc        tmp
dev         home        mk_mod_.sh  sbin        usr
etc         lib         mnt         sys         var
/ # 

至此,SD卡移植完成。总结一下:

  1. 还是要仔细分析错误信息
  2. 一般来说,Linux的驱动已经比较完善,出错还是首先看看设备树的写法是否有误,可以结合compatible查看驱动程序中查看需要设置哪些属性。

你还有什么启发,请评论区留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值