diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 4a24db028d87..f2bc87ac24f7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver | 2 | * linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. | 4 | * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. |
5 | * | 5 | * |
@@ -34,6 +34,7 @@ static unsigned int debug_quirks = 0; | |||
34 | /* Controller doesn't like some resets when there is no card inserted. */ | 34 | /* Controller doesn't like some resets when there is no card inserted. */ |
35 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | 35 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) |
36 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | 36 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) |
37 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
37 | 38 | ||
38 | static const struct pci_device_id pci_ids[] __devinitdata = { | 39 | static const struct pci_device_id pci_ids[] __devinitdata = { |
39 | { | 40 | { |
@@ -78,6 +79,24 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
78 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, | 79 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, |
79 | }, | 80 | }, |
80 | 81 | ||
82 | { | ||
83 | .vendor = PCI_VENDOR_ID_ENE, | ||
84 | .device = PCI_DEVICE_ID_ENE_CB714_SD, | ||
85 | .subvendor = PCI_ANY_ID, | ||
86 | .subdevice = PCI_ANY_ID, | ||
87 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
88 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, | ||
89 | }, | ||
90 | |||
91 | { | ||
92 | .vendor = PCI_VENDOR_ID_ENE, | ||
93 | .device = PCI_DEVICE_ID_ENE_CB714_SD_2, | ||
94 | .subvendor = PCI_ANY_ID, | ||
95 | .subdevice = PCI_ANY_ID, | ||
96 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
97 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS, | ||
98 | }, | ||
99 | |||
81 | { /* Generic SD host controller */ | 100 | { /* Generic SD host controller */ |
82 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 101 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
83 | }, | 102 | }, |
@@ -361,11 +380,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
361 | if (data == NULL) | 380 | if (data == NULL) |
362 | return; | 381 | return; |
363 | 382 | ||
364 | DBG("blksz %04x blks %04x flags %08x\n", | ||
365 | data->blksz, data->blocks, data->flags); | ||
366 | DBG("tsac %d ms nsac %d clk\n", | ||
367 | data->timeout_ns / 1000000, data->timeout_clks); | ||
368 | |||
369 | /* Sanity checks */ | 383 | /* Sanity checks */ |
370 | BUG_ON(data->blksz * data->blocks > 524288); | 384 | BUG_ON(data->blksz * data->blocks > 524288); |
371 | BUG_ON(data->blksz > host->mmc->max_blk_size); | 385 | BUG_ON(data->blksz > host->mmc->max_blk_size); |
@@ -476,8 +490,6 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
476 | data->error = MMC_ERR_FAILED; | 490 | data->error = MMC_ERR_FAILED; |
477 | } | 491 | } |
478 | 492 | ||
479 | DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered); | ||
480 | |||
481 | if (data->stop) { | 493 | if (data->stop) { |
482 | /* | 494 | /* |
483 | * The controller needs a reset of internal state machines | 495 | * The controller needs a reset of internal state machines |
@@ -501,8 +513,6 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
501 | 513 | ||
502 | WARN_ON(host->cmd); | 514 | WARN_ON(host->cmd); |
503 | 515 | ||
504 | DBG("Sending cmd (%x)\n", cmd->opcode); | ||
505 | |||
506 | /* Wait max 10 ms */ | 516 | /* Wait max 10 ms */ |
507 | timeout = 10; | 517 | timeout = 10; |
508 | 518 | ||
@@ -590,8 +600,6 @@ static void sdhci_finish_command(struct sdhci_host *host) | |||
590 | 600 | ||
591 | host->cmd->error = MMC_ERR_NONE; | 601 | host->cmd->error = MMC_ERR_NONE; |
592 | 602 | ||
593 | DBG("Ending cmd (%x)\n", host->cmd->opcode); | ||
594 | |||
595 | if (host->cmd->data) | 603 | if (host->cmd->data) |
596 | host->data = host->cmd->data; | 604 | host->data = host->cmd->data; |
597 | else | 605 | else |
@@ -759,6 +767,14 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
759 | 767 | ||
760 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | 768 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); |
761 | 769 | ||
770 | /* | ||
771 | * Some (ENE) controllers go apeshit on some ios operation, | ||
772 | * signalling timeout and CRC errors even on CMD0. Resetting | ||
773 | * it on each ios seems to solve the problem. | ||
774 | */ | ||
775 | if(host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) | ||
776 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); | ||
777 | |||
762 | mmiowb(); | 778 | mmiowb(); |
763 | spin_unlock_irqrestore(&host->lock, flags); | 779 | spin_unlock_irqrestore(&host->lock, flags); |
764 | } | 780 | } |
@@ -835,8 +851,6 @@ static void sdhci_tasklet_finish(unsigned long param) | |||
835 | 851 | ||
836 | mrq = host->mrq; | 852 | mrq = host->mrq; |
837 | 853 | ||
838 | DBG("Ending request, cmd (%x)\n", mrq->cmd->opcode); | ||
839 | |||
840 | /* | 854 | /* |
841 | * The controller needs a reset of internal state machines | 855 | * The controller needs a reset of internal state machines |
842 | * upon error conditions. | 856 | * upon error conditions. |
@@ -922,20 +936,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
922 | return; | 936 | return; |
923 | } | 937 | } |
924 | 938 | ||
925 | if (intmask & SDHCI_INT_RESPONSE) | 939 | if (intmask & SDHCI_INT_TIMEOUT) |
926 | sdhci_finish_command(host); | 940 | host->cmd->error = MMC_ERR_TIMEOUT; |
927 | else { | 941 | else if (intmask & SDHCI_INT_CRC) |
928 | if (intmask & SDHCI_INT_TIMEOUT) | 942 | host->cmd->error = MMC_ERR_BADCRC; |
929 | host->cmd->error = MMC_ERR_TIMEOUT; | 943 | else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) |
930 | else if (intmask & SDHCI_INT_CRC) | 944 | host->cmd->error = MMC_ERR_FAILED; |
931 | host->cmd->error = MMC_ERR_BADCRC; | ||
932 | else if (intmask & (SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) | ||
933 | host->cmd->error = MMC_ERR_FAILED; | ||
934 | else | ||
935 | host->cmd->error = MMC_ERR_INVALID; | ||
936 | 945 | ||
946 | if (host->cmd->error != MMC_ERR_NONE) | ||
937 | tasklet_schedule(&host->finish_tasklet); | 947 | tasklet_schedule(&host->finish_tasklet); |
938 | } | 948 | else if (intmask & SDHCI_INT_RESPONSE) |
949 | sdhci_finish_command(host); | ||
939 | } | 950 | } |
940 | 951 | ||
941 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | 952 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |