1515#include <linux/module.h>
1616#include <linux/of.h>
1717#include <linux/platform_device.h>
18+ #include <linux/pm_runtime.h>
1819#include <linux/reset.h>
1920#include <linux/sizes.h>
2021
@@ -548,9 +549,13 @@ static int dwcmshc_probe(struct platform_device *pdev)
548549
549550 host -> mmc -> caps |= MMC_CAP_WAIT_WHILE_BUSY ;
550551
552+ pm_runtime_get_noresume (dev );
553+ pm_runtime_set_active (dev );
554+ pm_runtime_enable (dev );
555+
551556 err = sdhci_setup_host (host );
552557 if (err )
553- goto err_clk ;
558+ goto err_rpm ;
554559
555560 if (rk_priv )
556561 dwcmshc_rk35xx_postinit (host , priv );
@@ -559,10 +564,15 @@ static int dwcmshc_probe(struct platform_device *pdev)
559564 if (err )
560565 goto err_setup_host ;
561566
567+ pm_runtime_put (dev );
568+
562569 return 0 ;
563570
564571err_setup_host :
565572 sdhci_cleanup_host (host );
573+ err_rpm :
574+ pm_runtime_disable (dev );
575+ pm_runtime_put_noidle (dev );
566576err_clk :
567577 clk_disable_unprepare (pltfm_host -> clk );
568578 clk_disable_unprepare (priv -> bus_clk );
@@ -600,6 +610,8 @@ static int dwcmshc_suspend(struct device *dev)
600610 struct rk35xx_priv * rk_priv = priv -> priv ;
601611 int ret ;
602612
613+ pm_runtime_resume (dev );
614+
603615 ret = sdhci_suspend_host (host );
604616 if (ret )
605617 return ret ;
@@ -659,7 +671,55 @@ static int dwcmshc_resume(struct device *dev)
659671}
660672#endif
661673
662- static SIMPLE_DEV_PM_OPS (dwcmshc_pmops , dwcmshc_suspend , dwcmshc_resume ) ;
674+ #ifdef CONFIG_PM
675+
676+ static void dwcmshc_enable_card_clk (struct sdhci_host * host )
677+ {
678+ u16 ctrl ;
679+
680+ ctrl = sdhci_readw (host , SDHCI_CLOCK_CONTROL );
681+ if ((ctrl & SDHCI_CLOCK_INT_EN ) && !(ctrl & SDHCI_CLOCK_CARD_EN )) {
682+ ctrl |= SDHCI_CLOCK_CARD_EN ;
683+ sdhci_writew (host , ctrl , SDHCI_CLOCK_CONTROL );
684+ }
685+ }
686+
687+ static void dwcmshc_disable_card_clk (struct sdhci_host * host )
688+ {
689+ u16 ctrl ;
690+
691+ ctrl = sdhci_readw (host , SDHCI_CLOCK_CONTROL );
692+ if (ctrl & SDHCI_CLOCK_CARD_EN ) {
693+ ctrl &= ~SDHCI_CLOCK_CARD_EN ;
694+ sdhci_writew (host , ctrl , SDHCI_CLOCK_CONTROL );
695+ }
696+ }
697+
698+ static int dwcmshc_runtime_suspend (struct device * dev )
699+ {
700+ struct sdhci_host * host = dev_get_drvdata (dev );
701+
702+ dwcmshc_disable_card_clk (host );
703+
704+ return 0 ;
705+ }
706+
707+ static int dwcmshc_runtime_resume (struct device * dev )
708+ {
709+ struct sdhci_host * host = dev_get_drvdata (dev );
710+
711+ dwcmshc_enable_card_clk (host );
712+
713+ return 0 ;
714+ }
715+
716+ #endif
717+
718+ static const struct dev_pm_ops dwcmshc_pmops = {
719+ SET_SYSTEM_SLEEP_PM_OPS (dwcmshc_suspend , dwcmshc_resume )
720+ SET_RUNTIME_PM_OPS (dwcmshc_runtime_suspend ,
721+ dwcmshc_runtime_resume , NULL )
722+ };
663723
664724static struct platform_driver sdhci_dwcmshc_driver = {
665725 .driver = {
0 commit comments