diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5d20661bc357..ab17344fc7b3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -40,7 +40,6 @@ | |||
40 | 40 | ||
41 | static unsigned int debug_quirks = 0; | 41 | static unsigned int debug_quirks = 0; |
42 | 42 | ||
43 | static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); | ||
44 | static void sdhci_finish_data(struct sdhci_host *); | 43 | static void sdhci_finish_data(struct sdhci_host *); |
45 | 44 | ||
46 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); | 45 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); |
@@ -591,9 +590,10 @@ static void sdhci_adma_table_post(struct sdhci_host *host, | |||
591 | data->sg_len, direction); | 590 | data->sg_len, direction); |
592 | } | 591 | } |
593 | 592 | ||
594 | static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | 593 | static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) |
595 | { | 594 | { |
596 | u8 count; | 595 | u8 count; |
596 | struct mmc_data *data = cmd->data; | ||
597 | unsigned target_timeout, current_timeout; | 597 | unsigned target_timeout, current_timeout; |
598 | 598 | ||
599 | /* | 599 | /* |
@@ -605,12 +605,16 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
605 | if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) | 605 | if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) |
606 | return 0xE; | 606 | return 0xE; |
607 | 607 | ||
608 | /* timeout in us */ | 608 | /* Unspecified timeout, assume max */ |
609 | target_timeout = data->timeout_ns / 1000 + | 609 | if (!data && !cmd->cmd_timeout_ms) |
610 | data->timeout_clks / host->clock; | 610 | return 0xE; |
611 | 611 | ||
612 | if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) | 612 | /* timeout in us */ |
613 | host->timeout_clk = host->clock / 1000; | 613 | if (!data) |
614 | target_timeout = cmd->cmd_timeout_ms * 1000; | ||
615 | else | ||
616 | target_timeout = data->timeout_ns / 1000 + | ||
617 | data->timeout_clks / host->clock; | ||
614 | 618 | ||
615 | /* | 619 | /* |
616 | * Figure out needed cycles. | 620 | * Figure out needed cycles. |
@@ -632,8 +636,8 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
632 | } | 636 | } |
633 | 637 | ||
634 | if (count >= 0xF) { | 638 | if (count >= 0xF) { |
635 | printk(KERN_WARNING "%s: Too large timeout requested!\n", | 639 | printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n", |
636 | mmc_hostname(host->mmc)); | 640 | mmc_hostname(host->mmc), cmd->opcode); |
637 | count = 0xE; | 641 | count = 0xE; |
638 | } | 642 | } |
639 | 643 | ||
@@ -651,15 +655,21 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) | |||
651 | sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); | 655 | sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); |
652 | } | 656 | } |
653 | 657 | ||
654 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | 658 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) |
655 | { | 659 | { |
656 | u8 count; | 660 | u8 count; |
657 | u8 ctrl; | 661 | u8 ctrl; |
662 | struct mmc_data *data = cmd->data; | ||
658 | int ret; | 663 | int ret; |
659 | 664 | ||
660 | WARN_ON(host->data); | 665 | WARN_ON(host->data); |
661 | 666 | ||
662 | if (data == NULL) | 667 | if (data || (cmd->flags & MMC_RSP_BUSY)) { |
668 | count = sdhci_calc_timeout(host, cmd); | ||
669 | sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); | ||
670 | } | ||
671 | |||
672 | if (!data) | ||
663 | return; | 673 | return; |
664 | 674 | ||
665 | /* Sanity checks */ | 675 | /* Sanity checks */ |
@@ -670,9 +680,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
670 | host->data = data; | 680 | host->data = data; |
671 | host->data_early = 0; | 681 | host->data_early = 0; |
672 | 682 | ||
673 | count = sdhci_calc_timeout(host, data); | ||
674 | sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); | ||
675 | |||
676 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) | 683 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) |
677 | host->flags |= SDHCI_REQ_USE_DMA; | 684 | host->flags |= SDHCI_REQ_USE_DMA; |
678 | 685 | ||
@@ -920,7 +927,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
920 | 927 | ||
921 | host->cmd = cmd; | 928 | host->cmd = cmd; |
922 | 929 | ||
923 | sdhci_prepare_data(host, cmd->data); | 930 | sdhci_prepare_data(host, cmd); |
924 | 931 | ||
925 | sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); | 932 | sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); |
926 | 933 | ||
@@ -1874,6 +1881,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1874 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | 1881 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) |
1875 | host->timeout_clk *= 1000; | 1882 | host->timeout_clk *= 1000; |
1876 | 1883 | ||
1884 | if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) | ||
1885 | host->timeout_clk = host->clock / 1000; | ||
1886 | |||
1877 | /* | 1887 | /* |
1878 | * Set host parameters. | 1888 | * Set host parameters. |
1879 | */ | 1889 | */ |
@@ -1886,7 +1896,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1886 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; | 1896 | mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; |
1887 | 1897 | ||
1888 | mmc->f_max = host->max_clk; | 1898 | mmc->f_max = host->max_clk; |
1889 | mmc->caps |= MMC_CAP_SDIO_IRQ; | 1899 | mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; |
1890 | 1900 | ||
1891 | /* | 1901 | /* |
1892 | * A controller may support 8-bit width, but the board itself | 1902 | * A controller may support 8-bit width, but the board itself |