diff options
-rw-r--r-- | drivers/mmc/host/mmci.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 8741d0f5146a..031141a7c87e 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -38,6 +38,33 @@ | |||
38 | 38 | ||
39 | static unsigned int fmax = 515633; | 39 | static unsigned int fmax = 515633; |
40 | 40 | ||
41 | /* | ||
42 | * This must be called with host->lock held | ||
43 | */ | ||
44 | static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | ||
45 | { | ||
46 | u32 clk = 0; | ||
47 | |||
48 | if (desired) { | ||
49 | if (desired >= host->mclk) { | ||
50 | clk = MCI_CLK_BYPASS; | ||
51 | host->cclk = host->mclk; | ||
52 | } else { | ||
53 | clk = host->mclk / (2 * desired) - 1; | ||
54 | if (clk >= 256) | ||
55 | clk = 255; | ||
56 | host->cclk = host->mclk / (2 * (clk + 1)); | ||
57 | } | ||
58 | if (host->hw_designer == 0x80) | ||
59 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ | ||
60 | clk |= MCI_CLK_ENABLE; | ||
61 | /* This hasn't proven to be worthwhile */ | ||
62 | /* clk |= MCI_CLK_PWRSAVE; */ | ||
63 | } | ||
64 | |||
65 | writel(clk, host->base + MMCICLOCK); | ||
66 | } | ||
67 | |||
41 | static void | 68 | static void |
42 | mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) | 69 | mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) |
43 | { | 70 | { |
@@ -419,22 +446,8 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
419 | static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 446 | static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
420 | { | 447 | { |
421 | struct mmci_host *host = mmc_priv(mmc); | 448 | struct mmci_host *host = mmc_priv(mmc); |
422 | u32 clk = 0, pwr = 0; | 449 | u32 pwr = 0; |
423 | 450 | unsigned long flags; | |
424 | if (ios->clock) { | ||
425 | if (ios->clock >= host->mclk) { | ||
426 | clk = MCI_CLK_BYPASS; | ||
427 | host->cclk = host->mclk; | ||
428 | } else { | ||
429 | clk = host->mclk / (2 * ios->clock) - 1; | ||
430 | if (clk >= 256) | ||
431 | clk = 255; | ||
432 | host->cclk = host->mclk / (2 * (clk + 1)); | ||
433 | } | ||
434 | if (host->hw_designer == AMBA_VENDOR_ST) | ||
435 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ | ||
436 | clk |= MCI_CLK_ENABLE; | ||
437 | } | ||
438 | 451 | ||
439 | if (host->plat->translate_vdd) | 452 | if (host->plat->translate_vdd) |
440 | pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); | 453 | pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); |
@@ -465,12 +478,16 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
465 | } | 478 | } |
466 | } | 479 | } |
467 | 480 | ||
468 | writel(clk, host->base + MMCICLOCK); | 481 | spin_lock_irqsave(&host->lock, flags); |
482 | |||
483 | mmci_set_clkreg(host, ios->clock); | ||
469 | 484 | ||
470 | if (host->pwr != pwr) { | 485 | if (host->pwr != pwr) { |
471 | host->pwr = pwr; | 486 | host->pwr = pwr; |
472 | writel(pwr, host->base + MMCIPOWER); | 487 | writel(pwr, host->base + MMCIPOWER); |
473 | } | 488 | } |
489 | |||
490 | spin_unlock_irqrestore(&host->lock, flags); | ||
474 | } | 491 | } |
475 | 492 | ||
476 | static int mmci_get_ro(struct mmc_host *mmc) | 493 | static int mmci_get_ro(struct mmc_host *mmc) |