diff options
Diffstat (limited to 'drivers/mmc/host/atmel-mci.c')
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 60 |
1 files changed, 22 insertions, 38 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index d834e3756aef..14ab28da7fa8 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -279,23 +279,6 @@ err: | |||
279 | "failed to initialize debugfs for controller\n"); | 279 | "failed to initialize debugfs for controller\n"); |
280 | } | 280 | } |
281 | 281 | ||
282 | static void atmci_enable(struct atmel_mci *host) | ||
283 | { | ||
284 | clk_enable(host->mck); | ||
285 | mci_writel(host, CR, MCI_CR_MCIEN); | ||
286 | mci_writel(host, MR, host->mode_reg); | ||
287 | mci_writel(host, SDCR, host->sdc_reg); | ||
288 | } | ||
289 | |||
290 | static void atmci_disable(struct atmel_mci *host) | ||
291 | { | ||
292 | mci_writel(host, CR, MCI_CR_SWRST); | ||
293 | |||
294 | /* Stall until write is complete, then disable the bus clock */ | ||
295 | mci_readl(host, SR); | ||
296 | clk_disable(host->mck); | ||
297 | } | ||
298 | |||
299 | static inline unsigned int ns_to_clocks(struct atmel_mci *host, | 282 | static inline unsigned int ns_to_clocks(struct atmel_mci *host, |
300 | unsigned int ns) | 283 | unsigned int ns) |
301 | { | 284 | { |
@@ -408,8 +391,6 @@ static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq) | |||
408 | WARN_ON(host->cmd || host->data); | 391 | WARN_ON(host->cmd || host->data); |
409 | host->mrq = NULL; | 392 | host->mrq = NULL; |
410 | 393 | ||
411 | atmci_disable(host); | ||
412 | |||
413 | mmc_request_done(mmc, mrq); | 394 | mmc_request_done(mmc, mrq); |
414 | } | 395 | } |
415 | 396 | ||
@@ -476,8 +457,6 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
476 | host->completed_events = 0; | 457 | host->completed_events = 0; |
477 | host->state = STATE_SENDING_CMD; | 458 | host->state = STATE_SENDING_CMD; |
478 | 459 | ||
479 | atmci_enable(host); | ||
480 | |||
481 | /* We don't support multiple blocks of weird lengths. */ | 460 | /* We don't support multiple blocks of weird lengths. */ |
482 | data = mrq->data; | 461 | data = mrq->data; |
483 | if (data) { | 462 | if (data) { |
@@ -520,7 +499,6 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
520 | return; | 499 | return; |
521 | 500 | ||
522 | fail: | 501 | fail: |
523 | atmci_disable(host); | ||
524 | host->mrq = NULL; | 502 | host->mrq = NULL; |
525 | mrq->cmd->error = -EINVAL; | 503 | mrq->cmd->error = -EINVAL; |
526 | mmc_request_done(mmc, mrq); | 504 | mmc_request_done(mmc, mrq); |
@@ -530,9 +508,21 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
530 | { | 508 | { |
531 | struct atmel_mci *host = mmc_priv(mmc); | 509 | struct atmel_mci *host = mmc_priv(mmc); |
532 | 510 | ||
511 | switch (ios->bus_width) { | ||
512 | case MMC_BUS_WIDTH_1: | ||
513 | host->sdc_reg = 0; | ||
514 | break; | ||
515 | case MMC_BUS_WIDTH_4: | ||
516 | host->sdc_reg = MCI_SDCBUS_4BIT; | ||
517 | break; | ||
518 | } | ||
519 | |||
533 | if (ios->clock) { | 520 | if (ios->clock) { |
534 | u32 clkdiv; | 521 | u32 clkdiv; |
535 | 522 | ||
523 | if (!host->mode_reg) | ||
524 | clk_enable(host->mck); | ||
525 | |||
536 | /* Set clock rate */ | 526 | /* Set clock rate */ |
537 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1; | 527 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1; |
538 | if (clkdiv > 255) { | 528 | if (clkdiv > 255) { |
@@ -544,26 +534,20 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
544 | 534 | ||
545 | host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF | 535 | host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF |
546 | | MCI_MR_RDPROOF; | 536 | | MCI_MR_RDPROOF; |
547 | } | ||
548 | 537 | ||
549 | switch (ios->bus_width) { | 538 | mci_writel(host, CR, MCI_CR_MCIEN); |
550 | case MMC_BUS_WIDTH_1: | 539 | mci_writel(host, MR, host->mode_reg); |
551 | host->sdc_reg = 0; | 540 | mci_writel(host, SDCR, host->sdc_reg); |
552 | break; | 541 | } else { |
553 | case MMC_BUS_WIDTH_4: | 542 | mci_writel(host, CR, MCI_CR_MCIDIS); |
554 | host->sdc_reg = MCI_SDCBUS_4BIT; | 543 | if (host->mode_reg) { |
555 | break; | 544 | mci_readl(host, MR); |
545 | clk_disable(host->mck); | ||
546 | } | ||
547 | host->mode_reg = 0; | ||
556 | } | 548 | } |
557 | 549 | ||
558 | switch (ios->power_mode) { | 550 | switch (ios->power_mode) { |
559 | case MMC_POWER_ON: | ||
560 | /* Send init sequence (74 clock cycles) */ | ||
561 | atmci_enable(host); | ||
562 | mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT); | ||
563 | while (!(mci_readl(host, SR) & MCI_CMDRDY)) | ||
564 | cpu_relax(); | ||
565 | atmci_disable(host); | ||
566 | break; | ||
567 | default: | 551 | default: |
568 | /* | 552 | /* |
569 | * TODO: None of the currently available AVR32-based | 553 | * TODO: None of the currently available AVR32-based |