Answer
SDIO reset would rely on SDIO card detection function, which can be done by broken-cd setting in device tree.
1. Modify the dts file:
For example if you use NXP IMX6UL board, the dts file is located at “~/projects/fsl-release-bsp/build-imx6ul-fb/tmp/work-shared/imx6ulevk/kernel-source/arch/arm/boot/dts/imx6ul-14x14-evk.dts”. If you use mmc0, the setting will be in usdhc1.
Add broken-cd function in the setting of usdhc1 as below and also need to make sure there is no setting of “non-removable”.
&usdhc1 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
keep-power-in-suspend;
broken-cd;
enable-sdio-wakeup;
vmmc-supply = <®_sd1_vmmc>;
status = "okay";
};
2. Rebuild kernel and then it will set MMC_CAP_NEEDS_POLL during mmc driver initialization.
int mmc_of_parse(struct mmc_host *host)
{
…
if (of_property_read_bool(np, "non-removable")) {
dev_warn(host->parent,"Parse Card Detection: non-removable\n");
host->caps |= MMC_CAP_NONREMOVABLE;
if (of_property_read_bool(np, "cd-post"))
host->caps2 |= MMC_CAP2_CD_POST;
} else {
cd_cap_invert = of_property_read_bool(np, "cd-inverted");
if (of_property_read_bool(np, "broken-cd"))
{
dev_info(host->parent,"Parse Card Detection: broken-cd\n");
host->caps |= MMC_CAP_NEEDS_POLL;
}
…
}
…
}
Then SDHC will check the SDIO bus per second and once there is any PMU_EN or PDN assert event, SDHC will detect the bus no longer available and will unload/reload the SDIO again automatically.