8585#define DRIVER_STRENGTH_40_OHM 0x4
8686
8787#define CLOCK_TOO_SLOW_HZ 50000000
88+ #define SDHCI_AM654_AUTOSUSPEND_DELAY -1
8889
8990/* Command Queue Host Controller Interface Base address */
9091#define SDHCI_AM654_CQE_BASE_ADDR 0x200
@@ -808,48 +809,58 @@ static int sdhci_am654_probe(struct platform_device *pdev)
808809
809810 pltfm_host -> clk = clk_xin ;
810811
811- /* Clocks are enabled using pm_runtime */
812- pm_runtime_enable (dev );
813- ret = pm_runtime_resume_and_get (dev );
814- if (ret )
815- goto pm_runtime_disable ;
816-
817812 base = devm_platform_ioremap_resource (pdev , 1 );
818813 if (IS_ERR (base )) {
819814 ret = PTR_ERR (base );
820- goto pm_runtime_put ;
815+ goto err_pltfm_free ;
821816 }
822817
823818 sdhci_am654 -> base = devm_regmap_init_mmio (dev , base ,
824819 & sdhci_am654_regmap_config );
825820 if (IS_ERR (sdhci_am654 -> base )) {
826821 dev_err (dev , "Failed to initialize regmap\n" );
827822 ret = PTR_ERR (sdhci_am654 -> base );
828- goto pm_runtime_put ;
823+ goto err_pltfm_free ;
829824 }
830825
831826 ret = sdhci_am654_get_of_property (pdev , sdhci_am654 );
832827 if (ret )
833- goto pm_runtime_put ;
828+ goto err_pltfm_free ;
834829
835830 ret = mmc_of_parse (host -> mmc );
836831 if (ret ) {
837832 dev_err_probe (dev , ret , "parsing dt failed\n" );
838- goto pm_runtime_put ;
833+ goto err_pltfm_free ;
839834 }
840835
841836 host -> mmc_host_ops .execute_tuning = sdhci_am654_execute_tuning ;
842837
838+ pm_runtime_get_noresume (dev );
839+ ret = pm_runtime_set_active (dev );
840+ if (ret )
841+ goto pm_put ;
842+ pm_runtime_enable (dev );
843+ ret = clk_prepare_enable (pltfm_host -> clk );
844+ if (ret )
845+ goto pm_disable ;
846+
843847 ret = sdhci_am654_init (host );
844848 if (ret )
845- goto pm_runtime_put ;
849+ goto clk_disable ;
846850
851+ /* Setting up autosuspend */
852+ pm_runtime_set_autosuspend_delay (dev , SDHCI_AM654_AUTOSUSPEND_DELAY );
853+ pm_runtime_use_autosuspend (dev );
854+ pm_runtime_mark_last_busy (dev );
855+ pm_runtime_put_autosuspend (dev );
847856 return 0 ;
848857
849- pm_runtime_put :
850- pm_runtime_put_sync ( dev );
851- pm_runtime_disable :
858+ clk_disable :
859+ clk_disable_unprepare ( pltfm_host -> clk );
860+ pm_disable :
852861 pm_runtime_disable (dev );
862+ pm_put :
863+ pm_runtime_put_noidle (dev );
853864err_pltfm_free :
854865 sdhci_pltfm_free (pdev );
855866 return ret ;
@@ -858,23 +869,127 @@ static int sdhci_am654_probe(struct platform_device *pdev)
858869static int sdhci_am654_remove (struct platform_device * pdev )
859870{
860871 struct sdhci_host * host = platform_get_drvdata (pdev );
872+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
861873 int ret ;
862874
863- sdhci_remove_host (host , true);
864- ret = pm_runtime_put_sync (& pdev -> dev );
875+ ret = pm_runtime_resume_and_get (& pdev -> dev );
865876 if (ret < 0 )
866877 return ret ;
867878
879+ sdhci_remove_host (host , true);
880+ clk_disable_unprepare (pltfm_host -> clk );
868881 pm_runtime_disable (& pdev -> dev );
882+ pm_runtime_put_noidle (& pdev -> dev );
869883 sdhci_pltfm_free (pdev );
884+ return 0 ;
885+ }
886+
887+ #ifdef CONFIG_PM
888+ static int sdhci_am654_restore (struct sdhci_host * host )
889+ {
890+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
891+ struct sdhci_am654_data * sdhci_am654 = sdhci_pltfm_priv (pltfm_host );
892+ u32 ctl_cfg_2 = 0 ;
893+ u32 val ;
894+ int ret ;
895+
896+ if (sdhci_am654 -> flags & DLL_CALIB ) {
897+ regmap_read (sdhci_am654 -> base , PHY_STAT1 , & val );
898+ if (~val & CALDONE_MASK ) {
899+ /* Calibrate IO lines */
900+ regmap_update_bits (sdhci_am654 -> base , PHY_CTRL1 ,
901+ PDB_MASK , PDB_MASK );
902+ ret = regmap_read_poll_timeout (sdhci_am654 -> base ,
903+ PHY_STAT1 , val ,
904+ val & CALDONE_MASK ,
905+ 1 , 20 );
906+ if (ret )
907+ return ret ;
908+ }
909+ }
910+
911+ /* Enable pins by setting IO mux to 0 */
912+ if (sdhci_am654 -> flags & IOMUX_PRESENT )
913+ regmap_update_bits (sdhci_am654 -> base , PHY_CTRL1 ,
914+ IOMUX_ENABLE_MASK , 0 );
870915
916+ /* Set slot type based on SD or eMMC */
917+ if (host -> mmc -> caps & MMC_CAP_NONREMOVABLE )
918+ ctl_cfg_2 = SLOTTYPE_EMBEDDED ;
919+
920+ regmap_update_bits (sdhci_am654 -> base , CTL_CFG_2 , SLOTTYPE_MASK ,
921+ ctl_cfg_2 );
922+
923+ regmap_read (sdhci_am654 -> base , CTL_CFG_3 , & val );
924+ if (~val & TUNINGFORSDR50_MASK )
925+ /* Enable tuning for SDR50 */
926+ regmap_update_bits (sdhci_am654 -> base , CTL_CFG_3 , TUNINGFORSDR50_MASK ,
927+ TUNINGFORSDR50_MASK );
928+
929+ return 0 ;
930+ }
931+
932+ static int sdhci_am654_runtime_suspend (struct device * dev )
933+ {
934+ struct sdhci_host * host = dev_get_drvdata (dev );
935+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
936+ int ret ;
937+
938+ if (host -> tuning_mode != SDHCI_TUNING_MODE_3 )
939+ mmc_retune_needed (host -> mmc );
940+
941+ ret = cqhci_suspend (host -> mmc );
942+ if (ret )
943+ return ret ;
944+
945+ ret = sdhci_runtime_suspend_host (host );
946+ if (ret )
947+ return ret ;
948+
949+ /* disable the clock */
950+ clk_disable_unprepare (pltfm_host -> clk );
871951 return 0 ;
872952}
873953
954+ static int sdhci_am654_runtime_resume (struct device * dev )
955+ {
956+ struct sdhci_host * host = dev_get_drvdata (dev );
957+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
958+ int ret ;
959+
960+ /* Enable the clock */
961+ ret = clk_prepare_enable (pltfm_host -> clk );
962+ if (ret )
963+ return ret ;
964+
965+ ret = sdhci_am654_restore (host );
966+ if (ret )
967+ return ret ;
968+
969+ ret = sdhci_runtime_resume_host (host , 0 );
970+ if (ret )
971+ return ret ;
972+
973+ ret = cqhci_resume (host -> mmc );
974+ if (ret )
975+ return ret ;
976+
977+ return 0 ;
978+ }
979+ #endif
980+
981+ static const struct dev_pm_ops sdhci_am654_dev_pm_ops = {
982+ SET_RUNTIME_PM_OPS (sdhci_am654_runtime_suspend ,
983+ sdhci_am654_runtime_resume , NULL )
984+ SET_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend ,
985+ pm_runtime_force_resume )
986+ };
987+
874988static struct platform_driver sdhci_am654_driver = {
875989 .driver = {
876990 .name = "sdhci-am654" ,
877991 .probe_type = PROBE_PREFER_ASYNCHRONOUS ,
992+ .pm = & sdhci_am654_dev_pm_ops ,
878993 .of_match_table = sdhci_am654_of_match ,
879994 },
880995 .probe = sdhci_am654_probe ,
0 commit comments