background
In the process of using emmc device, because of the need to use the sleep wake-up function, emmc is frequently switched on and off, in order to reduce the sleep power consumption and extend the battery power on time.
DTS
Since sdhc2 ﹣ CD ﹣ pin is not used, polling polling is needed to detect the device loaded after power on:
sdhc_2: sdhci@07864900 { compatible = "qcom,sdhci-msm"; reg = <0x07864900 0x200>, <0x07864000 0x800>; reg-names = "hc_mem", "core_mem"; interrupts = <0 125 0>, <0 221 0>; interrupt-names = "hc_irq", "pwr_irq"; qcom,bus-width = <4>; qcom,devfreq,freq-table = <50000000 200000000>; qcom,msm-bus,name = "sdhc2"; qcom,msm-bus,num-cases = <8>; qcom,msm-bus,num-paths = <1>; qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */ <81 512 1600 3200>, /* 400 KB/s*/ <81 512 80000 160000>, /* 20 MB/s */ <81 512 100000 200000>, /* 25 MB/s */ <81 512 200000 400000>, /* 50 MB/s */ <81 512 400000 800000>, /* 100 MB/s */ <81 512 800000 800000>, /* 200 MB/s */ <81 512 2048000 4096000>; /* Max. bandwidth */ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>; clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>, <&clock_gcc clk_gcc_sdcc2_apps_clk>; clock-names = "iface_clk", "core_clk"; qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>; qcom,pm-qos-irq-type = "affine_irq"; qcom,pm-qos-irq-latency = <2 250>; status = "disabled"; };
&sdhc_2 { /*vdd-supply = <&sdcard_ext_vreg>;*/ qcom,vdd-voltage-level = <2850000 2850000>; qcom,vdd-current-level = <15000 400000>; vdd-io-supply = <&mdm9607_l13>; qcom,vdd-io-always-on; qcom,vdd-io-voltage-level = <1800000 2850000>; qcom,vdd-io-current-level = <200 50000>; #address-cells = <0>; interrupt-parent = <&sdhc_2>; interrupts = <0 1 2>; #interrupt-cells = <1>; interrupt-map-mask = <0xffffffff>; interrupt-map = <0 &intc 0 125 0 1 &intc 0 221 0 2 &tlmm_pinmux 26 0>; interrupt-names = "hc_irq", "pwr_irq", "status_irq"; /*cd-gpios = <&tlmm_pinmux 26 0x1>;*/ /*qcom,nonhotplug;*/ pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>; status = "ok"; };
Code
View the corresponding sdhci MSM driver code to read the configuration in dts:
drivers/mmc/host/sdhci-msm.c
sdhci_msm_populate_pdata if (of_get_property(np, "qcom,nonremovable", NULL)) pdata->nonremovable = true; if (of_get_property(np, "qcom,nonhotplug", NULL)) pdata->nonhotplug = true;
sdhci_msm_probe if (msm_host->pdata->nonremovable) msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE; if (msm_host->pdata->nonhotplug) msm_host->mmc->caps2 |= MMC_CAP2_NONHOTPLUG;
drivers/mmc/host/sdhci.c
sdhci_add_host /* * Enable polling on when card detection is broken and no card detect * gpio is present. */ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && !(mmc->caps & MMC_CAP_NONREMOVABLE) && (mmc_gpio_get_cd(host->mmc) < 0) && !(mmc->caps2 & MMC_CAP2_NONHOTPLUG)) mmc->caps |= MMC_CAP_NEEDS_POLL;
According to the above code, if you need to turn on MMC ﹣ cap ﹣ needs ﹣ poll, you need to turn off nonhotplug and nonremoveable in dts, so you have annotated / * qcom,nonhotplug; * /, so the polling function of emmc is turned on by default.
The polling function control file is in / sys/devices/7864900.sdhci/polling, 1 is on, 0 is off, and the default is on
Sleep wake up
During sleep, polling will be turned off and emmc will be unloaded and powered off. During wake-up, polling will be turned on and emmc will be mounted.
Since polling takes 1 second, it takes more than 1 second to complete the creation of device nodes when the emmc is powered on and the drive is loaded. When polling is turned on, mounting the emmc immediately will lead to failure. At this time, the waiting timeout of 5 seconds needs to be set in the mount emmc script.
If the order of switching polling and mounting emmc is reversed, it will lead to a high probability of mounting failure.