sdhci polling探索分析

背景

在使用emmc设备过程中,由于需要用到休眠唤醒功能,对emmc频繁的开关电和挂载卸载,为了降低休眠功耗延长电池通电时间。

DTS

由于没有使用到sdhc2_cd_pin,所以需要使用polling轮询的方式来检测上电后加载设备:

	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";
};

代码

查看对应的sdhci-msm驱动代码读取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;

根据上面的代码看出,如果需要开启MMC_CAP_NEEDS_POLL则需要把nonhotplug和nonremovable在dts中关闭掉,所以已经在dts中注释了/*qcom,nonhotplug;*/,这样默认就开启了emmc 的polling功能。

polling功能控制文件在:/sys/devices/7864900.sdhci/polling,1为开启,0为关闭,默认开

休眠唤醒

休眠时会关闭polling并卸载emmc并关电,唤醒时开电然后开启polling并挂载emmc。

由于polling轮询时间需要1秒,所以emmc上电后驱动加载完成时需要1秒多时间完成设备节点的创建,开启polling后马上去挂载emmc会导致失败,这时需要在挂载emmc脚本里面设置等待超时时间5秒。

开关polling和挂载emmc的顺序搞反了会导致大概率的出现挂载失败问题,需注意。

猜你喜欢

转载自blog.csdn.net/TSZ0000/article/details/89704918
今日推荐