From efe690d5f51ae4234695c1dd76a68e6f44e83b51 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 Dec 2022 17:34:13 +0100 Subject: [PATCH] 4.14-stable patches added patches: mmc-sdhci-fix-voltage-switch-delay.patch mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch --- .../mmc-sdhci-fix-voltage-switch-delay.patch | 180 ++++++++++++++++++ ...field_get-for-preset-value-bit-masks.patch | 81 ++++++++ queue-4.14/series | 2 + 3 files changed, 263 insertions(+) create mode 100644 queue-4.14/mmc-sdhci-fix-voltage-switch-delay.patch create mode 100644 queue-4.14/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch diff --git a/queue-4.14/mmc-sdhci-fix-voltage-switch-delay.patch b/queue-4.14/mmc-sdhci-fix-voltage-switch-delay.patch new file mode 100644 index 00000000000..04b741a486c --- /dev/null +++ b/queue-4.14/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 +@@ -264,6 +264,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); + } + } +@@ -1658,11 +1659,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; + +@@ -1688,6 +1724,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; + +@@ -1714,6 +1752,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)) { +@@ -1757,6 +1806,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 +@@ -1784,19 +1834,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 */ +@@ -3022,6 +3067,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)); +@@ -3086,6 +3132,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 +@@ -486,6 +486,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-4.14/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch b/queue-4.14/mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch new file mode 100644 index 00000000000..2f482fc391c --- /dev/null +++ b/queue-4.14/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 +@@ -13,6 +13,7 @@ + * - JMicron (hardware and technical support) + */ + ++#include + #include + #include + #include +@@ -1340,10 +1341,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; +@@ -1795,8 +1795,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 +@@ -13,6 +13,7 @@ + #ifndef __SDHCI_HW_H + #define __SDHCI_HW_H + ++#include + #include + #include + #include +@@ -259,12 +260,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-4.14/series b/queue-4.14/series index 7322a15059d..687e2a31c31 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -73,3 +73,5 @@ x86-tsx-add-a-feature-bit-for-tsx-control-msr-support.patch x86-pm-add-enumeration-check-before-spec-msrs-save-restore-setup.patch bluetooth-l2cap-fix-accepting-connection-request-for-invalid-spsm.patch x86-ioremap-fix-page-aligned-size-calculation-in-__i.patch +mmc-sdhci-use-field_get-for-preset-value-bit-masks.patch +mmc-sdhci-fix-voltage-switch-delay.patch -- 2.47.3