@@ -373,6 +373,7 @@ static void sdhci_init(struct sdhci_host *host, int soft)
373373 if (soft ) {
374374 /* force clock reconfiguration */
375375 host -> clock = 0 ;
376+ host -> reinit_uhs = true;
376377 mmc -> ops -> set_ios (mmc , & mmc -> ios );
377378 }
378379}
@@ -2293,11 +2294,46 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
22932294}
22942295EXPORT_SYMBOL_GPL (sdhci_set_uhs_signaling );
22952296
2297+ static bool sdhci_timing_has_preset (unsigned char timing )
2298+ {
2299+ switch (timing ) {
2300+ case MMC_TIMING_UHS_SDR12 :
2301+ case MMC_TIMING_UHS_SDR25 :
2302+ case MMC_TIMING_UHS_SDR50 :
2303+ case MMC_TIMING_UHS_SDR104 :
2304+ case MMC_TIMING_UHS_DDR50 :
2305+ case MMC_TIMING_MMC_DDR52 :
2306+ return true;
2307+ };
2308+ return false;
2309+ }
2310+
2311+ static bool sdhci_preset_needed (struct sdhci_host * host , unsigned char timing )
2312+ {
2313+ return !(host -> quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN ) &&
2314+ sdhci_timing_has_preset (timing );
2315+ }
2316+
2317+ static bool sdhci_presetable_values_change (struct sdhci_host * host , struct mmc_ios * ios )
2318+ {
2319+ /*
2320+ * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
2321+ * Frequency. Check if preset values need to be enabled, or the Driver
2322+ * Strength needs updating. Note, clock changes are handled separately.
2323+ */
2324+ return !host -> preset_enabled &&
2325+ (sdhci_preset_needed (host , ios -> timing ) || host -> drv_type != ios -> drv_type );
2326+ }
2327+
22962328void sdhci_set_ios (struct mmc_host * mmc , struct mmc_ios * ios )
22972329{
22982330 struct sdhci_host * host = mmc_priv (mmc );
2331+ bool reinit_uhs = host -> reinit_uhs ;
2332+ bool turning_on_clk = false;
22992333 u8 ctrl ;
23002334
2335+ host -> reinit_uhs = false;
2336+
23012337 if (ios -> power_mode == MMC_POWER_UNDEFINED )
23022338 return ;
23032339
@@ -2323,6 +2359,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
23232359 sdhci_enable_preset_value (host , false);
23242360
23252361 if (!ios -> clock || ios -> clock != host -> clock ) {
2362+ turning_on_clk = ios -> clock && !host -> clock ;
2363+
23262364 host -> ops -> set_clock (host , ios -> clock );
23272365 host -> clock = ios -> clock ;
23282366
@@ -2349,6 +2387,17 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
23492387
23502388 host -> ops -> set_bus_width (host , ios -> bus_width );
23512389
2390+ /*
2391+ * Special case to avoid multiple clock changes during voltage
2392+ * switching.
2393+ */
2394+ if (!reinit_uhs &&
2395+ turning_on_clk &&
2396+ host -> timing == ios -> timing &&
2397+ host -> version >= SDHCI_SPEC_300 &&
2398+ !sdhci_presetable_values_change (host , ios ))
2399+ return ;
2400+
23522401 ctrl = sdhci_readb (host , SDHCI_HOST_CONTROL );
23532402
23542403 if (!(host -> quirks & SDHCI_QUIRK_NO_HISPD_BIT )) {
@@ -2392,6 +2441,7 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
23922441 }
23932442
23942443 sdhci_writew (host , ctrl_2 , SDHCI_HOST_CONTROL2 );
2444+ host -> drv_type = ios -> drv_type ;
23952445 } else {
23962446 /*
23972447 * According to SDHC Spec v3.00, if the Preset Value
@@ -2419,19 +2469,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
24192469 host -> ops -> set_uhs_signaling (host , ios -> timing );
24202470 host -> timing = ios -> timing ;
24212471
2422- if (!(host -> quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN ) &&
2423- ((ios -> timing == MMC_TIMING_UHS_SDR12 ) ||
2424- (ios -> timing == MMC_TIMING_UHS_SDR25 ) ||
2425- (ios -> timing == MMC_TIMING_UHS_SDR50 ) ||
2426- (ios -> timing == MMC_TIMING_UHS_SDR104 ) ||
2427- (ios -> timing == MMC_TIMING_UHS_DDR50 ) ||
2428- (ios -> timing == MMC_TIMING_MMC_DDR52 ))) {
2472+ if (sdhci_preset_needed (host , ios -> timing )) {
24292473 u16 preset ;
24302474
24312475 sdhci_enable_preset_value (host , true);
24322476 preset = sdhci_get_preset_value (host );
24332477 ios -> drv_type = FIELD_GET (SDHCI_PRESET_DRV_MASK ,
24342478 preset );
2479+ host -> drv_type = ios -> drv_type ;
24352480 }
24362481
24372482 /* Re-enable SD Clock */
@@ -3768,6 +3813,7 @@ int sdhci_resume_host(struct sdhci_host *host)
37683813 sdhci_init (host , 0 );
37693814 host -> pwr = 0 ;
37703815 host -> clock = 0 ;
3816+ host -> reinit_uhs = true;
37713817 mmc -> ops -> set_ios (mmc , & mmc -> ios );
37723818 } else {
37733819 sdhci_init (host , (mmc -> pm_flags & MMC_PM_KEEP_POWER ));
@@ -3830,6 +3876,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
38303876 /* Force clock and power re-program */
38313877 host -> pwr = 0 ;
38323878 host -> clock = 0 ;
3879+ host -> reinit_uhs = true;
38333880 mmc -> ops -> start_signal_voltage_switch (mmc , & mmc -> ios );
38343881 mmc -> ops -> set_ios (mmc , & mmc -> ios );
38353882
0 commit comments