Skip to content

Commit 5497159

Browse files
ldesrochesstorulf
authored andcommitted
mmc: sdhci: switch from programmable clock mode to divided one if needed
In programmable mode, if the clock frequency is too high, the divider can be too small to meet the clock frequency requirement especially to init the SD card. In this case, switch to the divided clock mode. Signed-off-by: Ludovic Desroches <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent 57e1048 commit 5497159

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

drivers/mmc/host/sdhci.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
11511151
int real_div = div, clk_mul = 1;
11521152
u16 clk = 0;
11531153
unsigned long timeout;
1154+
bool switch_base_clk = false;
11541155

11551156
host->mmc->actual_clock = 0;
11561157

@@ -1188,15 +1189,25 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
11881189
<= clock)
11891190
break;
11901191
}
1191-
/*
1192-
* Set Programmable Clock Mode in the Clock
1193-
* Control register.
1194-
*/
1195-
clk = SDHCI_PROG_CLOCK_MODE;
1196-
real_div = div;
1197-
clk_mul = host->clk_mul;
1198-
div--;
1199-
} else {
1192+
if ((host->max_clk * host->clk_mul / div) <= clock) {
1193+
/*
1194+
* Set Programmable Clock Mode in the Clock
1195+
* Control register.
1196+
*/
1197+
clk = SDHCI_PROG_CLOCK_MODE;
1198+
real_div = div;
1199+
clk_mul = host->clk_mul;
1200+
div--;
1201+
} else {
1202+
/*
1203+
* Divisor can be too small to reach clock
1204+
* speed requirement. Then use the base clock.
1205+
*/
1206+
switch_base_clk = true;
1207+
}
1208+
}
1209+
1210+
if (!host->clk_mul || switch_base_clk) {
12001211
/* Version 3.00 divisors must be a multiple of 2. */
12011212
if (host->max_clk <= clock)
12021213
div = 1;

0 commit comments

Comments
 (0)