diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 11b00688aaa6f..89b9a32b6201a 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2259,6 +2259,7 @@ static int mmc_cache_card_ext_csd(struct mmc_host *host) return 0; } +#if defined(CONFIG_SDC_QTI) static int mmc_test_awake_ext_csd(struct mmc_host *host) { int err; @@ -2273,7 +2274,6 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host) } /* only compare read/write fields that the sw changes */ -#if defined(CONFIG_SDC_QTI) pr_debug("%s: %s: type(cached:current) cmdq(%d:%d) cache_ctrl(%d:%d) bus_width (%d:%d) timing(%d:%d)\n", mmc_hostname(host), __func__, card->ext_csd.raw_ext_csd_cmdq, @@ -2292,12 +2292,12 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host) ext_csd[EXT_CSD_BUS_WIDTH]) && (card->ext_csd.raw_ext_csd_hs_timing == ext_csd[EXT_CSD_HS_TIMING])); -#endif kfree(ext_csd); return err; } +#endif static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { @@ -2305,11 +2305,13 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : EXT_CSD_POWER_OFF_LONG; #if defined(CONFIG_SDC_QTI) - err = mmc_suspend_clk_scaling(host); - if (err) { - pr_err("%s: %s: fail to suspend clock scaling (%d)\n", - mmc_hostname(host), __func__, err); - return err; + if (!host->partial_init_broken) { + err = mmc_suspend_clk_scaling(host); + if (err) { + pr_err("%s: %s: fail to suspend clock scaling (%d)\n", + mmc_hostname(host), __func__, err); + return err; + } } #endif mmc_log_string(host, "Enter\n"); @@ -2328,8 +2330,9 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_can_sleep(host->card)) { #if defined(CONFIG_SDC_QTI) memcpy(&host->cached_ios, &host->ios, sizeof(host->cached_ios)); + if (!host->partial_init_broken) #endif - mmc_cache_card_ext_csd(host); + mmc_cache_card_ext_csd(host); } if (mmc_can_sleep(host->card)) err = mmc_sleepawake(host, true); @@ -2351,24 +2354,21 @@ out: return err; } +#if defined(CONFIG_SDC_QTI) static int mmc_partial_init(struct mmc_host *host) { int err = 0; struct mmc_card *card = host->card; -#if defined(CONFIG_SDC_QTI) mmc_set_bus_width(host, host->cached_ios.bus_width); mmc_set_timing(host, host->cached_ios.timing); if (host->cached_ios.enhanced_strobe) { -#endif host->ios.enhanced_strobe = true; if (host->ops->hs400_enhanced_strobe) host->ops->hs400_enhanced_strobe(host, &host->ios); -#if defined(CONFIG_SDC_QTI) } mmc_set_clock(host, host->cached_ios.clock); mmc_set_bus_mode(host, host->cached_ios.bus_mode); -#endif if (!mmc_card_hs400es(card) && (mmc_card_hs200(card) || mmc_card_hs400(card))) { @@ -2396,6 +2396,7 @@ static int mmc_partial_init(struct mmc_host *host) out: return err; } +#endif /* * Suspend callback @@ -2440,14 +2441,23 @@ static int _mmc_resume(struct mmc_host *host) if (mmc_can_sleep(host->card)) { err = mmc_sleepawake(host, false); - if (!err) - err = mmc_partial_init(host); + +#if defined(CONFIG_SDC_QTI) + if (!err) { + if (host->partial_init_broken) + err = mmc_init_card(host, host->card->ocr, host->card); + else + err = mmc_partial_init(host); + } else pr_err("%s: %s: awake failed (%d), fallback to full init\n", mmc_hostname(host), __func__, err); +#endif } +#if defined(CONFIG_SDC_QTI) if (err) +#endif err = mmc_init_card(host, host->card->ocr, host->card); mmc_card_clr_suspended(host->card); @@ -2458,10 +2468,12 @@ out: mmc_release_host(host); #if defined(CONFIG_SDC_QTI) - err = mmc_resume_clk_scaling(host); - if (err) - pr_err("%s: %s: fail to resume clock scaling (%d)\n", - mmc_hostname(host), __func__, err); + if (!host->partial_init_broken) { + err = mmc_resume_clk_scaling(host); + if (err) + pr_err("%s: %s: fail to resume clock scaling (%d)\n", + mmc_hostname(host), __func__, err); + } out: #endif mmc_log_string(host, "Exit err %d\n", err); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 91cc197d5e206..302a779387876 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -3,6 +3,7 @@ * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver * * Copyright (c) 2013-2014,2020. The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1869,6 +1870,12 @@ static bool sdhci_msm_populate_pdata(struct device *dev, if (sdhci_msm_dt_parse_hsr_info(dev, msm_host)) goto out; +#if defined(CONFIG_SDC_QTI) + msm_host->mmc->partial_init_broken = + of_property_read_bool(dev->of_node, + "qcom,partial_init_broken"); +#endif + if (!sdhci_msm_dt_get_array(dev, "qcom,ice-clk-rates", &ice_clk_table, &ice_clk_table_len, 0)) { if (ice_clk_table && ice_clk_table_len) { @@ -4268,6 +4275,11 @@ static void sdhci_msm_set_caps(struct sdhci_msm_host *msm_host) { msm_host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM; msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY; + +#if defined(CONFIG_SDC_QTI) + if (!msm_host->mmc->partial_init_broken) + msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE; +#endif } static int sdhci_msm_probe(struct platform_device *pdev) @@ -4546,8 +4558,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) #if defined(CONFIG_SDC_QTI) host->timeout_clk_div = 4; - msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE; #endif + sdhci_msm_setup_pm(pdev, msm_host); host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 38cfd8faa2d25..af6bc6f7bfd40 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -597,6 +597,7 @@ struct mmc_host { bool hsq_enabled; #if defined(CONFIG_SDC_QTI) bool need_hw_reset; + bool partial_init_broken; #endif #if defined(CONFIG_SDC_QTI)