From: Greg Kroah-Hartman Date: Mon, 5 Dec 2022 16:34:28 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v4.9.335~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bca417789eb739c0bff396fdb918f2f99a4c048d;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: mmc-sdhci-fix-voltage-switch-delay.patch mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch --- diff --git a/queue-5.4/mmc-sdhci-fix-voltage-switch-delay.patch b/queue-5.4/mmc-sdhci-fix-voltage-switch-delay.patch new file mode 100644 index 00000000000..ae454f00190 --- /dev/null +++ b/queue-5.4/mmc-sdhci-fix-voltage-switch-delay.patch @@ -0,0 +1,180 @@ +From c981cdfb9925f64a364f13c2b4f98f877308a408 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Mon, 28 Nov 2022 15:32:56 +0200 +Subject: mmc: sdhci: Fix voltage switch delay + +From: Adrian Hunter + +commit c981cdfb9925f64a364f13c2b4f98f877308a408 upstream. + +Commit 20b92a30b561 ("mmc: sdhci: update signal voltage switch code") +removed voltage switch delays from sdhci because mmc core had been +enhanced to support them. However that assumed that sdhci_set_ios() +did a single clock change, which it did not, and so the delays in mmc +core, which should have come after the first clock change, were not +effective. + +Fix by avoiding re-configuring UHS and preset settings when the clock +is turning on and the settings have not changed. That then also avoids +the associated clock changes, so that then sdhci_set_ios() does a single +clock change when voltage switching, and the mmc core delays become +effective. + +To do that has meant keeping track of driver strength (host->drv_type), +and cases of reinitialization (host->reinit_uhs). + +Note also, the 'turning_on_clk' restriction should not be necessary +but is done to minimize the impact of the change on stable kernels. + +Fixes: 20b92a30b561 ("mmc: sdhci: update signal voltage switch code") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Link: https://lore.kernel.org/r/20221128133259.38305-2-adrian.hunter@intel.com +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci.c | 61 +++++++++++++++++++++++++++++++++++++++++------ + drivers/mmc/host/sdhci.h | 2 + + 2 files changed, 56 insertions(+), 7 deletions(-) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -332,6 +332,7 @@ static void sdhci_init(struct sdhci_host + if (soft) { + /* force clock reconfiguration */ + host->clock = 0; ++ host->reinit_uhs = true; + mmc->ops->set_ios(mmc, &mmc->ios); + } + } +@@ -1911,11 +1912,46 @@ void sdhci_set_uhs_signaling(struct sdhc + } + EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); + ++static bool sdhci_timing_has_preset(unsigned char timing) ++{ ++ switch (timing) { ++ case MMC_TIMING_UHS_SDR12: ++ case MMC_TIMING_UHS_SDR25: ++ case MMC_TIMING_UHS_SDR50: ++ case MMC_TIMING_UHS_SDR104: ++ case MMC_TIMING_UHS_DDR50: ++ case MMC_TIMING_MMC_DDR52: ++ return true; ++ }; ++ return false; ++} ++ ++static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing) ++{ ++ return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ++ sdhci_timing_has_preset(timing); ++} ++ ++static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios) ++{ ++ /* ++ * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK ++ * Frequency. Check if preset values need to be enabled, or the Driver ++ * Strength needs updating. Note, clock changes are handled separately. ++ */ ++ return !host->preset_enabled && ++ (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type); ++} ++ + void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + { + struct sdhci_host *host = mmc_priv(mmc); ++ bool reinit_uhs = host->reinit_uhs; ++ bool turning_on_clk = false; + u8 ctrl; + ++ host->reinit_uhs = false; ++ + if (ios->power_mode == MMC_POWER_UNDEFINED) + return; + +@@ -1941,6 +1977,8 @@ void sdhci_set_ios(struct mmc_host *mmc, + sdhci_enable_preset_value(host, false); + + if (!ios->clock || ios->clock != host->clock) { ++ turning_on_clk = ios->clock && !host->clock; ++ + host->ops->set_clock(host, ios->clock); + host->clock = ios->clock; + +@@ -1967,6 +2005,17 @@ void sdhci_set_ios(struct mmc_host *mmc, + + host->ops->set_bus_width(host, ios->bus_width); + ++ /* ++ * Special case to avoid multiple clock changes during voltage ++ * switching. ++ */ ++ if (!reinit_uhs && ++ turning_on_clk && ++ host->timing == ios->timing && ++ host->version >= SDHCI_SPEC_300 && ++ !sdhci_presetable_values_change(host, ios)) ++ return; ++ + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + + if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { +@@ -2010,6 +2059,7 @@ void sdhci_set_ios(struct mmc_host *mmc, + } + + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); ++ host->drv_type = ios->drv_type; + } else { + /* + * According to SDHC Spec v3.00, if the Preset Value +@@ -2037,19 +2087,14 @@ void sdhci_set_ios(struct mmc_host *mmc, + host->ops->set_uhs_signaling(host, ios->timing); + host->timing = ios->timing; + +- if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && +- ((ios->timing == MMC_TIMING_UHS_SDR12) || +- (ios->timing == MMC_TIMING_UHS_SDR25) || +- (ios->timing == MMC_TIMING_UHS_SDR50) || +- (ios->timing == MMC_TIMING_UHS_SDR104) || +- (ios->timing == MMC_TIMING_UHS_DDR50) || +- (ios->timing == MMC_TIMING_MMC_DDR52))) { ++ if (sdhci_preset_needed(host, ios->timing)) { + u16 preset; + + sdhci_enable_preset_value(host, true); + preset = sdhci_get_preset_value(host); + ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, + preset); ++ host->drv_type = ios->drv_type; + } + + /* Re-enable SD Clock */ +@@ -3327,6 +3372,7 @@ int sdhci_resume_host(struct sdhci_host + sdhci_init(host, 0); + host->pwr = 0; + host->clock = 0; ++ host->reinit_uhs = true; + mmc->ops->set_ios(mmc, &mmc->ios); + } else { + sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); +@@ -3389,6 +3435,7 @@ int sdhci_runtime_resume_host(struct sdh + /* Force clock and power re-program */ + host->pwr = 0; + host->clock = 0; ++ host->reinit_uhs = true; + mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); + mmc->ops->set_ios(mmc, &mmc->ios); + +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -528,6 +528,8 @@ struct sdhci_host { + + unsigned int clock; /* Current clock (MHz) */ + u8 pwr; /* Current voltage */ ++ u8 drv_type; /* Current UHS-I driver type */ ++ bool reinit_uhs; /* Force UHS-related re-initialization */ + + bool runtime_suspended; /* Host is runtime suspended */ + bool bus_on; /* Bus power prevents runtime suspend */ diff --git a/queue-5.4/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch b/queue-5.4/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch new file mode 100644 index 00000000000..fdac8a76f5c --- /dev/null +++ b/queue-5.4/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch @@ -0,0 +1,81 @@ +From fa0910107a9fea170b817f31da2a65463e00e80e Mon Sep 17 00:00:00 2001 +From: Masahiro Yamada +Date: Thu, 12 Mar 2020 20:00:50 +0900 +Subject: mmc: sdhci: use FIELD_GET for preset value bit masks + +From: Masahiro Yamada + +commit fa0910107a9fea170b817f31da2a65463e00e80e upstream. + +Use the FIELD_GET macro to get access to the register fields. +Delete the shift macros. + +Signed-off-by: Masahiro Yamada +Link: https://lore.kernel.org/r/20200312110050.21732-1-yamada.masahiro@socionext.com +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman +--- + drivers/mmc/host/sdhci.c | 10 +++++----- + drivers/mmc/host/sdhci.h | 10 ++++------ + 2 files changed, 9 insertions(+), 11 deletions(-) + +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -9,6 +9,7 @@ + * - JMicron (hardware and technical support) + */ + ++#include + #include + #include + #include +@@ -1570,10 +1571,9 @@ u16 sdhci_calc_clk(struct sdhci_host *ho + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + pre_val = sdhci_get_preset_value(host); +- div = (pre_val & SDHCI_PRESET_SDCLK_FREQ_MASK) +- >> SDHCI_PRESET_SDCLK_FREQ_SHIFT; ++ div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); + if (host->clk_mul && +- (pre_val & SDHCI_PRESET_CLKGEN_SEL_MASK)) { ++ (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { + clk = SDHCI_PROG_CLOCK_MODE; + real_div = div + 1; + clk_mul = host->clk_mul; +@@ -2048,8 +2048,8 @@ void sdhci_set_ios(struct mmc_host *mmc, + + sdhci_enable_preset_value(host, true); + preset = sdhci_get_preset_value(host); +- ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK) +- >> SDHCI_PRESET_DRV_SHIFT; ++ ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, ++ preset); + } + + /* Re-enable SD Clock */ +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -9,6 +9,7 @@ + #ifndef __SDHCI_HW_H + #define __SDHCI_HW_H + ++#include + #include + #include + #include +@@ -268,12 +269,9 @@ + #define SDHCI_PRESET_FOR_SDR104 0x6C + #define SDHCI_PRESET_FOR_DDR50 0x6E + #define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ +-#define SDHCI_PRESET_DRV_MASK 0xC000 +-#define SDHCI_PRESET_DRV_SHIFT 14 +-#define SDHCI_PRESET_CLKGEN_SEL_MASK 0x400 +-#define SDHCI_PRESET_CLKGEN_SEL_SHIFT 10 +-#define SDHCI_PRESET_SDCLK_FREQ_MASK 0x3FF +-#define SDHCI_PRESET_SDCLK_FREQ_SHIFT 0 ++#define SDHCI_PRESET_DRV_MASK GENMASK(15, 14) ++#define SDHCI_PRESET_CLKGEN_SEL BIT(10) ++#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0) + + #define SDHCI_SLOT_INT_STATUS 0xFC + diff --git a/queue-5.4/series b/queue-5.4/series index ac34bb0403a..ba286d09a34 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -156,3 +156,5 @@ bluetooth-l2cap-fix-accepting-connection-request-for-invalid-spsm.patch x86-ioremap-fix-page-aligned-size-calculation-in-__i.patch revert-clocksource-drivers-riscv-events-are-stopped-.patch char-tpm-protect-tpm_pm_suspend-with-locks.patch +mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch +mmc-sdhci-fix-voltage-switch-delay.patch