Commit 6d0e34bf4e21596563e5f5950d097a2eab4c81a8

Authored by Stefan Herbrechtsmeier
Committed by Jaehoon Chung
1 parent 0c9e85f67c

mmc: sdhci: Distinguish between base clock and maximum peripheral frequency

The sdhci controller assumes that the base clock frequency is fully supported by
the peripheral and doesn't support hardware limitations. The Linux kernel
distinguishes between base clock (max_clk) of the host controller and maximum
frequency (f_max) of the card interface. Use the same differentiation and allow
the platform to constrain the peripheral interface.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Showing 13 changed files with 52 additions and 34 deletions Side-by-side Diff

drivers/mmc/atmel_sdhci.c
... ... @@ -35,8 +35,9 @@
35 35 free(host);
36 36 return -ENODEV;
37 37 }
  38 + host->max_clk = max_clk;
38 39  
39   - add_sdhci(host, max_clk, min_clk);
  40 + add_sdhci(host, 0, min_clk);
40 41  
41 42 return 0;
42 43 }
... ... @@ -95,7 +96,9 @@
95 96 if (!max_clk)
96 97 return -EINVAL;
97 98  
98   - ret = sdhci_setup_cfg(&plat->cfg, host, max_clk, ATMEL_SDHC_MIN_FREQ);
  99 + host->max_clk = max_clk;
  100 +
  101 + ret = sdhci_setup_cfg(&plat->cfg, host, 0, ATMEL_SDHC_MIN_FREQ);
99 102 if (ret)
100 103 return ret;
101 104  
drivers/mmc/bcm2835_sdhci.c
... ... @@ -181,10 +181,11 @@
181 181 host->ioaddr = (void *)(unsigned long)regbase;
182 182 host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
183 183 SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT;
  184 + host->max_clk = emmc_freq;
184 185 host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
185 186 host->ops = &bcm2835_ops;
186 187  
187   - add_sdhci(host, emmc_freq, MIN_FREQ);
  188 + add_sdhci(host, 0, MIN_FREQ);
188 189  
189 190 return 0;
190 191 }
drivers/mmc/ftsdc021_sdhci.c
... ... @@ -27,7 +27,8 @@
27 27 host->name = "FTSDC021";
28 28 host->ioaddr = (void __iomem *)regbase;
29 29 host->quirks = 0;
30   - add_sdhci(host, freq, 0);
  30 + host->max_clk = freq;
  31 + add_sdhci(host, 0, 0);
31 32  
32 33 return 0;
33 34 }
drivers/mmc/kona_sdhci.c
... ... @@ -121,13 +121,14 @@
121 121 host->name = "kona-sdhci";
122 122 host->ioaddr = reg_base;
123 123 host->quirks = quirks;
  124 + host->max_clk = max_clk;
124 125  
125 126 if (init_kona_mmc_core(host)) {
126 127 free(host);
127 128 return -EINVAL;
128 129 }
129 130  
130   - add_sdhci(host, max_clk, min_clk);
  131 + add_sdhci(host, 0, min_clk);
131 132 return ret;
132 133 }
drivers/mmc/msm_sdhci.c
... ... @@ -96,6 +96,8 @@
96 96  
97 97 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
98 98  
  99 + host->max_clk = 0;
  100 +
99 101 /* Init clocks */
100 102 ret = msm_sdc_clk_init(dev);
101 103 if (ret)
drivers/mmc/mv_sdhci.c
... ... @@ -77,6 +77,7 @@
77 77 host->name = MVSDH_NAME;
78 78 host->ioaddr = (void *)regbase;
79 79 host->quirks = quirks;
  80 + host->max_clk = max_clk;
80 81 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
81 82 memset(&mv_ops, 0, sizeof(struct sdhci_ops));
82 83 mv_ops.write_b = mv_sdhci_writeb;
... ... @@ -88,6 +89,6 @@
88 89 sdhci_mvebu_mbus_config((void __iomem *)regbase);
89 90 }
90 91  
91   - return add_sdhci(host, max_clk, min_clk);
  92 + return add_sdhci(host, 0, min_clk);
92 93 }
drivers/mmc/pci_mmc.c
... ... @@ -32,6 +32,7 @@
32 32 dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
33 33 mmc_host->ioaddr = (void *)(ulong)iobase;
34 34 mmc_host->quirks = 0;
  35 + mmc_host->max_clk = 0;
35 36 ret = add_sdhci(mmc_host, 0, 0);
36 37 if (ret)
37 38 return ret;
drivers/mmc/pic32_sdhci.c
... ... @@ -56,7 +56,9 @@
56 56 return ret;
57 57 }
58 58  
59   - ret = add_sdhci(host, f_min_max[1], f_min_max[0]);
  59 + host->max_clk = f_min_max[1];
  60 +
  61 + ret = add_sdhci(host, 0, f_min_max[0]);
60 62 if (ret)
61 63 return ret;
62 64 host->mmc->dev = dev;
drivers/mmc/rockchip_sdhci.c
... ... @@ -50,9 +50,9 @@
50 50 }
51 51  
52 52 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
  53 + host->max_clk = max_frequency;
53 54  
54   - ret = sdhci_setup_cfg(&plat->cfg, host, max_frequency,
55   - EMMC_MIN_FREQ);
  55 + ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
56 56  
57 57 host->mmc = &plat->mmc;
58 58 if (ret)
drivers/mmc/s5p_sdhci.c
... ... @@ -91,6 +91,7 @@
91 91 host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
92 92 SDHCI_QUIRK_32BIT_DMA_ADDR |
93 93 SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_USE_WIDE8;
  94 + host->max_clk = 52000000;
94 95 host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
95 96 host->ops = &s5p_sdhci_ops;
96 97  
... ... @@ -98,7 +99,7 @@
98 99 host->host_caps |= MMC_MODE_8BIT;
99 100  
100 101 #ifndef CONFIG_BLK
101   - return add_sdhci(host, 52000000, 400000);
  102 + return add_sdhci(host, 0, 400000);
102 103 #else
103 104 return 0;
104 105 #endif
... ... @@ -254,7 +255,7 @@
254 255 if (ret)
255 256 return ret;
256 257  
257   - ret = sdhci_setup_cfg(&plat->cfg, host, 52000000, 400000);
  258 + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 400000);
258 259 if (ret)
259 260 return ret;
260 261  
... ... @@ -325,7 +325,7 @@
325 325 */
326 326 if (host->clk_mul) {
327 327 for (div = 1; div <= 1024; div++) {
328   - if ((mmc->cfg->f_max * host->clk_mul / div)
  328 + if ((host->max_clk * host->clk_mul / div)
329 329 <= clock)
330 330 break;
331 331 }
332 332  
... ... @@ -338,13 +338,13 @@
338 338 div--;
339 339 } else {
340 340 /* Version 3.00 divisors must be a multiple of 2. */
341   - if (mmc->cfg->f_max <= clock) {
  341 + if (host->max_clk <= clock) {
342 342 div = 1;
343 343 } else {
344 344 for (div = 2;
345 345 div < SDHCI_MAX_DIV_SPEC_300;
346 346 div += 2) {
347   - if ((mmc->cfg->f_max / div) <= clock)
  347 + if ((host->max_clk / div) <= clock)
348 348 break;
349 349 }
350 350 }
... ... @@ -353,7 +353,7 @@
353 353 } else {
354 354 /* Version 2.00 divisors must be a power of 2. */
355 355 for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
356   - if ((mmc->cfg->f_max / div) <= clock)
  356 + if ((host->max_clk / div) <= clock)
357 357 break;
358 358 }
359 359 div >>= 1;
... ... @@ -513,7 +513,7 @@
513 513 #endif
514 514  
515 515 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
516   - u32 max_clk, u32 min_clk)
  516 + u32 f_max, u32 f_min)
517 517 {
518 518 u32 caps, caps_1;
519 519  
520 520  
521 521  
522 522  
523 523  
524 524  
... ... @@ -536,24 +536,26 @@
536 536 #ifndef CONFIG_DM_MMC_OPS
537 537 cfg->ops = &sdhci_ops;
538 538 #endif
539   - if (max_clk)
540   - cfg->f_max = max_clk;
541   - else {
  539 + if (host->max_clk == 0) {
542 540 if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
543   - cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
  541 + host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
544 542 SDHCI_CLOCK_BASE_SHIFT;
545 543 else
546   - cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >>
  544 + host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >>
547 545 SDHCI_CLOCK_BASE_SHIFT;
548   - cfg->f_max *= 1000000;
  546 + host->max_clk *= 1000000;
549 547 }
550   - if (cfg->f_max == 0) {
  548 + if (host->max_clk == 0) {
551 549 printf("%s: Hardware doesn't specify base clock frequency\n",
552 550 __func__);
553 551 return -EINVAL;
554 552 }
555   - if (min_clk)
556   - cfg->f_min = min_clk;
  553 + if (f_max && (f_max < host->max_clk))
  554 + cfg->f_max = f_max;
  555 + else
  556 + cfg->f_max = host->max_clk;
  557 + if (f_min)
  558 + cfg->f_min = f_min;
557 559 else {
558 560 if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
559 561 cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;
560 562  
... ... @@ -598,11 +600,11 @@
598 600 return mmc_bind(dev, mmc, cfg);
599 601 }
600 602 #else
601   -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
  603 +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min)
602 604 {
603 605 int ret;
604 606  
605   - ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk);
  607 + ret = sdhci_setup_cfg(&host->cfg, host, f_max, f_min);
606 608 if (ret)
607 609 return ret;
608 610  
drivers/mmc/zynq_sdhci.c
... ... @@ -36,7 +36,9 @@
36 36 host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
37 37 #endif
38 38  
39   - ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
  39 + host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
  40 +
  41 + ret = sdhci_setup_cfg(&plat->cfg, host, 0,
40 42 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
41 43 host->mmc = &plat->mmc;
42 44 if (ret)
... ... @@ -244,6 +244,7 @@
244 244 unsigned int quirks;
245 245 unsigned int host_caps;
246 246 unsigned int version;
  247 + unsigned int max_clk; /* Maximum Base Clock frequency */
247 248 unsigned int clk_mul; /* Clock Multiplier value */
248 249 unsigned int clock;
249 250 struct mmc *mmc;
250 251  
... ... @@ -371,11 +372,11 @@
371 372 *
372 373 * @cfg: Configuration structure to fill in (generally &plat->mmc)
373 374 * @host: SDHCI host structure
374   - * @max_clk: Maximum supported clock speed in HZ (0 for default)
375   - * @min_clk: Minimum supported clock speed in HZ (0 for default)
  375 + * @f_max: Maximum supported clock frequency in HZ (0 for default)
  376 + * @f_min: Minimum supported clock frequency in HZ (0 for default)
376 377 */
377 378 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
378   - u32 max_clk, u32 min_clk);
  379 + u32 f_max, u32 f_min);
379 380  
380 381 /**
381 382 * sdhci_bind() - Set up a new MMC block device
382 383  
... ... @@ -401,11 +402,11 @@
401 402 * This is used when you are not using CONFIG_BLK. Convert your driver over!
402 403 *
403 404 * @host: SDHCI host structure
404   - * @max_clk: Maximum supported clock speed in HZ (0 for default)
405   - * @min_clk: Minimum supported clock speed in HZ (0 for default)
  405 + * @f_max: Maximum supported clock frequency in HZ (0 for default)
  406 + * @f_min: Minimum supported clock frequency in HZ (0 for default)
406 407 * @return 0 if OK, -ve on error
407 408 */
408   -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk);
  409 +int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
409 410 #endif /* !CONFIG_BLK */
410 411  
411 412 #ifdef CONFIG_DM_MMC_OPS