Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mmc: dw_mmc-rockchip: Fix runtime PM support for internal phase support

RK3576 is the first platform to introduce internal phase support, and
subsequent platforms are expected to adopt a similar design. In this
architecture, runtime suspend powers off the attached power domain, which
resets registers, including vendor-specific ones such as SDMMC_TIMING_CON0,
SDMMC_TIMING_CON1, and SDMMC_MISC_CON. These registers must be saved and
restored, a requirement that falls outside the scope of the dw_mmc core.

Fixes: 59903441f5e4 ("mmc: dw_mmc-rockchip: Add internal phase support")
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Tested-by: Marco Schirrmeister <mschirrmeister@gmail.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Shawn Lin and committed by
Ulf Hansson
6465a8bb af12e64a

+37 -1
+37 -1
drivers/mmc/host/dw_mmc-rockchip.c
··· 36 36 int default_sample_phase; 37 37 int num_phases; 38 38 bool internal_phase; 39 + int sample_phase; 40 + int drv_phase; 39 41 }; 40 42 41 43 /* ··· 575 573 dw_mci_pltfm_remove(pdev); 576 574 } 577 575 576 + static int dw_mci_rockchip_runtime_suspend(struct device *dev) 577 + { 578 + struct platform_device *pdev = to_platform_device(dev); 579 + struct dw_mci *host = platform_get_drvdata(pdev); 580 + struct dw_mci_rockchip_priv_data *priv = host->priv; 581 + 582 + if (priv->internal_phase) { 583 + priv->sample_phase = rockchip_mmc_get_phase(host, true); 584 + priv->drv_phase = rockchip_mmc_get_phase(host, false); 585 + } 586 + 587 + return dw_mci_runtime_suspend(dev); 588 + } 589 + 590 + static int dw_mci_rockchip_runtime_resume(struct device *dev) 591 + { 592 + struct platform_device *pdev = to_platform_device(dev); 593 + struct dw_mci *host = platform_get_drvdata(pdev); 594 + struct dw_mci_rockchip_priv_data *priv = host->priv; 595 + int ret; 596 + 597 + ret = dw_mci_runtime_resume(dev); 598 + if (ret) 599 + return ret; 600 + 601 + if (priv->internal_phase) { 602 + rockchip_mmc_set_phase(host, true, priv->sample_phase); 603 + rockchip_mmc_set_phase(host, false, priv->drv_phase); 604 + mci_writel(host, MISC_CON, MEM_CLK_AUTOGATE_ENABLE); 605 + } 606 + 607 + return ret; 608 + } 609 + 578 610 static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { 579 611 SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 580 - RUNTIME_PM_OPS(dw_mci_runtime_suspend, dw_mci_runtime_resume, NULL) 612 + RUNTIME_PM_OPS(dw_mci_rockchip_runtime_suspend, dw_mci_rockchip_runtime_resume, NULL) 581 613 }; 582 614 583 615 static struct platform_driver dw_mci_rockchip_pltfm_driver = {