diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 35789c6edc19..6779b4ecab18 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -584,7 +584,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
584 | * longer to time out, but that's much better than having a too-short | 584 | * longer to time out, but that's much better than having a too-short |
585 | * timeout value. | 585 | * timeout value. |
586 | */ | 586 | */ |
587 | if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)) | 587 | if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) |
588 | return 0xE; | 588 | return 0xE; |
589 | 589 | ||
590 | /* timeout in us */ | 590 | /* timeout in us */ |
@@ -1051,12 +1051,19 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1051 | * At least the Marvell CaFe chip gets confused if we set the voltage | 1051 | * At least the Marvell CaFe chip gets confused if we set the voltage |
1052 | * and set turn on power at the same time, so set the voltage first. | 1052 | * and set turn on power at the same time, so set the voltage first. |
1053 | */ | 1053 | */ |
1054 | if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) | 1054 | if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) |
1055 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1055 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1056 | 1056 | ||
1057 | pwr |= SDHCI_POWER_ON; | 1057 | pwr |= SDHCI_POWER_ON; |
1058 | 1058 | ||
1059 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1059 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1060 | |||
1061 | /* | ||
1062 | * Some controllers need an extra 10ms delay of 10ms before they | ||
1063 | * can apply clock after applying power | ||
1064 | */ | ||
1065 | if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) | ||
1066 | mdelay(10); | ||
1060 | } | 1067 | } |
1061 | 1068 | ||
1062 | /*****************************************************************************\ | 1069 | /*****************************************************************************\ |
@@ -1382,6 +1389,35 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
1382 | sdhci_finish_command(host); | 1389 | sdhci_finish_command(host); |
1383 | } | 1390 | } |
1384 | 1391 | ||
1392 | #ifdef DEBUG | ||
1393 | static void sdhci_show_adma_error(struct sdhci_host *host) | ||
1394 | { | ||
1395 | const char *name = mmc_hostname(host->mmc); | ||
1396 | u8 *desc = host->adma_desc; | ||
1397 | __le32 *dma; | ||
1398 | __le16 *len; | ||
1399 | u8 attr; | ||
1400 | |||
1401 | sdhci_dumpregs(host); | ||
1402 | |||
1403 | while (true) { | ||
1404 | dma = (__le32 *)(desc + 4); | ||
1405 | len = (__le16 *)(desc + 2); | ||
1406 | attr = *desc; | ||
1407 | |||
1408 | DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", | ||
1409 | name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); | ||
1410 | |||
1411 | desc += 8; | ||
1412 | |||
1413 | if (attr & 2) | ||
1414 | break; | ||
1415 | } | ||
1416 | } | ||
1417 | #else | ||
1418 | static void sdhci_show_adma_error(struct sdhci_host *host) { } | ||
1419 | #endif | ||
1420 | |||
1385 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | 1421 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |
1386 | { | 1422 | { |
1387 | BUG_ON(intmask == 0); | 1423 | BUG_ON(intmask == 0); |
@@ -1411,8 +1447,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1411 | host->data->error = -ETIMEDOUT; | 1447 | host->data->error = -ETIMEDOUT; |
1412 | else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) | 1448 | else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) |
1413 | host->data->error = -EILSEQ; | 1449 | host->data->error = -EILSEQ; |
1414 | else if (intmask & SDHCI_INT_ADMA_ERROR) | 1450 | else if (intmask & SDHCI_INT_ADMA_ERROR) { |
1451 | printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); | ||
1452 | sdhci_show_adma_error(host); | ||
1415 | host->data->error = -EIO; | 1453 | host->data->error = -EIO; |
1454 | } | ||
1416 | 1455 | ||
1417 | if (host->data->error) | 1456 | if (host->data->error) |
1418 | sdhci_finish_data(host); | 1457 | sdhci_finish_data(host); |
@@ -1729,7 +1768,10 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1729 | mmc->ops = &sdhci_ops; | 1768 | mmc->ops = &sdhci_ops; |
1730 | mmc->f_min = host->max_clk / 256; | 1769 | mmc->f_min = host->max_clk / 256; |
1731 | mmc->f_max = host->max_clk; | 1770 | mmc->f_max = host->max_clk; |
1732 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 1771 | mmc->caps = MMC_CAP_SDIO_IRQ; |
1772 | |||
1773 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | ||
1774 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1733 | 1775 | ||
1734 | if (caps & SDHCI_CAN_DO_HISPD) | 1776 | if (caps & SDHCI_CAN_DO_HISPD) |
1735 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1777 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
@@ -1802,7 +1844,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1802 | /* | 1844 | /* |
1803 | * Maximum block count. | 1845 | * Maximum block count. |
1804 | */ | 1846 | */ |
1805 | mmc->max_blk_count = 65535; | 1847 | mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; |
1806 | 1848 | ||
1807 | /* | 1849 | /* |
1808 | * Init tasklets. | 1850 | * Init tasklets. |