Skip to content

Commit 9285d04

Browse files
sartgarggregkh
authored andcommitted
mmc: sdhci-msm: Avoid early clock doubling during HS400 transition
commit b1f856b upstream. According to the hardware programming guide, the clock frequency must remain below 52MHz during the transition to HS400 mode. However,in the current implementation, the timing is set to HS400 (a DDR mode) before adjusting the clock. This causes the clock to double prematurely to 104MHz during the transition phase, violating the specification and potentially resulting in CRC errors or CMD timeouts. This change ensures that clock doubling is avoided during intermediate transitions and is applied only when the card requires a 200MHz clock for HS400 operation. Signed-off-by: Sarthak Garg <sarthak.garg@oss.qualcomm.com> Reviewed-by: Bjorn Andersson <andersson@kernel.org> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4bb9164 commit 9285d04

1 file changed

Lines changed: 15 additions & 12 deletions

File tree

drivers/mmc/host/sdhci-msm.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -344,41 +344,43 @@ static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
344344
writel_relaxed(val, host->ioaddr + offset);
345345
}
346346

347-
static unsigned int msm_get_clock_mult_for_bus_mode(struct sdhci_host *host)
347+
static unsigned int msm_get_clock_mult_for_bus_mode(struct sdhci_host *host,
348+
unsigned int clock,
349+
unsigned int timing)
348350
{
349-
struct mmc_ios ios = host->mmc->ios;
350351
/*
351352
* The SDHC requires internal clock frequency to be double the
352353
* actual clock that will be set for DDR mode. The controller
353354
* uses the faster clock(100/400MHz) for some of its parts and
354355
* send the actual required clock (50/200MHz) to the card.
355356
*/
356-
if (ios.timing == MMC_TIMING_UHS_DDR50 ||
357-
ios.timing == MMC_TIMING_MMC_DDR52 ||
358-
ios.timing == MMC_TIMING_MMC_HS400 ||
357+
if (timing == MMC_TIMING_UHS_DDR50 ||
358+
timing == MMC_TIMING_MMC_DDR52 ||
359+
(timing == MMC_TIMING_MMC_HS400 &&
360+
clock == MMC_HS200_MAX_DTR) ||
359361
host->flags & SDHCI_HS400_TUNING)
360362
return 2;
361363
return 1;
362364
}
363365

364366
static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host,
365-
unsigned int clock)
367+
unsigned int clock,
368+
unsigned int timing)
366369
{
367370
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
368371
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
369-
struct mmc_ios curr_ios = host->mmc->ios;
370372
struct clk *core_clk = msm_host->bulk_clks[0].clk;
371373
unsigned long achieved_rate;
372374
unsigned int desired_rate;
373375
unsigned int mult;
374376
int rc;
375377

376-
mult = msm_get_clock_mult_for_bus_mode(host);
378+
mult = msm_get_clock_mult_for_bus_mode(host, clock, timing);
377379
desired_rate = clock * mult;
378380
rc = dev_pm_opp_set_rate(mmc_dev(host->mmc), desired_rate);
379381
if (rc) {
380382
pr_err("%s: Failed to set clock at rate %u at timing %d\n",
381-
mmc_hostname(host->mmc), desired_rate, curr_ios.timing);
383+
mmc_hostname(host->mmc), desired_rate, timing);
382384
return;
383385
}
384386

@@ -397,7 +399,7 @@ static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host,
397399
msm_host->clk_rate = desired_rate;
398400

399401
pr_debug("%s: Setting clock at rate %lu at timing %d\n",
400-
mmc_hostname(host->mmc), achieved_rate, curr_ios.timing);
402+
mmc_hostname(host->mmc), achieved_rate, timing);
401403
}
402404

403405
/* Platform specific tuning */
@@ -1239,7 +1241,7 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
12391241
*/
12401242
if (host->flags & SDHCI_HS400_TUNING) {
12411243
sdhci_msm_hc_select_mode(host);
1242-
msm_set_clock_rate_for_bus_mode(host, ios.clock);
1244+
msm_set_clock_rate_for_bus_mode(host, ios.clock, ios.timing);
12431245
host->flags &= ~SDHCI_HS400_TUNING;
12441246
}
12451247

@@ -1864,6 +1866,7 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
18641866
{
18651867
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
18661868
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
1869+
struct mmc_ios ios = host->mmc->ios;
18671870

18681871
if (!clock) {
18691872
host->mmc->actual_clock = msm_host->clk_rate = 0;
@@ -1872,7 +1875,7 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
18721875

18731876
sdhci_msm_hc_select_mode(host);
18741877

1875-
msm_set_clock_rate_for_bus_mode(host, clock);
1878+
msm_set_clock_rate_for_bus_mode(host, ios.clock, ios.timing);
18761879
out:
18771880
__sdhci_msm_set_clock(host, clock);
18781881
}

0 commit comments

Comments
 (0)