Hi,
On SDHC version 3.0 controllers the divisor doesn't have to be a power
of two, but can be a multiple of two. This means we can get a lot
closer to the target clock.
E.g. to reach 400 kHz on a 200 MHz bus clock, the old mechanism would
take 512 as divisor (== 390.612 kHz) while the new mechanism would use
divisor 500 and reach exactly 400 kHz.
ok?
Patrick
diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c
index 28923e22279..a2866b23ce5 100644
--- a/sys/dev/sdmmc/sdhc.c
+++ b/sys/dev/sdmmc/sdhc.c
@@ -635,15 +635,21 @@ sdhc_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr)
static int
sdhc_clock_divisor(struct sdhc_host *hp, u_int freq)
{
- int max_div = SDHC_SDCLK_DIV_MAX;
int div;
- if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3)
- max_div = SDHC_SDCLK_DIV_MAX_V3;
+ if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
+ if (hp->clkbase <= freq)
+ return 0;
+
+ for (div = 2; div <= SDHC_SDCLK_DIV_MAX_V3; div += 2)
+ if ((hp->clkbase / div) <= freq)
+ return (div / 2);
+ } else {
+ for (div = 1; div <= SDHC_SDCLK_DIV_MAX; div *= 2)
+ if ((hp->clkbase / div) <= freq)
+ return (div / 2);
+ }
- for (div = 1; div <= max_div; div *= 2)
- if ((hp->clkbase / div) <= freq)
- return (div / 2);
/* No divisor found. */
return -1;
}