summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/mmc.c32
-rw-r--r--include/linux/mmc/host.h2
2 files changed, 32 insertions, 2 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index fda54ff43720..39bf4455d16a 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1550,6 +1550,24 @@ out:
return ret;
}
+static int mmc_select_hs_ddr52(struct mmc_host *host)
+{
+ int err;
+
+ mmc_select_hs(host->card);
+ mmc_set_clock(host, MMC_HIGH_52_MAX_DTR);
+ err = mmc_select_bus_width(host->card);
+ if (err < 0) {
+ pr_err("%s: %s: select_bus_width failed(%d)\n",
+ mmc_hostname(host), __func__, err);
+ return err;
+ }
+
+ err = mmc_select_hs_ddr(host->card);
+
+ return err;
+}
+
/*
* Scale down from HS400 to HS in order to allow frequency change.
* This is needed for cards that doesn't support changing frequency in HS400
@@ -1561,10 +1579,20 @@ static int mmc_scale_low(struct mmc_host *host, unsigned long freq)
mmc_set_timing(host, MMC_TIMING_LEGACY);
mmc_set_clock(host, MMC_HIGH_26_MAX_DTR);
+ if (host->clk_scaling.lower_bus_speed_mode &
+ MMC_SCALING_LOWER_DDR52_MODE) {
+ err = mmc_select_hs_ddr52(host);
+ if (err)
+ pr_err("%s: %s: failed to switch to DDR52: err: %d\n",
+ mmc_hostname(host), __func__, err);
+ else
+ return err;
+ }
+
err = mmc_select_hs(host->card);
if (err) {
- pr_err("%s: %s: selecting HS (52Mhz) failed (%d)\n",
- mmc_hostname(host), __func__, err);
+ pr_err("%s: %s: scaling low: failed (%d)\n",
+ mmc_hostname(host), __func__, err);
return err;
}
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index e6dd9eb4ead4..38731725cc80 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -335,6 +335,8 @@ struct mmc_devfeq_clk_scaling {
unsigned long polling_delay_ms;
unsigned int upthreshold;
unsigned int downthreshold;
+ unsigned int lower_bus_speed_mode;
+#define MMC_SCALING_LOWER_DDR52_MODE 1
bool need_freq_change;
bool clk_scaling_in_progress;
bool is_busy_started;